From b7b6160d0eb922c44d174f7e1199713e4285c54e Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Fri, 6 May 2022 19:29:41 +0300 Subject: [PATCH 001/427] fs/ntfs3: Refactoring of indx_find function This commit makes function a bit more readable Cc: Joe Perches Signed-off-by: Konstantin Komarov --- fs/ntfs3/index.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c index 6f81e3a49abfb..8468cca5d54d8 100644 --- a/fs/ntfs3/index.c +++ b/fs/ntfs3/index.c @@ -1042,19 +1042,16 @@ int indx_find(struct ntfs_index *indx, struct ntfs_inode *ni, { int err; struct NTFS_DE *e; - const struct INDEX_HDR *hdr; struct indx_node *node; if (!root) root = indx_get_root(&ni->dir, ni, NULL, NULL); if (!root) { - err = -EINVAL; - goto out; + /* Should not happen. */ + return -EINVAL; } - hdr = &root->ihdr; - /* Check cache. */ e = fnd->level ? fnd->de[fnd->level - 1] : fnd->root_de; if (e && !de_is_last(e) && @@ -1068,39 +1065,35 @@ int indx_find(struct ntfs_index *indx, struct ntfs_inode *ni, fnd_clear(fnd); /* Lookup entry that is <= to the search value. */ - e = hdr_find_e(indx, hdr, key, key_len, ctx, diff); + e = hdr_find_e(indx, &root->ihdr, key, key_len, ctx, diff); if (!e) return -EINVAL; fnd->root_de = e; - err = 0; for (;;) { node = NULL; - if (*diff >= 0 || !de_has_vcn_ex(e)) { - *entry = e; - goto out; - } + if (*diff >= 0 || !de_has_vcn_ex(e)) + break; /* Read next level. */ err = indx_read(indx, ni, de_get_vbn(e), &node); if (err) - goto out; + return err; /* Lookup entry that is <= to the search value. */ e = hdr_find_e(indx, &node->index->ihdr, key, key_len, ctx, diff); if (!e) { - err = -EINVAL; put_indx_node(node); - goto out; + return -EINVAL; } fnd_push(fnd, node, e); } -out: - return err; + *entry = e; + return 0; } int indx_find_sort(struct ntfs_index *indx, struct ntfs_inode *ni, From cd39981fb92adf0cc736112f87e3e61602baa415 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Wed, 11 May 2022 19:58:36 +0300 Subject: [PATCH 002/427] fs/ntfs3: Fix double free on remount Pointer to options was freed twice on remount Fixes xfstest generic/361 Fixes: 82cae269cfa9 ("fs/ntfs3: Add initialization of super block") Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 278dcf5024102..4b0dad2ac5988 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -390,7 +391,7 @@ static int ntfs_fs_reconfigure(struct fs_context *fc) return -EINVAL; } - memcpy(sbi->options, new_opts, sizeof(*new_opts)); + swap(sbi->options, fc->fs_private); return 0; } @@ -897,6 +898,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) ref.high = 0; sbi->sb = sb; + sbi->options = fc->fs_private; + fc->fs_private = NULL; sb->s_flags |= SB_NODIRATIME; sb->s_magic = 0x7366746e; // "ntfs" sb->s_op = &ntfs_sops; @@ -1260,8 +1263,6 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) goto put_inode_out; } - fc->fs_private = NULL; - return 0; put_inode_out: @@ -1414,7 +1415,6 @@ static int ntfs_init_fs_context(struct fs_context *fc) mutex_init(&sbi->compress.mtx_lzx); #endif - sbi->options = opts; fc->s_fs_info = sbi; ok: fc->fs_private = opts; From 19d1b7872d1ebf0658b5032b79f536a715303ee4 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 12 May 2022 12:25:48 +0300 Subject: [PATCH 003/427] fs/ntfs3: Refactor ni_try_remove_attr_list function Now we save a copy of primary record for restoration. Also now we remove all attributes from subrecords. Signed-off-by: Konstantin Komarov --- fs/ntfs3/frecord.c | 49 ++++++++++++++++++++++++++++++++++------------ fs/ntfs3/record.c | 5 ++--- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index 18842998c8fa3..3576268ee0a1d 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -7,6 +7,7 @@ #include #include +#include #include #include "debug.h" @@ -649,6 +650,7 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni) struct mft_inode *mi; u32 asize, free; struct MFT_REF ref; + struct MFT_REC *mrec; __le16 id; if (!ni->attr_list.dirty) @@ -692,11 +694,17 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni) free -= asize; } + /* Make a copy of primary record to restore if error. */ + mrec = kmemdup(ni->mi.mrec, sbi->record_size, GFP_NOFS); + if (!mrec) + return 0; /* Not critical. */ + /* It seems that attribute list can be removed from primary record. */ mi_remove_attr(NULL, &ni->mi, attr_list); /* - * Repeat the cycle above and move all attributes to primary record. + * Repeat the cycle above and copy all attributes to primary record. + * Do not remove original attributes from subrecords! * It should be success! */ le = NULL; @@ -707,14 +715,14 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni) mi = ni_find_mi(ni, ino_get(&le->ref)); if (!mi) { /* Should never happened, 'cause already checked. */ - goto bad; + goto out; } attr = mi_find_attr(mi, NULL, le->type, le_name(le), le->name_len, &le->id); if (!attr) { /* Should never happened, 'cause already checked. */ - goto bad; + goto out; } asize = le32_to_cpu(attr->size); @@ -724,18 +732,33 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni) le16_to_cpu(attr->name_off)); if (!attr_ins) { /* - * Internal error. - * Either no space in primary record (already checked). - * Either tried to insert another - * non indexed attribute (logic error). + * No space in primary record (already checked). */ - goto bad; + goto out; } /* Copy all except id. */ id = attr_ins->id; memcpy(attr_ins, attr, asize); attr_ins->id = id; + } + + /* + * Repeat the cycle above and remove all attributes from subrecords. + */ + le = NULL; + while ((le = al_enumerate(ni, le))) { + if (!memcmp(&le->ref, &ref, sizeof(ref))) + continue; + + mi = ni_find_mi(ni, ino_get(&le->ref)); + if (!mi) + continue; + + attr = mi_find_attr(mi, NULL, le->type, le_name(le), + le->name_len, &le->id); + if (!attr) + continue; /* Remove from original record. */ mi_remove_attr(NULL, mi, attr); @@ -748,11 +771,13 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni) ni->attr_list.le = NULL; ni->attr_list.dirty = false; + kfree(mrec); + return 0; +out: + /* Restore primary record. */ + swap(mrec, ni->mi.mrec); + kfree(mrec); return 0; -bad: - ntfs_inode_err(&ni->vfs_inode, "Internal error"); - make_bad_inode(&ni->vfs_inode); - return -EINVAL; } /* diff --git a/fs/ntfs3/record.c b/fs/ntfs3/record.c index 861e35791506e..8fe0a876400ad 100644 --- a/fs/ntfs3/record.c +++ b/fs/ntfs3/record.c @@ -445,12 +445,11 @@ struct ATTRIB *mi_insert_attr(struct mft_inode *mi, enum ATTR_TYPE type, attr = NULL; while ((attr = mi_enum_attr(mi, attr))) { diff = compare_attr(attr, type, name, name_len, upcase); - if (diff > 0) - break; + if (diff < 0) continue; - if (!is_attr_indexed(attr)) + if (!diff && !is_attr_indexed(attr)) return NULL; break; } From 37a530bfe56ca9a0d3129598803f2794c7428aae Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 26 May 2022 12:51:03 +0300 Subject: [PATCH 004/427] fs/ntfs3: Fix missing i_op in ntfs_read_mft There is null pointer dereference because i_op == NULL. The bug happens because we don't initialize i_op for records in $Extend. Fixes: 82cae269cfa9 ("fs/ntfs3: Add initialization of super block") Reported-by: Liangbin Lian Signed-off-by: Konstantin Komarov --- fs/ntfs3/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 38045264a61bd..6c78930be0357 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -430,6 +430,7 @@ static struct inode *ntfs_read_mft(struct inode *inode, } else if (fname && fname->home.low == cpu_to_le32(MFT_REC_EXTEND) && fname->home.seq == cpu_to_le16(MFT_REC_EXTEND)) { /* Records in $Extend are not a files or general directories. */ + inode->i_op = &ntfs_file_inode_operations; } else { err = -EINVAL; goto out; From 548744f84456946181ed6dc0ac6be8267f167d28 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 23 Dec 2021 15:20:00 +0300 Subject: [PATCH 005/427] fs/ntfs3: Remove a useless test 'new_free' has just been allocated by kmalloc() and is known to be not NULL. So this pointer can't be equal to a previous memory allocation. Signed-off-by: Christophe JAILLET Signed-off-by: Konstantin Komarov --- fs/ntfs3/bitmap.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fs/ntfs3/bitmap.c b/fs/ntfs3/bitmap.c index aa184407520f0..e3b5680fd5168 100644 --- a/fs/ntfs3/bitmap.c +++ b/fs/ntfs3/bitmap.c @@ -1333,9 +1333,7 @@ int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits) if (!new_free) return -ENOMEM; - if (new_free != wnd->free_bits) - memcpy(new_free, wnd->free_bits, - wnd->nwnd * sizeof(short)); + memcpy(new_free, wnd->free_bits, wnd->nwnd * sizeof(short)); memset(new_free + wnd->nwnd, 0, (new_wnd - wnd->nwnd) * sizeof(short)); kfree(wnd->free_bits); From 560e613352b4a65c5c397e689a997fb04bd5f928 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 30 Dec 2021 18:59:00 +0300 Subject: [PATCH 006/427] fs/ntfs3: Remove redundant assignment to variable frame Variable frame is assigned a value that is never read. The assignment is redundant and can be removed. Cleans up the clang-scan build warning: fs/ntfs3/file.c:995:3: warning: Value stored to 'frame' is never read [deadcode.DeadStores] frame = pos >> frame_bits; Signed-off-by: Colin Ian King Signed-off-by: Konstantin Komarov --- fs/ntfs3/file.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 3bae76930e68a..27c32692513c4 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -992,7 +992,6 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) if (bytes > count) bytes = count; - frame = pos >> frame_bits; frame_vbo = pos & ~(frame_size - 1); index = frame_vbo >> PAGE_SHIFT; From dc8965ab5e338abfd8dfd65d12a62ad5be65a776 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 18 Apr 2022 17:00:00 +0300 Subject: [PATCH 007/427] fs/ntfs3: Remove redundant assignment to variable vcn Variable vcn is being assigned a value that is never read, it is being re-assigned again in the initialization of a for-loop. The assignment is redundant and can be removed. Cleans up clang scan build warning: fs/ntfs3/attrib.c:1176:7: warning: Value stored to 'vcn' during its initialization is never read [deadcode.DeadStores] Signed-off-by: Colin Ian King Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index e8c00dda42adb..fc0623b029e6b 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -1173,7 +1173,7 @@ int attr_load_runs_range(struct ntfs_inode *ni, enum ATTR_TYPE type, { struct ntfs_sb_info *sbi = ni->mi.sbi; u8 cluster_bits = sbi->cluster_bits; - CLST vcn = from >> cluster_bits; + CLST vcn; CLST vcn_last = (to - 1) >> cluster_bits; CLST lcn, clen; int err; From ae5a4e46916fc307288227b64c1d062352eb93b7 Mon Sep 17 00:00:00 2001 From: Yan Lei Date: Sun, 10 Apr 2022 09:09:00 +0300 Subject: [PATCH 008/427] fs/ntfs3: Fix using uninitialized value n when calling indx_read This value is checked in indx_read, so it must be initialized Fixes: 82cae269cfa9 ("fs/ntfs3: Add initialization of super block") Signed-off-by: Yan Lei Signed-off-by: Konstantin Komarov --- fs/ntfs3/index.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c index 8468cca5d54d8..84ccc14098747 100644 --- a/fs/ntfs3/index.c +++ b/fs/ntfs3/index.c @@ -1987,7 +1987,7 @@ static int indx_free_children(struct ntfs_index *indx, struct ntfs_inode *ni, const struct NTFS_DE *e, bool trim) { int err; - struct indx_node *n; + struct indx_node *n = NULL; struct INDEX_HDR *hdr; CLST vbn = de_get_vbn(e); size_t i; From 19e890ff3bedc36fe3cd1cb7d03bfb66c5fdf1db Mon Sep 17 00:00:00 2001 From: Yang Xu Date: Wed, 20 Apr 2022 11:48:00 +0300 Subject: [PATCH 009/427] fs/ntfs3: Use the same order for acl pointer check in ntfs_init_acl For the readability and unity of the code, adjust the order Signed-off-by: Yang Xu Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/xattr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index 5e0e0280e70de..2d29afe4b40b1 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -706,13 +706,13 @@ int ntfs_init_acl(struct user_namespace *mnt_userns, struct inode *inode, inode->i_default_acl = NULL; } - if (!acl) - inode->i_acl = NULL; - else { + if (acl) { if (!err) err = ntfs_set_acl_ex(mnt_userns, inode, acl, ACL_TYPE_ACCESS, true); posix_acl_release(acl); + } else { + inode->i_acl = NULL; } return err; From 926034353d3c67db1ffeab47dcb7f6bdac02a263 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 9 May 2022 12:03:00 +0300 Subject: [PATCH 010/427] fs/ntfs3: Don't clear upper bits accidentally in log_replay() The "vcn" variable is a 64 bit. The "log->clst_per_page" variable is a u32. This means that the mask accidentally clears out the high 32 bits when it was only supposed to clear some low bits. Fix this by adding a cast to u64. Fixes: b46acd6a6a62 ("fs/ntfs3: Add NTFS journal") Signed-off-by: Dan Carpenter Reviewed-by: Namjae Jeon Signed-off-by: Konstantin Komarov --- fs/ntfs3/fslog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c index 49b7df6167785..614513460b8e0 100644 --- a/fs/ntfs3/fslog.c +++ b/fs/ntfs3/fslog.c @@ -5057,7 +5057,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) goto add_allocated_vcns; vcn = le64_to_cpu(lrh->target_vcn); - vcn &= ~(log->clst_per_page - 1); + vcn &= ~(u64)(log->clst_per_page - 1); add_allocated_vcns: for (i = 0, vcn = le64_to_cpu(lrh->target_vcn), From f759942b72a9ad309282b2fedcebcee3c4c58e24 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 6 Jun 2022 18:57:21 +0300 Subject: [PATCH 011/427] fs/ntfs3: Add missing error check We must check return value of log_read_rst Signed-off-by: Konstantin Komarov --- fs/ntfs3/fslog.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c index 614513460b8e0..e7c494005122c 100644 --- a/fs/ntfs3/fslog.c +++ b/fs/ntfs3/fslog.c @@ -3843,6 +3843,8 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) memset(&rst_info2, 0, sizeof(struct restart_info)); err = log_read_rst(log, l_size, false, &rst_info2); + if (err) + goto out; /* Determine which restart area to use. */ if (!rst_info2.restart || rst_info2.last_lsn <= rst_info.last_lsn) From aa30eccb24e5a66a2cf7f7b34a69c3651d12cc6a Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Tue, 21 Jun 2022 12:46:25 +0300 Subject: [PATCH 012/427] fs/ntfs3: Fallocate (FALLOC_FL_INSERT_RANGE) implementation Add functions for inserting hole in file and inserting range in run. Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 176 +++++++++++++++++++++++++++++++++++++++++++++ fs/ntfs3/ntfs_fs.h | 4 +- fs/ntfs3/run.c | 43 +++++++++++ 3 files changed, 222 insertions(+), 1 deletion(-) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index fc0623b029e6b..86e688b95ad57 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -2081,3 +2081,179 @@ int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size) return err; } + +/* + * attr_insert_range - Insert range (hole) in file. + * Not for normal files. + */ +int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) +{ + int err = 0; + struct runs_tree *run = &ni->file.run; + struct ntfs_sb_info *sbi = ni->mi.sbi; + struct ATTRIB *attr = NULL, *attr_b; + struct ATTR_LIST_ENTRY *le, *le_b; + struct mft_inode *mi, *mi_b; + CLST vcn, svcn, evcn1, len, next_svcn; + u64 data_size, alloc_size; + u32 mask; + __le16 a_flags; + + if (!bytes) + return 0; + + le_b = NULL; + attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, 0, NULL, &mi_b); + if (!attr_b) + return -ENOENT; + + if (!is_attr_ext(attr_b)) { + /* It was checked above. See fallocate. */ + return -EOPNOTSUPP; + } + + if (!attr_b->non_res) { + data_size = le32_to_cpu(attr_b->res.data_size); + mask = sbi->cluster_mask; /* cluster_size - 1 */ + } else { + data_size = le64_to_cpu(attr_b->nres.data_size); + mask = (sbi->cluster_size << attr_b->nres.c_unit) - 1; + } + + if (vbo > data_size) { + /* Insert range after the file size is not allowed. */ + return -EINVAL; + } + + if ((vbo & mask) || (bytes & mask)) { + /* Allow to insert only frame aligned ranges. */ + return -EINVAL; + } + + vcn = vbo >> sbi->cluster_bits; + len = bytes >> sbi->cluster_bits; + + down_write(&ni->file.run_lock); + + if (!attr_b->non_res) { + err = attr_set_size(ni, ATTR_DATA, NULL, 0, run, + data_size + bytes, NULL, false, &attr); + if (err) + goto out; + if (!attr->non_res) { + /* Still resident. */ + char *data = Add2Ptr(attr, attr->res.data_off); + + memmove(data + bytes, data, bytes); + memset(data, 0, bytes); + err = 0; + goto out; + } + /* Resident files becomes nonresident. */ + le_b = NULL; + attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, 0, NULL, + &mi_b); + if (!attr_b) + return -ENOENT; + if (!attr_b->non_res) { + err = -EINVAL; + goto out; + } + data_size = le64_to_cpu(attr_b->nres.data_size); + alloc_size = le64_to_cpu(attr_b->nres.alloc_size); + } + + /* + * Enumerate all attribute segments and shift start vcn. + */ + a_flags = attr_b->flags; + svcn = le64_to_cpu(attr_b->nres.svcn); + evcn1 = le64_to_cpu(attr_b->nres.evcn) + 1; + + if (svcn <= vcn && vcn < evcn1) { + attr = attr_b; + le = le_b; + mi = mi_b; + } else if (!le_b) { + err = -EINVAL; + goto out; + } else { + le = le_b; + attr = ni_find_attr(ni, attr_b, &le, ATTR_DATA, NULL, 0, &vcn, + &mi); + if (!attr) { + err = -EINVAL; + goto out; + } + + svcn = le64_to_cpu(attr->nres.svcn); + evcn1 = le64_to_cpu(attr->nres.evcn) + 1; + } + + run_truncate(run, 0); /* clear cached values. */ + err = attr_load_runs(attr, ni, run, NULL); + if (err) + goto out; + + if (!run_insert_range(run, vcn, len)) { + err = -ENOMEM; + goto out; + } + + /* Try to pack in current record as much as possible. */ + err = mi_pack_runs(mi, attr, run, evcn1 + len - svcn); + if (err) + goto out; + + next_svcn = le64_to_cpu(attr->nres.evcn) + 1; + run_truncate_head(run, next_svcn); + + while ((attr = ni_enum_attr_ex(ni, attr, &le, &mi)) && + attr->type == ATTR_DATA && !attr->name_len) { + le64_add_cpu(&attr->nres.svcn, len); + le64_add_cpu(&attr->nres.evcn, len); + if (le) { + le->vcn = attr->nres.svcn; + ni->attr_list.dirty = true; + } + mi->dirty = true; + } + + /* + * Update primary attribute segment in advance. + * pointer attr_b may become invalid (layout of mft is changed) + */ + if (vbo <= ni->i_valid) + ni->i_valid += bytes; + + attr_b->nres.data_size = le64_to_cpu(data_size + bytes); + attr_b->nres.alloc_size = le64_to_cpu(alloc_size + bytes); + + /* ni->valid may be not equal valid_size (temporary). */ + if (ni->i_valid > data_size + bytes) + attr_b->nres.valid_size = attr_b->nres.data_size; + else + attr_b->nres.valid_size = cpu_to_le64(ni->i_valid); + mi_b->dirty = true; + + if (next_svcn < evcn1 + len) { + err = ni_insert_nonresident(ni, ATTR_DATA, NULL, 0, run, + next_svcn, evcn1 + len - next_svcn, + a_flags, NULL, NULL); + if (err) + goto out; + } + + ni->vfs_inode.i_size += bytes; + ni->ni_flags |= NI_FLAG_UPDATE_PARENT; + mark_inode_dirty(&ni->vfs_inode); + +out: + run_truncate(run, 0); /* clear cached values. */ + + up_write(&ni->file.run_lock); + if (err) + make_bad_inode(&ni->vfs_inode); + + return err; +} diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index fb825059d4886..1f92e3a05f61e 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -440,6 +440,7 @@ int attr_is_frame_compressed(struct ntfs_inode *ni, struct ATTRIB *attr, int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size, u64 new_valid); int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes); +int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes); int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size); /* Functions from attrlist.c */ @@ -775,10 +776,11 @@ bool run_lookup_entry(const struct runs_tree *run, CLST vcn, CLST *lcn, void run_truncate(struct runs_tree *run, CLST vcn); void run_truncate_head(struct runs_tree *run, CLST vcn); void run_truncate_around(struct runs_tree *run, CLST vcn); -bool run_lookup(const struct runs_tree *run, CLST vcn, size_t *Index); +bool run_lookup(const struct runs_tree *run, CLST vcn, size_t *index); bool run_add_entry(struct runs_tree *run, CLST vcn, CLST lcn, CLST len, bool is_mft); bool run_collapse_range(struct runs_tree *run, CLST vcn, CLST len); +bool run_insert_range(struct runs_tree *run, CLST vcn, CLST len); bool run_get_entry(const struct runs_tree *run, size_t index, CLST *vcn, CLST *lcn, CLST *len); bool run_is_mapped_full(const struct runs_tree *run, CLST svcn, CLST evcn); diff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index a8fec651f9732..7609d45a2d721 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -547,6 +547,49 @@ bool run_collapse_range(struct runs_tree *run, CLST vcn, CLST len) return true; } +/* run_insert_range + * + * Helper for attr_insert_range(), + * which is helper for fallocate(insert_range). + */ +bool run_insert_range(struct runs_tree *run, CLST vcn, CLST len) +{ + size_t index; + struct ntfs_run *r, *e; + + if (WARN_ON(!run_lookup(run, vcn, &index))) + return false; /* Should never be here. */ + + e = run->runs + run->count; + r = run->runs + index; + + r = run->runs + index; + if (vcn > r->vcn) + r += 1; + + for (; r < e; r++) + r->vcn += len; + + r = run->runs + index; + + if (vcn > r->vcn) { + /* split fragment. */ + CLST len1 = vcn - r->vcn; + CLST len2 = r->len - len1; + CLST lcn2 = r->lcn == SPARSE_LCN ? SPARSE_LCN : (r->lcn + len1); + + r->len = len1; + + if (!run_add_entry(run, vcn + len, lcn2, len2, false)) + return false; + } + + if (!run_add_entry(run, vcn, SPARSE_LCN, len, false)) + return false; + + return true; +} + /* * run_get_entry - Return index-th mapped region. */ From e4d2f4fd5341064d2b3c5158da69421a581e7ec1 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Tue, 21 Jun 2022 12:49:52 +0300 Subject: [PATCH 013/427] fs/ntfs3: Enable FALLOC_FL_INSERT_RANGE Changed logic in ntfs_fallocate - more clear checks in beginning instead of the middle of function and added FALLOC_FL_INSERT_RANGE. Fixes xfstest generic/064 Fixes: 4342306f0f0d ("fs/ntfs3: Add file operations and implementation") Signed-off-by: Konstantin Komarov --- fs/ntfs3/file.c | 97 ++++++++++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 42 deletions(-) diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 27c32692513c4..bdffe4b8554bd 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -533,21 +533,35 @@ static int ntfs_truncate(struct inode *inode, loff_t new_size) static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) { struct inode *inode = file->f_mapping->host; + struct address_space *mapping = inode->i_mapping; struct super_block *sb = inode->i_sb; struct ntfs_sb_info *sbi = sb->s_fs_info; struct ntfs_inode *ni = ntfs_i(inode); loff_t end = vbo + len; loff_t vbo_down = round_down(vbo, PAGE_SIZE); - loff_t i_size; + bool is_supported_holes = is_sparsed(ni) || is_compressed(ni); + loff_t i_size, new_size; + bool map_locked; int err; /* No support for dir. */ if (!S_ISREG(inode->i_mode)) return -EOPNOTSUPP; - /* Return error if mode is not supported. */ - if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | - FALLOC_FL_COLLAPSE_RANGE)) { + /* + * vfs_fallocate checks all possible combinations of mode. + * Do additional checks here before ntfs_set_state(dirty). + */ + if (mode & FALLOC_FL_PUNCH_HOLE) { + if (!is_supported_holes) + return -EOPNOTSUPP; + } else if (mode & FALLOC_FL_COLLAPSE_RANGE) { + } else if (mode & FALLOC_FL_INSERT_RANGE) { + if (!is_supported_holes) + return -EOPNOTSUPP; + } else if (mode & + ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | + FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE)) { ntfs_inode_warn(inode, "fallocate(0x%x) is not supported", mode); return -EOPNOTSUPP; @@ -557,6 +571,8 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) inode_lock(inode); i_size = inode->i_size; + new_size = max(end, i_size); + map_locked = false; if (WARN_ON(ni->ni_flags & NI_FLAG_COMPRESSED_MASK)) { /* Should never be here, see ntfs_file_open. */ @@ -564,38 +580,27 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) goto out; } + if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE | + FALLOC_FL_INSERT_RANGE)) { + inode_dio_wait(inode); + filemap_invalidate_lock(mapping); + map_locked = true; + } + if (mode & FALLOC_FL_PUNCH_HOLE) { u32 frame_size; loff_t mask, vbo_a, end_a, tmp; - if (!(mode & FALLOC_FL_KEEP_SIZE)) { - err = -EINVAL; - goto out; - } - - err = filemap_write_and_wait_range(inode->i_mapping, vbo, - end - 1); + err = filemap_write_and_wait_range(mapping, vbo, end - 1); if (err) goto out; - err = filemap_write_and_wait_range(inode->i_mapping, end, - LLONG_MAX); + err = filemap_write_and_wait_range(mapping, end, LLONG_MAX); if (err) goto out; - inode_dio_wait(inode); - truncate_pagecache(inode, vbo_down); - if (!is_sparsed(ni) && !is_compressed(ni)) { - /* - * Normal file, can't make hole. - * TODO: Try to find way to save info about hole. - */ - err = -EOPNOTSUPP; - goto out; - } - ni_lock(ni); err = attr_punch_hole(ni, vbo, len, &frame_size); ni_unlock(ni); @@ -627,17 +632,11 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) ni_unlock(ni); } } else if (mode & FALLOC_FL_COLLAPSE_RANGE) { - if (mode & ~FALLOC_FL_COLLAPSE_RANGE) { - err = -EINVAL; - goto out; - } - /* * Write tail of the last page before removed range since * it will get removed from the page cache below. */ - err = filemap_write_and_wait_range(inode->i_mapping, vbo_down, - vbo); + err = filemap_write_and_wait_range(mapping, vbo_down, vbo); if (err) goto out; @@ -645,34 +644,45 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) * Write data that will be shifted to preserve them * when discarding page cache below. */ - err = filemap_write_and_wait_range(inode->i_mapping, end, - LLONG_MAX); + err = filemap_write_and_wait_range(mapping, end, LLONG_MAX); if (err) goto out; - /* Wait for existing dio to complete. */ - inode_dio_wait(inode); - truncate_pagecache(inode, vbo_down); ni_lock(ni); err = attr_collapse_range(ni, vbo, len); ni_unlock(ni); - } else { - /* - * Normal file: Allocate clusters, do not change 'valid' size. - */ - loff_t new_size = max(end, i_size); + } else if (mode & FALLOC_FL_INSERT_RANGE) { + /* Check new size. */ + err = inode_newsize_ok(inode, new_size); + if (err) + goto out; + + /* Write out all dirty pages. */ + err = filemap_write_and_wait_range(mapping, vbo_down, + LLONG_MAX); + if (err) + goto out; + truncate_pagecache(inode, vbo_down); + ni_lock(ni); + err = attr_insert_range(ni, vbo, len); + ni_unlock(ni); + } else { + /* Check new size. */ err = inode_newsize_ok(inode, new_size); if (err) goto out; + /* + * Allocate clusters, do not change 'valid' size. + */ err = ntfs_set_size(inode, new_size); if (err) goto out; - if (is_sparsed(ni) || is_compressed(ni)) { + if (is_supported_holes) { CLST vcn_v = ni->i_valid >> sbi->cluster_bits; CLST vcn = vbo >> sbi->cluster_bits; CLST cend = bytes_to_cluster(sbi, end); @@ -720,6 +730,9 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) } out: + if (map_locked) + filemap_invalidate_unlock(mapping); + if (err == -EFBIG) err = -ENOSPC; From 321460ca3b55f48b3ba6008248264ab2bd6407d9 Mon Sep 17 00:00:00 2001 From: Pavel Skripkin Date: Thu, 21 Apr 2022 23:53:36 +0300 Subject: [PATCH 014/427] fs/ntfs3: Fix NULL deref in ntfs_update_mftmirr If ntfs_fill_super() wasn't called then sbi->sb will be equal to NULL. Code should check this ptr before dereferencing. Syzbot hit this issue via passing wrong mount param as can be seen from log below Fail log: ntfs3: Unknown parameter 'iochvrset' general protection fault, probably for non-canonical address 0xdffffc0000000003: 0000 [#1] PREEMPT SMP KASAN KASAN: null-ptr-deref in range [0x0000000000000018-0x000000000000001f] CPU: 1 PID: 3589 Comm: syz-executor210 Not tainted 5.18.0-rc3-syzkaller-00016-gb253435746d9 #0 ... Call Trace: put_ntfs+0x1ed/0x2a0 fs/ntfs3/super.c:463 ntfs_fs_free+0x6a/0xe0 fs/ntfs3/super.c:1363 put_fs_context+0x119/0x7a0 fs/fs_context.c:469 do_new_mount+0x2b4/0xad0 fs/namespace.c:3044 do_mount fs/namespace.c:3383 [inline] __do_sys_mount fs/namespace.c:3591 [inline] Fixes: 82cae269cfa9 ("fs/ntfs3: Add initialization of super block") Reported-and-tested-by: syzbot+c95173762127ad76a824@syzkaller.appspotmail.com Signed-off-by: Pavel Skripkin Signed-off-by: Konstantin Komarov --- fs/ntfs3/fsntfs.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c index 3de5700a9b833..891125ca68488 100644 --- a/fs/ntfs3/fsntfs.c +++ b/fs/ntfs3/fsntfs.c @@ -831,10 +831,15 @@ int ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait) { int err; struct super_block *sb = sbi->sb; - u32 blocksize = sb->s_blocksize; + u32 blocksize; sector_t block1, block2; u32 bytes; + if (!sb) + return -EINVAL; + + blocksize = sb->s_blocksize; + if (!(sbi->flags & NTFS_FLAGS_MFTMIRR)) return 0; From e66af07ca2b57e01dbf6001ae565ab40037b2df3 Mon Sep 17 00:00:00 2001 From: Pavel Skripkin Date: Thu, 21 Apr 2022 23:53:45 +0300 Subject: [PATCH 015/427] fs/ntfs3: Make ntfs_update_mftmirr return void None of callers check the return value of ntfs_update_mftmirr(), so make it return void to make code simpler. Signed-off-by: Pavel Skripkin Signed-off-by: Konstantin Komarov --- fs/ntfs3/fsntfs.c | 20 +++++++------------- fs/ntfs3/ntfs_fs.h | 2 +- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c index 891125ca68488..938acb246b58b 100644 --- a/fs/ntfs3/fsntfs.c +++ b/fs/ntfs3/fsntfs.c @@ -827,7 +827,7 @@ int ntfs_refresh_zone(struct ntfs_sb_info *sbi) /* * ntfs_update_mftmirr - Update $MFTMirr data. */ -int ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait) +void ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait) { int err; struct super_block *sb = sbi->sb; @@ -836,12 +836,12 @@ int ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait) u32 bytes; if (!sb) - return -EINVAL; + return; blocksize = sb->s_blocksize; if (!(sbi->flags & NTFS_FLAGS_MFTMIRR)) - return 0; + return; err = 0; bytes = sbi->mft.recs_mirr << sbi->record_bits; @@ -852,16 +852,13 @@ int ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait) struct buffer_head *bh1, *bh2; bh1 = sb_bread(sb, block1++); - if (!bh1) { - err = -EIO; - goto out; - } + if (!bh1) + return; bh2 = sb_getblk(sb, block2++); if (!bh2) { put_bh(bh1); - err = -EIO; - goto out; + return; } if (buffer_locked(bh2)) @@ -881,13 +878,10 @@ int ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait) put_bh(bh2); if (err) - goto out; + return; } sbi->flags &= ~NTFS_FLAGS_MFTMIRR; - -out: - return err; } /* diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 1f92e3a05f61e..8f05b91f3c5e6 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -593,7 +593,7 @@ int ntfs_look_free_mft(struct ntfs_sb_info *sbi, CLST *rno, bool mft, void ntfs_mark_rec_free(struct ntfs_sb_info *sbi, CLST rno); int ntfs_clear_mft_tail(struct ntfs_sb_info *sbi, size_t from, size_t to); int ntfs_refresh_zone(struct ntfs_sb_info *sbi); -int ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait); +void ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait); enum NTFS_DIRTY_FLAGS { NTFS_DIRTY_CLEAR = 0, NTFS_DIRTY_DIRTY = 1, From 4838ec0d80b110a5f30c7e3169dc5021efd203d4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 30 Jun 2022 16:10:56 +0300 Subject: [PATCH 016/427] fs/ntfs3: Unlock on error in attr_insert_range() This error path needs to call up_write(&ni->file.run_lock) and do some other clean up before returning. Fixes: aa30eccb24e5 ("fs/ntfs3: Fallocate (FALLOC_FL_INSERT_RANGE) implementation") Signed-off-by: Dan Carpenter Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 86e688b95ad57..3e9aefcb3e6c1 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -2153,8 +2153,10 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) le_b = NULL; attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, 0, NULL, &mi_b); - if (!attr_b) - return -ENOENT; + if (!attr_b) { + err = -ENOENT; + goto out; + } if (!attr_b->non_res) { err = -EINVAL; goto out; From cc83b0c7e3064e2bb1f9d099bbfdaf493cd669fe Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 4 Jul 2022 19:53:19 +0100 Subject: [PATCH 017/427] fs/ntfs3: Remove duplicated assignment to variable r The assignment to variable r is duplicated, the second assignment is redundant and can be removed. Signed-off-by: Colin Ian King Signed-off-by: Konstantin Komarov --- fs/ntfs3/run.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 7609d45a2d721..aba8ab1b9fcb9 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -563,7 +563,6 @@ bool run_insert_range(struct runs_tree *run, CLST vcn, CLST len) e = run->runs + run->count; r = run->runs + index; - r = run->runs + index; if (vcn > r->vcn) r += 1; From 604a9d272dc3802d880e0510b9d145b1090b3f8a Mon Sep 17 00:00:00 2001 From: Li kunyu Date: Mon, 4 Jul 2022 18:31:13 +0800 Subject: [PATCH 018/427] fs/ntfs3: Remove unnecessary 'NULL' values from pointers There is no need to initialize with NULL as it'll be rewritten later. Signed-off-by: Li kunyu Signed-off-by: Konstantin Komarov --- fs/ntfs3/index.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c index 84ccc14098747..ba2a07dfeaf52 100644 --- a/fs/ntfs3/index.c +++ b/fs/ntfs3/index.c @@ -1678,8 +1678,8 @@ indx_insert_into_buffer(struct ntfs_index *indx, struct ntfs_inode *ni, { int err; const struct NTFS_DE *sp; - struct NTFS_DE *e, *de_t, *up_e = NULL; - struct indx_node *n2 = NULL; + struct NTFS_DE *e, *de_t, *up_e; + struct indx_node *n2; struct indx_node *n1 = fnd->nodes[level]; struct INDEX_HDR *hdr1 = &n1->index->ihdr; struct INDEX_HDR *hdr2; From 74944c873602a3ed8d16ff7af3f64af80c0f9dac Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Mon, 25 Jul 2022 13:05:05 -0400 Subject: [PATCH 019/427] btrfs: reset RO counter on block group if we fail to relocate With the automatic block group reclaim code we will preemptively try to mark the block group RO before we start the relocation. We do this to make sure we should actually try to relocate the block group. However if we hit an error during the actual relocation we won't clean up our RO counter and the block group will remain RO. This was observed internally with file systems reporting less space available from df when we had failed background relocations. Fix this by doing the dec_ro in the error case. Fixes: 18bb8bbf13c1 ("btrfs: zoned: automatically reclaim zones") CC: stable@vger.kernel.org # 5.15+ Reviewed-by: Boris Burkov Signed-off-by: Josef Bacik Signed-off-by: David Sterba --- fs/btrfs/block-group.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index c3aecfb0a71d2..993aca2f1e181 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -1640,9 +1640,11 @@ void btrfs_reclaim_bgs_work(struct work_struct *work) div64_u64(zone_unusable * 100, bg->length)); trace_btrfs_reclaim_block_group(bg); ret = btrfs_relocate_chunk(fs_info, bg->start); - if (ret) + if (ret) { + btrfs_dec_block_group_ro(bg); btrfs_err(fs_info, "error relocating chunk %llu", bg->start); + } next: btrfs_put_block_group(bg); From c0fc96fed7ffa3e58f58b9cdb7158b5c61e026a2 Mon Sep 17 00:00:00 2001 From: syed sabakareem Date: Tue, 2 Aug 2022 11:55:00 +0530 Subject: [PATCH 020/427] ASoC: amd: yc: Update DMI table entries for AMD platforms Updated DMI entries 21EM, 21EN, 21J5 and 21J6 for AMD platforms P15v Gen 3 and P14s Gen 3. Link: https://bugzilla.kernel.org/show_bug.cgi?id=216267 Signed-off-by: syed saba kareem Reported-by: Pananchikkal Renjith Link: https://lore.kernel.org/r/20220802062503.159328-1-Syed.SabaKareem@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/yc/acp6x-mach.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index ecfe7a7907901..e0b24e1daef3d 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -143,6 +143,34 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "21CL"), } }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21EM"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21EN"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21J5"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21J6"), + } + }, {} }; From b0de7fa706506bf0591037908376351beda8c5d6 Mon Sep 17 00:00:00 2001 From: Frieder Schrempf Date: Tue, 2 Aug 2022 08:43:34 +0200 Subject: [PATCH 021/427] regulator: pca9450: Remove restrictions for regulator-name The device bindings shouldn't put any constraints on the regulator-name property specified in the generic bindings. This allows using arbitrary and descriptive names for the regulators. Suggested-by: Mark Brown Fixes: 7ae9e3a6bf3f ("dt-bindings: regulator: add pca9450 regulator yaml") Signed-off-by: Frieder Schrempf Link: https://lore.kernel.org/r/20220802064335.8481-1-frieder@fris.de Signed-off-by: Mark Brown --- .../bindings/regulator/nxp,pca9450-regulator.yaml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/nxp,pca9450-regulator.yaml b/Documentation/devicetree/bindings/regulator/nxp,pca9450-regulator.yaml index b539781e39aa4..835b53302db80 100644 --- a/Documentation/devicetree/bindings/regulator/nxp,pca9450-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/nxp,pca9450-regulator.yaml @@ -47,12 +47,6 @@ properties: description: Properties for single LDO regulator. - properties: - regulator-name: - pattern: "^LDO[1-5]$" - description: - should be "LDO1", ..., "LDO5" - unevaluatedProperties: false "^BUCK[1-6]$": @@ -62,11 +56,6 @@ properties: Properties for single BUCK regulator. properties: - regulator-name: - pattern: "^BUCK[1-6]$" - description: - should be "BUCK1", ..., "BUCK6" - nxp,dvs-run-voltage: $ref: "/schemas/types.yaml#/definitions/uint32" minimum: 600000 From 460bbf2990b3fdc597601c2cf669a3371c069242 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 12 May 2022 19:08:40 +0300 Subject: [PATCH 022/427] fs/ntfs3: Do not change mode if ntfs_set_ea failed ntfs_set_ea can fail with NOSPC, so we don't need to change mode in this situation. Fixes xfstest generic/449 Fixes: be71b5cba2e6 ("fs/ntfs3: Add attrib operations") Signed-off-by: Konstantin Komarov --- fs/ntfs3/xattr.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index 2d29afe4b40b1..ddd9fc9129edd 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -547,28 +547,23 @@ static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns, { const char *name; size_t size, name_len; - void *value = NULL; - int err = 0; + void *value; + int err; int flags; + umode_t mode; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; + mode = inode->i_mode; switch (type) { case ACL_TYPE_ACCESS: /* Do not change i_mode if we are in init_acl */ if (acl && !init_acl) { - umode_t mode; - err = posix_acl_update_mode(mnt_userns, inode, &mode, &acl); if (err) goto out; - - if (inode->i_mode != mode) { - inode->i_mode = mode; - mark_inode_dirty(inode); - } } name = XATTR_NAME_POSIX_ACL_ACCESS; name_len = sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1; @@ -604,8 +599,13 @@ static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns, err = ntfs_set_ea(inode, name, name_len, value, size, flags, 0); if (err == -ENODATA && !size) err = 0; /* Removing non existed xattr. */ - if (!err) + if (!err) { set_cached_acl(inode, type, acl); + if (inode->i_mode != mode) { + inode->i_mode = mode; + mark_inode_dirty(inode); + } + } out: kfree(value); From 13747aac8984e069427e5de5d68bb6cefa98551e Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 12 May 2022 19:18:11 +0300 Subject: [PATCH 023/427] fs/ntfs3: Check reserved size for maximum allowed Also don't mask EFBIG Fixes xfstest generic/485 Fixes: 4342306f0f0d ("fs/ntfs3: Add file operations and implementation") Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 9 +++++++++ fs/ntfs3/file.c | 3 --- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 3e9aefcb3e6c1..c9b7181436039 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -2114,9 +2114,11 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) if (!attr_b->non_res) { data_size = le32_to_cpu(attr_b->res.data_size); + alloc_size = data_size; mask = sbi->cluster_mask; /* cluster_size - 1 */ } else { data_size = le64_to_cpu(attr_b->nres.data_size); + alloc_size = le64_to_cpu(attr_b->nres.alloc_size); mask = (sbi->cluster_size << attr_b->nres.c_unit) - 1; } @@ -2130,6 +2132,13 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) return -EINVAL; } + /* + * valid_size <= data_size <= alloc_size + * Check alloc_size for maximum possible. + */ + if (bytes > sbi->maxbytes_sparse - alloc_size) + return -EFBIG; + vcn = vbo >> sbi->cluster_bits; len = bytes >> sbi->cluster_bits; diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index bdffe4b8554bd..cf16bde810cce 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -733,9 +733,6 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) if (map_locked) filemap_invalidate_unlock(mapping); - if (err == -EFBIG) - err = -ENOSPC; - if (!err) { inode->i_ctime = inode->i_mtime = current_time(inode); mark_inode_dirty(inode); From c1e0ab3789215a3dfbe95f226955e93ea4803391 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Fri, 13 May 2022 18:25:04 +0300 Subject: [PATCH 024/427] fs/ntfs3: extend ni_insert_nonresident to return inserted ATTR_LIST_ENTRY Fixes xfstest generic/300 Fixes: 4534a70b7056 ("fs/ntfs3: Add headers and misc files") Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 35 +++++++++++++++++++++-------------- fs/ntfs3/frecord.c | 4 ++-- fs/ntfs3/index.c | 2 +- fs/ntfs3/ntfs_fs.h | 2 +- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index c9b7181436039..ad713f6201552 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -320,7 +320,7 @@ int attr_make_nonresident(struct ntfs_inode *ni, struct ATTRIB *attr, err = ni_insert_nonresident(ni, attr_s->type, attr_name(attr_s), attr_s->name_len, run, 0, alen, - attr_s->flags, &attr, NULL); + attr_s->flags, &attr, NULL, NULL); if (err) goto out3; @@ -637,7 +637,7 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, /* Insert new attribute segment. */ err = ni_insert_nonresident(ni, type, name, name_len, run, next_svcn, vcn - next_svcn, - attr_b->flags, &attr, &mi); + attr_b->flags, &attr, &mi, NULL); if (err) goto out; @@ -855,7 +855,7 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn, goto out; } - asize = le64_to_cpu(attr_b->nres.alloc_size) >> sbi->cluster_bits; + asize = le64_to_cpu(attr_b->nres.alloc_size) >> cluster_bits; if (vcn >= asize) { err = -EINVAL; goto out; @@ -1047,7 +1047,7 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn, if (evcn1 > next_svcn) { err = ni_insert_nonresident(ni, ATTR_DATA, NULL, 0, run, next_svcn, evcn1 - next_svcn, - attr_b->flags, &attr, &mi); + attr_b->flags, &attr, &mi, NULL); if (err) goto out; } @@ -1647,7 +1647,7 @@ int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size, if (evcn1 > next_svcn) { err = ni_insert_nonresident(ni, ATTR_DATA, NULL, 0, run, next_svcn, evcn1 - next_svcn, - attr_b->flags, &attr, &mi); + attr_b->flags, &attr, &mi, NULL); if (err) goto out; } @@ -1812,18 +1812,12 @@ int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) err = ni_insert_nonresident( ni, ATTR_DATA, NULL, 0, run, next_svcn, evcn1 - eat - next_svcn, a_flags, &attr, - &mi); + &mi, &le); if (err) goto out; /* Layout of records maybe changed. */ attr_b = NULL; - le = al_find_ex(ni, NULL, ATTR_DATA, NULL, 0, - &next_svcn); - if (!le) { - err = -EINVAL; - goto out; - } } /* Free all allocated memory. */ @@ -1936,9 +1930,10 @@ int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size) struct ATTRIB *attr = NULL, *attr_b; struct ATTR_LIST_ENTRY *le, *le_b; struct mft_inode *mi, *mi_b; - CLST svcn, evcn1, vcn, len, end, alen, dealloc; + CLST svcn, evcn1, vcn, len, end, alen, dealloc, next_svcn; u64 total_size, alloc_size; u32 mask; + __le16 a_flags; if (!bytes) return 0; @@ -2001,6 +1996,7 @@ int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size) svcn = le64_to_cpu(attr_b->nres.svcn); evcn1 = le64_to_cpu(attr_b->nres.evcn) + 1; + a_flags = attr_b->flags; if (svcn <= vcn && vcn < evcn1) { attr = attr_b; @@ -2048,6 +2044,17 @@ int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size) err = mi_pack_runs(mi, attr, run, evcn1 - svcn); if (err) goto out; + next_svcn = le64_to_cpu(attr->nres.evcn) + 1; + if (next_svcn < evcn1) { + err = ni_insert_nonresident(ni, ATTR_DATA, NULL, + 0, run, next_svcn, + evcn1 - next_svcn, + a_flags, &attr, &mi, + &le); + if (err) + goto out; + /* Layout of records maybe changed. */ + } } /* Free all allocated memory. */ run_truncate(run, 0); @@ -2250,7 +2257,7 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) if (next_svcn < evcn1 + len) { err = ni_insert_nonresident(ni, ATTR_DATA, NULL, 0, run, next_svcn, evcn1 + len - next_svcn, - a_flags, NULL, NULL); + a_flags, NULL, NULL, NULL); if (err) goto out; } diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index 3576268ee0a1d..64041152fd982 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -1406,7 +1406,7 @@ int ni_insert_nonresident(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name, u8 name_len, const struct runs_tree *run, CLST svcn, CLST len, __le16 flags, struct ATTRIB **new_attr, - struct mft_inode **mi) + struct mft_inode **mi, struct ATTR_LIST_ENTRY **le) { int err; CLST plen; @@ -1439,7 +1439,7 @@ int ni_insert_nonresident(struct ntfs_inode *ni, enum ATTR_TYPE type, } err = ni_insert_attr(ni, type, name, name_len, asize, name_off, svcn, - &attr, mi, NULL); + &attr, mi, le); if (err) goto out; diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c index ba2a07dfeaf52..440328147e7e3 100644 --- a/fs/ntfs3/index.c +++ b/fs/ntfs3/index.c @@ -1347,7 +1347,7 @@ static int indx_create_allocate(struct ntfs_index *indx, struct ntfs_inode *ni, goto out; err = ni_insert_nonresident(ni, ATTR_ALLOC, in->name, in->name_len, - &run, 0, len, 0, &alloc, NULL); + &run, 0, len, 0, &alloc, NULL, NULL); if (err) goto out1; diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 8f05b91f3c5e6..27b610c5bb295 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -529,7 +529,7 @@ int ni_insert_nonresident(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name, u8 name_len, const struct runs_tree *run, CLST svcn, CLST len, __le16 flags, struct ATTRIB **new_attr, - struct mft_inode **mi); + struct mft_inode **mi, struct ATTR_LIST_ENTRY **le); int ni_insert_resident(struct ntfs_inode *ni, u32 data_size, enum ATTR_TYPE type, const __le16 *name, u8 name_len, struct ATTRIB **new_attr, struct mft_inode **mi, From b3e048720dee5641c522015d3f0ff0f0dc9cdc37 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Fri, 13 May 2022 19:21:54 +0300 Subject: [PATCH 025/427] fs/ntfs3: Make ntfs_fallocate return -ENOSPC instead of -EFBIG In some cases we need to return ENOSPC Fixes xfstest generic/213 Fixes: 114346978cf6 ("fs/ntfs3: Check new size for limits") Signed-off-by: Konstantin Komarov --- fs/ntfs3/file.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index cf16bde810cce..b5f8837f41454 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -671,6 +671,19 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) ni_unlock(ni); } else { /* Check new size. */ + + /* generic/213: expected -ENOSPC instead of -EFBIG. */ + if (!is_supported_holes) { + loff_t to_alloc = new_size - inode_get_bytes(inode); + + if (to_alloc > 0 && + (to_alloc >> sbi->cluster_bits) > + wnd_zeroes(&sbi->used.bitmap)) { + err = -ENOSPC; + goto out; + } + } + err = inode_newsize_ok(inode, new_size); if (err) goto out; From 42f86b1226a42bfc79a7125af435432ad4680a32 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Fri, 13 May 2022 19:54:23 +0300 Subject: [PATCH 026/427] fs/ntfs3: Fix work with fragmented xattr In some cases xattr is too fragmented, so we need to load it before writing. Signed-off-by: Konstantin Komarov --- fs/ntfs3/xattr.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index ddd9fc9129edd..02f6a933ee797 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -118,7 +118,7 @@ static int ntfs_read_ea(struct ntfs_inode *ni, struct EA_FULL **ea, run_init(&run); - err = attr_load_runs(attr_ea, ni, &run, NULL); + err = attr_load_runs_range(ni, ATTR_EA, NULL, 0, &run, 0, size); if (!err) err = ntfs_read_run_nb(sbi, &run, 0, ea_p, size, NULL); run_close(&run); @@ -444,6 +444,11 @@ static noinline int ntfs_set_ea(struct inode *inode, const char *name, /* Delete xattr, ATTR_EA */ ni_remove_attr_le(ni, attr, mi, le); } else if (attr->non_res) { + err = attr_load_runs_range(ni, ATTR_EA, NULL, 0, &ea_run, 0, + size); + if (err) + goto out; + err = ntfs_sb_write_run(sbi, &ea_run, 0, ea_all, size, 0); if (err) goto out; From 560f7736b94622c077344e2c541c43c63b4e90e4 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 30 Jun 2022 18:31:26 +0300 Subject: [PATCH 027/427] fs/ntfs3: Fix very fragmented case in attr_punch_hole In some cases we need to ni_find_attr attr_b Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index ad713f6201552..3d64335fa4c7a 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -2054,6 +2054,7 @@ int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size) if (err) goto out; /* Layout of records maybe changed. */ + attr_b = NULL; } } /* Free all allocated memory. */ @@ -2073,6 +2074,14 @@ int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size) } total_size -= (u64)dealloc << sbi->cluster_bits; + if (!attr_b) { + attr_b = ni_find_attr(ni, NULL, NULL, ATTR_DATA, NULL, 0, NULL, + &mi_b); + if (!attr_b) { + err = -EINVAL; + goto out; + } + } attr_b->nres.total_size = cpu_to_le64(total_size); mi_b->dirty = true; @@ -2083,8 +2092,10 @@ int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size) out: up_write(&ni->file.run_lock); - if (err) + if (err) { + ntfs_set_state(sbi, NTFS_DIRTY_ERROR); make_bad_inode(&ni->vfs_inode); + } return err; } From 6700eabb90d50c50be21ecbb71131cd6ecf91ded Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 30 Jun 2022 18:49:24 +0300 Subject: [PATCH 028/427] fs/ntfs3: Remove unused mi_mark_free Cleaning up dead code Fix wrong comments Signed-off-by: Konstantin Komarov --- fs/ntfs3/namei.c | 2 +- fs/ntfs3/ntfs_fs.h | 1 - fs/ntfs3/record.c | 22 ---------------------- fs/ntfs3/super.c | 2 +- 4 files changed, 2 insertions(+), 25 deletions(-) diff --git a/fs/ntfs3/namei.c b/fs/ntfs3/namei.c index bc741213ad848..1cc700760c7ed 100644 --- a/fs/ntfs3/namei.c +++ b/fs/ntfs3/namei.c @@ -208,7 +208,7 @@ static int ntfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir, } /* - * ntfs_rmdir - inode_operations::rm_dir + * ntfs_rmdir - inode_operations::rmdir */ static int ntfs_rmdir(struct inode *dir, struct dentry *dentry) { diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 27b610c5bb295..0ea0cdab46b3d 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -734,7 +734,6 @@ static inline struct ATTRIB *rec_find_attr_le(struct mft_inode *rec, int mi_write(struct mft_inode *mi, int wait); int mi_format_new(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno, __le16 flags, bool is_mft); -void mi_mark_free(struct mft_inode *mi); struct ATTRIB *mi_insert_attr(struct mft_inode *mi, enum ATTR_TYPE type, const __le16 *name, u8 name_len, u32 asize, u16 name_off); diff --git a/fs/ntfs3/record.c b/fs/ntfs3/record.c index 8fe0a876400ad..7d2fac5ee2156 100644 --- a/fs/ntfs3/record.c +++ b/fs/ntfs3/record.c @@ -394,28 +394,6 @@ int mi_format_new(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno, return err; } -/* - * mi_mark_free - Mark record as unused and marks it as free in bitmap. - */ -void mi_mark_free(struct mft_inode *mi) -{ - CLST rno = mi->rno; - struct ntfs_sb_info *sbi = mi->sbi; - - if (rno >= MFT_REC_RESERVED && rno < MFT_REC_FREE) { - ntfs_clear_mft_tail(sbi, rno, rno + 1); - mi->dirty = false; - return; - } - - if (mi->mrec) { - clear_rec_inuse(mi->mrec); - mi->dirty = true; - mi_write(mi, 0); - } - ntfs_mark_rec_free(sbi, rno); -} - /* * mi_insert_attr - Reserve space for new attribute. * diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 4b0dad2ac5988..eacea72ff92f6 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -1377,7 +1377,7 @@ static const struct fs_context_operations ntfs_context_ops = { /* * ntfs_init_fs_context - Initialize spi and opts * - * This will called when mount/remount. We will first initiliaze + * This will called when mount/remount. We will first initialize * options so that if remount we can use just that. */ static int ntfs_init_fs_context(struct fs_context *fc) From 071100ea0e6c353258f322cb2f8dde9be62d6808 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 30 Jun 2022 19:14:43 +0300 Subject: [PATCH 029/427] fs/ntfs3: Add new argument is_mft to ntfs_mark_rec_free This argument helps in avoiding double locking Signed-off-by: Konstantin Komarov --- fs/ntfs3/frecord.c | 12 ++++++------ fs/ntfs3/fsntfs.c | 9 ++++++--- fs/ntfs3/inode.c | 2 +- fs/ntfs3/ntfs_fs.h | 2 +- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index 64041152fd982..756d9a18fa00c 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -1048,7 +1048,7 @@ static int ni_ins_attr_ext(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le, err = -EINVAL; out1: - ntfs_mark_rec_free(sbi, rno); + ntfs_mark_rec_free(sbi, rno, is_mft); out: return err; @@ -1243,7 +1243,7 @@ static int ni_expand_mft_list(struct ntfs_inode *ni) mft_min = mft_new; mi_min = mi_new; } else { - ntfs_mark_rec_free(sbi, mft_new); + ntfs_mark_rec_free(sbi, mft_new, true); mft_new = 0; ni_remove_mi(ni, mi_new); } @@ -1326,7 +1326,7 @@ static int ni_expand_mft_list(struct ntfs_inode *ni) out: if (mft_new) { - ntfs_mark_rec_free(sbi, mft_new); + ntfs_mark_rec_free(sbi, mft_new, true); ni_remove_mi(ni, mi_new); } @@ -1585,7 +1585,7 @@ int ni_delete_all(struct ntfs_inode *ni) mi->dirty = true; mi_write(mi, 0); - ntfs_mark_rec_free(sbi, mi->rno); + ntfs_mark_rec_free(sbi, mi->rno, false); ni_remove_mi(ni, mi); mi_put(mi); node = next; @@ -1596,7 +1596,7 @@ int ni_delete_all(struct ntfs_inode *ni) ni->mi.dirty = true; err = mi_write(&ni->mi, 0); - ntfs_mark_rec_free(sbi, ni->mi.rno); + ntfs_mark_rec_free(sbi, ni->mi.rno, false); return err; } @@ -3286,7 +3286,7 @@ int ni_write_inode(struct inode *inode, int sync, const char *hint) err = err2; if (is_empty) { - ntfs_mark_rec_free(sbi, mi->rno); + ntfs_mark_rec_free(sbi, mi->rno, false); rb_erase(node, &ni->mi_tree); mi_put(mi); } diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c index 938acb246b58b..fa4ca8b9b499e 100644 --- a/fs/ntfs3/fsntfs.c +++ b/fs/ntfs3/fsntfs.c @@ -703,12 +703,14 @@ int ntfs_look_free_mft(struct ntfs_sb_info *sbi, CLST *rno, bool mft, /* * ntfs_mark_rec_free - Mark record as free. + * is_mft - true if we are changing MFT */ -void ntfs_mark_rec_free(struct ntfs_sb_info *sbi, CLST rno) +void ntfs_mark_rec_free(struct ntfs_sb_info *sbi, CLST rno, bool is_mft) { struct wnd_bitmap *wnd = &sbi->mft.bitmap; - down_write_nested(&wnd->rw_lock, BITMAP_MUTEX_MFT); + if (!is_mft) + down_write_nested(&wnd->rw_lock, BITMAP_MUTEX_MFT); if (rno >= wnd->nbits) goto out; @@ -727,7 +729,8 @@ void ntfs_mark_rec_free(struct ntfs_sb_info *sbi, CLST rno) sbi->mft.next_free = rno; out: - up_write(&wnd->rw_lock); + if (!is_mft) + up_write(&wnd->rw_lock); } /* diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 6c78930be0357..a49da4ec6dc38 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -1636,7 +1636,7 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns, ni->mi.dirty = false; discard_new_inode(inode); out3: - ntfs_mark_rec_free(sbi, ino); + ntfs_mark_rec_free(sbi, ino, false); out2: __putname(new_de); diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 0ea0cdab46b3d..34c6ee56225c8 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -590,7 +590,7 @@ int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len, enum ALLOCATE_OPT opt); int ntfs_look_free_mft(struct ntfs_sb_info *sbi, CLST *rno, bool mft, struct ntfs_inode *ni, struct mft_inode **mi); -void ntfs_mark_rec_free(struct ntfs_sb_info *sbi, CLST rno); +void ntfs_mark_rec_free(struct ntfs_sb_info *sbi, CLST rno, bool is_mft); int ntfs_clear_mft_tail(struct ntfs_sb_info *sbi, size_t from, size_t to); int ntfs_refresh_zone(struct ntfs_sb_info *sbi); void ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait); From cf760ec0a0b4015ccf3b5e9ecb4caf6b5fb52f0b Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Fri, 1 Jul 2022 15:15:32 +0300 Subject: [PATCH 030/427] fs/ntfs3: Make static function attr_load_runs attr_load_runs is an internal function Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 4 ++-- fs/ntfs3/ntfs_fs.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 3d64335fa4c7a..7454bd3ea02d7 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -84,8 +84,8 @@ static inline bool attr_must_be_resident(struct ntfs_sb_info *sbi, /* * attr_load_runs - Load all runs stored in @attr. */ -int attr_load_runs(struct ATTRIB *attr, struct ntfs_inode *ni, - struct runs_tree *run, const CLST *vcn) +static int attr_load_runs(struct ATTRIB *attr, struct ntfs_inode *ni, + struct runs_tree *run, const CLST *vcn) { int err; CLST svcn = le64_to_cpu(attr->nres.svcn); diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 34c6ee56225c8..83ed27bb624e9 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -408,8 +408,6 @@ enum REPARSE_SIGN { }; /* Functions from attrib.c */ -int attr_load_runs(struct ATTRIB *attr, struct ntfs_inode *ni, - struct runs_tree *run, const CLST *vcn); int attr_allocate_clusters(struct ntfs_sb_info *sbi, struct runs_tree *run, CLST vcn, CLST lcn, CLST len, CLST *pre_alloc, enum ALLOCATE_OPT opt, CLST *alen, const size_t fr, From 42f66a7fdaa0d15691467fb7a808040f2d5ad0c0 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Fri, 1 Jul 2022 15:18:29 +0300 Subject: [PATCH 031/427] fs/ntfs3: Fill duplicate info in ni_add_name Work with names must be completed in ni_add_name Signed-off-by: Konstantin Komarov --- fs/ntfs3/frecord.c | 20 ++++++++++++++------ fs/ntfs3/inode.c | 10 ---------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index 756d9a18fa00c..acd9f444bd642 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -1614,7 +1614,8 @@ struct ATTR_FILE_NAME *ni_fname_name(struct ntfs_inode *ni, struct ATTRIB *attr = NULL; struct ATTR_FILE_NAME *fname; - *le = NULL; + if (le) + *le = NULL; /* Enumerate all names. */ next: @@ -1630,7 +1631,7 @@ struct ATTR_FILE_NAME *ni_fname_name(struct ntfs_inode *ni, goto next; if (!uni) - goto next; + return fname; if (uni->len != fname->name_len) goto next; @@ -2969,7 +2970,7 @@ bool ni_remove_name_undo(struct ntfs_inode *dir_ni, struct ntfs_inode *ni, } /* - * ni_add_name - Add new name in MFT and in directory. + * ni_add_name - Add new name into MFT and into directory. */ int ni_add_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni, struct NTFS_DE *de) @@ -2978,13 +2979,20 @@ int ni_add_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni, struct ATTRIB *attr; struct ATTR_LIST_ENTRY *le; struct mft_inode *mi; + struct ATTR_FILE_NAME *fname; struct ATTR_FILE_NAME *de_name = (struct ATTR_FILE_NAME *)(de + 1); u16 de_key_size = le16_to_cpu(de->key_size); mi_get_ref(&ni->mi, &de->ref); mi_get_ref(&dir_ni->mi, &de_name->home); - /* Insert new name in MFT. */ + /* Fill duplicate from any ATTR_NAME. */ + fname = ni_fname_name(ni, NULL, NULL, NULL, NULL); + if (fname) + memcpy(&de_name->dup, &fname->dup, sizeof(fname->dup)); + de_name->dup.fa = ni->std_fa; + + /* Insert new name into MFT. */ err = ni_insert_resident(ni, de_key_size, ATTR_NAME, NULL, 0, &attr, &mi, &le); if (err) @@ -2992,7 +3000,7 @@ int ni_add_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni, memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), de_name, de_key_size); - /* Insert new name in directory. */ + /* Insert new name into directory. */ err = indx_insert_entry(&dir_ni->dir, dir_ni, de, ni->mi.sbi, NULL, 0); if (err) ni_remove_attr_le(ni, attr, mi, le); @@ -3016,7 +3024,7 @@ int ni_rename(struct ntfs_inode *dir_ni, struct ntfs_inode *new_dir_ni, * 1) Add new name and remove old name. * 2) Remove old name and add new name. * - * In most cases (not all!) adding new name in MFT and in directory can + * In most cases (not all!) adding new name into MFT and into directory can * allocate additional cluster(s). * Second way may result to bad inode if we can't add new name * and then can't restore (add) old name. diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index a49da4ec6dc38..3ed3196637474 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -1659,7 +1659,6 @@ int ntfs_link_inode(struct inode *inode, struct dentry *dentry) struct ntfs_inode *ni = ntfs_i(inode); struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info; struct NTFS_DE *de; - struct ATTR_FILE_NAME *de_name; /* Allocate PATH_MAX bytes. */ de = __getname(); @@ -1674,15 +1673,6 @@ int ntfs_link_inode(struct inode *inode, struct dentry *dentry) if (err) goto out; - de_name = (struct ATTR_FILE_NAME *)(de + 1); - /* Fill duplicate info. */ - de_name->dup.cr_time = de_name->dup.m_time = de_name->dup.c_time = - de_name->dup.a_time = kernel2nt(&inode->i_ctime); - de_name->dup.alloc_size = de_name->dup.data_size = - cpu_to_le64(inode->i_size); - de_name->dup.fa = ni->std_fa; - de_name->dup.ea_size = de_name->dup.reparse = 0; - err = ni_add_name(ntfs_i(d_inode(dentry->d_parent)), ni, de); out: __putname(de); From 54033c135061b52d4405facba2e49177a5716a31 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Wed, 6 Jul 2022 20:01:11 +0300 Subject: [PATCH 032/427] fs/ntfs3: Added comments to frecord functions Added some comments in frecord.c for more context. Also changed run_lookup to static because it's an internal function. Signed-off-by: Konstantin Komarov --- fs/ntfs3/bitmap.c | 3 +-- fs/ntfs3/frecord.c | 8 ++++---- fs/ntfs3/ntfs_fs.h | 1 - fs/ntfs3/run.c | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/fs/ntfs3/bitmap.c b/fs/ntfs3/bitmap.c index e3b5680fd5168..bb9ebb160227b 100644 --- a/fs/ntfs3/bitmap.c +++ b/fs/ntfs3/bitmap.c @@ -1393,9 +1393,8 @@ int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits) void wnd_zone_set(struct wnd_bitmap *wnd, size_t lcn, size_t len) { - size_t zlen; + size_t zlen = wnd->zone_end - wnd->zone_bit; - zlen = wnd->zone_end - wnd->zone_bit; if (zlen) wnd_add_free_ext(wnd, wnd->zone_bit, zlen, false); diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index acd9f444bd642..bc48923693a97 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -1287,7 +1287,7 @@ static int ni_expand_mft_list(struct ntfs_inode *ni) done = asize - run_size - SIZEOF_NONRESIDENT; le32_sub_cpu(&ni->mi.mrec->used, done); - /* Estimate the size of second part: run_buf=NULL. */ + /* Estimate packed size (run_buf=NULL). */ err = run_pack(run, svcn, evcn + 1 - svcn, NULL, sbi->record_size, &plen); if (err < 0) @@ -1317,6 +1317,7 @@ static int ni_expand_mft_list(struct ntfs_inode *ni) attr->name_off = SIZEOF_NONRESIDENT_LE; attr->flags = 0; + /* This function can't fail - cause already checked above. */ run_pack(run, svcn, evcn + 1 - svcn, Add2Ptr(attr, SIZEOF_NONRESIDENT), run_size, &plen); @@ -1392,8 +1393,6 @@ int ni_expand_list(struct ntfs_inode *ni) /* Split MFT data as much as possible. */ err = ni_expand_mft_list(ni); - if (err) - goto out; out: return !err && !done ? -EOPNOTSUPP : err; @@ -1419,6 +1418,7 @@ int ni_insert_nonresident(struct ntfs_inode *ni, enum ATTR_TYPE type, u32 run_size, asize; struct ntfs_sb_info *sbi = ni->mi.sbi; + /* Estimate packed size (run_buf=NULL). */ err = run_pack(run, svcn, len, NULL, sbi->max_bytes_per_attr - run_off, &plen); if (err < 0) @@ -1448,12 +1448,12 @@ int ni_insert_nonresident(struct ntfs_inode *ni, enum ATTR_TYPE type, attr->name_off = cpu_to_le16(name_off); attr->flags = flags; + /* This function can't fail - cause already checked above. */ run_pack(run, svcn, len, Add2Ptr(attr, run_off), run_size, &plen); attr->nres.svcn = cpu_to_le64(svcn); attr->nres.evcn = cpu_to_le64((u64)svcn + len - 1); - err = 0; if (new_attr) *new_attr = attr; diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 83ed27bb624e9..7a728d3589cfd 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -773,7 +773,6 @@ bool run_lookup_entry(const struct runs_tree *run, CLST vcn, CLST *lcn, void run_truncate(struct runs_tree *run, CLST vcn); void run_truncate_head(struct runs_tree *run, CLST vcn); void run_truncate_around(struct runs_tree *run, CLST vcn); -bool run_lookup(const struct runs_tree *run, CLST vcn, size_t *index); bool run_add_entry(struct runs_tree *run, CLST vcn, CLST lcn, CLST len, bool is_mft); bool run_collapse_range(struct runs_tree *run, CLST vcn, CLST len); diff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index aba8ab1b9fcb9..4168b8adc1313 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -31,7 +31,7 @@ struct ntfs_run { * Case of entry missing from list 'index' will be set to * point to insertion position for the entry question. */ -bool run_lookup(const struct runs_tree *run, CLST vcn, size_t *index) +static bool run_lookup(const struct runs_tree *run, CLST vcn, size_t *index) { size_t min_idx, max_idx, mid_idx; struct ntfs_run *r; From e6d9398c077d8e21a2ca50efab5cbf7ff5aff728 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Wed, 6 Jul 2022 20:17:28 +0300 Subject: [PATCH 033/427] fs/ntfs3: Check possible errors in run_pack in advance Checking in advance speeds things up in some cases. Signed-off-by: Konstantin Komarov --- fs/ntfs3/run.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 4168b8adc1313..987a150108df6 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -820,26 +820,36 @@ int run_pack(const struct runs_tree *run, CLST svcn, CLST len, u8 *run_buf, CLST next_vcn, vcn, lcn; CLST prev_lcn = 0; CLST evcn1 = svcn + len; + const struct ntfs_run *r, *r_end; int packed_size = 0; size_t i; - bool ok; s64 dlcn; int offset_size, size_size, tmp; - next_vcn = vcn = svcn; - *packed_vcns = 0; if (!len) goto out; - ok = run_lookup_entry(run, vcn, &lcn, &len, &i); + /* Check all required entries [svcn, encv1) available. */ + if (!run_lookup(run, svcn, &i)) + return -ENOENT; - if (!ok) - goto error; + r_end = run->runs + run->count; + r = run->runs + i; - if (next_vcn != vcn) - goto error; + for (next_vcn = r->vcn + r->len; next_vcn < evcn1; + next_vcn = r->vcn + r->len) { + if (++r >= r_end || r->vcn != next_vcn) + return -ENOENT; + } + + /* Repeat cycle above and pack runs. Assume no errors. */ + r = run->runs + i; + len = svcn - r->vcn; + vcn = svcn; + lcn = r->lcn == SPARSE_LCN ? SPARSE_LCN : (r->lcn + len); + len = r->len - len; for (;;) { next_vcn = vcn + len; @@ -888,12 +898,10 @@ int run_pack(const struct runs_tree *run, CLST svcn, CLST len, u8 *run_buf, if (packed_size + 1 >= run_buf_size || next_vcn >= evcn1) goto out; - ok = run_get_entry(run, ++i, &vcn, &lcn, &len); - if (!ok) - goto error; - - if (next_vcn != vcn) - goto error; + r += 1; + vcn = r->vcn; + lcn = r->lcn; + len = r->len; } out: @@ -902,9 +910,6 @@ int run_pack(const struct runs_tree *run, CLST svcn, CLST len, u8 *run_buf, run_buf[0] = 0; return packed_size + 1; - -error: - return -EOPNOTSUPP; } /* From 8335ebe195dcc76ece418485a9f08b9a9ad7fe23 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 7 Jul 2022 19:25:43 +0300 Subject: [PATCH 034/427] fs/ntfs3: Make MFT zone less fragmented Now we take free space after the MFT zone if the MFT zone shrinks. Signed-off-by: Konstantin Komarov --- fs/ntfs3/fsntfs.c | 39 +++++++++++++++++++++++++-------------- fs/ntfs3/ntfs_fs.h | 1 + fs/ntfs3/super.c | 7 +++++++ 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c index fa4ca8b9b499e..af1dca273b598 100644 --- a/fs/ntfs3/fsntfs.c +++ b/fs/ntfs3/fsntfs.c @@ -783,7 +783,7 @@ int ntfs_clear_mft_tail(struct ntfs_sb_info *sbi, size_t from, size_t to) */ int ntfs_refresh_zone(struct ntfs_sb_info *sbi) { - CLST zone_limit, zone_max, lcn, vcn, len; + CLST lcn, vcn, len; size_t lcn_s, zlen; struct wnd_bitmap *wnd = &sbi->used.bitmap; struct ntfs_inode *ni = sbi->mft.ni; @@ -792,16 +792,6 @@ int ntfs_refresh_zone(struct ntfs_sb_info *sbi) if (wnd_zone_len(wnd)) return 0; - /* - * Compute the MFT zone at two steps. - * It would be nice if we are able to allocate 1/8 of - * total clusters for MFT but not more then 512 MB. - */ - zone_limit = (512 * 1024 * 1024) >> sbi->cluster_bits; - zone_max = wnd->nbits >> 3; - if (zone_max > zone_limit) - zone_max = zone_limit; - vcn = bytes_to_cluster(sbi, (u64)sbi->mft.bitmap.nbits << sbi->record_bits); @@ -815,7 +805,7 @@ int ntfs_refresh_zone(struct ntfs_sb_info *sbi) lcn_s = lcn + 1; /* Try to allocate clusters after last MFT run. */ - zlen = wnd_find(wnd, zone_max, lcn_s, 0, &lcn_s); + zlen = wnd_find(wnd, sbi->zone_max, lcn_s, 0, &lcn_s); if (!zlen) { ntfs_notice(sbi->sb, "MftZone: unavailable"); return 0; @@ -1397,7 +1387,7 @@ int ntfs_write_bh(struct ntfs_sb_info *sbi, struct NTFS_RECORD_HEADER *rhdr, if (buffer_locked(bh)) __wait_on_buffer(bh); - lock_buffer(nb->bh[idx]); + lock_buffer(bh); bh_data = bh->b_data + off; end_data = Add2Ptr(bh_data, op); @@ -2426,7 +2416,7 @@ static inline void ntfs_unmap_and_discard(struct ntfs_sb_info *sbi, CLST lcn, void mark_as_free_ex(struct ntfs_sb_info *sbi, CLST lcn, CLST len, bool trim) { - CLST end, i; + CLST end, i, zone_len, zlen; struct wnd_bitmap *wnd = &sbi->used.bitmap; down_write_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS); @@ -2461,6 +2451,27 @@ void mark_as_free_ex(struct ntfs_sb_info *sbi, CLST lcn, CLST len, bool trim) ntfs_unmap_and_discard(sbi, lcn, len); wnd_set_free(wnd, lcn, len); + /* append to MFT zone, if possible. */ + zone_len = wnd_zone_len(wnd); + zlen = min(zone_len + len, sbi->zone_max); + + if (zlen == zone_len) { + /* MFT zone already has maximum size. */ + } else if (!zone_len) { + /* Create MFT zone. */ + wnd_zone_set(wnd, lcn, zlen); + } else { + CLST zone_lcn = wnd_zone_bit(wnd); + + if (lcn + len == zone_lcn) { + /* Append into head MFT zone. */ + wnd_zone_set(wnd, lcn, zlen); + } else if (zone_lcn + zone_len == lcn) { + /* Append into tail MFT zone. */ + wnd_zone_set(wnd, zone_lcn, zlen); + } + } + out: up_write(&wnd->rw_lock); } diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 7a728d3589cfd..6a2bbf889faaf 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -220,6 +220,7 @@ struct ntfs_sb_info { u32 flags; // See NTFS_FLAGS_XXX. + CLST zone_max; // Maximum MFT zone length in clusters CLST bad_clusters; // The count of marked bad clusters. u16 max_bytes_per_attr; // Maximum attribute size in record. diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index eacea72ff92f6..6fad173a8b8f4 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -867,6 +867,13 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size, sb->s_maxbytes = 0xFFFFFFFFull << sbi->cluster_bits; #endif + /* + * Compute the MFT zone at two steps. + * It would be nice if we are able to allocate 1/8 of + * total clusters for MFT but not more then 512 MB. + */ + sbi->zone_max = min_t(CLST, 0x20000000 >> sbi->cluster_bits, clusters >> 3); + err = 0; out: From c12df45ee690112782049b8e85dff2e6cb1b3853 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Wed, 13 Jul 2022 17:55:27 +0300 Subject: [PATCH 035/427] fs/ntfs3: New function ntfs_bad_inode There are repetitive steps in case of bad inode This commit wraps them in function Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 10 ++++------ fs/ntfs3/frecord.c | 6 ++---- fs/ntfs3/fsntfs.c | 14 ++++++++++++++ fs/ntfs3/inode.c | 6 ++---- fs/ntfs3/namei.c | 4 +--- fs/ntfs3/ntfs_fs.h | 2 ++ 6 files changed, 25 insertions(+), 17 deletions(-) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 7454bd3ea02d7..5ba83eb0fc074 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -1912,7 +1912,7 @@ int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) out: up_write(&ni->file.run_lock); if (err) - make_bad_inode(&ni->vfs_inode); + _ntfs_bad_inode(&ni->vfs_inode); return err; } @@ -2092,10 +2092,8 @@ int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size) out: up_write(&ni->file.run_lock); - if (err) { - ntfs_set_state(sbi, NTFS_DIRTY_ERROR); - make_bad_inode(&ni->vfs_inode); - } + if (err) + _ntfs_bad_inode(&ni->vfs_inode); return err; } @@ -2282,7 +2280,7 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) up_write(&ni->file.run_lock); if (err) - make_bad_inode(&ni->vfs_inode); + _ntfs_bad_inode(&ni->vfs_inode); return err; } diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index bc48923693a97..bdc568053fae2 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -2328,10 +2328,8 @@ int ni_decompress_file(struct ntfs_inode *ni) out: kfree(pages); - if (err) { - make_bad_inode(inode); - ntfs_set_state(sbi, NTFS_DIRTY_ERROR); - } + if (err) + _ntfs_bad_inode(inode); return err; } diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c index af1dca273b598..3f9903baa53f8 100644 --- a/fs/ntfs3/fsntfs.c +++ b/fs/ntfs3/fsntfs.c @@ -877,6 +877,20 @@ void ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait) sbi->flags &= ~NTFS_FLAGS_MFTMIRR; } +/* + * ntfs_bad_inode + * + * Marks inode as bad and marks fs as 'dirty' + */ +void ntfs_bad_inode(struct inode *inode, const char *hint) +{ + struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info; + + ntfs_inode_err(inode, "%s", hint); + make_bad_inode(inode); + ntfs_set_state(sbi, NTFS_DIRTY_ERROR); +} + /* * ntfs_set_state * diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 3ed3196637474..cd48687127c16 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -501,7 +501,7 @@ struct inode *ntfs_iget5(struct super_block *sb, const struct MFT_REF *ref, inode = ntfs_read_mft(inode, name, ref); else if (ref->seq != ntfs_i(inode)->mi.mrec->seq) { /* Inode overlaps? */ - make_bad_inode(inode); + _ntfs_bad_inode(inode); } return inode; @@ -1725,9 +1725,7 @@ int ntfs_unlink_inode(struct inode *dir, const struct dentry *dentry) if (inode->i_nlink) mark_inode_dirty(inode); } else if (!ni_remove_name_undo(dir_ni, ni, de, de2, undo_remove)) { - make_bad_inode(inode); - ntfs_inode_err(inode, "failed to undo unlink"); - ntfs_set_state(sbi, NTFS_DIRTY_ERROR); + _ntfs_bad_inode(inode); } else { if (ni_is_dirty(dir)) mark_inode_dirty(dir); diff --git a/fs/ntfs3/namei.c b/fs/ntfs3/namei.c index 1cc700760c7ed..bc22cc321a74b 100644 --- a/fs/ntfs3/namei.c +++ b/fs/ntfs3/namei.c @@ -308,9 +308,7 @@ static int ntfs_rename(struct user_namespace *mnt_userns, struct inode *dir, err = ni_rename(dir_ni, new_dir_ni, ni, de, new_de, &is_bad); if (is_bad) { /* Restore after failed rename failed too. */ - make_bad_inode(inode); - ntfs_inode_err(inode, "failed to undo rename"); - ntfs_set_state(sbi, NTFS_DIRTY_ERROR); + _ntfs_bad_inode(inode); } else if (!err) { inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(dir); diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 6a2bbf889faaf..a9359675299f4 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -593,6 +593,8 @@ void ntfs_mark_rec_free(struct ntfs_sb_info *sbi, CLST rno, bool is_mft); int ntfs_clear_mft_tail(struct ntfs_sb_info *sbi, size_t from, size_t to); int ntfs_refresh_zone(struct ntfs_sb_info *sbi); void ntfs_update_mftmirr(struct ntfs_sb_info *sbi, int wait); +void ntfs_bad_inode(struct inode *inode, const char *hint); +#define _ntfs_bad_inode(i) ntfs_bad_inode(i, __func__) enum NTFS_DIRTY_FLAGS { NTFS_DIRTY_CLEAR = 0, NTFS_DIRTY_DIRTY = 1, From 0e5b044cbf3a41b4efad7d9616342338f88b373d Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Wed, 13 Jul 2022 18:00:03 +0300 Subject: [PATCH 036/427] fs/ntfs3: Refactoring attr_set_size to restore after errors Added comments to code Added two undo labels for restoring after errors Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 180 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 126 insertions(+), 54 deletions(-) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 5ba83eb0fc074..c29b2debc9099 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -173,7 +173,6 @@ int attr_allocate_clusters(struct ntfs_sb_info *sbi, struct runs_tree *run, { int err; CLST flen, vcn0 = vcn, pre = pre_alloc ? *pre_alloc : 0; - struct wnd_bitmap *wnd = &sbi->used.bitmap; size_t cnt = run->count; for (;;) { @@ -196,9 +195,7 @@ int attr_allocate_clusters(struct ntfs_sb_info *sbi, struct runs_tree *run, /* Add new fragment into run storage. */ if (!run_add_entry(run, vcn, lcn, flen, opt == ALLOCATE_MFT)) { /* Undo last 'ntfs_look_for_free_space' */ - down_write_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS); - wnd_set_free(wnd, lcn, flen); - up_write(&wnd->rw_lock); + mark_as_free_ex(sbi, lcn, len, false); err = -ENOMEM; goto out; } @@ -419,40 +416,44 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, struct mft_inode *mi, *mi_b; CLST alen, vcn, lcn, new_alen, old_alen, svcn, evcn; CLST next_svcn, pre_alloc = -1, done = 0; - bool is_ext; + bool is_ext, is_bad = false; u32 align; struct MFT_REC *rec; again: + alen = 0; le_b = NULL; attr_b = ni_find_attr(ni, NULL, &le_b, type, name, name_len, NULL, &mi_b); if (!attr_b) { err = -ENOENT; - goto out; + goto bad_inode; } if (!attr_b->non_res) { err = attr_set_size_res(ni, attr_b, le_b, mi_b, new_size, run, &attr_b); - if (err || !attr_b->non_res) - goto out; + if (err) + return err; + + /* Return if file is still resident. */ + if (!attr_b->non_res) + goto ok1; /* Layout of records may be changed, so do a full search. */ goto again; } is_ext = is_attr_ext(attr_b); - -again_1: align = sbi->cluster_size; - if (is_ext) align <<= attr_b->nres.c_unit; old_valid = le64_to_cpu(attr_b->nres.valid_size); old_size = le64_to_cpu(attr_b->nres.data_size); old_alloc = le64_to_cpu(attr_b->nres.alloc_size); + +again_1: old_alen = old_alloc >> cluster_bits; new_alloc = (new_size + align - 1) & ~(u64)(align - 1); @@ -475,24 +476,27 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, mi = mi_b; } else if (!le_b) { err = -EINVAL; - goto out; + goto bad_inode; } else { le = le_b; attr = ni_find_attr(ni, attr_b, &le, type, name, name_len, &vcn, &mi); if (!attr) { err = -EINVAL; - goto out; + goto bad_inode; } next_le_1: svcn = le64_to_cpu(attr->nres.svcn); evcn = le64_to_cpu(attr->nres.evcn); } - + /* + * Here we have: + * attr,mi,le - last attribute segment (containing 'vcn'). + * attr_b,mi_b,le_b - base (primary) attribute segment. + */ next_le: rec = mi->mrec; - err = attr_load_runs(attr, ni, run, NULL); if (err) goto out; @@ -507,6 +511,13 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, goto ok; } + /* + * Add clusters. In simple case we have to: + * - allocate space (vcn, lcn, len) + * - update packed run in 'mi' + * - update attr->nres.evcn + * - update attr_b->nres.data_size/attr_b->nres.alloc_size + */ to_allocate = new_alen - old_alen; add_alloc_in_same_attr_seg: lcn = 0; @@ -520,9 +531,11 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, pre_alloc = 0; if (type == ATTR_DATA && !name_len && sbi->options->prealloc) { - CLST new_alen2 = bytes_to_cluster( - sbi, get_pre_allocated(new_size)); - pre_alloc = new_alen2 - new_alen; + pre_alloc = + bytes_to_cluster( + sbi, + get_pre_allocated(new_size)) - + new_alen; } /* Get the last LCN to allocate from. */ @@ -580,7 +593,7 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, pack_runs: err = mi_pack_runs(mi, attr, run, vcn - svcn); if (err) - goto out; + goto undo_1; next_svcn = le64_to_cpu(attr->nres.evcn) + 1; new_alloc_tmp = (u64)next_svcn << cluster_bits; @@ -614,7 +627,7 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, if (type == ATTR_LIST) { err = ni_expand_list(ni); if (err) - goto out; + goto undo_2; if (next_svcn < vcn) goto pack_runs; @@ -624,8 +637,9 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, if (!ni->attr_list.size) { err = ni_create_attr_list(ni); + /* In case of error layout of records is not changed. */ if (err) - goto out; + goto undo_2; /* Layout of records is changed. */ } @@ -638,47 +652,56 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, err = ni_insert_nonresident(ni, type, name, name_len, run, next_svcn, vcn - next_svcn, attr_b->flags, &attr, &mi, NULL); - if (err) - goto out; - - if (!is_mft) - run_truncate_head(run, evcn + 1); - svcn = le64_to_cpu(attr->nres.svcn); - evcn = le64_to_cpu(attr->nres.evcn); - - le_b = NULL; /* * Layout of records maybe changed. * Find base attribute to update. */ + le_b = NULL; attr_b = ni_find_attr(ni, NULL, &le_b, type, name, name_len, NULL, &mi_b); if (!attr_b) { - err = -ENOENT; - goto out; + err = -EINVAL; + goto bad_inode; } - attr_b->nres.alloc_size = cpu_to_le64((u64)vcn << cluster_bits); - attr_b->nres.data_size = attr_b->nres.alloc_size; - attr_b->nres.valid_size = attr_b->nres.alloc_size; + if (err) { + /* ni_insert_nonresident failed. */ + attr = NULL; + goto undo_2; + } + + if (!is_mft) + run_truncate_head(run, evcn + 1); + + svcn = le64_to_cpu(attr->nres.svcn); + evcn = le64_to_cpu(attr->nres.evcn); + + /* + * Attribute is in consistency state. + * Save this point to restore to if next steps fail. + */ + old_valid = old_size = old_alloc = (u64)vcn << cluster_bits; + attr_b->nres.valid_size = attr_b->nres.data_size = + attr_b->nres.alloc_size = cpu_to_le64(old_size); mi_b->dirty = true; goto again_1; } if (new_size != old_size || (new_alloc != old_alloc && !keep_prealloc)) { + /* + * Truncate clusters. In simple case we have to: + * - update packed run in 'mi' + * - update attr->nres.evcn + * - update attr_b->nres.data_size/attr_b->nres.alloc_size + * - mark and trim clusters as free (vcn, lcn, len) + */ + CLST dlen = 0; + vcn = max(svcn, new_alen); new_alloc_tmp = (u64)vcn << cluster_bits; - alen = 0; - err = run_deallocate_ex(sbi, run, vcn, evcn - vcn + 1, &alen, - true); - if (err) - goto out; - - run_truncate(run, vcn); - if (vcn > svcn) { err = mi_pack_runs(mi, attr, run, vcn - svcn); if (err) @@ -697,7 +720,7 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, if (!al_remove_le(ni, le)) { err = -EINVAL; - goto out; + goto bad_inode; } le = (struct ATTR_LIST_ENTRY *)((u8 *)le - le_sz); @@ -723,12 +746,20 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, attr_b->nres.valid_size = attr_b->nres.alloc_size; } + mi_b->dirty = true; - if (is_ext) + err = run_deallocate_ex(sbi, run, vcn, evcn - vcn + 1, &dlen, + true); + if (err) + goto out; + + if (is_ext) { + /* dlen - really deallocated clusters. */ le64_sub_cpu(&attr_b->nres.total_size, - ((u64)alen << cluster_bits)); + ((u64)dlen << cluster_bits)); + } - mi_b->dirty = true; + run_truncate(run, vcn); if (new_alloc_tmp <= new_alloc) goto ok; @@ -747,7 +778,7 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, if (le->type != type || le->name_len != name_len || memcmp(le_name(le), name, name_len * sizeof(short))) { err = -EINVAL; - goto out; + goto bad_inode; } err = ni_load_mi(ni, le, &mi); @@ -757,7 +788,7 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, attr = mi_find_attr(mi, NULL, type, name, name_len, &le->id); if (!attr) { err = -EINVAL; - goto out; + goto bad_inode; } goto next_le_1; } @@ -772,13 +803,13 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, } } -out: - if (!err && attr_b && ret) +ok1: + if (ret) *ret = attr_b; /* Update inode_set_bytes. */ - if (!err && ((type == ATTR_DATA && !name_len) || - (type == ATTR_ALLOC && name == I30_NAME))) { + if (((type == ATTR_DATA && !name_len) || + (type == ATTR_ALLOC && name == I30_NAME))) { bool dirty = false; if (ni->vfs_inode.i_size != new_size) { @@ -786,7 +817,7 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, dirty = true; } - if (attr_b && attr_b->non_res) { + if (attr_b->non_res) { new_alloc = le64_to_cpu(attr_b->nres.alloc_size); if (inode_get_bytes(&ni->vfs_inode) != new_alloc) { inode_set_bytes(&ni->vfs_inode, new_alloc); @@ -800,6 +831,47 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type, } } + return 0; + +undo_2: + vcn -= alen; + attr_b->nres.data_size = cpu_to_le64(old_size); + attr_b->nres.valid_size = cpu_to_le64(old_valid); + attr_b->nres.alloc_size = cpu_to_le64(old_alloc); + + /* Restore 'attr' and 'mi'. */ + if (attr) + goto restore_run; + + if (le64_to_cpu(attr_b->nres.svcn) <= svcn && + svcn <= le64_to_cpu(attr_b->nres.evcn)) { + attr = attr_b; + le = le_b; + mi = mi_b; + } else if (!le_b) { + err = -EINVAL; + goto bad_inode; + } else { + le = le_b; + attr = ni_find_attr(ni, attr_b, &le, type, name, name_len, + &svcn, &mi); + if (!attr) + goto bad_inode; + } + +restore_run: + if (mi_pack_runs(mi, attr, run, evcn - svcn + 1)) + is_bad = true; + +undo_1: + run_deallocate_ex(sbi, run, vcn, alen, NULL, false); + + run_truncate(run, vcn); +out: + if (is_bad) { +bad_inode: + _ntfs_bad_inode(&ni->vfs_inode); + } return err; } From 20abc64f78346ac591344133301661b77e1c8253 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Wed, 13 Jul 2022 18:18:48 +0300 Subject: [PATCH 037/427] fs/ntfs3: Refactoring attr_punch_hole to restore after errors Added comments to code Added new function run_clone to make a copy of run Added done and undo labels for restoring after errors Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 117 ++++++++++++++++++++++++++++++--------------- fs/ntfs3/ntfs_fs.h | 1 + fs/ntfs3/run.c | 25 ++++++++++ 3 files changed, 105 insertions(+), 38 deletions(-) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index c29b2debc9099..cf3729ce771bb 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -140,7 +140,10 @@ static int run_deallocate_ex(struct ntfs_sb_info *sbi, struct runs_tree *run, } if (lcn != SPARSE_LCN) { - mark_as_free_ex(sbi, lcn, clen, trim); + if (sbi) { + /* mark bitmap range [lcn + clen) as free and trim clusters. */ + mark_as_free_ex(sbi, lcn, clen, trim); + } dn += clen; } @@ -2002,10 +2005,11 @@ int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size) struct ATTRIB *attr = NULL, *attr_b; struct ATTR_LIST_ENTRY *le, *le_b; struct mft_inode *mi, *mi_b; - CLST svcn, evcn1, vcn, len, end, alen, dealloc, next_svcn; + CLST svcn, evcn1, vcn, len, end, alen, hole, next_svcn; u64 total_size, alloc_size; u32 mask; __le16 a_flags; + struct runs_tree run2; if (!bytes) return 0; @@ -2057,6 +2061,9 @@ int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size) } down_write(&ni->file.run_lock); + run_init(&run2); + run_truncate(run, 0); + /* * Enumerate all attribute segments and punch hole where necessary. */ @@ -2064,7 +2071,7 @@ int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size) vcn = vbo >> sbi->cluster_bits; len = bytes >> sbi->cluster_bits; end = vcn + len; - dealloc = 0; + hole = 0; svcn = le64_to_cpu(attr_b->nres.svcn); evcn1 = le64_to_cpu(attr_b->nres.evcn) + 1; @@ -2076,14 +2083,14 @@ int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size) mi = mi_b; } else if (!le_b) { err = -EINVAL; - goto out; + goto bad_inode; } else { le = le_b; attr = ni_find_attr(ni, attr_b, &le, ATTR_DATA, NULL, 0, &vcn, &mi); if (!attr) { err = -EINVAL; - goto out; + goto bad_inode; } svcn = le64_to_cpu(attr->nres.svcn); @@ -2091,69 +2098,91 @@ int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size) } while (svcn < end) { - CLST vcn1, zero, dealloc2; + CLST vcn1, zero, hole2 = hole; err = attr_load_runs(attr, ni, run, &svcn); if (err) - goto out; + goto done; vcn1 = max(vcn, svcn); zero = min(end, evcn1) - vcn1; - dealloc2 = dealloc; - err = run_deallocate_ex(sbi, run, vcn1, zero, &dealloc, true); + /* + * Check range [vcn1 + zero). + * Calculate how many clusters there are. + * Don't do any destructive actions. + */ + err = run_deallocate_ex(NULL, run, vcn1, zero, &hole2, false); if (err) - goto out; + goto done; - if (dealloc2 == dealloc) { - /* Looks like the required range is already sparsed. */ - } else { - if (!run_add_entry(run, vcn1, SPARSE_LCN, zero, - false)) { - err = -ENOMEM; - goto out; - } + /* Check if required range is already hole. */ + if (hole2 == hole) + goto next_attr; - err = mi_pack_runs(mi, attr, run, evcn1 - svcn); + /* Make a clone of run to undo. */ + err = run_clone(run, &run2); + if (err) + goto done; + + /* Make a hole range (sparse) [vcn1 + zero). */ + if (!run_add_entry(run, vcn1, SPARSE_LCN, zero, false)) { + err = -ENOMEM; + goto done; + } + + /* Update run in attribute segment. */ + err = mi_pack_runs(mi, attr, run, evcn1 - svcn); + if (err) + goto done; + next_svcn = le64_to_cpu(attr->nres.evcn) + 1; + if (next_svcn < evcn1) { + /* Insert new attribute segment. */ + err = ni_insert_nonresident(ni, ATTR_DATA, NULL, 0, run, + next_svcn, + evcn1 - next_svcn, a_flags, + &attr, &mi, &le); if (err) - goto out; - next_svcn = le64_to_cpu(attr->nres.evcn) + 1; - if (next_svcn < evcn1) { - err = ni_insert_nonresident(ni, ATTR_DATA, NULL, - 0, run, next_svcn, - evcn1 - next_svcn, - a_flags, &attr, &mi, - &le); - if (err) - goto out; - /* Layout of records maybe changed. */ - attr_b = NULL; - } + goto undo_punch; + + /* Layout of records maybe changed. */ + attr_b = NULL; } + + /* Real deallocate. Should not fail. */ + run_deallocate_ex(sbi, &run2, vcn1, zero, &hole, true); + +next_attr: /* Free all allocated memory. */ run_truncate(run, 0); if (evcn1 >= alen) break; + /* Get next attribute segment. */ attr = ni_enum_attr_ex(ni, attr, &le, &mi); if (!attr) { err = -EINVAL; - goto out; + goto bad_inode; } svcn = le64_to_cpu(attr->nres.svcn); evcn1 = le64_to_cpu(attr->nres.evcn) + 1; } - total_size -= (u64)dealloc << sbi->cluster_bits; +done: + if (!hole) + goto out; + if (!attr_b) { attr_b = ni_find_attr(ni, NULL, NULL, ATTR_DATA, NULL, 0, NULL, &mi_b); if (!attr_b) { err = -EINVAL; - goto out; + goto bad_inode; } } + + total_size -= (u64)hole << sbi->cluster_bits; attr_b->nres.total_size = cpu_to_le64(total_size); mi_b->dirty = true; @@ -2163,11 +2192,23 @@ int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size) mark_inode_dirty(&ni->vfs_inode); out: + run_close(&run2); up_write(&ni->file.run_lock); - if (err) - _ntfs_bad_inode(&ni->vfs_inode); - return err; + +bad_inode: + _ntfs_bad_inode(&ni->vfs_inode); + goto out; + +undo_punch: + /* + * Restore packed runs. + * 'mi_pack_runs' should not fail, cause we restore original. + */ + if (mi_pack_runs(mi, attr, &run2, evcn1 - svcn)) + goto bad_inode; + + goto done; } /* diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index a9359675299f4..c37fa9ca56896 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -798,6 +798,7 @@ int run_unpack_ex(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, #define run_unpack_ex run_unpack #endif int run_get_highest_vcn(CLST vcn, const u8 *run_buf, u64 *highest_vcn); +int run_clone(const struct runs_tree *run, struct runs_tree *new_run); /* Globals from super.c */ void *ntfs_set_shared(void *ptr, u32 bytes); diff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 987a150108df6..aaaa0d3d35a24 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1156,3 +1156,28 @@ int run_get_highest_vcn(CLST vcn, const u8 *run_buf, u64 *highest_vcn) *highest_vcn = vcn64 - 1; return 0; } + +/* + * run_clone + * + * Make a copy of run + */ +int run_clone(const struct runs_tree *run, struct runs_tree *new_run) +{ + size_t bytes = run->count * sizeof(struct ntfs_run); + + if (bytes > new_run->allocated) { + struct ntfs_run *new_ptr = kvmalloc(bytes, GFP_KERNEL); + + if (!new_ptr) + return -ENOMEM; + + kvfree(new_run->runs); + new_run->runs = new_ptr; + new_run->allocated = bytes; + } + + memcpy(new_run->runs, run->runs, bytes); + new_run->count = run->count; + return 0; +} From 9256ec35359f52c1e390cf419873cf519ee332b6 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Wed, 13 Jul 2022 18:44:24 +0300 Subject: [PATCH 038/427] fs/ntfs3: Refactoring attr_insert_range to restore after errors Added done and undo labels for restoring after errors Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 117 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 86 insertions(+), 31 deletions(-) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index cf3729ce771bb..71f870d497aed 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -2275,30 +2275,29 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) if (!attr_b->non_res) { err = attr_set_size(ni, ATTR_DATA, NULL, 0, run, - data_size + bytes, NULL, false, &attr); - if (err) - goto out; - if (!attr->non_res) { - /* Still resident. */ - char *data = Add2Ptr(attr, attr->res.data_off); + data_size + bytes, NULL, false, NULL); - memmove(data + bytes, data, bytes); - memset(data, 0, bytes); - err = 0; - goto out; - } - /* Resident files becomes nonresident. */ le_b = NULL; attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, 0, NULL, &mi_b); if (!attr_b) { - err = -ENOENT; - goto out; - } - if (!attr_b->non_res) { err = -EINVAL; + goto bad_inode; + } + + if (err) goto out; + + if (!attr_b->non_res) { + /* Still resident. */ + char *data = Add2Ptr(attr_b, attr_b->res.data_off); + + memmove(data + bytes, data, bytes); + memset(data, 0, bytes); + goto done; } + + /* Resident files becomes nonresident. */ data_size = le64_to_cpu(attr_b->nres.data_size); alloc_size = le64_to_cpu(attr_b->nres.alloc_size); } @@ -2316,14 +2315,14 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) mi = mi_b; } else if (!le_b) { err = -EINVAL; - goto out; + goto bad_inode; } else { le = le_b; attr = ni_find_attr(ni, attr_b, &le, ATTR_DATA, NULL, 0, &vcn, &mi); if (!attr) { err = -EINVAL; - goto out; + goto bad_inode; } svcn = le64_to_cpu(attr->nres.svcn); @@ -2346,7 +2345,6 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) goto out; next_svcn = le64_to_cpu(attr->nres.evcn) + 1; - run_truncate_head(run, next_svcn); while ((attr = ni_enum_attr_ex(ni, attr, &le, &mi)) && attr->type == ATTR_DATA && !attr->name_len) { @@ -2359,9 +2357,27 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) mi->dirty = true; } + if (next_svcn < evcn1 + len) { + err = ni_insert_nonresident(ni, ATTR_DATA, NULL, 0, run, + next_svcn, evcn1 + len - next_svcn, + a_flags, NULL, NULL, NULL); + + le_b = NULL; + attr_b = ni_find_attr(ni, NULL, &le_b, ATTR_DATA, NULL, 0, NULL, + &mi_b); + if (!attr_b) { + err = -EINVAL; + goto bad_inode; + } + + if (err) { + /* ni_insert_nonresident failed. Try to undo. */ + goto undo_insert_range; + } + } + /* - * Update primary attribute segment in advance. - * pointer attr_b may become invalid (layout of mft is changed) + * Update primary attribute segment. */ if (vbo <= ni->i_valid) ni->i_valid += bytes; @@ -2376,14 +2392,7 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) attr_b->nres.valid_size = cpu_to_le64(ni->i_valid); mi_b->dirty = true; - if (next_svcn < evcn1 + len) { - err = ni_insert_nonresident(ni, ATTR_DATA, NULL, 0, run, - next_svcn, evcn1 + len - next_svcn, - a_flags, NULL, NULL, NULL); - if (err) - goto out; - } - +done: ni->vfs_inode.i_size += bytes; ni->ni_flags |= NI_FLAG_UPDATE_PARENT; mark_inode_dirty(&ni->vfs_inode); @@ -2392,8 +2401,54 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes) run_truncate(run, 0); /* clear cached values. */ up_write(&ni->file.run_lock); - if (err) - _ntfs_bad_inode(&ni->vfs_inode); return err; + +bad_inode: + _ntfs_bad_inode(&ni->vfs_inode); + goto out; + +undo_insert_range: + svcn = le64_to_cpu(attr_b->nres.svcn); + evcn1 = le64_to_cpu(attr_b->nres.evcn) + 1; + + if (svcn <= vcn && vcn < evcn1) { + attr = attr_b; + le = le_b; + mi = mi_b; + } else if (!le_b) { + goto bad_inode; + } else { + le = le_b; + attr = ni_find_attr(ni, attr_b, &le, ATTR_DATA, NULL, 0, &vcn, + &mi); + if (!attr) { + goto bad_inode; + } + + svcn = le64_to_cpu(attr->nres.svcn); + evcn1 = le64_to_cpu(attr->nres.evcn) + 1; + } + + if (attr_load_runs(attr, ni, run, NULL)) + goto bad_inode; + + if (!run_collapse_range(run, vcn, len)) + goto bad_inode; + + if (mi_pack_runs(mi, attr, run, evcn1 + len - svcn)) + goto bad_inode; + + while ((attr = ni_enum_attr_ex(ni, attr, &le, &mi)) && + attr->type == ATTR_DATA && !attr->name_len) { + le64_sub_cpu(&attr->nres.svcn, len); + le64_sub_cpu(&attr->nres.evcn, len); + if (le) { + le->vcn = attr->nres.svcn; + ni->attr_list.dirty = true; + } + mi->dirty = true; + } + + goto out; } From 8039edba043d1eaee74bd76e0280a49ba5e195d7 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Wed, 13 Jul 2022 19:11:15 +0300 Subject: [PATCH 039/427] fs/ntfs3: Create MFT zone only if length is large enough Also removed uninformative print Signed-off-by: Konstantin Komarov --- fs/ntfs3/fsntfs.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c index 3f9903baa53f8..209ca71c3ba0c 100644 --- a/fs/ntfs3/fsntfs.c +++ b/fs/ntfs3/fsntfs.c @@ -806,12 +806,6 @@ int ntfs_refresh_zone(struct ntfs_sb_info *sbi) /* Try to allocate clusters after last MFT run. */ zlen = wnd_find(wnd, sbi->zone_max, lcn_s, 0, &lcn_s); - if (!zlen) { - ntfs_notice(sbi->sb, "MftZone: unavailable"); - return 0; - } - - /* Truncate too large zone. */ wnd_zone_set(wnd, lcn_s, zlen); return 0; @@ -2472,8 +2466,9 @@ void mark_as_free_ex(struct ntfs_sb_info *sbi, CLST lcn, CLST len, bool trim) if (zlen == zone_len) { /* MFT zone already has maximum size. */ } else if (!zone_len) { - /* Create MFT zone. */ - wnd_zone_set(wnd, lcn, zlen); + /* Create MFT zone only if 'zlen' is large enough. */ + if (zlen == sbi->zone_max) + wnd_zone_set(wnd, lcn, zlen); } else { CLST zone_lcn = wnd_zone_bit(wnd); From 451e45a0e6df21e63acfd493feb5194f4697ce11 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Wed, 13 Jul 2022 19:18:19 +0300 Subject: [PATCH 040/427] fs/ntfs3: Make ni_ins_new_attr return error Function ni_ins_new_attr now returns ERR_PTR(err), so we check it now in other functions like ni_expand_mft_list Signed-off-by: Konstantin Komarov --- fs/ntfs3/frecord.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index bdc568053fae2..381a38a06ec22 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -469,7 +469,7 @@ ni_ins_new_attr(struct ntfs_inode *ni, struct mft_inode *mi, &ref, &le); if (err) { /* No memory or no space. */ - return NULL; + return ERR_PTR(err); } le_added = true; @@ -1011,6 +1011,8 @@ static int ni_ins_attr_ext(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le, name_off, svcn, ins_le); if (!attr) continue; + if (IS_ERR(attr)) + return PTR_ERR(attr); if (ins_attr) *ins_attr = attr; @@ -1032,8 +1034,15 @@ static int ni_ins_attr_ext(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le, attr = ni_ins_new_attr(ni, mi, le, type, name, name_len, asize, name_off, svcn, ins_le); - if (!attr) + if (!attr) { + err = -EINVAL; goto out2; + } + + if (IS_ERR(attr)) { + err = PTR_ERR(attr); + goto out2; + } if (ins_attr) *ins_attr = attr; @@ -1045,7 +1054,6 @@ static int ni_ins_attr_ext(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le, out2: ni_remove_mi(ni, mi); mi_put(mi); - err = -EINVAL; out1: ntfs_mark_rec_free(sbi, rno, is_mft); @@ -1101,6 +1109,11 @@ static int ni_insert_attr(struct ntfs_inode *ni, enum ATTR_TYPE type, if (asize <= free) { attr = ni_ins_new_attr(ni, &ni->mi, NULL, type, name, name_len, asize, name_off, svcn, ins_le); + if (IS_ERR(attr)) { + err = PTR_ERR(attr); + goto out; + } + if (attr) { if (ins_attr) *ins_attr = attr; @@ -1198,6 +1211,11 @@ static int ni_insert_attr(struct ntfs_inode *ni, enum ATTR_TYPE type, goto out; } + if (IS_ERR(attr)) { + err = PTR_ERR(attr); + goto out; + } + if (ins_attr) *ins_attr = attr; if (ins_mi) @@ -1313,6 +1331,11 @@ static int ni_expand_mft_list(struct ntfs_inode *ni) goto out; } + if (IS_ERR(attr)) { + err = PTR_ERR(attr); + goto out; + } + attr->non_res = 1; attr->name_off = SIZEOF_NONRESIDENT_LE; attr->flags = 0; From b0a4ab7ca4ce993d1cc51cbc85e9f341c729a3d4 Mon Sep 17 00:00:00 2001 From: Michael Kelley Date: Mon, 25 Jul 2022 17:53:40 -0700 Subject: [PATCH 041/427] iommu/hyper-v: Use helper instead of directly accessing affinity Recent changes to solve inconsistencies in handling IRQ masks #ifdef out the affinity field in irq_common_data for non-SMP configurations. The current code in hyperv_irq_remapping_alloc() gets a compiler error in that case. Fix this by using the new irq_data_update_affinity() helper, which handles the non-SMP case correctly. Signed-off-by: Michael Kelley Reported-by: Randy Dunlap Tested-by: Randy Dunlap Acked-by: Randy Dunlap Acked-by: Joerg Roedel Signed-off-by: Marc Zyngier Fixes: aa0813581b8d ("genirq: Provide an IRQ affinity mask in non-SMP configs") Link: https://lore.kernel.org/r/1658796820-2261-1-git-send-email-mikelley@microsoft.com --- drivers/iommu/hyperv-iommu.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/iommu/hyperv-iommu.c b/drivers/iommu/hyperv-iommu.c index 51bd66a45a11e..e190bb8c225cd 100644 --- a/drivers/iommu/hyperv-iommu.c +++ b/drivers/iommu/hyperv-iommu.c @@ -68,7 +68,6 @@ static int hyperv_irq_remapping_alloc(struct irq_domain *domain, { struct irq_alloc_info *info = arg; struct irq_data *irq_data; - struct irq_desc *desc; int ret = 0; if (!info || info->type != X86_IRQ_ALLOC_TYPE_IOAPIC || nr_irqs > 1) @@ -90,8 +89,7 @@ static int hyperv_irq_remapping_alloc(struct irq_domain *domain, * Hypver-V IO APIC irq affinity should be in the scope of * ioapic_max_cpumask because no irq remapping support. */ - desc = irq_data_to_desc(irq_data); - cpumask_copy(desc->irq_common_data.affinity, &ioapic_max_cpumask); + irq_data_update_affinity(irq_data, &ioapic_max_cpumask); return 0; } From e260cfe6fb503292f183a43b51177664b222435d Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 4 Aug 2022 10:54:21 +0800 Subject: [PATCH 042/427] irqchip/loongson-eiointc: Fix irq affinity setting In multi-node case, csr_any_send() should set EIOINTC_REG_ENABLE of the first core of target node, not the first core of the whole. Signed-off-by: Huacai Chen Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20220804025421.211958-1-chenhuacai@loongson.cn --- drivers/irqchip/irq-loongson-eiointc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index 80d8ca6f2d462..317467857478a 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -111,11 +111,15 @@ static int eiointc_set_irq_affinity(struct irq_data *d, const struct cpumask *af regaddr = EIOINTC_REG_ENABLE + ((vector >> 5) << 2); /* Mask target vector */ - csr_any_send(regaddr, EIOINTC_ALL_ENABLE & (~BIT(vector & 0x1F)), 0x0, 0); + csr_any_send(regaddr, EIOINTC_ALL_ENABLE & (~BIT(vector & 0x1F)), + 0x0, priv->node * CORES_PER_EIO_NODE); + /* Set route for target vector */ eiointc_set_irq_route(vector, cpu, priv->node, &priv->node_map); + /* Unmask target vector */ - csr_any_send(regaddr, EIOINTC_ALL_ENABLE, 0x0, 0); + csr_any_send(regaddr, EIOINTC_ALL_ENABLE, + 0x0, priv->node * CORES_PER_EIO_NODE); irq_data_update_effective_affinity(d, cpumask_of(cpu)); From 54cfa910b443b3d90b3e00bd96cdf563a285390b Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 4 Aug 2022 10:54:57 +0800 Subject: [PATCH 043/427] irqchip/loongson-eiointc: Fix a build warning Make acpi_get_vec_parent() be a static function, to avoid: drivers/irqchip/irq-loongson-eiointc.c:289:20: warning: no previous prototype for 'acpi_get_vec_parent' Reported-by: kernel test robot Signed-off-by: Huacai Chen Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20220804025457.213979-1-chenhuacai@loongson.cn --- drivers/irqchip/irq-loongson-eiointc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index 317467857478a..bffb7b3128e8c 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -290,7 +290,7 @@ static void acpi_set_vec_parent(int node, struct irq_domain *parent, struct acpi } } -struct irq_domain *acpi_get_vec_parent(int node, struct acpi_vector_group *vec_group) +static struct irq_domain *acpi_get_vec_parent(int node, struct acpi_vector_group *vec_group) { int i; From 30bdc36b8c776cd4fce5de2a96ff28b37f96942f Mon Sep 17 00:00:00 2001 From: Laurentiu Palcu Date: Thu, 21 Jul 2022 15:09:12 +0300 Subject: [PATCH 044/427] drm/imx/dcss: get rid of HPD warning message When DCSS + MIPI_DSI is used, and the last bridge in the chain supports HPD, we can see a "Hot plug detection already enabled" warning stack trace dump that's thrown when DCSS is initialized. The problem appeared when HPD was enabled by default in the bridge_connector initialization, which made the drm_bridge_connector_enable_hpd() call, in DCSS init path, redundant. So, let's remove that call. Fixes: 09077bc311658 ("drm/bridge_connector: enable HPD by default if supported") Signed-off-by: Laurentiu Palcu Reviewed-by: Laurent Pinchart Link: https://patchwork.freedesktop.org/patch/msgid/20220721120912.6639-1-laurentiu.palcu@oss.nxp.com --- drivers/gpu/drm/imx/dcss/dcss-kms.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/imx/dcss/dcss-kms.c b/drivers/gpu/drm/imx/dcss/dcss-kms.c index 9b84df34a6a12..8cf3352d88582 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-kms.c +++ b/drivers/gpu/drm/imx/dcss/dcss-kms.c @@ -142,8 +142,6 @@ struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss) drm_kms_helper_poll_init(drm); - drm_bridge_connector_enable_hpd(kms->connector); - ret = drm_dev_register(drm, 0); if (ret) goto cleanup_crtc; From 54d91b55c7f3f9f2c86e0b6be4501433b32ddc89 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Wed, 11 May 2022 11:37:16 -0500 Subject: [PATCH 045/427] drm/nouveau: fix another off-by-one in nvbios_addr This check determines whether a given address is part of image 0 or image 1. Image 1 starts at offset image0_size, so that address should be included. Fixes: 4d4e9907ff572 ("drm/nouveau/bios: guard against out-of-bounds accesses to image") Signed-off-by: Timur Tabi Reviewed-by: Karol Herbst Signed-off-by: Karol Herbst Link: https://patchwork.freedesktop.org/patch/msgid/20220511163716.3520591-1-ttabi@nvidia.com --- drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c index 64e423dddd9e7..6c318e41bde04 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c @@ -33,7 +33,7 @@ nvbios_addr(struct nvkm_bios *bios, u32 *addr, u8 size) { u32 p = *addr; - if (*addr > bios->image0_size && bios->imaged_addr) { + if (*addr >= bios->image0_size && bios->imaged_addr) { *addr -= bios->image0_size; *addr += bios->imaged_addr; } From c20ee5749a3f688d9bab83a3b09b75587153ff13 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Wed, 3 Aug 2022 16:27:45 +0200 Subject: [PATCH 046/427] drm/nouveau: recognise GA103 Appears to be ok with general GA10x code. Signed-off-by: Karol Herbst Cc: # v5.15+ Reviewed-by: Lyude Paul Link: https://patchwork.freedesktop.org/patch/msgid/20220803142745.2679510-1-kherbst@redhat.com --- .../gpu/drm/nouveau/nvkm/engine/device/base.c | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 62efbd0f38466..b7246b146e51d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2605,6 +2605,27 @@ nv172_chipset = { .fifo = { 0x00000001, ga102_fifo_new }, }; +static const struct nvkm_device_chip +nv173_chipset = { + .name = "GA103", + .bar = { 0x00000001, tu102_bar_new }, + .bios = { 0x00000001, nvkm_bios_new }, + .devinit = { 0x00000001, ga100_devinit_new }, + .fb = { 0x00000001, ga102_fb_new }, + .gpio = { 0x00000001, ga102_gpio_new }, + .i2c = { 0x00000001, gm200_i2c_new }, + .imem = { 0x00000001, nv50_instmem_new }, + .mc = { 0x00000001, ga100_mc_new }, + .mmu = { 0x00000001, tu102_mmu_new }, + .pci = { 0x00000001, gp100_pci_new }, + .privring = { 0x00000001, gm200_privring_new }, + .timer = { 0x00000001, gk20a_timer_new }, + .top = { 0x00000001, ga100_top_new }, + .disp = { 0x00000001, ga102_disp_new }, + .dma = { 0x00000001, gv100_dma_new }, + .fifo = { 0x00000001, ga102_fifo_new }, +}; + static const struct nvkm_device_chip nv174_chipset = { .name = "GA104", @@ -3092,6 +3113,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, case 0x167: device->chip = &nv167_chipset; break; case 0x168: device->chip = &nv168_chipset; break; case 0x172: device->chip = &nv172_chipset; break; + case 0x173: device->chip = &nv173_chipset; break; case 0x174: device->chip = &nv174_chipset; break; case 0x176: device->chip = &nv176_chipset; break; case 0x177: device->chip = &nv177_chipset; break; From ca3b7b9dc9bc1fa552f4697b7cccfa0258a44d00 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 1 Aug 2022 18:54:18 +0200 Subject: [PATCH 047/427] ASoC: Intel: avs: Fix potential buffer overflow by snprintf() snprintf() returns the would-be-filled size when the string overflows the given buffer size, hence using this value may result in a buffer overflow (although it's unrealistic). This patch replaces it with a safer version, scnprintf() for papering over such a potential issue. Fixes: f1b3b320bd65 ("ASoC: Intel: avs: Generic soc component driver") Signed-off-by: Takashi Iwai Acked-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220801165420.25978-2-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/intel/avs/pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index f21b0cdd32063..8fe5917b1e263 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -636,8 +636,8 @@ static ssize_t topology_name_read(struct file *file, char __user *user_buf, size char buf[64]; size_t len; - len = snprintf(buf, sizeof(buf), "%s/%s\n", component->driver->topology_name_prefix, - mach->tplg_filename); + len = scnprintf(buf, sizeof(buf), "%s/%s\n", component->driver->topology_name_prefix, + mach->tplg_filename); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } From 1eb123ce985e6cf302ac6e3f19862d132d86fa8f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 1 Aug 2022 18:54:19 +0200 Subject: [PATCH 048/427] ASoC: SOF: debug: Fix potential buffer overflow by snprintf() snprintf() returns the would-be-filled size when the string overflows the given buffer size, hence using this value may result in the buffer overflow (although it's unrealistic). This patch replaces with a safer version, scnprintf() for papering over such a potential issue. Fixes: 5b10b6298921 ("ASoC: SOF: Add `memory_info` file to debugfs") Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20220801165420.25978-3-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/sof/debug.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index c5d797e97c027..d9a3ce7b69e16 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -252,9 +252,9 @@ static int memory_info_update(struct snd_sof_dev *sdev, char *buf, size_t buff_s } for (i = 0, len = 0; i < reply->num_elems; i++) { - ret = snprintf(buf + len, buff_size - len, "zone %d.%d used %#8x free %#8x\n", - reply->elems[i].zone, reply->elems[i].id, - reply->elems[i].used, reply->elems[i].free); + ret = scnprintf(buf + len, buff_size - len, "zone %d.%d used %#8x free %#8x\n", + reply->elems[i].zone, reply->elems[i].id, + reply->elems[i].used, reply->elems[i].free); if (ret < 0) goto error; len += ret; From 94c1ceb043c1a002de9649bb630c8e8347645982 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 1 Aug 2022 18:54:20 +0200 Subject: [PATCH 049/427] ASoC: SOF: Intel: hda: Fix potential buffer overflow by snprintf() snprintf() returns the would-be-filled size when the string overflows the given buffer size, hence using this value may result in the buffer overflow (although it's unrealistic). This patch replaces with a safer version, scnprintf() for papering over such a potential issue. Fixes: 29c8e4398f02 ("ASoC: SOF: Intel: hda: add extended rom status dump to error log") Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20220801165420.25978-4-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 8639ea63a10db..6d4ecbe14adf3 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -574,7 +574,7 @@ static void hda_dsp_dump_ext_rom_status(struct snd_sof_dev *sdev, const char *le chip = get_chip_info(sdev->pdata); for (i = 0; i < HDA_EXT_ROM_STATUS_SIZE; i++) { value = snd_sof_dsp_read(sdev, HDA_DSP_BAR, chip->rom_status_reg + i * 0x4); - len += snprintf(msg + len, sizeof(msg) - len, " 0x%x", value); + len += scnprintf(msg + len, sizeof(msg) - len, " 0x%x", value); } dev_printk(level, sdev->dev, "extended rom status: %s", msg); From c75ed9f54ce8d349fee557f2b471a4d637ed2a6b Mon Sep 17 00:00:00 2001 From: Biju Das Date: Thu, 28 Jul 2022 10:26:12 +0100 Subject: [PATCH 050/427] ASoC: sh: rz-ssi: Improve error handling in rz_ssi_probe() error path We usually do cleanup in reverse order of init. Currently in case of error rz_ssi_release_dma_channels() done in the reverse order. This patch improves error handling in rz_ssi_probe() error path. While at it, use "goto cleanup" style to reduce code duplication. Reported-by: Pavel Machek Signed-off-by: Biju Das Link: https://lore.kernel.org/r/20220728092612.38858-1-biju.das.jz@bp.renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rz-ssi.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c index 0d0594a0e4f6c..7ace0c0db5b15 100644 --- a/sound/soc/sh/rz-ssi.c +++ b/sound/soc/sh/rz-ssi.c @@ -1017,32 +1017,36 @@ static int rz_ssi_probe(struct platform_device *pdev) ssi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); if (IS_ERR(ssi->rstc)) { - rz_ssi_release_dma_channels(ssi); - return PTR_ERR(ssi->rstc); + ret = PTR_ERR(ssi->rstc); + goto err_reset; } reset_control_deassert(ssi->rstc); pm_runtime_enable(&pdev->dev); ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) { - rz_ssi_release_dma_channels(ssi); - pm_runtime_disable(ssi->dev); - reset_control_assert(ssi->rstc); - return dev_err_probe(ssi->dev, ret, "pm_runtime_resume_and_get failed\n"); + dev_err(&pdev->dev, "pm_runtime_resume_and_get failed\n"); + goto err_pm; } ret = devm_snd_soc_register_component(&pdev->dev, &rz_ssi_soc_component, rz_ssi_soc_dai, ARRAY_SIZE(rz_ssi_soc_dai)); if (ret < 0) { - rz_ssi_release_dma_channels(ssi); - - pm_runtime_put(ssi->dev); - pm_runtime_disable(ssi->dev); - reset_control_assert(ssi->rstc); dev_err(&pdev->dev, "failed to register snd component\n"); + goto err_snd_soc; } + return 0; + +err_snd_soc: + pm_runtime_put(ssi->dev); +err_pm: + pm_runtime_disable(ssi->dev); + reset_control_assert(ssi->rstc); +err_reset: + rz_ssi_release_dma_channels(ssi); + return ret; } From b7bf23c0865faac61564425ddc96a4a79ebf19b0 Mon Sep 17 00:00:00 2001 From: Justin Stitt Date: Wed, 3 Aug 2022 13:44:42 -0700 Subject: [PATCH 051/427] ASoC: SOF: ipc3-topology: Fix clang -Wformat warning When building with Clang we encounter these warnings: | sound/soc/sof/ipc3-topology.c:2343:4: error: format specifies type | 'unsigned char' but the argument has type 'int' [-Werror,-Wformat] | SOF_ABI_MAJOR, SOF_ABI_MINOR, SOF_ABI_PATCH); | ^~~~~~~~~~~~~~~^~~~~~~~~~~~~~~^~~~~~~~~~~~~ Use correct format specifier `%d` since args are of type int. Link: https://github.com/ClangBuiltLinux/linux/issues/378 Reported-by: Nathan Chancellor Suggested-by: Nathan Chancellor Signed-off-by: Justin Stitt Reviewed-by: Nathan Chancellor Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20220803204442.2996580-1-justinstitt@google.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc3-topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index b2cc046b9f606..65923e7a5976f 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -2338,7 +2338,7 @@ static int sof_ipc3_parse_manifest(struct snd_soc_component *scomp, int index, } dev_info(scomp->dev, - "Topology: ABI %d:%d:%d Kernel ABI %hhu:%hhu:%hhu\n", + "Topology: ABI %d:%d:%d Kernel ABI %d:%d:%d\n", man->priv.data[0], man->priv.data[1], man->priv.data[2], SOF_ABI_MAJOR, SOF_ABI_MINOR, SOF_ABI_PATCH); From d501cc4cfc6be1ab9aef3ff0fa3b2afc52a1af23 Mon Sep 17 00:00:00 2001 From: David Jander Date: Fri, 5 Aug 2022 10:44:58 +0200 Subject: [PATCH 052/427] spi: spi.c: Add missing __percpu annotations in users of spi_statistics Fixes sparse warnings of this kind: drivers/spi/spi.c:117:16: sparse: expected struct spi_statistics * drivers/spi/spi.c:117:16: sparse: got struct spi_statistics [noderef] __percpu *[assigned] pcpu_stats Reported-by: kernel test robot Signed-off-by: David Jander Link: https://lore.kernel.org/r/20220805084458.1602277-1-david@protonic.nl Signed-off-by: Mark Brown --- drivers/spi/spi.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 1c14d682ffedd..1b59694485422 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -95,7 +95,7 @@ static ssize_t driver_override_show(struct device *dev, } static DEVICE_ATTR_RW(driver_override); -static struct spi_statistics *spi_alloc_pcpu_stats(struct device *dev) +static struct spi_statistics __percpu *spi_alloc_pcpu_stats(struct device *dev) { struct spi_statistics __percpu *pcpu_stats; @@ -162,7 +162,7 @@ static struct device_attribute dev_attr_spi_device_##field = { \ } #define SPI_STATISTICS_SHOW_NAME(name, file, field) \ -static ssize_t spi_statistics_##name##_show(struct spi_statistics *stat, \ +static ssize_t spi_statistics_##name##_show(struct spi_statistics __percpu *stat, \ char *buf) \ { \ ssize_t len; \ @@ -309,7 +309,7 @@ static const struct attribute_group *spi_master_groups[] = { NULL, }; -static void spi_statistics_add_transfer_stats(struct spi_statistics *pcpu_stats, +static void spi_statistics_add_transfer_stats(struct spi_statistics __percpu *pcpu_stats, struct spi_transfer *xfer, struct spi_controller *ctlr) { @@ -1275,8 +1275,8 @@ static int spi_transfer_wait(struct spi_controller *ctlr, struct spi_message *msg, struct spi_transfer *xfer) { - struct spi_statistics *statm = ctlr->pcpu_statistics; - struct spi_statistics *stats = msg->spi->pcpu_statistics; + struct spi_statistics __percpu *statm = ctlr->pcpu_statistics; + struct spi_statistics __percpu *stats = msg->spi->pcpu_statistics; u32 speed_hz = xfer->speed_hz; unsigned long long ms; @@ -1432,8 +1432,8 @@ static int spi_transfer_one_message(struct spi_controller *ctlr, struct spi_transfer *xfer; bool keep_cs = false; int ret = 0; - struct spi_statistics *statm = ctlr->pcpu_statistics; - struct spi_statistics *stats = msg->spi->pcpu_statistics; + struct spi_statistics __percpu *statm = ctlr->pcpu_statistics; + struct spi_statistics __percpu *stats = msg->spi->pcpu_statistics; spi_set_cs(msg->spi, true, false); From 706864c99e0e2d301da9e749395909bc309c50a0 Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Thu, 4 Aug 2022 18:18:23 +0200 Subject: [PATCH 053/427] MAINTAINERS: rectify entry for ARM/HPE GXP ARCHITECTURE Commit 8cc35b86546d ("spi: dt-bindings: add documentation for hpe,gxp-spifi") adds the spi dt-binding file hpe,gxp-spifi.yaml and commit a1848b0fa251 ("MAINTAINERS: add spi support to GXP") adds a file entry hpe,gxp-spi.yaml in ARM/HPE GXP ARCHITECTURE. Note the different file name. Hence, ./scripts/get_maintainer.pl --self-test=patterns complains about a broken reference. Repair this file reference in ARM/HPE GXP ARCHITECTURE. Signed-off-by: Lukas Bulwahn Link: https://lore.kernel.org/r/20220804161823.20912-1-lukas.bulwahn@gmail.com Signed-off-by: Mark Brown --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 8678dcb2de92f..09fdd1e3d987f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2140,7 +2140,7 @@ M: Jean-Marie Verdun M: Nick Hawkins S: Maintained F: Documentation/devicetree/bindings/arm/hpe,gxp.yaml -F: Documentation/devicetree/bindings/spi/hpe,gxp-spi.yaml +F: Documentation/devicetree/bindings/spi/hpe,gxp-spifi.yaml F: Documentation/devicetree/bindings/timer/hpe,gxp-timer.yaml F: arch/arm/boot/dts/hpe-bmc* F: arch/arm/boot/dts/hpe-gxp* From 754590651ccbbcc74a7c20907be4bb15d642bde3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 1 Aug 2022 19:05:10 +0200 Subject: [PATCH 054/427] ASoC: DPCM: Don't pick up BE without substream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When DPCM tries to add valid BE connections at dpcm_add_paths(), it doesn't check whether the picked BE actually supports for the given stream direction. Due to that, when an asymmetric BE stream is present, it picks up wrongly and this may result in a NULL dereference at a later point where the code assumes the existence of a corresponding BE substream. This patch adds the check for the presence of the substream for the target BE for avoiding the problem above. Note that we have already some fix for non-existing BE substream at commit 6246f283d5e0 ("ASoC: dpcm: skip missing substream while applying symmetry"). But the code path we've hit recently is rather happening before the previous fix. So this patch tries to fix at picking up a BE instead of parsing BE lists. Fixes: bbf7d3b1c4f4 ("ASoC: soc-pcm: align BE 'atomicity' with that of the FE") Reported-by: Alex Natalsson Cc: Pierre-Louis Bossart Cc: Péter Ujfalusi Link: https://lore.kernel.org/r/CADs9LoPZH_D+eJ9qjTxSLE5jGyhKsjMN7g2NighZ16biVxsyKw@mail.gmail.com Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20220801170510.26582-1-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 5b99bf2dbd085..4f60c0a833110 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1317,6 +1317,9 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, if (!be->dai_link->no_pcm) continue; + if (!snd_soc_dpcm_get_substream(be, stream)) + continue; + for_each_rtd_dais(be, i, dai) { w = snd_soc_dai_get_widget(dai, stream); From d5beb74f17e25a3cb331a0cd8af795e8cfc5d36c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 5 Aug 2022 15:33:32 +0200 Subject: [PATCH 055/427] ASoC: Intel: fix sof_es8336 probe Changes to add HDMI capture support broke the machine driver probe for all other platforms. The commit listed in the Fixes tag added a board_id descriptor but didn't add the default name for the sof_essx8336 machine driver. Add the missing entry and remove the now-useless platform driver alias. Reported-by: Eugene J Markow BugLink: https://github.com/thesofproject/linux/issues/3336 Fixes: 86b1959a2ccb ("ASoC: Intel: sof_es8336: add support for HDMI_In capture") Reviewed-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20220805133332.207932-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_es8336.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c index c7f33c89588e7..606cc3242a60f 100644 --- a/sound/soc/intel/boards/sof_es8336.c +++ b/sound/soc/intel/boards/sof_es8336.c @@ -759,6 +759,9 @@ static int sof_es8336_remove(struct platform_device *pdev) } static const struct platform_device_id board_ids[] = { + { + .name = "sof-essx8336", /* default quirk == 0 */ + }, { .name = "adl_es83x6_c1_h02", .driver_data = (kernel_ulong_t)(SOF_ES8336_SSP_CODEC(1) | @@ -786,5 +789,4 @@ module_platform_driver(sof_es8336_driver); MODULE_DESCRIPTION("ASoC Intel(R) SOF + ES8336 Machine driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:sof-essx8336"); MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); From 91b3c8dbe898df158fd2a84675f3a284ff6666f7 Mon Sep 17 00:00:00 2001 From: Liang He Date: Tue, 26 Jul 2022 09:07:22 +0800 Subject: [PATCH 056/427] drm/meson: Fix refcount bugs in meson_vpu_has_available_connectors() In this function, there are two refcount leak bugs: (1) when breaking out of for_each_endpoint_of_node(), we need call the of_node_put() for the 'ep'; (2) we should call of_node_put() for the reference returned by of_graph_get_remote_port() when it is not used anymore. Fixes: bbbe775ec5b5 ("drm: Add support for Amlogic Meson Graphic Controller") Signed-off-by: Liang He Acked-by: Martin Blumenstingl Acked-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20220726010722.1319416-1-windhl@126.com --- drivers/gpu/drm/meson/meson_drv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c index 1b70938cfd2c4..bd4ca11d3ff53 100644 --- a/drivers/gpu/drm/meson/meson_drv.c +++ b/drivers/gpu/drm/meson/meson_drv.c @@ -115,8 +115,11 @@ static bool meson_vpu_has_available_connectors(struct device *dev) for_each_endpoint_of_node(dev->of_node, ep) { /* If the endpoint node exists, consider it enabled */ remote = of_graph_get_remote_port(ep); - if (remote) + if (remote) { + of_node_put(remote); + of_node_put(ep); return true; + } } return false; From fda7409a8fcfa457814f8186f2861a9f00008e75 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Mon, 8 Aug 2022 17:32:05 +0800 Subject: [PATCH 057/427] irqchip/loongson-pch-pic: Move find_pch_pic() into CONFIG_ACPI MIPS doesn't declare find_pch_pic(), which makes a build warning: >> drivers/irqchip/irq-loongson-pch-pic.c:51:5: warning: no previous prototype for function 'find_pch_pic' [-Wmissing-prototypes] int find_pch_pic(u32 gsi) ^ drivers/irqchip/irq-loongson-pch-pic.c:51:1: note: declare 'static' if the function is not intended to be used outside of this translation unit int find_pch_pic(u32 gsi) ^ static 1 warning generated. Move find_pch_pic() into CONFIG_ACPI which only used by LoongArch to fix the warning. BTW, remove the duplicated declaration of find_pch_pic() in irq.h. Reported-by: kernel test robot Signed-off-by: Huacai Chen Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20220808093205.3658485-1-chenhuacai@loongson.cn --- arch/loongarch/include/asm/irq.h | 1 - drivers/irqchip/irq-loongson-pch-pic.c | 38 +++++++++++++------------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h index 149b2123e7f4f..093aee99167df 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -81,7 +81,6 @@ extern struct acpi_vector_group msi_group[MAX_IO_PICS]; #define GSI_MIN_PCH_IRQ LOONGSON_PCH_IRQ_BASE #define GSI_MAX_PCH_IRQ (LOONGSON_PCH_IRQ_BASE + 256 - 1) -extern int find_pch_pic(u32 gsi); extern int eiointc_get_node(int id); struct acpi_madt_lio_pic; diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c index b6f1392964b14..b987b6517d59b 100644 --- a/drivers/irqchip/irq-loongson-pch-pic.c +++ b/drivers/irqchip/irq-loongson-pch-pic.c @@ -48,25 +48,6 @@ static struct pch_pic *pch_pic_priv[MAX_IO_PICS]; struct fwnode_handle *pch_pic_handle[MAX_IO_PICS]; -int find_pch_pic(u32 gsi) -{ - int i; - - /* Find the PCH_PIC that manages this GSI. */ - for (i = 0; i < MAX_IO_PICS; i++) { - struct pch_pic *priv = pch_pic_priv[i]; - - if (!priv) - return -1; - - if (gsi >= priv->gsi_base && gsi < (priv->gsi_base + priv->vec_count)) - return i; - } - - pr_err("ERROR: Unable to locate PCH_PIC for GSI %d\n", gsi); - return -1; -} - static void pch_pic_bitset(struct pch_pic *priv, int offset, int bit) { u32 reg; @@ -325,6 +306,25 @@ IRQCHIP_DECLARE(pch_pic, "loongson,pch-pic-1.0", pch_pic_of_init); #endif #ifdef CONFIG_ACPI +int find_pch_pic(u32 gsi) +{ + int i; + + /* Find the PCH_PIC that manages this GSI. */ + for (i = 0; i < MAX_IO_PICS; i++) { + struct pch_pic *priv = pch_pic_priv[i]; + + if (!priv) + return -1; + + if (gsi >= priv->gsi_base && gsi < (priv->gsi_base + priv->vec_count)) + return i; + } + + pr_err("ERROR: Unable to locate PCH_PIC for GSI %d\n", gsi); + return -1; +} + static int __init pch_lpc_parse_madt(union acpi_subtable_headers *header, const unsigned long end) From 9cae5b3189eb9cd12a9c3f6e8afda2d81958640b Mon Sep 17 00:00:00 2001 From: Nirmoy Das Date: Wed, 27 Jul 2022 19:33:06 +0200 Subject: [PATCH 058/427] drm/i915: disable pci resize on 32-bit machine PCI bar resize only works with 64 bit BAR so disable this on 32-bit machine and resolve below compilation error: drivers/gpu/drm/i915/gt/intel_region_lmem.c:94:23: error: result of comparison of constant 4294967296 with expression of type 'resource_size_t' (aka 'unsigned int') is always false [-Werror,-Wtautological-constant-out-of-range-compare] root_res->start > 0x100000000ull) Fixes: a91d1a17cd341 ("drm/i915: Add support for LMEM PCIe resizable bar") Reported-by: Linux Kernel Functional Testing Tested-by: Linux Kernel Functional Testing Acked-by: Matthew Auld Signed-off-by: Nirmoy Das Reviewed-by: Andi Shyti Signed-off-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20220727173306.16247-1-nirmoy.das@intel.com (cherry picked from commit f5dfbfc0ae00c2c2c0518da9e1f9a8cca50ae544) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/intel_region_lmem.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_region_lmem.c b/drivers/gpu/drm/i915/gt/intel_region_lmem.c index 6e90032e12e9b..aa6aed8371947 100644 --- a/drivers/gpu/drm/i915/gt/intel_region_lmem.c +++ b/drivers/gpu/drm/i915/gt/intel_region_lmem.c @@ -15,6 +15,7 @@ #include "gt/intel_gt_mcr.h" #include "gt/intel_gt_regs.h" +#ifdef CONFIG_64BIT static void _release_bars(struct pci_dev *pdev) { int resno; @@ -111,6 +112,9 @@ static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t pci_assign_unassigned_bus_resources(pdev->bus); pci_write_config_dword(pdev, PCI_COMMAND, pci_cmd); } +#else +static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t lmem_size) {} +#endif static int region_lmem_release(struct intel_memory_region *mem) From 232d150fa15606e96c0e01e5c7a2d4e03f621787 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Wed, 27 Jul 2022 17:43:46 +0100 Subject: [PATCH 059/427] drm/i915/ttm: don't leak the ccs state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kernel only manages the ccs state with lmem-only objects, however the kernel should still take care not to leak the CCS state from the previous user. Fixes: 48760ffe923a ("drm/i915/gt: Clear compress metadata for Flat-ccs objects") Signed-off-by: Matthew Auld Cc: Thomas Hellström Cc: Ramalingam C Reviewed-by: Ramalingam C Link: https://patchwork.freedesktop.org/patch/msgid/20220727164346.282407-1-matthew.auld@intel.com (cherry picked from commit 353819d85f87be46aeb9c1dd929d445a006fc6ec) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/intel_migrate.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_migrate.c b/drivers/gpu/drm/i915/gt/intel_migrate.c index 2c35324b5f68c..2b10b96b17b5b 100644 --- a/drivers/gpu/drm/i915/gt/intel_migrate.c +++ b/drivers/gpu/drm/i915/gt/intel_migrate.c @@ -708,7 +708,7 @@ intel_context_migrate_copy(struct intel_context *ce, u8 src_access, dst_access; struct i915_request *rq; int src_sz, dst_sz; - bool ccs_is_src; + bool ccs_is_src, overwrite_ccs; int err; GEM_BUG_ON(ce->vm != ce->engine->gt->migrate.context->vm); @@ -749,6 +749,8 @@ intel_context_migrate_copy(struct intel_context *ce, get_ccs_sg_sgt(&it_ccs, bytes_to_cpy); } + overwrite_ccs = HAS_FLAT_CCS(i915) && !ccs_bytes_to_cpy && dst_is_lmem; + src_offset = 0; dst_offset = CHUNK_SZ; if (HAS_64K_PAGES(ce->engine->i915)) { @@ -852,6 +854,25 @@ intel_context_migrate_copy(struct intel_context *ce, if (err) goto out_rq; ccs_bytes_to_cpy -= ccs_sz; + } else if (overwrite_ccs) { + err = rq->engine->emit_flush(rq, EMIT_INVALIDATE); + if (err) + goto out_rq; + + /* + * While we can't always restore/manage the CCS state, + * we still need to ensure we don't leak the CCS state + * from the previous user, so make sure we overwrite it + * with something. + */ + err = emit_copy_ccs(rq, dst_offset, INDIRECT_ACCESS, + dst_offset, DIRECT_ACCESS, len); + if (err) + goto out_rq; + + err = rq->engine->emit_flush(rq, EMIT_INVALIDATE); + if (err) + goto out_rq; } /* Arbitration is re-enabled between requests. */ From db100e28fdf026a1fc10657c5170bb1e65663805 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 27 Jul 2022 14:29:51 +0200 Subject: [PATCH 060/427] drm/i915/gt: Ignore TLB invalidations on idle engines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check if the device is powered down prior to any engine activity, as, on such cases, all the TLBs were already invalidated, so an explicit TLB invalidation is not needed, thus reducing the performance regression impact due to it. This becomes more significant with GuC, as it can only do so when the connection to the GuC is awake. Cc: stable@vger.kernel.org Fixes: 7938d61591d3 ("drm/i915: Flush TLBs before releasing backing store") Signed-off-by: Chris Wilson Cc: Fei Yang Reviewed-by: Andi Shyti Acked-by: Thomas Hellström Acked-by: Tvrtko Ursulin Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/278a57a672edac75683f0818b292e95da583a5fe.1658924372.git.mchehab@kernel.org (cherry picked from commit 4bedceaed1ae1172cfe72d3ff752b3a1d32fe4d9) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gem/i915_gem_pages.c | 10 ++++++---- drivers/gpu/drm/i915/gt/intel_gt.c | 17 ++++++++++------- drivers/gpu/drm/i915/gt/intel_gt_pm.h | 3 +++ 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c index 97c820eee115a..6835279943df8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c @@ -6,14 +6,15 @@ #include +#include "gt/intel_gt.h" +#include "gt/intel_gt_pm.h" + #include "i915_drv.h" #include "i915_gem_object.h" #include "i915_scatterlist.h" #include "i915_gem_lmem.h" #include "i915_gem_mman.h" -#include "gt/intel_gt.h" - void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, struct sg_table *pages, unsigned int sg_page_sizes) @@ -217,10 +218,11 @@ __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj) if (test_and_clear_bit(I915_BO_WAS_BOUND_BIT, &obj->flags)) { struct drm_i915_private *i915 = to_i915(obj->base.dev); + struct intel_gt *gt = to_gt(i915); intel_wakeref_t wakeref; - with_intel_runtime_pm_if_active(&i915->runtime_pm, wakeref) - intel_gt_invalidate_tlbs(to_gt(i915)); + with_intel_gt_pm_if_awake(gt, wakeref) + intel_gt_invalidate_tlbs(gt); } return pages; diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 68c2b0d8f1876..c4d43da84d8ed 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -12,6 +12,7 @@ #include "i915_drv.h" #include "intel_context.h" +#include "intel_engine_pm.h" #include "intel_engine_regs.h" #include "intel_ggtt_gmch.h" #include "intel_gt.h" @@ -924,6 +925,7 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) struct drm_i915_private *i915 = gt->i915; struct intel_uncore *uncore = gt->uncore; struct intel_engine_cs *engine; + intel_engine_mask_t awake, tmp; enum intel_engine_id id; const i915_reg_t *regs; unsigned int num = 0; @@ -947,26 +949,31 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) GEM_TRACE("\n"); - assert_rpm_wakelock_held(&i915->runtime_pm); - mutex_lock(>->tlb_invalidate_lock); intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); spin_lock_irq(&uncore->lock); /* serialise invalidate with GT reset */ + awake = 0; for_each_engine(engine, gt, id) { struct reg_and_bit rb; + if (!intel_engine_pm_is_awake(engine)) + continue; + rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num); if (!i915_mmio_reg_offset(rb.reg)) continue; intel_uncore_write_fw(uncore, rb.reg, rb.bit); + awake |= engine->mask; } spin_unlock_irq(&uncore->lock); - for_each_engine(engine, gt, id) { + for_each_engine_masked(engine, gt, awake, tmp) { + struct reg_and_bit rb; + /* * HW architecture suggest typical invalidation time at 40us, * with pessimistic cases up to 100us and a recommendation to @@ -974,12 +981,8 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) */ const unsigned int timeout_us = 100; const unsigned int timeout_ms = 4; - struct reg_and_bit rb; rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num); - if (!i915_mmio_reg_offset(rb.reg)) - continue; - if (__intel_wait_for_register_fw(uncore, rb.reg, rb.bit, 0, timeout_us, timeout_ms, diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.h b/drivers/gpu/drm/i915/gt/intel_gt_pm.h index bc898df7a48cc..a334787a4939f 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.h @@ -55,6 +55,9 @@ static inline void intel_gt_pm_might_put(struct intel_gt *gt) for (tmp = 1, intel_gt_pm_get(gt); tmp; \ intel_gt_pm_put(gt), tmp = 0) +#define with_intel_gt_pm_if_awake(gt, wf) \ + for (wf = intel_gt_pm_get_if_awake(gt); wf; intel_gt_pm_put_async(gt), wf = 0) + static inline int intel_gt_pm_wait_for_idle(struct intel_gt *gt) { return intel_wakeref_wait_for_idle(>->wakeref); From 180abeb2c5032704787151135b6a38c6b71295a6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 27 Jul 2022 14:29:53 +0200 Subject: [PATCH 061/427] drm/i915/gt: Invalidate TLB of the OA unit at TLB invalidations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure that the TLB of the OA unit is also invalidated on gen12 HW, as just invalidating the TLB of an engine is not enough. Cc: stable@vger.kernel.org Fixes: 7938d61591d3 ("drm/i915: Flush TLBs before releasing backing store") Signed-off-by: Chris Wilson Cc: Fei Yang Reviewed-by: Andi Shyti Acked-by: Tvrtko Ursulin Acked-by: Thomas Hellström Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/59724d9f5cf1e93b1620d01b8332ac991555283d.1658924372.git.mchehab@kernel.org (cherry picked from commit dfc83de118ff7930acc9a4c8dfdba7c153aa44d6) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/intel_gt.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index c4d43da84d8ed..1d84418e8676f 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -11,6 +11,7 @@ #include "pxp/intel_pxp.h" #include "i915_drv.h" +#include "i915_perf_oa_regs.h" #include "intel_context.h" #include "intel_engine_pm.h" #include "intel_engine_regs.h" @@ -969,6 +970,15 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) awake |= engine->mask; } + /* Wa_2207587034:tgl,dg1,rkl,adl-s,adl-p */ + if (awake && + (IS_TIGERLAKE(i915) || + IS_DG1(i915) || + IS_ROCKETLAKE(i915) || + IS_ALDERLAKE_S(i915) || + IS_ALDERLAKE_P(i915))) + intel_uncore_write_fw(uncore, GEN12_OA_TLB_INV_CR, 1); + spin_unlock_irq(&uncore->lock); for_each_engine_masked(engine, gt, awake, tmp) { From e5a95c83ed1492c0f442b448b20c90c8faaf702b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 27 Jul 2022 14:29:54 +0200 Subject: [PATCH 062/427] drm/i915/gt: Skip TLB invalidations once wedged MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Skip all further TLB invalidations once the device is wedged and had been reset, as, on such cases, it can no longer process instructions on the GPU and the user no longer has access to the TLB's in each engine. So, an attempt to do a TLB cache invalidation will produce a timeout. That helps to reduce the performance regression introduced by TLB invalidate logic. Cc: stable@vger.kernel.org Fixes: 7938d61591d3 ("drm/i915: Flush TLBs before releasing backing store") Signed-off-by: Chris Wilson Cc: Fei Yang Cc: Tvrtko Ursulin Reviewed-by: Andi Shyti Acked-by: Thomas Hellström Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/5aa86564b9ec5fe7fe605c1dd7de76855401ed73.1658924372.git.mchehab@kernel.org (cherry picked from commit be0366f168033374a93e4c43fdaa1a90ab905184) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/intel_gt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 1d84418e8676f..5c55a90672f4f 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -934,6 +934,9 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) if (I915_SELFTEST_ONLY(gt->awake == -ENODEV)) return; + if (intel_gt_is_wedged(gt)) + return; + if (GRAPHICS_VER(i915) == 12) { regs = gen12_regs; num = ARRAY_SIZE(gen12_regs); From 59eda6ce824e95b98c45628fe6c0adb9130c6df2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 27 Jul 2022 14:29:55 +0200 Subject: [PATCH 063/427] drm/i915/gt: Batch TLB invalidations Invalidate TLB in batches, in order to reduce performance regressions. Currently, every caller performs a full barrier around a TLB invalidation, ignoring all other invalidations that may have already removed their PTEs from the cache. As this is a synchronous operation and can be quite slow, we cause multiple threads to contend on the TLB invalidate mutex blocking userspace. We only need to invalidate the TLB once after replacing our PTE to ensure that there is no possible continued access to the physical address before releasing our pages. By tracking a seqno for each full TLB invalidate we can quickly determine if one has been performed since rewriting the PTE, and only if necessary trigger one for ourselves. That helps to reduce the performance regression introduced by TLB invalidate logic. [mchehab: rebased to not require moving the code to a separate file] Cc: stable@vger.kernel.org Fixes: 7938d61591d3 ("drm/i915: Flush TLBs before releasing backing store") Suggested-by: Tvrtko Ursulin Signed-off-by: Chris Wilson Cc: Fei Yang Signed-off-by: Mauro Carvalho Chehab Acked-by: Tvrtko Ursulin Reviewed-by: Andi Shyti Signed-off-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/4e97ef5deb6739cadaaf40aa45620547e9c4ec06.1658924372.git.mchehab@kernel.org (cherry picked from commit 5d36acb7198b0e5eb88e6b701f9ad7b9448f8df9) Signed-off-by: Rodrigo Vivi --- .../gpu/drm/i915/gem/i915_gem_object_types.h | 3 +- drivers/gpu/drm/i915/gem/i915_gem_pages.c | 21 +++++--- drivers/gpu/drm/i915/gt/intel_gt.c | 53 ++++++++++++++----- drivers/gpu/drm/i915/gt/intel_gt.h | 12 ++++- drivers/gpu/drm/i915/gt/intel_gt_types.h | 18 ++++++- drivers/gpu/drm/i915/gt/intel_ppgtt.c | 8 ++- drivers/gpu/drm/i915/i915_vma.c | 33 +++++++++--- drivers/gpu/drm/i915/i915_vma.h | 1 + drivers/gpu/drm/i915/i915_vma_resource.c | 5 +- drivers/gpu/drm/i915/i915_vma_resource.h | 6 ++- 10 files changed, 125 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index 5cf36a130061d..9f6b14ec189a2 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -335,7 +335,6 @@ struct drm_i915_gem_object { #define I915_BO_READONLY BIT(7) #define I915_TILING_QUIRK_BIT 8 /* unknown swizzling; do not release! */ #define I915_BO_PROTECTED BIT(9) -#define I915_BO_WAS_BOUND_BIT 10 /** * @mem_flags - Mutable placement-related flags * @@ -616,6 +615,8 @@ struct drm_i915_gem_object { * pages were last acquired. */ bool dirty:1; + + u32 tlb; } mm; struct { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c index 6835279943df8..8357dbdcab5cb 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c @@ -191,6 +191,18 @@ static void unmap_object(struct drm_i915_gem_object *obj, void *ptr) vunmap(ptr); } +static void flush_tlb_invalidate(struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *i915 = to_i915(obj->base.dev); + struct intel_gt *gt = to_gt(i915); + + if (!obj->mm.tlb) + return; + + intel_gt_invalidate_tlb(gt, obj->mm.tlb); + obj->mm.tlb = 0; +} + struct sg_table * __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj) { @@ -216,14 +228,7 @@ __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj) __i915_gem_object_reset_page_iter(obj); obj->mm.page_sizes.phys = obj->mm.page_sizes.sg = 0; - if (test_and_clear_bit(I915_BO_WAS_BOUND_BIT, &obj->flags)) { - struct drm_i915_private *i915 = to_i915(obj->base.dev); - struct intel_gt *gt = to_gt(i915); - intel_wakeref_t wakeref; - - with_intel_gt_pm_if_awake(gt, wakeref) - intel_gt_invalidate_tlbs(gt); - } + flush_tlb_invalidate(obj); return pages; } diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 5c55a90672f4f..f435e06125aab 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -38,8 +38,6 @@ static void __intel_gt_init_early(struct intel_gt *gt) { spin_lock_init(>->irq_lock); - mutex_init(>->tlb_invalidate_lock); - INIT_LIST_HEAD(>->closed_vma); spin_lock_init(>->closed_lock); @@ -50,6 +48,8 @@ static void __intel_gt_init_early(struct intel_gt *gt) intel_gt_init_reset(gt); intel_gt_init_requests(gt); intel_gt_init_timelines(gt); + mutex_init(>->tlb.invalidate_lock); + seqcount_mutex_init(>->tlb.seqno, >->tlb.invalidate_lock); intel_gt_pm_init_early(gt); intel_uc_init_early(>->uc); @@ -770,6 +770,7 @@ void intel_gt_driver_late_release_all(struct drm_i915_private *i915) intel_gt_fini_requests(gt); intel_gt_fini_reset(gt); intel_gt_fini_timelines(gt); + mutex_destroy(>->tlb.invalidate_lock); intel_engines_free(gt); } } @@ -908,7 +909,7 @@ get_reg_and_bit(const struct intel_engine_cs *engine, const bool gen8, return rb; } -void intel_gt_invalidate_tlbs(struct intel_gt *gt) +static void mmio_invalidate_full(struct intel_gt *gt) { static const i915_reg_t gen8_regs[] = { [RENDER_CLASS] = GEN8_RTCR, @@ -931,12 +932,6 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) const i915_reg_t *regs; unsigned int num = 0; - if (I915_SELFTEST_ONLY(gt->awake == -ENODEV)) - return; - - if (intel_gt_is_wedged(gt)) - return; - if (GRAPHICS_VER(i915) == 12) { regs = gen12_regs; num = ARRAY_SIZE(gen12_regs); @@ -951,9 +946,6 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) "Platform does not implement TLB invalidation!")) return; - GEM_TRACE("\n"); - - mutex_lock(>->tlb_invalidate_lock); intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); spin_lock_irq(&uncore->lock); /* serialise invalidate with GT reset */ @@ -973,6 +965,8 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) awake |= engine->mask; } + GT_TRACE(gt, "invalidated engines %08x\n", awake); + /* Wa_2207587034:tgl,dg1,rkl,adl-s,adl-p */ if (awake && (IS_TIGERLAKE(i915) || @@ -1012,5 +1006,38 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) * transitions. */ intel_uncore_forcewake_put_delayed(uncore, FORCEWAKE_ALL); - mutex_unlock(>->tlb_invalidate_lock); +} + +static bool tlb_seqno_passed(const struct intel_gt *gt, u32 seqno) +{ + u32 cur = intel_gt_tlb_seqno(gt); + + /* Only skip if a *full* TLB invalidate barrier has passed */ + return (s32)(cur - ALIGN(seqno, 2)) > 0; +} + +void intel_gt_invalidate_tlb(struct intel_gt *gt, u32 seqno) +{ + intel_wakeref_t wakeref; + + if (I915_SELFTEST_ONLY(gt->awake == -ENODEV)) + return; + + if (intel_gt_is_wedged(gt)) + return; + + if (tlb_seqno_passed(gt, seqno)) + return; + + with_intel_gt_pm_if_awake(gt, wakeref) { + mutex_lock(>->tlb.invalidate_lock); + if (tlb_seqno_passed(gt, seqno)) + goto unlock; + + mmio_invalidate_full(gt); + + write_seqcount_invalidate(>->tlb.seqno); +unlock: + mutex_unlock(>->tlb.invalidate_lock); + } } diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h index 82d6f248d8762..40b06adf509a2 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.h +++ b/drivers/gpu/drm/i915/gt/intel_gt.h @@ -101,6 +101,16 @@ void intel_gt_info_print(const struct intel_gt_info *info, void intel_gt_watchdog_work(struct work_struct *work); -void intel_gt_invalidate_tlbs(struct intel_gt *gt); +static inline u32 intel_gt_tlb_seqno(const struct intel_gt *gt) +{ + return seqprop_sequence(>->tlb.seqno); +} + +static inline u32 intel_gt_next_invalidate_tlb_full(const struct intel_gt *gt) +{ + return intel_gt_tlb_seqno(gt) | 1; +} + +void intel_gt_invalidate_tlb(struct intel_gt *gt, u32 seqno); #endif /* __INTEL_GT_H__ */ diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h b/drivers/gpu/drm/i915/gt/intel_gt_types.h index df708802889df..3804a583382ba 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_types.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -83,7 +84,22 @@ struct intel_gt { struct intel_uc uc; struct intel_gsc gsc; - struct mutex tlb_invalidate_lock; + struct { + /* Serialize global tlb invalidations */ + struct mutex invalidate_lock; + + /* + * Batch TLB invalidations + * + * After unbinding the PTE, we need to ensure the TLB + * are invalidated prior to releasing the physical pages. + * But we only need one such invalidation for all unbinds, + * so we track how many TLB invalidations have been + * performed since unbind the PTE and only emit an extra + * invalidate if no full barrier has been passed. + */ + seqcount_mutex_t seqno; + } tlb; struct i915_wa_list wa_list; diff --git a/drivers/gpu/drm/i915/gt/intel_ppgtt.c b/drivers/gpu/drm/i915/gt/intel_ppgtt.c index d8b94d6385598..2da6c82a8bd2a 100644 --- a/drivers/gpu/drm/i915/gt/intel_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ppgtt.c @@ -206,8 +206,12 @@ void ppgtt_bind_vma(struct i915_address_space *vm, void ppgtt_unbind_vma(struct i915_address_space *vm, struct i915_vma_resource *vma_res) { - if (vma_res->allocated) - vm->clear_range(vm, vma_res->start, vma_res->vma_size); + if (!vma_res->allocated) + return; + + vm->clear_range(vm, vma_res->start, vma_res->vma_size); + if (vma_res->tlb) + vma_invalidate_tlb(vm, *vma_res->tlb); } static unsigned long pd_count(u64 size, int shift) diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index ef3b04c7e1537..84a9ccbc5fc5e 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -538,8 +538,6 @@ int i915_vma_bind(struct i915_vma *vma, bind_flags); } - set_bit(I915_BO_WAS_BOUND_BIT, &vma->obj->flags); - atomic_or(bind_flags, &vma->flags); return 0; } @@ -1310,6 +1308,19 @@ I915_SELFTEST_EXPORT int i915_vma_get_pages(struct i915_vma *vma) return err; } +void vma_invalidate_tlb(struct i915_address_space *vm, u32 tlb) +{ + /* + * Before we release the pages that were bound by this vma, we + * must invalidate all the TLBs that may still have a reference + * back to our physical address. It only needs to be done once, + * so after updating the PTE to point away from the pages, record + * the most recent TLB invalidation seqno, and if we have not yet + * flushed the TLBs upon release, perform a full invalidation. + */ + WRITE_ONCE(tlb, intel_gt_next_invalidate_tlb_full(vm->gt)); +} + static void __vma_put_pages(struct i915_vma *vma, unsigned int count) { /* We allocate under vma_get_pages, so beware the shrinker */ @@ -1941,7 +1952,12 @@ struct dma_fence *__i915_vma_evict(struct i915_vma *vma, bool async) vma->vm->skip_pte_rewrite; trace_i915_vma_unbind(vma); - unbind_fence = i915_vma_resource_unbind(vma_res); + if (async) + unbind_fence = i915_vma_resource_unbind(vma_res, + &vma->obj->mm.tlb); + else + unbind_fence = i915_vma_resource_unbind(vma_res, NULL); + vma->resource = NULL; atomic_and(~(I915_VMA_BIND_MASK | I915_VMA_ERROR | I915_VMA_GGTT_WRITE), @@ -1949,10 +1965,13 @@ struct dma_fence *__i915_vma_evict(struct i915_vma *vma, bool async) i915_vma_detach(vma); - if (!async && unbind_fence) { - dma_fence_wait(unbind_fence, false); - dma_fence_put(unbind_fence); - unbind_fence = NULL; + if (!async) { + if (unbind_fence) { + dma_fence_wait(unbind_fence, false); + dma_fence_put(unbind_fence); + unbind_fence = NULL; + } + vma_invalidate_tlb(vma->vm, vma->obj->mm.tlb); } /* diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index 88ca0bd9c9003..5048eed536da4 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h @@ -213,6 +213,7 @@ bool i915_vma_misplaced(const struct i915_vma *vma, u64 size, u64 alignment, u64 flags); void __i915_vma_set_map_and_fenceable(struct i915_vma *vma); void i915_vma_revoke_mmap(struct i915_vma *vma); +void vma_invalidate_tlb(struct i915_address_space *vm, u32 tlb); struct dma_fence *__i915_vma_evict(struct i915_vma *vma, bool async); int __i915_vma_unbind(struct i915_vma *vma); int __must_check i915_vma_unbind(struct i915_vma *vma); diff --git a/drivers/gpu/drm/i915/i915_vma_resource.c b/drivers/gpu/drm/i915/i915_vma_resource.c index 27c55027387a0..5a67995ea5fe2 100644 --- a/drivers/gpu/drm/i915/i915_vma_resource.c +++ b/drivers/gpu/drm/i915/i915_vma_resource.c @@ -223,10 +223,13 @@ i915_vma_resource_fence_notify(struct i915_sw_fence *fence, * Return: A refcounted pointer to a dma-fence that signals when unbinding is * complete. */ -struct dma_fence *i915_vma_resource_unbind(struct i915_vma_resource *vma_res) +struct dma_fence *i915_vma_resource_unbind(struct i915_vma_resource *vma_res, + u32 *tlb) { struct i915_address_space *vm = vma_res->vm; + vma_res->tlb = tlb; + /* Reference for the sw fence */ i915_vma_resource_get(vma_res); diff --git a/drivers/gpu/drm/i915/i915_vma_resource.h b/drivers/gpu/drm/i915/i915_vma_resource.h index 5d8427caa2ba2..06923d1816e7e 100644 --- a/drivers/gpu/drm/i915/i915_vma_resource.h +++ b/drivers/gpu/drm/i915/i915_vma_resource.h @@ -67,6 +67,7 @@ struct i915_page_sizes { * taken when the unbind is scheduled. * @skip_pte_rewrite: During ggtt suspend and vm takedown pte rewriting * needs to be skipped for unbind. + * @tlb: pointer for obj->mm.tlb, if async unbind. Otherwise, NULL * * The lifetime of a struct i915_vma_resource is from a binding request to * the actual possible asynchronous unbind has completed. @@ -119,6 +120,8 @@ struct i915_vma_resource { bool immediate_unbind:1; bool needs_wakeref:1; bool skip_pte_rewrite:1; + + u32 *tlb; }; bool i915_vma_resource_hold(struct i915_vma_resource *vma_res, @@ -131,7 +134,8 @@ struct i915_vma_resource *i915_vma_resource_alloc(void); void i915_vma_resource_free(struct i915_vma_resource *vma_res); -struct dma_fence *i915_vma_resource_unbind(struct i915_vma_resource *vma_res); +struct dma_fence *i915_vma_resource_unbind(struct i915_vma_resource *vma_res, + u32 *tlb); void __i915_vma_resource_init(struct i915_vma_resource *vma_res); From 2826d447fbd60e6a05e53d5f918bceb8c04e315c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 26 Jul 2022 16:48:44 +0200 Subject: [PATCH 064/427] drm/i915/gem: Remove shared locking on freeing objects The obj->base.resv may be shared across many objects, some of which may still be live and locked, preventing objects from being freed indefintely. We could individualise the lock during the free, or rely on a freed object having no contention and being able to immediately free the pages it owns. References: https://gitlab.freedesktop.org/drm/intel/-/issues/6469 Fixes: be7612fd6665 ("drm/i915: Require object lock when freeing pages during destruction") Fixes: 6cb12fbda1c2 ("drm/i915: Use trylock instead of blocking lock for __i915_gem_free_objects.") Cc: # v5.17+ Signed-off-by: Chris Wilson Tested-by: Nirmoy Das Acked-by: Nirmoy Das Signed-off-by: Nirmoy Das Reviewed-by: Matthew Auld Signed-off-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20220726144844.18429-1-nirmoy.das@intel.com (cherry picked from commit 7dd5c56531eb03696acdb17774721de5ef481c0b) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gem/i915_gem_object.c | 16 ++++------------ drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c index ccec4055fde3e..389e9f157ca5e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c @@ -268,7 +268,7 @@ static void __i915_gem_object_free_mmaps(struct drm_i915_gem_object *obj) */ void __i915_gem_object_pages_fini(struct drm_i915_gem_object *obj) { - assert_object_held(obj); + assert_object_held_shared(obj); if (!list_empty(&obj->vma.list)) { struct i915_vma *vma; @@ -331,15 +331,7 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, continue; } - if (!i915_gem_object_trylock(obj, NULL)) { - /* busy, toss it back to the pile */ - if (llist_add(&obj->freed, &i915->mm.free_list)) - queue_delayed_work(i915->wq, &i915->mm.free_work, msecs_to_jiffies(10)); - continue; - } - __i915_gem_object_pages_fini(obj); - i915_gem_object_unlock(obj); __i915_gem_free_object(obj); /* But keep the pointer alive for RCU-protected lookups */ @@ -359,7 +351,7 @@ void i915_gem_flush_free_objects(struct drm_i915_private *i915) static void __i915_gem_free_work(struct work_struct *work) { struct drm_i915_private *i915 = - container_of(work, struct drm_i915_private, mm.free_work.work); + container_of(work, struct drm_i915_private, mm.free_work); i915_gem_flush_free_objects(i915); } @@ -391,7 +383,7 @@ static void i915_gem_free_object(struct drm_gem_object *gem_obj) */ if (llist_add(&obj->freed, &i915->mm.free_list)) - queue_delayed_work(i915->wq, &i915->mm.free_work, 0); + queue_work(i915->wq, &i915->mm.free_work); } void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj, @@ -745,7 +737,7 @@ bool i915_gem_object_needs_ccs_pages(struct drm_i915_gem_object *obj) void i915_gem_init__objects(struct drm_i915_private *i915) { - INIT_DELAYED_WORK(&i915->mm.free_work, __i915_gem_free_work); + INIT_WORK(&i915->mm.free_work, __i915_gem_free_work); } void i915_objects_module_exit(void) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d25647be25d18..086bbe8945d6c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -247,7 +247,7 @@ struct i915_gem_mm { * List of objects which are pending destruction. */ struct llist_head free_list; - struct delayed_work free_work; + struct work_struct free_work; /** * Count of objects pending destructions. Used to skip needlessly * waiting on an RCU barrier if no objects are waiting to be freed. @@ -1378,7 +1378,7 @@ static inline void i915_gem_drain_freed_objects(struct drm_i915_private *i915) * armed the work again. */ while (atomic_read(&i915->mm.free_count)) { - flush_delayed_work(&i915->mm.free_work); + flush_work(&i915->mm.free_work); flush_delayed_work(&i915->bdev.wq); rcu_barrier(); } From 9d50bff40e3e366886ec37299fc317edf84be0c9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Aug 2022 09:37:22 +0200 Subject: [PATCH 065/427] drm/i915: pass a pointer for tlb seqno at vma_invalidate_tlb() WRITE_ONCE() should happen at the original var, not on a local copy of it. Cc: stable@vger.kernel.org Fixes: 59eda6ce824e ("drm/i915/gt: Batch TLB invalidations") Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Andi Shyti Signed-off-by: Rodrigo Vivi [added cc-stable while merging it] Link: https://patchwork.freedesktop.org/patch/msgid/f9550e6bacea10131ff40dd8981b69eb9251cdcd.1659598090.git.mchehab@kernel.org (cherry picked from commit 3d037d99e61a1e7a3ae3d214146d88db349dd19f) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/intel_ppgtt.c | 2 +- drivers/gpu/drm/i915/i915_vma.c | 6 +++--- drivers/gpu/drm/i915/i915_vma.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ppgtt.c b/drivers/gpu/drm/i915/gt/intel_ppgtt.c index 2da6c82a8bd2a..6ee8d11270168 100644 --- a/drivers/gpu/drm/i915/gt/intel_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ppgtt.c @@ -211,7 +211,7 @@ void ppgtt_unbind_vma(struct i915_address_space *vm, vm->clear_range(vm, vma_res->start, vma_res->vma_size); if (vma_res->tlb) - vma_invalidate_tlb(vm, *vma_res->tlb); + vma_invalidate_tlb(vm, vma_res->tlb); } static unsigned long pd_count(u64 size, int shift) diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 84a9ccbc5fc5e..2603717164900 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -1308,7 +1308,7 @@ I915_SELFTEST_EXPORT int i915_vma_get_pages(struct i915_vma *vma) return err; } -void vma_invalidate_tlb(struct i915_address_space *vm, u32 tlb) +void vma_invalidate_tlb(struct i915_address_space *vm, u32 *tlb) { /* * Before we release the pages that were bound by this vma, we @@ -1318,7 +1318,7 @@ void vma_invalidate_tlb(struct i915_address_space *vm, u32 tlb) * the most recent TLB invalidation seqno, and if we have not yet * flushed the TLBs upon release, perform a full invalidation. */ - WRITE_ONCE(tlb, intel_gt_next_invalidate_tlb_full(vm->gt)); + WRITE_ONCE(*tlb, intel_gt_next_invalidate_tlb_full(vm->gt)); } static void __vma_put_pages(struct i915_vma *vma, unsigned int count) @@ -1971,7 +1971,7 @@ struct dma_fence *__i915_vma_evict(struct i915_vma *vma, bool async) dma_fence_put(unbind_fence); unbind_fence = NULL; } - vma_invalidate_tlb(vma->vm, vma->obj->mm.tlb); + vma_invalidate_tlb(vma->vm, &vma->obj->mm.tlb); } /* diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index 5048eed536da4..33a58f605d75c 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h @@ -213,7 +213,7 @@ bool i915_vma_misplaced(const struct i915_vma *vma, u64 size, u64 alignment, u64 flags); void __i915_vma_set_map_and_fenceable(struct i915_vma *vma); void i915_vma_revoke_mmap(struct i915_vma *vma); -void vma_invalidate_tlb(struct i915_address_space *vm, u32 tlb); +void vma_invalidate_tlb(struct i915_address_space *vm, u32 *tlb); struct dma_fence *__i915_vma_evict(struct i915_vma *vma, bool async); int __i915_vma_unbind(struct i915_vma *vma); int __must_check i915_vma_unbind(struct i915_vma *vma); From e9ac31f0a5d0e246b046c20348954519f91a297f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Mon, 8 Aug 2022 16:12:43 +0200 Subject: [PATCH 066/427] ASoC: tas2770: Set correct FSYNC polarity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix setting of FSYNC polarity for DAI formats other than I2S. Also add support for polarity inversion. Fixes: 1a476abc723e ("tas2770: add tas2770 smart PA kernel driver") Signed-off-by: Martin Povišer Link: https://lore.kernel.org/r/20220808141246.5749-2-povik+lin@cutebit.org Signed-off-by: Mark Brown --- sound/soc/codecs/tas2770.c | 20 +++++++++++++++++++- sound/soc/codecs/tas2770.h | 3 +++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index 3cb634c282610..46b0b31c01254 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -337,7 +337,7 @@ static int tas2770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) struct snd_soc_component *component = dai->component; struct tas2770_priv *tas2770 = snd_soc_component_get_drvdata(component); - u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0; + u8 tdm_rx_start_slot = 0, invert_fpol = 0, fpol_preinv = 0, asi_cfg_1 = 0; int ret; switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { @@ -349,9 +349,15 @@ static int tas2770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) } switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_IF: + invert_fpol = 1; + fallthrough; case SND_SOC_DAIFMT_NB_NF: asi_cfg_1 |= TAS2770_TDM_CFG_REG1_RX_RSING; break; + case SND_SOC_DAIFMT_IB_IF: + invert_fpol = 1; + fallthrough; case SND_SOC_DAIFMT_IB_NF: asi_cfg_1 |= TAS2770_TDM_CFG_REG1_RX_FALING; break; @@ -369,15 +375,19 @@ static int tas2770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: tdm_rx_start_slot = 1; + fpol_preinv = 0; break; case SND_SOC_DAIFMT_DSP_A: tdm_rx_start_slot = 0; + fpol_preinv = 1; break; case SND_SOC_DAIFMT_DSP_B: tdm_rx_start_slot = 1; + fpol_preinv = 1; break; case SND_SOC_DAIFMT_LEFT_J: tdm_rx_start_slot = 0; + fpol_preinv = 1; break; default: dev_err(tas2770->dev, @@ -391,6 +401,14 @@ static int tas2770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) if (ret < 0) return ret; + ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG0, + TAS2770_TDM_CFG_REG0_FPOL_MASK, + (fpol_preinv ^ invert_fpol) + ? TAS2770_TDM_CFG_REG0_FPOL_RSING + : TAS2770_TDM_CFG_REG0_FPOL_FALING); + if (ret < 0) + return ret; + return 0; } diff --git a/sound/soc/codecs/tas2770.h b/sound/soc/codecs/tas2770.h index d156666bcc552..d51e88d8c3383 100644 --- a/sound/soc/codecs/tas2770.h +++ b/sound/soc/codecs/tas2770.h @@ -41,6 +41,9 @@ #define TAS2770_TDM_CFG_REG0_31_44_1_48KHZ 0x6 #define TAS2770_TDM_CFG_REG0_31_88_2_96KHZ 0x8 #define TAS2770_TDM_CFG_REG0_31_176_4_192KHZ 0xa +#define TAS2770_TDM_CFG_REG0_FPOL_MASK BIT(0) +#define TAS2770_TDM_CFG_REG0_FPOL_RSING 0 +#define TAS2770_TDM_CFG_REG0_FPOL_FALING 1 /* TDM Configuration Reg1 */ #define TAS2770_TDM_CFG_REG1 TAS2770_REG(0X0, 0x0B) #define TAS2770_TDM_CFG_REG1_MASK GENMASK(5, 1) From bf54d97a835dfe62d4d29e245e170c63d0089be7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Mon, 8 Aug 2022 16:12:44 +0200 Subject: [PATCH 067/427] ASoC: tas2770: Allow mono streams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The part is a mono speaker amp, but it can do downmix and switch between left and right channel, so the right channel range is 1 to 2. Fixes: 1a476abc723e ("tas2770: add tas2770 smart PA kernel driver") Signed-off-by: Martin Povišer Link: https://lore.kernel.org/r/20220808141246.5749-3-povik+lin@cutebit.org Signed-off-by: Mark Brown --- sound/soc/codecs/tas2770.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index 46b0b31c01254..8812b975f70f6 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -507,7 +507,7 @@ static struct snd_soc_dai_driver tas2770_dai_driver[] = { .id = 0, .playback = { .stream_name = "ASI1 Playback", - .channels_min = 2, + .channels_min = 1, .channels_max = 2, .rates = TAS2770_RATES, .formats = TAS2770_FORMATS, From 482c23fbc7e9bf5a7a74defd0735d5346215db58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Mon, 8 Aug 2022 16:12:45 +0200 Subject: [PATCH 068/427] ASoC: tas2770: Drop conflicting set_bias_level power setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver is setting the PWR_CTRL field in both the set_bias_level callback and on DAPM events of the DAC widget (and also in the mute_stream method). Drop the set_bias_level callback altogether as the power setting it does is in conflict with the other code paths. Fixes: 1a476abc723e ("tas2770: add tas2770 smart PA kernel driver") Signed-off-by: Martin Povišer Link: https://lore.kernel.org/r/20220808141246.5749-4-povik+lin@cutebit.org Signed-off-by: Mark Brown --- sound/soc/codecs/tas2770.c | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index 8812b975f70f6..fba4aa27caa39 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -46,38 +46,6 @@ static void tas2770_reset(struct tas2770_priv *tas2770) usleep_range(1000, 2000); } -static int tas2770_set_bias_level(struct snd_soc_component *component, - enum snd_soc_bias_level level) -{ - struct tas2770_priv *tas2770 = - snd_soc_component_get_drvdata(component); - - switch (level) { - case SND_SOC_BIAS_ON: - snd_soc_component_update_bits(component, TAS2770_PWR_CTRL, - TAS2770_PWR_CTRL_MASK, - TAS2770_PWR_CTRL_ACTIVE); - break; - case SND_SOC_BIAS_STANDBY: - case SND_SOC_BIAS_PREPARE: - snd_soc_component_update_bits(component, TAS2770_PWR_CTRL, - TAS2770_PWR_CTRL_MASK, - TAS2770_PWR_CTRL_MUTE); - break; - case SND_SOC_BIAS_OFF: - snd_soc_component_update_bits(component, TAS2770_PWR_CTRL, - TAS2770_PWR_CTRL_MASK, - TAS2770_PWR_CTRL_SHUTDOWN); - break; - - default: - dev_err(tas2770->dev, "wrong power level setting %d\n", level); - return -EINVAL; - } - - return 0; -} - #ifdef CONFIG_PM static int tas2770_codec_suspend(struct snd_soc_component *component) { @@ -555,7 +523,6 @@ static const struct snd_soc_component_driver soc_component_driver_tas2770 = { .probe = tas2770_codec_probe, .suspend = tas2770_codec_suspend, .resume = tas2770_codec_resume, - .set_bias_level = tas2770_set_bias_level, .controls = tas2770_snd_controls, .num_controls = ARRAY_SIZE(tas2770_snd_controls), .dapm_widgets = tas2770_dapm_widgets, From 1e5907bcb3a3b569be0a03ebe668bba2ed320a50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Mon, 8 Aug 2022 16:12:46 +0200 Subject: [PATCH 069/427] ASoC: tas2770: Fix handling of mute/unmute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because the PWR_CTRL field is modeled as the power state of the DAC widget, and at the same time it is used to implement mute/unmute, we need some additional book-keeping to have the right end result no matter the sequence of calls. Without this fix, one can mute an ongoing stream by toggling a speaker pin control. Fixes: 1a476abc723e ("tas2770: add tas2770 smart PA kernel driver") Signed-off-by: Martin Povišer Link: https://lore.kernel.org/r/20220808141246.5749-5-povik+lin@cutebit.org Signed-off-by: Mark Brown --- sound/soc/codecs/tas2770.c | 57 ++++++++++++++++++++------------------ sound/soc/codecs/tas2770.h | 2 ++ 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index fba4aa27caa39..bb653b6641466 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -46,6 +46,26 @@ static void tas2770_reset(struct tas2770_priv *tas2770) usleep_range(1000, 2000); } +static int tas2770_update_pwr_ctrl(struct tas2770_priv *tas2770) +{ + struct snd_soc_component *component = tas2770->component; + unsigned int val; + int ret; + + if (tas2770->dac_powered) + val = tas2770->unmuted ? + TAS2770_PWR_CTRL_ACTIVE : TAS2770_PWR_CTRL_MUTE; + else + val = TAS2770_PWR_CTRL_SHUTDOWN; + + ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL, + TAS2770_PWR_CTRL_MASK, val); + if (ret < 0) + return ret; + + return 0; +} + #ifdef CONFIG_PM static int tas2770_codec_suspend(struct snd_soc_component *component) { @@ -82,9 +102,7 @@ static int tas2770_codec_resume(struct snd_soc_component *component) gpiod_set_value_cansleep(tas2770->sdz_gpio, 1); usleep_range(1000, 2000); } else { - ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL, - TAS2770_PWR_CTRL_MASK, - TAS2770_PWR_CTRL_ACTIVE); + ret = tas2770_update_pwr_ctrl(tas2770); if (ret < 0) return ret; } @@ -120,24 +138,19 @@ static int tas2770_dac_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: - ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL, - TAS2770_PWR_CTRL_MASK, - TAS2770_PWR_CTRL_MUTE); + tas2770->dac_powered = 1; + ret = tas2770_update_pwr_ctrl(tas2770); break; case SND_SOC_DAPM_PRE_PMD: - ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL, - TAS2770_PWR_CTRL_MASK, - TAS2770_PWR_CTRL_SHUTDOWN); + tas2770->dac_powered = 0; + ret = tas2770_update_pwr_ctrl(tas2770); break; default: dev_err(tas2770->dev, "Not supported evevt\n"); return -EINVAL; } - if (ret < 0) - return ret; - - return 0; + return ret; } static const struct snd_kcontrol_new isense_switch = @@ -171,21 +184,11 @@ static const struct snd_soc_dapm_route tas2770_audio_map[] = { static int tas2770_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - int ret; - - if (mute) - ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL, - TAS2770_PWR_CTRL_MASK, - TAS2770_PWR_CTRL_MUTE); - else - ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL, - TAS2770_PWR_CTRL_MASK, - TAS2770_PWR_CTRL_ACTIVE); - - if (ret < 0) - return ret; + struct tas2770_priv *tas2770 = + snd_soc_component_get_drvdata(component); - return 0; + tas2770->unmuted = !mute; + return tas2770_update_pwr_ctrl(tas2770); } static int tas2770_set_bitwidth(struct tas2770_priv *tas2770, int bitwidth) diff --git a/sound/soc/codecs/tas2770.h b/sound/soc/codecs/tas2770.h index d51e88d8c3383..f75f40781ab13 100644 --- a/sound/soc/codecs/tas2770.h +++ b/sound/soc/codecs/tas2770.h @@ -138,6 +138,8 @@ struct tas2770_priv { struct device *dev; int v_sense_slot; int i_sense_slot; + bool dac_powered; + bool unmuted; }; #endif /* __TAS2770__ */ From afb176d45870048eea540991b082208270824037 Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Mon, 8 Aug 2022 13:28:36 +0800 Subject: [PATCH 070/427] ASoC: rt5640: Fix the JD voltage dropping issue The patch fixes the JD voltage dropping issue in the HDA JD using. Signed-off-by: Oder Chiou Reported-by: Mohan Kumar D Link: https://lore.kernel.org/r/20220808052836.25791-1-oder_chiou@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5640.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 38ab8d4291c2d..5a844329800f0 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -1986,7 +1986,7 @@ static int rt5640_set_bias_level(struct snd_soc_component *component, snd_soc_component_write(component, RT5640_PWR_MIXER, 0x0000); if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER) snd_soc_component_write(component, RT5640_PWR_ANLG1, - 0x0018); + 0x2818); else snd_soc_component_write(component, RT5640_PWR_ANLG1, 0x0000); @@ -2600,7 +2600,8 @@ static void rt5640_enable_hda_jack_detect( snd_soc_component_update_bits(component, RT5640_DUMMY1, 0x400, 0x0); snd_soc_component_update_bits(component, RT5640_PWR_ANLG1, - RT5640_PWR_VREF2, RT5640_PWR_VREF2); + RT5640_PWR_VREF2 | RT5640_PWR_MB | RT5640_PWR_BG, + RT5640_PWR_VREF2 | RT5640_PWR_MB | RT5640_PWR_BG); usleep_range(10000, 15000); snd_soc_component_update_bits(component, RT5640_PWR_ANLG1, RT5640_PWR_FV2, RT5640_PWR_FV2); From 7e4fd7a1a6fdf23d069eeb0ae0e8e46b9fb40723 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 8 Aug 2022 11:50:20 +0100 Subject: [PATCH 071/427] irqchip/loongarch: Fix irq_domain_alloc_fwnode() abuse The recently merged LoongArch drivers paper over the lack of topology information by creating a bunch of fwnodes for the irqchips. So far, so good. However, irq_domain_alloc_fwnode() is supposed to take a PA, and not a kernel VA blindly cast as a PA, potentially disclosing kernel VAs to userspace. In some other cases, even NULL is used as the PA, which is entertaining. Fix this by using the actual PA of the block when available, and switch to a named fwnode in the other cases. Signed-off-by: Marc Zyngier Reviewed-by: Jianmin Lv Link: https://lore.kernel.org/r/20220808105020.2689757-1-maz@kernel.org --- drivers/irqchip/irq-loongarch-cpu.c | 2 +- drivers/irqchip/irq-loongson-eiointc.c | 3 ++- drivers/irqchip/irq-loongson-liointc.c | 2 +- drivers/irqchip/irq-loongson-pch-msi.c | 2 +- drivers/irqchip/irq-loongson-pch-pic.c | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-loongarch-cpu.c b/drivers/irqchip/irq-loongarch-cpu.c index 327f3ab62c036..741612ba6a520 100644 --- a/drivers/irqchip/irq-loongarch-cpu.c +++ b/drivers/irqchip/irq-loongarch-cpu.c @@ -129,7 +129,7 @@ static int __init cpuintc_acpi_init(union acpi_subtable_headers *header, clear_csr_ecfg(ECFG0_IM); clear_csr_estat(ESTATF_IP); - cpuintc_handle = irq_domain_alloc_fwnode(NULL); + cpuintc_handle = irq_domain_alloc_named_fwnode("CPUINTC"); irq_domain = irq_domain_create_linear(cpuintc_handle, EXCCODE_INT_NUM, &loongarch_cpu_intc_irq_domain_ops, NULL); diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index bffb7b3128e8c..16e9af8d8b1ea 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -348,7 +348,8 @@ int __init eiointc_acpi_init(struct irq_domain *parent, if (!priv) return -ENOMEM; - priv->domain_handle = irq_domain_alloc_fwnode((phys_addr_t *)acpi_eiointc); + priv->domain_handle = irq_domain_alloc_named_id_fwnode("EIOPIC", + acpi_eiointc->node); if (!priv->domain_handle) { pr_err("Unable to allocate domain handle\n"); goto out_free_priv; diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c index c4f3c886ad615..acd1a4b897df0 100644 --- a/drivers/irqchip/irq-loongson-liointc.c +++ b/drivers/irqchip/irq-loongson-liointc.c @@ -360,7 +360,7 @@ int __init liointc_acpi_init(struct irq_domain *parent, struct acpi_madt_lio_pic parent_irq[0] = irq_create_mapping(parent, acpi_liointc->cascade[0]); parent_irq[1] = irq_create_mapping(parent, acpi_liointc->cascade[1]); - domain_handle = irq_domain_alloc_fwnode((phys_addr_t *)acpi_liointc); + domain_handle = irq_domain_alloc_fwnode(&acpi_liointc->address); if (!domain_handle) { pr_err("Unable to allocate domain handle\n"); return -ENOMEM; diff --git a/drivers/irqchip/irq-loongson-pch-msi.c b/drivers/irqchip/irq-loongson-pch-msi.c index d0e8551bebfab..a72ede90ffc69 100644 --- a/drivers/irqchip/irq-loongson-pch-msi.c +++ b/drivers/irqchip/irq-loongson-pch-msi.c @@ -282,7 +282,7 @@ int __init pch_msi_acpi_init(struct irq_domain *parent, int ret; struct fwnode_handle *domain_handle; - domain_handle = irq_domain_alloc_fwnode((phys_addr_t *)acpi_pchmsi); + domain_handle = irq_domain_alloc_fwnode(&acpi_pchmsi->msg_address); ret = pch_msi_init(acpi_pchmsi->msg_address, acpi_pchmsi->start, acpi_pchmsi->count, parent, domain_handle); if (ret < 0) diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c index b987b6517d59b..c01b9c2570053 100644 --- a/drivers/irqchip/irq-loongson-pch-pic.c +++ b/drivers/irqchip/irq-loongson-pch-pic.c @@ -349,7 +349,7 @@ int __init pch_pic_acpi_init(struct irq_domain *parent, vec_base = acpi_pchpic->gsi_base - GSI_MIN_PCH_IRQ; - domain_handle = irq_domain_alloc_fwnode((phys_addr_t *)acpi_pchpic); + domain_handle = irq_domain_alloc_fwnode(&acpi_pchpic->address); if (!domain_handle) { pr_err("Unable to allocate domain handle\n"); return -ENOMEM; From cf4b7387c0a842d64bdd7c353e6d3298174a7740 Mon Sep 17 00:00:00 2001 From: Arunpravin Paneer Selvam Date: Tue, 9 Aug 2022 02:56:23 -0700 Subject: [PATCH 072/427] drm/ttm: Fix dummy res NULL ptr deref bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check the bo->resource value before accessing the resource mem_type. v2: Fix commit description unwrapped warning [ 40.191227][ T184] general protection fault, probably for non-canonical address 0xdffffc0000000002: 0000 [#1] SMP KASAN PTI [ 40.192995][ T184] KASAN: null-ptr-deref in range [0x0000000000000010-0x0000000000000017] [ 40.194411][ T184] CPU: 1 PID: 184 Comm: systemd-udevd Not tainted 5.19.0-rc4-00721-gb297c22b7070 #1 [ 40.196063][ T184] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-debian-1.16.0-4 04/01/2014 [ 40.199605][ T184] RIP: 0010:ttm_bo_validate+0x1b3/0x240 [ttm] [ 40.200754][ T184] Code: e8 72 c5 ff ff 83 f8 b8 74 d4 85 c0 75 54 49 8b 9e 58 01 00 00 48 b8 00 00 00 00 00 fc ff df 48 8d 7b 10 48 89 fa 48 c1 ea 03 <0f> b6 04 02 84 c0 74 04 3c 03 7e 44 8b 53 10 31 c0 85 d2 0f 85 58 [ 40.203685][ T184] RSP: 0018:ffffc900006df0c8 EFLAGS: 00010202 [ 40.204630][ T184] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 1ffff1102f4bb71b [ 40.205864][ T184] RDX: 0000000000000002 RSI: ffffc900006df208 RDI: 0000000000000010 [ 40.207102][ T184] RBP: 1ffff920000dbe1a R08: ffffc900006df208 R09: 0000000000000000 [ 40.208394][ T184] R10: ffff88817a5f0000 R11: 0000000000000001 R12: ffffc900006df110 [ 40.209692][ T184] R13: ffffc900006df0f0 R14: ffff88817a5db800 R15: ffffc900006df208 [ 40.210862][ T184] FS: 00007f6b1d16e8c0(0000) GS:ffff88839d700000(0000) knlGS:0000000000000000 [ 40.212250][ T184] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 40.213275][ T184] CR2: 000055a1001d4ff0 CR3: 00000001700f4000 CR4: 00000000000006e0 [ 40.214469][ T184] Call Trace: [ 40.214974][ T184] [ 40.215438][ T184] ? ttm_bo_bounce_temp_buffer+0x140/0x140 [ttm] [ 40.216572][ T184] ? mutex_spin_on_owner+0x240/0x240 [ 40.217456][ T184] ? drm_vma_offset_add+0xaa/0x100 [drm] [ 40.218457][ T184] ttm_bo_init_reserved+0x3d6/0x540 [ttm] [ 40.219410][ T184] ? shmem_get_inode+0x744/0x980 [ 40.220231][ T184] ttm_bo_init_validate+0xb1/0x200 [ttm] [ 40.221172][ T184] ? bo_driver_evict_flags+0x340/0x340 [drm_vram_helper] [ 40.222530][ T184] ? ttm_bo_init_reserved+0x540/0x540 [ttm] [ 40.223643][ T184] ? __do_sys_finit_module+0x11a/0x1c0 [ 40.224654][ T184] ? __shmem_file_setup+0x102/0x280 [ 40.234764][ T184] drm_gem_vram_create+0x305/0x480 [drm_vram_helper] [ 40.235766][ T184] ? bo_driver_evict_flags+0x340/0x340 [drm_vram_helper] [ 40.236846][ T184] ? __kasan_slab_free+0x108/0x180 [ 40.237650][ T184] drm_gem_vram_fill_create_dumb+0x134/0x340 [drm_vram_helper] [ 40.238864][ T184] ? local_pci_probe+0xdf/0x180 [ 40.239674][ T184] ? drmm_vram_helper_init+0x400/0x400 [drm_vram_helper] [ 40.240826][ T184] drm_client_framebuffer_create+0x19c/0x400 [drm] [ 40.241955][ T184] ? drm_client_buffer_delete+0x200/0x200 [drm] [ 40.243001][ T184] ? drm_client_pick_crtcs+0x554/0xb80 [drm] [ 40.244030][ T184] drm_fb_helper_generic_probe+0x23f/0x940 [drm_kms_helper] [ 40.245226][ T184] ? __cond_resched+0x1c/0xc0 [ 40.245987][ T184] ? drm_fb_helper_memory_range_to_clip+0x180/0x180 [drm_kms_helper] [ 40.247316][ T184] ? mutex_unlock+0x80/0x100 [ 40.248005][ T184] ? __mutex_unlock_slowpath+0x2c0/0x2c0 [ 40.249083][ T184] drm_fb_helper_single_fb_probe+0x907/0xf00 [drm_kms_helper] [ 40.250314][ T184] ? drm_fb_helper_check_var+0x1180/0x1180 [drm_kms_helper] [ 40.251540][ T184] ? __cond_resched+0x1c/0xc0 [ 40.252321][ T184] ? mutex_lock+0x9f/0x100 [ 40.253062][ T184] __drm_fb_helper_initial_config_and_unlock+0xb9/0x2c0 [drm_kms_helper] [ 40.254394][ T184] drm_fbdev_client_hotplug+0x56f/0x840 [drm_kms_helper] [ 40.255477][ T184] drm_fbdev_generic_setup+0x165/0x3c0 [drm_kms_helper] [ 40.256607][ T184] bochs_pci_probe+0x6b7/0x900 [bochs] [ 40.257515][ T184] ? _raw_spin_lock_irqsave+0x87/0x100 [ 40.258312][ T184] ? bochs_hw_init+0x480/0x480 [bochs] [ 40.259244][ T184] ? bochs_hw_init+0x480/0x480 [bochs] [ 40.260186][ T184] local_pci_probe+0xdf/0x180 [ 40.260928][ T184] pci_call_probe+0x15f/0x500 [ 40.265798][ T184] ? _raw_spin_lock+0x81/0x100 [ 40.266508][ T184] ? pci_pm_suspend_noirq+0x980/0x980 [ 40.267322][ T184] ? pci_assign_irq+0x81/0x280 [ 40.268096][ T184] ? pci_match_device+0x351/0x6c0 [ 40.268883][ T184] ? kernfs_put+0x18/0x40 [ 40.269611][ T184] pci_device_probe+0xee/0x240 [ 40.270352][ T184] really_probe+0x435/0xa80 [ 40.271021][ T184] __driver_probe_device+0x2ab/0x480 [ 40.271828][ T184] driver_probe_device+0x49/0x140 [ 40.272627][ T184] __driver_attach+0x1bd/0x4c0 [ 40.273372][ T184] ? __device_attach_driver+0x240/0x240 [ 40.274273][ T184] bus_for_each_dev+0x11e/0x1c0 [ 40.275080][ T184] ? subsys_dev_iter_exit+0x40/0x40 [ 40.275951][ T184] ? klist_add_tail+0x132/0x280 [ 40.276767][ T184] bus_add_driver+0x39b/0x580 [ 40.277574][ T184] driver_register+0x20f/0x3c0 [ 40.278281][ T184] ? 0xffffffffc04a2000 [ 40.278894][ T184] do_one_initcall+0x8a/0x300 [ 40.279642][ T184] ? trace_event_raw_event_initcall_level+0x1c0/0x1c0 [ 40.280707][ T184] ? kasan_unpoison+0x23/0x80 [ 40.281479][ T184] ? kasan_unpoison+0x23/0x80 [ 40.282197][ T184] do_init_module+0x190/0x640 [ 40.282926][ T184] load_module+0x221b/0x2780 [ 40.283611][ T184] ? layout_and_allocate+0x5c0/0x5c0 [ 40.284401][ T184] ? kernel_read_file+0x286/0x6c0 [ 40.285216][ T184] ? __x64_sys_fspick+0x2c0/0x2c0 [ 40.286043][ T184] ? mmap_region+0x4e7/0x1300 [ 40.286832][ T184] ? __do_sys_finit_module+0x11a/0x1c0 [ 40.287743][ T184] __do_sys_finit_module+0x11a/0x1c0 [ 40.288636][ T184] ? __ia32_sys_init_module+0xc0/0xc0 [ 40.289557][ T184] ? __seccomp_filter+0x15e/0xc80 [ 40.290341][ T184] ? vm_mmap_pgoff+0x185/0x240 [ 40.291060][ T184] do_syscall_64+0x3b/0xc0 [ 40.291763][ T184] entry_SYSCALL_64_after_hwframe+0x46/0xb0 [ 40.292678][ T184] RIP: 0033:0x7f6b1d6279b9 [ 40.293438][ T184] Code: 00 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d a7 54 0c 00 f7 d8 64 89 01 48 [ 40.296302][ T184] RSP: 002b:00007ffe7f51b798 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 [ 40.297633][ T184] RAX: ffffffffffffffda RBX: 00005642dcca2880 RCX: 00007f6b1d6279b9 [ 40.298890][ T184] RDX: 0000000000000000 RSI: 00007f6b1d7b2e2d RDI: 0000000000000016 [ 40.300199][ T184] RBP: 0000000000020000 R08: 0000000000000000 R09: 00005642dccd5530 [ 40.301547][ T184] R10: 0000000000000016 R11: 0000000000000246 R12: 00007f6b1d7b2e2d [ 40.302698][ T184] R13: 0000000000000000 R14: 00005642dcca4230 R15: 00005642dcca2880 Signed-off-by: Arunpravin Paneer Selvam Reported-by: kernel test robot Reviewed-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20220726162205.2778-1-Arunpravin.PaneerSelvam@amd.com Link: https://patchwork.freedesktop.org/patch/msgid/20220809095623.3569-1-Arunpravin.PaneerSelvam@amd.com Signed-off-by: Christian König CC: stable@vger.kernel.org --- drivers/gpu/drm/ttm/ttm_bo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 406e9c324e76a..5bf7124ece96d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -918,7 +918,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, /* * We might need to add a TTM. */ - if (bo->resource->mem_type == TTM_PL_SYSTEM) { + if (!bo->resource || bo->resource->mem_type == TTM_PL_SYSTEM) { ret = ttm_tt_create(bo, true); if (ret) return ret; From ae3b1da95413614f96ffa23d200929c6f809c807 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Wed, 10 Aug 2022 09:34:35 +0800 Subject: [PATCH 073/427] KVM: arm64: Fix compile error due to sign extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use GENMASK() to generate the masks of device type and device id, fixing compilation errors due to the sign extension when using older versions of GCC (such as is 7.5): In function ‘kvm_vm_ioctl_set_device_addr.isra.38’, inlined from ‘kvm_arch_vm_ioctl’ at arch/arm64/kvm/arm.c:1454:10: ././include/linux/compiler_types.h:354:38: error: call to ‘__compiletime_assert_599’ \ declared with attribute error: FIELD_GET: mask is not constant _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) Fixes: 9f968c9266aa ("KVM: arm64: vgic-v2: Add helper for legacy dist/cpuif base address setting") Signed-off-by: Yang Yingliang [maz: tidy up commit message] Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20220810013435.1525363-1-yangyingliang@huawei.com --- arch/arm64/include/uapi/asm/kvm.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 3bb134355874c..316917b987070 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -75,9 +75,11 @@ struct kvm_regs { /* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */ #define KVM_ARM_DEVICE_TYPE_SHIFT 0 -#define KVM_ARM_DEVICE_TYPE_MASK (0xffff << KVM_ARM_DEVICE_TYPE_SHIFT) +#define KVM_ARM_DEVICE_TYPE_MASK GENMASK(KVM_ARM_DEVICE_TYPE_SHIFT + 15, \ + KVM_ARM_DEVICE_TYPE_SHIFT) #define KVM_ARM_DEVICE_ID_SHIFT 16 -#define KVM_ARM_DEVICE_ID_MASK (0xffff << KVM_ARM_DEVICE_ID_SHIFT) +#define KVM_ARM_DEVICE_ID_MASK GENMASK(KVM_ARM_DEVICE_ID_SHIFT + 15, \ + KVM_ARM_DEVICE_ID_SHIFT) /* Supported device IDs */ #define KVM_ARM_DEVICE_VGIC_V2 0 From b4b5f29a076e52181f63e45a2ad1bc88593072e3 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 10 Aug 2022 12:41:56 +0200 Subject: [PATCH 074/427] ASoC: codec: tlv320aic32x4: fix mono playback via I2S The two commits referenced below break mono playback via I2S DAI because they set BCLK to half the required speed. For PCM transport over I2S, the number of transmitted channels is always 2, even for mono playback. Fixes: dcd79364bff3 ("ASoC: codec: tlv3204: Enable 24 bit audio support") Fixes: 40b37136287b ("ASoC: tlv320aic32x4: Fix bdiv clock rate derivation") Signed-off-by: Philipp Zabel Link: https://lore.kernel.org/r/20220810104156.665452-1-p.zabel@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 4b74805cdd2e5..ffe1828a4b7ed 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -49,6 +49,8 @@ struct aic32x4_priv { struct aic32x4_setup_data *setup; struct device *dev; enum aic32x4_type type; + + unsigned int fmt; }; static int aic32x4_reset_adc(struct snd_soc_dapm_widget *w, @@ -611,6 +613,7 @@ static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai, static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_component *component = codec_dai->component; + struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component); u8 iface_reg_1 = 0; u8 iface_reg_2 = 0; u8 iface_reg_3 = 0; @@ -653,6 +656,8 @@ static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) return -EINVAL; } + aic32x4->fmt = fmt; + snd_soc_component_update_bits(component, AIC32X4_IFACE1, AIC32X4_IFACE1_DATATYPE_MASK | AIC32X4_IFACE1_MASTER_MASK, iface_reg_1); @@ -757,6 +762,10 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component, return -EINVAL; } + /* PCM over I2S is always 2-channel */ + if ((aic32x4->fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) + channels = 2; + madc = DIV_ROUND_UP((32 * adc_resource_class), aosr); max_dosr = (AIC32X4_MAX_DOSR_FREQ / sample_rate / dosr_increment) * dosr_increment; From d511e8a7e850db567cd7f633288aa96a19508e5b Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 9 Aug 2022 14:27:45 -0700 Subject: [PATCH 075/427] regulator: core: Fix missing error return from regulator_bulk_get() In commit 6eabfc018e8d ("regulator: core: Allow specifying an initial load w/ the bulk API") I changed the error handling but had a subtle that caused us to always return no error even if there was an error. Fix it. Fixes: 6eabfc018e8d ("regulator: core: Allow specifying an initial load w/ the bulk API") Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20220809142738.1.I91625242f137c707bb345c51c80c5ecee02eeff3@changeid Signed-off-by: Mark Brown --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 7150b1d0159e5..d8373cb04f903 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -4784,10 +4784,10 @@ int regulator_bulk_get(struct device *dev, int num_consumers, consumers[i].consumer = regulator_get(dev, consumers[i].supply); if (IS_ERR(consumers[i].consumer)) { - consumers[i].consumer = NULL; ret = dev_err_probe(dev, PTR_ERR(consumers[i].consumer), "Failed to get supply '%s'", consumers[i].supply); + consumers[i].consumer = NULL; goto err; } From 3400278328285a8c2f121904496aff5e7b610a01 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 9 Aug 2022 13:22:01 +0200 Subject: [PATCH 076/427] netfilter: nf_tables: use READ_ONCE and WRITE_ONCE for shared generation id access The generation ID is bumped from the commit path while holding the mutex, however, netlink dump operations rely on RCU. This patch also adds missing cb->base_eq initialization in nf_tables_dump_set(). Fixes: 38e029f14a97 ("netfilter: nf_tables: set NLM_F_DUMP_INTR if netlink dumping is stale") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 3cc88998b8795..8b084cd669ab5 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -889,7 +889,7 @@ static int nf_tables_dump_tables(struct sk_buff *skb, rcu_read_lock(); nft_net = nft_pernet(net); - cb->seq = nft_net->base_seq; + cb->seq = READ_ONCE(nft_net->base_seq); list_for_each_entry_rcu(table, &nft_net->tables, list) { if (family != NFPROTO_UNSPEC && family != table->family) @@ -1705,7 +1705,7 @@ static int nf_tables_dump_chains(struct sk_buff *skb, rcu_read_lock(); nft_net = nft_pernet(net); - cb->seq = nft_net->base_seq; + cb->seq = READ_ONCE(nft_net->base_seq); list_for_each_entry_rcu(table, &nft_net->tables, list) { if (family != NFPROTO_UNSPEC && family != table->family) @@ -3149,7 +3149,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb, rcu_read_lock(); nft_net = nft_pernet(net); - cb->seq = nft_net->base_seq; + cb->seq = READ_ONCE(nft_net->base_seq); list_for_each_entry_rcu(table, &nft_net->tables, list) { if (family != NFPROTO_UNSPEC && family != table->family) @@ -4133,7 +4133,7 @@ static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb) rcu_read_lock(); nft_net = nft_pernet(net); - cb->seq = nft_net->base_seq; + cb->seq = READ_ONCE(nft_net->base_seq); list_for_each_entry_rcu(table, &nft_net->tables, list) { if (ctx->family != NFPROTO_UNSPEC && @@ -5061,6 +5061,8 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) rcu_read_lock(); nft_net = nft_pernet(net); + cb->seq = READ_ONCE(nft_net->base_seq); + list_for_each_entry_rcu(table, &nft_net->tables, list) { if (dump_ctx->ctx.family != NFPROTO_UNSPEC && dump_ctx->ctx.family != table->family) @@ -6941,7 +6943,7 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) rcu_read_lock(); nft_net = nft_pernet(net); - cb->seq = nft_net->base_seq; + cb->seq = READ_ONCE(nft_net->base_seq); list_for_each_entry_rcu(table, &nft_net->tables, list) { if (family != NFPROTO_UNSPEC && family != table->family) @@ -7873,7 +7875,7 @@ static int nf_tables_dump_flowtable(struct sk_buff *skb, rcu_read_lock(); nft_net = nft_pernet(net); - cb->seq = nft_net->base_seq; + cb->seq = READ_ONCE(nft_net->base_seq); list_for_each_entry_rcu(table, &nft_net->tables, list) { if (family != NFPROTO_UNSPEC && family != table->family) @@ -8806,6 +8808,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) struct nft_trans_elem *te; struct nft_chain *chain; struct nft_table *table; + unsigned int base_seq; LIST_HEAD(adl); int err; @@ -8855,9 +8858,12 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) * Bump generation counter, invalidate any dump in progress. * Cannot fail after this point. */ - while (++nft_net->base_seq == 0) + base_seq = READ_ONCE(nft_net->base_seq); + while (++base_seq == 0) ; + WRITE_ONCE(nft_net->base_seq, base_seq); + /* step 3. Start new generation, rules_gen_X now in use. */ net->nft.gencursor = nft_gencursor_next(net); From 4963674c2e71fc062f8f089f0f58ffbb5533060b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 9 Aug 2022 13:39:18 +0200 Subject: [PATCH 077/427] netfilter: nf_tables: disallow NFTA_SET_ELEM_KEY_END with NFT_SET_ELEM_INTERVAL_END flag These are mutually exclusive, actually NFTA_SET_ELEM_KEY_END replaces the flag notation. Fixes: 7b225d0b5c6d ("netfilter: nf_tables: add NFTA_SET_ELEM_KEY_END attribute") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 8b084cd669ab5..ac549c5b88c2d 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -5901,6 +5901,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, nla[NFTA_SET_ELEM_EXPIRATION] || nla[NFTA_SET_ELEM_USERDATA] || nla[NFTA_SET_ELEM_EXPR] || + nla[NFTA_SET_ELEM_KEY_END] || nla[NFTA_SET_ELEM_EXPRESSIONS])) return -EINVAL; From c485c35ff6783ccd12c160fcac6a0e504e83e0bf Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 9 Aug 2022 17:23:52 +0200 Subject: [PATCH 078/427] netfilter: nf_tables: possible module reference underflow in error path dst->ops is set on when nft_expr_clone() fails, but module refcount has not been bumped yet, therefore nft_expr_destroy() leads to module reference underflow. Fixes: 8cfd9b0f8515 ("netfilter: nftables: generalize set expressions support") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index ac549c5b88c2d..989c9782ecc34 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -5601,7 +5601,7 @@ int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set, err = nft_expr_clone(expr, set->exprs[i]); if (err < 0) { - nft_expr_destroy(ctx, expr); + kfree(expr); goto err_expr; } expr_array[i] = expr; From f1432cd24c240cedf78c0d026631e3b10052c8e1 Mon Sep 17 00:00:00 2001 From: Alexandre Vicenzi Date: Mon, 8 Aug 2022 20:03:43 +0200 Subject: [PATCH 079/427] rtla: Fix tracer name The correct tracer name is timerlat and not timelat. Link: https://lore.kernel.org/linux-trace-devel/20220808180343.22262-1-alexandre.vicenzi@suse.com Signed-off-by: Alexandre Vicenzi Signed-off-by: Steven Rostedt (Google) --- Documentation/tools/rtla/rtla-timerlat-hist.rst | 2 +- tools/tracing/rtla/src/timerlat_hist.c | 2 +- tools/tracing/rtla/src/timerlat_top.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/tools/rtla/rtla-timerlat-hist.rst b/Documentation/tools/rtla/rtla-timerlat-hist.rst index e12eae1f33019..6bf7f0ca45564 100644 --- a/Documentation/tools/rtla/rtla-timerlat-hist.rst +++ b/Documentation/tools/rtla/rtla-timerlat-hist.rst @@ -33,7 +33,7 @@ EXAMPLE ======= In the example below, **rtla timerlat hist** is set to run for *10* minutes, in the cpus *0-4*, *skipping zero* only lines. Moreover, **rtla timerlat -hist** will change the priority of the *timelat* threads to run under +hist** will change the priority of the *timerlat* threads to run under *SCHED_DEADLINE* priority, with a *10us* runtime every *1ms* period. The *1ms* period is also passed to the *timerlat* tracer:: diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c index f3ec628f5e519..4b48af8a83096 100644 --- a/tools/tracing/rtla/src/timerlat_hist.c +++ b/tools/tracing/rtla/src/timerlat_hist.c @@ -892,7 +892,7 @@ int timerlat_hist_main(int argc, char *argv[]) return_value = 0; if (trace_is_off(&tool->trace, &record->trace)) { - printf("rtla timelat hit stop tracing\n"); + printf("rtla timerlat hit stop tracing\n"); if (params->trace_output) { printf(" Saving trace to %s\n", params->trace_output); save_trace_to_file(record->trace.inst, params->trace_output); diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c index 35452a1d45e9f..3342719352222 100644 --- a/tools/tracing/rtla/src/timerlat_top.c +++ b/tools/tracing/rtla/src/timerlat_top.c @@ -687,7 +687,7 @@ int timerlat_top_main(int argc, char *argv[]) return_value = 0; if (trace_is_off(&top->trace, &record->trace)) { - printf("rtla timelat hit stop tracing\n"); + printf("rtla timerlat hit stop tracing\n"); if (params->trace_output) { printf(" Saving trace to %s\n", params->trace_output); save_trace_to_file(record->trace.inst, params->trace_output); From ff5a55dcdb343e3db9b9fb08795b78544b032773 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 16 Jul 2022 15:47:08 +0200 Subject: [PATCH 080/427] tools/rtla: Fix command symlinks "ln -s" stores the next argument directly as the symlink target, so it needs to be a relative path. In this case, just "rtla". Link: https://lore.kernel.org/linux-trace-devel/YtLBXMI6Ui4HLIF1@decadent.org.uk Fixes: 0605bf009f18 ("rtla: Add osnoise tool") Fixes: a828cd18bc4a ("rtla: Add timerlat tool and timelart top mode") Signed-off-by: Ben Hutchings Acked-by: Daniel Bristot de Oliveira Signed-off-by: Steven Rostedt (Google) --- tools/tracing/rtla/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/tracing/rtla/Makefile b/tools/tracing/rtla/Makefile index 1bea2d16d4c11..b8fe10d941ce3 100644 --- a/tools/tracing/rtla/Makefile +++ b/tools/tracing/rtla/Makefile @@ -108,9 +108,9 @@ install: doc_install $(INSTALL) rtla -m 755 $(DESTDIR)$(BINDIR) $(STRIP) $(DESTDIR)$(BINDIR)/rtla @test ! -f $(DESTDIR)$(BINDIR)/osnoise || rm $(DESTDIR)$(BINDIR)/osnoise - ln -s $(DESTDIR)$(BINDIR)/rtla $(DESTDIR)$(BINDIR)/osnoise + ln -s rtla $(DESTDIR)$(BINDIR)/osnoise @test ! -f $(DESTDIR)$(BINDIR)/timerlat || rm $(DESTDIR)$(BINDIR)/timerlat - ln -s $(DESTDIR)$(BINDIR)/rtla $(DESTDIR)$(BINDIR)/timerlat + ln -s rtla $(DESTDIR)$(BINDIR)/timerlat .PHONY: clean tarball clean: doc_clean From 1a7b22ab15ebf643e10e54ae5387afee06e39ad0 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 16 Jul 2022 15:48:34 +0200 Subject: [PATCH 081/427] tools/rtla: Build with EXTRA_{C,LD}FLAGS To allow for distributions and other builders to apply hardening policy and other customisation, append EXTRA_CFLAGS and EXTRA_LDFLAGS to the corresponding variables. Link: https://lore.kernel.org/linux-trace-devel/YtLBshz0nMQ7530H@decadent.org.uk Signed-off-by: Ben Hutchings Acked-by: Daniel Bristot de Oliveira Signed-off-by: Steven Rostedt (Google) --- tools/tracing/rtla/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/tracing/rtla/Makefile b/tools/tracing/rtla/Makefile index b8fe10d941ce3..f392708c7a1e4 100644 --- a/tools/tracing/rtla/Makefile +++ b/tools/tracing/rtla/Makefile @@ -30,8 +30,8 @@ WOPTS := -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_A TRACEFS_HEADERS := $$($(PKG_CONFIG) --cflags libtracefs) -CFLAGS := -O -g -DVERSION=\"$(VERSION)\" $(FOPTS) $(MOPTS) $(WOPTS) $(TRACEFS_HEADERS) -LDFLAGS := -ggdb +CFLAGS := -O -g -DVERSION=\"$(VERSION)\" $(FOPTS) $(MOPTS) $(WOPTS) $(TRACEFS_HEADERS) $(EXTRA_CFLAGS) +LDFLAGS := -ggdb $(EXTRA_LDFLAGS) LIBS := $$($(PKG_CONFIG) --libs libtracefs) SRC := $(wildcard src/*.c) From 20aec89aac7761e3c096004f5c819aacc86fc542 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Wed, 10 Aug 2022 11:39:18 -0400 Subject: [PATCH 082/427] rtla: Consolidate and show all necessary libraries that failed for building When building rtla tools, if the necessary libraries are not installed (libtraceevent and libtracefs), show the ones that are missing in one consolidated output, and also show how to install them (at least for Fedora). Link: https://lore.kernel.org/all/CAHk-=wh+e1qcCnEYJ3JRDVLNCYbJ=0u+Ts5bOYZnY3mX_k-hFA@mail.gmail.com/ Link: https://lkml.kernel.org/r/20220810113918.5d19ce59@gandalf.local.home Suggested-by: Linus Torvalds Signed-off-by: Steven Rostedt (Google) --- tools/tracing/rtla/Makefile | 62 +++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/tools/tracing/rtla/Makefile b/tools/tracing/rtla/Makefile index f392708c7a1e4..22e28b76f8004 100644 --- a/tools/tracing/rtla/Makefile +++ b/tools/tracing/rtla/Makefile @@ -61,40 +61,50 @@ endif LIBTRACEEVENT_MIN_VERSION = 1.5 LIBTRACEFS_MIN_VERSION = 1.3 +.PHONY: all warnings show_warnings +all: warnings rtla + TEST_LIBTRACEEVENT = $(shell sh -c "$(PKG_CONFIG) --atleast-version $(LIBTRACEEVENT_MIN_VERSION) libtraceevent > /dev/null 2>&1 || echo n") ifeq ("$(TEST_LIBTRACEEVENT)", "n") -.PHONY: warning_traceevent -warning_traceevent: - @echo "********************************************" - @echo "** NOTICE: libtraceevent version $(LIBTRACEEVENT_MIN_VERSION) or higher not found" - @echo "**" - @echo "** Consider installing the latest libtraceevent from your" - @echo "** distribution, e.g., 'dnf install libtraceevent' on Fedora," - @echo "** or from source:" - @echo "**" - @echo "** https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ " - @echo "**" - @echo "********************************************" +WARNINGS = show_warnings +MISSING_LIBS += echo "** libtraceevent version $(LIBTRACEEVENT_MIN_VERSION) or higher"; +MISSING_PACKAGES += "libtraceevent-devel" +MISSING_SOURCE += echo "** https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ "; endif TEST_LIBTRACEFS = $(shell sh -c "$(PKG_CONFIG) --atleast-version $(LIBTRACEFS_MIN_VERSION) libtracefs > /dev/null 2>&1 || echo n") ifeq ("$(TEST_LIBTRACEFS)", "n") -.PHONY: warning_tracefs -warning_tracefs: - @echo "********************************************" - @echo "** NOTICE: libtracefs version $(LIBTRACEFS_MIN_VERSION) or higher not found" - @echo "**" - @echo "** Consider installing the latest libtracefs from your" - @echo "** distribution, e.g., 'dnf install libtracefs' on Fedora," - @echo "** or from source:" - @echo "**" - @echo "** https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/ " - @echo "**" - @echo "********************************************" +WARNINGS = show_warnings +MISSING_LIBS += echo "** libtracefs version $(LIBTRACEFS_MIN_VERSION) or higher"; +MISSING_PACKAGES += "libtracefs-devel" +MISSING_SOURCE += echo "** https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/ "; endif -.PHONY: all -all: rtla +define show_dependencies + @echo "********************************************"; \ + echo "** NOTICE: Failed build dependencies"; \ + echo "**"; \ + echo "** Required Libraries:"; \ + $(MISSING_LIBS) \ + echo "**"; \ + echo "** Consider installing the latest libtracefs from your"; \ + echo "** distribution, e.g., 'dnf install $(MISSING_PACKAGES)' on Fedora,"; \ + echo "** or from source:"; \ + echo "**"; \ + $(MISSING_SOURCE) \ + echo "**"; \ + echo "********************************************" +endef + +show_warnings: + $(call show_dependencies); + +ifneq ("$(WARNINGS)", "") +ERROR_OUT = $(error Please add the necessary dependencies) + +warnings: $(WARNINGS) + $(ERROR_OUT) +endif rtla: $(OBJ) $(CC) -o rtla $(LDFLAGS) $(OBJ) $(LIBS) From 96964352e21962f5e51ecad87527ae9b6fec9670 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Thu, 21 Jul 2022 11:18:41 +0800 Subject: [PATCH 083/427] fs/ntfs3: Remove unused function wnd_bits Since the function wnd_bits is defined but not called in any file, it is a useless function, and we delete it in view of the brevity of the code. Remove some warnings found by running scripts/kernel-doc, which is caused by using 'make W=1'. fs/ntfs3/bitmap.c:54:19: warning: unused function 'wnd_bits' [-Wunused-function]. Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Signed-off-by: Konstantin Komarov --- fs/ntfs3/bitmap.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/fs/ntfs3/bitmap.c b/fs/ntfs3/bitmap.c index bb9ebb160227b..5d44ceac855b7 100644 --- a/fs/ntfs3/bitmap.c +++ b/fs/ntfs3/bitmap.c @@ -51,11 +51,6 @@ void ntfs3_exit_bitmap(void) kmem_cache_destroy(ntfs_enode_cachep); } -static inline u32 wnd_bits(const struct wnd_bitmap *wnd, size_t i) -{ - return i + 1 == wnd->nwnd ? wnd->bits_last : wnd->sb->s_blocksize * 8; -} - /* * wnd_scan * From d4073595d0c61463ec3a87411b19e2a90f76d3f8 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 8 Aug 2022 11:34:41 +0300 Subject: [PATCH 084/427] fs/ntfs3: uninitialized variable in ntfs_set_acl_ex() The goto out calls kfree(value) on an uninitialized pointer. Just return directly as the other error paths do. Fixes: 460bbf2990b3 ("fs/ntfs3: Do not change mode if ntfs_set_ea failed") Signed-off-by: Dan Carpenter Signed-off-by: Konstantin Komarov --- fs/ntfs3/xattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index 02f6a933ee797..5bdff12a1232d 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -568,7 +568,7 @@ static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns, err = posix_acl_update_mode(mnt_userns, inode, &mode, &acl); if (err) - goto out; + return err; } name = XATTR_NAME_POSIX_ACL_ACCESS; name_len = sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1; From 37bc31f0e7da4fbad4664e64d906ae7b9009e550 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Fri, 29 Jul 2022 13:36:31 -0400 Subject: [PATCH 085/427] drm/amd/display: Add a missing register field for HPO DP stream encoder [Why&How] Add the missing definition to set the register field HBLANK_MINIMUM_SYMBOL_WIDTH Signed-off-by: Aurabindo Pillai Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.h index 7c77c71591a08..82c3b3ac1f0d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.h @@ -162,7 +162,8 @@ SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, AIP_ENABLE, mask_sh),\ SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, ACM_ENABLE, mask_sh),\ SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL, CRC_ENABLE, mask_sh),\ - SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL, CRC_CONT_MODE_ENABLE, mask_sh) + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL, CRC_CONT_MODE_ENABLE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_HBLANK_CONTROL, HBLANK_MINIMUM_SYMBOL_WIDTH, mask_sh) #define DCN3_1_HPO_DP_STREAM_ENC_REG_FIELD_LIST(type) \ From efcc970605a4e365151db247361bb013f5c84922 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Wed, 27 Jul 2022 17:55:10 -0400 Subject: [PATCH 086/427] Revert "drm/amd/display: reduce stack for dml32_CalculatePrefetchSchedule" This reverts commit 86e4863e67a9bd1e257f162f3d740ebb61206c91. This commit was a part of a patchset responsible for reducing the stack size. However, after some other changes, this commit becomes unnecessary, so we are reverting it here. Cc: Aurabindo Pillai Reported-by: Stephen Rothwell Reviewed-by: Alex Deucher Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- .../dc/dml/dcn32/display_mode_vba_32.c | 5 +- .../dc/dml/dcn32/display_mode_vba_util_32.c | 394 ++++++++++-------- .../dc/dml/dcn32/display_mode_vba_util_32.h | 1 - .../drm/amd/display/dc/dml/display_mode_vba.h | 38 -- 4 files changed, 211 insertions(+), 227 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index 890612db08dc4..04f1eefdabe80 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -757,9 +757,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.myPipe.BytePerPixelY = v->BytePerPixelY[k]; v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.myPipe.BytePerPixelC = v->BytePerPixelC[k]; v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.myPipe.ProgressiveToInterlaceUnitInOPP = mode_lib->vba.ProgressiveToInterlaceUnitInOPP; - v->ErrorResult[k] = dml32_CalculatePrefetchSchedule( - &v->dummy_vars.dml32_CalculatePrefetchSchedule, - v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.HostVMInefficiencyFactor, + v->ErrorResult[k] = dml32_CalculatePrefetchSchedule(v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.HostVMInefficiencyFactor, &v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.myPipe, v->DSCDelay[k], mode_lib->vba.DPPCLKDelaySubtotal + mode_lib->vba.DPPCLKDelayCNVCFormater, mode_lib->vba.DPPCLKDelaySCL, @@ -3266,7 +3264,6 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.NoTimeForPrefetch[i][j][k] = dml32_CalculatePrefetchSchedule( - &v->dummy_vars.dml32_CalculatePrefetchSchedule, v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.HostVMInefficiencyFactor, &v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.myPipe, mode_lib->vba.DSCDelayPerState[i][k], diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c index 07f8f3b8626b2..54dde0ea424ae 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c @@ -3342,7 +3342,6 @@ double dml32_CalculateExtraLatency( } // CalculateExtraLatency bool dml32_CalculatePrefetchSchedule( - struct dml32_CalculatePrefetchSchedule *st_vars, double HostVMInefficiencyFactor, DmlPipe *myPipe, unsigned int DSCDelay, @@ -3406,18 +3405,45 @@ bool dml32_CalculatePrefetchSchedule( double *VReadyOffsetPix) { bool MyError = false; - - st_vars->TimeForFetchingMetaPTE = 0; - st_vars->TimeForFetchingRowInVBlank = 0; - st_vars->LinesToRequestPrefetchPixelData = 0; - st_vars->max_vratio_pre = __DML_MAX_VRATIO_PRE__; - st_vars->Tsw_est1 = 0; - st_vars->Tsw_est3 = 0; + unsigned int DPPCycles, DISPCLKCycles; + double DSTTotalPixelsAfterScaler; + double LineTime; + double dst_y_prefetch_equ; + double prefetch_bw_oto; + double Tvm_oto; + double Tr0_oto; + double Tvm_oto_lines; + double Tr0_oto_lines; + double dst_y_prefetch_oto; + double TimeForFetchingMetaPTE = 0; + double TimeForFetchingRowInVBlank = 0; + double LinesToRequestPrefetchPixelData = 0; + unsigned int HostVMDynamicLevelsTrips; + double trip_to_mem; + double Tvm_trips; + double Tr0_trips; + double Tvm_trips_rounded; + double Tr0_trips_rounded; + double Lsw_oto; + double Tpre_rounded; + double prefetch_bw_equ; + double Tvm_equ; + double Tr0_equ; + double Tdmbf; + double Tdmec; + double Tdmsks; + double prefetch_sw_bytes; + double bytes_pp; + double dep_bytes; + unsigned int max_vratio_pre = __DML_MAX_VRATIO_PRE__; + double min_Lsw; + double Tsw_est1 = 0; + double Tsw_est3 = 0; if (GPUVMEnable == true && HostVMEnable == true) - st_vars->HostVMDynamicLevelsTrips = HostVMMaxNonCachedPageTableLevels; + HostVMDynamicLevelsTrips = HostVMMaxNonCachedPageTableLevels; else - st_vars->HostVMDynamicLevelsTrips = 0; + HostVMDynamicLevelsTrips = 0; #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: GPUVMEnable = %d\n", __func__, GPUVMEnable); dml_print("DML::%s: GPUVMPageTableLevels = %d\n", __func__, GPUVMPageTableLevels); @@ -3440,19 +3466,19 @@ bool dml32_CalculatePrefetchSchedule( TSetup, /* output */ - &st_vars->Tdmbf, - &st_vars->Tdmec, - &st_vars->Tdmsks, + &Tdmbf, + &Tdmec, + &Tdmsks, VUpdateOffsetPix, VUpdateWidthPix, VReadyOffsetPix); - st_vars->LineTime = myPipe->HTotal / myPipe->PixelClock; - st_vars->trip_to_mem = UrgentLatency; - st_vars->Tvm_trips = UrgentExtraLatency + st_vars->trip_to_mem * (GPUVMPageTableLevels * (st_vars->HostVMDynamicLevelsTrips + 1) - 1); + LineTime = myPipe->HTotal / myPipe->PixelClock; + trip_to_mem = UrgentLatency; + Tvm_trips = UrgentExtraLatency + trip_to_mem * (GPUVMPageTableLevels * (HostVMDynamicLevelsTrips + 1) - 1); if (DynamicMetadataVMEnabled == true) - *Tdmdl = TWait + st_vars->Tvm_trips + st_vars->trip_to_mem; + *Tdmdl = TWait + Tvm_trips + trip_to_mem; else *Tdmdl = TWait + UrgentExtraLatency; @@ -3462,15 +3488,15 @@ bool dml32_CalculatePrefetchSchedule( #endif if (DynamicMetadataEnable == true) { - if (VStartup * st_vars->LineTime < *TSetup + *Tdmdl + st_vars->Tdmbf + st_vars->Tdmec + st_vars->Tdmsks) { + if (VStartup * LineTime < *TSetup + *Tdmdl + Tdmbf + Tdmec + Tdmsks) { *NotEnoughTimeForDynamicMetadata = true; #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: Not Enough Time for Dynamic Meta!\n", __func__); dml_print("DML::%s: Tdmbf: %fus - time for dmd transfer from dchub to dio output buffer\n", - __func__, st_vars->Tdmbf); - dml_print("DML::%s: Tdmec: %fus - time dio takes to transfer dmd\n", __func__, st_vars->Tdmec); + __func__, Tdmbf); + dml_print("DML::%s: Tdmec: %fus - time dio takes to transfer dmd\n", __func__, Tdmec); dml_print("DML::%s: Tdmsks: %fus - time before active dmd must complete transmission at dio\n", - __func__, st_vars->Tdmsks); + __func__, Tdmsks); dml_print("DML::%s: Tdmdl: %fus - time for fabric to become ready and fetch dmd\n", __func__, *Tdmdl); #endif @@ -3482,21 +3508,21 @@ bool dml32_CalculatePrefetchSchedule( } *Tdmdl_vm = (DynamicMetadataEnable == true && DynamicMetadataVMEnabled == true && - GPUVMEnable == true ? TWait + st_vars->Tvm_trips : 0); + GPUVMEnable == true ? TWait + Tvm_trips : 0); if (myPipe->ScalerEnabled) - st_vars->DPPCycles = DPPCLKDelaySubtotalPlusCNVCFormater + DPPCLKDelaySCL; + DPPCycles = DPPCLKDelaySubtotalPlusCNVCFormater + DPPCLKDelaySCL; else - st_vars->DPPCycles = DPPCLKDelaySubtotalPlusCNVCFormater + DPPCLKDelaySCLLBOnly; + DPPCycles = DPPCLKDelaySubtotalPlusCNVCFormater + DPPCLKDelaySCLLBOnly; - st_vars->DPPCycles = st_vars->DPPCycles + myPipe->NumberOfCursors * DPPCLKDelayCNVCCursor; + DPPCycles = DPPCycles + myPipe->NumberOfCursors * DPPCLKDelayCNVCCursor; - st_vars->DISPCLKCycles = DISPCLKDelaySubtotal; + DISPCLKCycles = DISPCLKDelaySubtotal; if (myPipe->Dppclk == 0.0 || myPipe->Dispclk == 0.0) return true; - *DSTXAfterScaler = st_vars->DPPCycles * myPipe->PixelClock / myPipe->Dppclk + st_vars->DISPCLKCycles * + *DSTXAfterScaler = DPPCycles * myPipe->PixelClock / myPipe->Dppclk + DISPCLKCycles * myPipe->PixelClock / myPipe->Dispclk + DSCDelay; *DSTXAfterScaler = *DSTXAfterScaler + (myPipe->ODMMode != dm_odm_combine_mode_disabled ? 18 : 0) @@ -3506,10 +3532,10 @@ bool dml32_CalculatePrefetchSchedule( + ((myPipe->ODMMode == dm_odm_mode_mso_1to4) ? myPipe->HActive * 3 / 4 : 0); #ifdef __DML_VBA_DEBUG__ - dml_print("DML::%s: DPPCycles: %d\n", __func__, st_vars->DPPCycles); + dml_print("DML::%s: DPPCycles: %d\n", __func__, DPPCycles); dml_print("DML::%s: PixelClock: %f\n", __func__, myPipe->PixelClock); dml_print("DML::%s: Dppclk: %f\n", __func__, myPipe->Dppclk); - dml_print("DML::%s: DISPCLKCycles: %d\n", __func__, st_vars->DISPCLKCycles); + dml_print("DML::%s: DISPCLKCycles: %d\n", __func__, DISPCLKCycles); dml_print("DML::%s: DISPCLK: %f\n", __func__, myPipe->Dispclk); dml_print("DML::%s: DSCDelay: %d\n", __func__, DSCDelay); dml_print("DML::%s: ODMMode: %d\n", __func__, myPipe->ODMMode); @@ -3522,9 +3548,9 @@ bool dml32_CalculatePrefetchSchedule( else *DSTYAfterScaler = 0; - st_vars->DSTTotalPixelsAfterScaler = *DSTYAfterScaler * myPipe->HTotal + *DSTXAfterScaler; - *DSTYAfterScaler = dml_floor(st_vars->DSTTotalPixelsAfterScaler / myPipe->HTotal, 1); - *DSTXAfterScaler = st_vars->DSTTotalPixelsAfterScaler - ((double) (*DSTYAfterScaler * myPipe->HTotal)); + DSTTotalPixelsAfterScaler = *DSTYAfterScaler * myPipe->HTotal + *DSTXAfterScaler; + *DSTYAfterScaler = dml_floor(DSTTotalPixelsAfterScaler / myPipe->HTotal, 1); + *DSTXAfterScaler = DSTTotalPixelsAfterScaler - ((double) (*DSTYAfterScaler * myPipe->HTotal)); #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: DSTXAfterScaler: %d (final)\n", __func__, *DSTXAfterScaler); dml_print("DML::%s: DSTYAfterScaler: %d (final)\n", __func__, *DSTYAfterScaler); @@ -3532,132 +3558,132 @@ bool dml32_CalculatePrefetchSchedule( MyError = false; - st_vars->Tr0_trips = st_vars->trip_to_mem * (st_vars->HostVMDynamicLevelsTrips + 1); + Tr0_trips = trip_to_mem * (HostVMDynamicLevelsTrips + 1); if (GPUVMEnable == true) { - st_vars->Tvm_trips_rounded = dml_ceil(4.0 * st_vars->Tvm_trips / st_vars->LineTime, 1.0) / 4.0 * st_vars->LineTime; - st_vars->Tr0_trips_rounded = dml_ceil(4.0 * st_vars->Tr0_trips / st_vars->LineTime, 1.0) / 4.0 * st_vars->LineTime; + Tvm_trips_rounded = dml_ceil(4.0 * Tvm_trips / LineTime, 1.0) / 4.0 * LineTime; + Tr0_trips_rounded = dml_ceil(4.0 * Tr0_trips / LineTime, 1.0) / 4.0 * LineTime; if (GPUVMPageTableLevels >= 3) { - *Tno_bw = UrgentExtraLatency + st_vars->trip_to_mem * - (double) ((GPUVMPageTableLevels - 2) * (st_vars->HostVMDynamicLevelsTrips + 1) - 1); + *Tno_bw = UrgentExtraLatency + trip_to_mem * + (double) ((GPUVMPageTableLevels - 2) * (HostVMDynamicLevelsTrips + 1) - 1); } else if (GPUVMPageTableLevels == 1 && myPipe->DCCEnable != true) { - st_vars->Tr0_trips_rounded = dml_ceil(4.0 * UrgentExtraLatency / st_vars->LineTime, 1.0) / - 4.0 * st_vars->LineTime; // VBA_ERROR + Tr0_trips_rounded = dml_ceil(4.0 * UrgentExtraLatency / LineTime, 1.0) / + 4.0 * LineTime; // VBA_ERROR *Tno_bw = UrgentExtraLatency; } else { *Tno_bw = 0; } } else if (myPipe->DCCEnable == true) { - st_vars->Tvm_trips_rounded = st_vars->LineTime / 4.0; - st_vars->Tr0_trips_rounded = dml_ceil(4.0 * st_vars->Tr0_trips / st_vars->LineTime, 1.0) / 4.0 * st_vars->LineTime; + Tvm_trips_rounded = LineTime / 4.0; + Tr0_trips_rounded = dml_ceil(4.0 * Tr0_trips / LineTime, 1.0) / 4.0 * LineTime; *Tno_bw = 0; } else { - st_vars->Tvm_trips_rounded = st_vars->LineTime / 4.0; - st_vars->Tr0_trips_rounded = st_vars->LineTime / 2.0; + Tvm_trips_rounded = LineTime / 4.0; + Tr0_trips_rounded = LineTime / 2.0; *Tno_bw = 0; } - st_vars->Tvm_trips_rounded = dml_max(st_vars->Tvm_trips_rounded, st_vars->LineTime / 4.0); - st_vars->Tr0_trips_rounded = dml_max(st_vars->Tr0_trips_rounded, st_vars->LineTime / 4.0); + Tvm_trips_rounded = dml_max(Tvm_trips_rounded, LineTime / 4.0); + Tr0_trips_rounded = dml_max(Tr0_trips_rounded, LineTime / 4.0); if (myPipe->SourcePixelFormat == dm_420_8 || myPipe->SourcePixelFormat == dm_420_10 || myPipe->SourcePixelFormat == dm_420_12) { - st_vars->bytes_pp = myPipe->BytePerPixelY + myPipe->BytePerPixelC / 4; + bytes_pp = myPipe->BytePerPixelY + myPipe->BytePerPixelC / 4; } else { - st_vars->bytes_pp = myPipe->BytePerPixelY + myPipe->BytePerPixelC; + bytes_pp = myPipe->BytePerPixelY + myPipe->BytePerPixelC; } - st_vars->prefetch_sw_bytes = PrefetchSourceLinesY * swath_width_luma_ub * myPipe->BytePerPixelY + prefetch_sw_bytes = PrefetchSourceLinesY * swath_width_luma_ub * myPipe->BytePerPixelY + PrefetchSourceLinesC * swath_width_chroma_ub * myPipe->BytePerPixelC; - st_vars->prefetch_bw_oto = dml_max(st_vars->bytes_pp * myPipe->PixelClock / myPipe->DPPPerSurface, - st_vars->prefetch_sw_bytes / (dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * st_vars->LineTime)); + prefetch_bw_oto = dml_max(bytes_pp * myPipe->PixelClock / myPipe->DPPPerSurface, + prefetch_sw_bytes / (dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime)); - st_vars->min_Lsw = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) / st_vars->max_vratio_pre; - st_vars->min_Lsw = dml_max(st_vars->min_Lsw, 1.0); - st_vars->Lsw_oto = dml_ceil(4.0 * dml_max(st_vars->prefetch_sw_bytes / st_vars->prefetch_bw_oto / st_vars->LineTime, st_vars->min_Lsw), 1.0) / 4.0; + min_Lsw = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) / max_vratio_pre; + min_Lsw = dml_max(min_Lsw, 1.0); + Lsw_oto = dml_ceil(4.0 * dml_max(prefetch_sw_bytes / prefetch_bw_oto / LineTime, min_Lsw), 1.0) / 4.0; if (GPUVMEnable == true) { - st_vars->Tvm_oto = dml_max3( - st_vars->Tvm_trips, - *Tno_bw + PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor / st_vars->prefetch_bw_oto, - st_vars->LineTime / 4.0); + Tvm_oto = dml_max3( + Tvm_trips, + *Tno_bw + PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor / prefetch_bw_oto, + LineTime / 4.0); } else - st_vars->Tvm_oto = st_vars->LineTime / 4.0; + Tvm_oto = LineTime / 4.0; if ((GPUVMEnable == true || myPipe->DCCEnable == true)) { - st_vars->Tr0_oto = dml_max4( - st_vars->Tr0_trips, - (MetaRowByte + PixelPTEBytesPerRow * HostVMInefficiencyFactor) / st_vars->prefetch_bw_oto, - (st_vars->LineTime - st_vars->Tvm_oto)/2.0, - st_vars->LineTime / 4.0); + Tr0_oto = dml_max4( + Tr0_trips, + (MetaRowByte + PixelPTEBytesPerRow * HostVMInefficiencyFactor) / prefetch_bw_oto, + (LineTime - Tvm_oto)/2.0, + LineTime / 4.0); #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: Tr0_oto max0 = %f\n", __func__, - (MetaRowByte + PixelPTEBytesPerRow * HostVMInefficiencyFactor) / st_vars->prefetch_bw_oto); - dml_print("DML::%s: Tr0_oto max1 = %f\n", __func__, st_vars->Tr0_trips); - dml_print("DML::%s: Tr0_oto max2 = %f\n", __func__, st_vars->LineTime - st_vars->Tvm_oto); - dml_print("DML::%s: Tr0_oto max3 = %f\n", __func__, st_vars->LineTime / 4); + (MetaRowByte + PixelPTEBytesPerRow * HostVMInefficiencyFactor) / prefetch_bw_oto); + dml_print("DML::%s: Tr0_oto max1 = %f\n", __func__, Tr0_trips); + dml_print("DML::%s: Tr0_oto max2 = %f\n", __func__, LineTime - Tvm_oto); + dml_print("DML::%s: Tr0_oto max3 = %f\n", __func__, LineTime / 4); #endif } else - st_vars->Tr0_oto = (st_vars->LineTime - st_vars->Tvm_oto) / 2.0; + Tr0_oto = (LineTime - Tvm_oto) / 2.0; - st_vars->Tvm_oto_lines = dml_ceil(4.0 * st_vars->Tvm_oto / st_vars->LineTime, 1) / 4.0; - st_vars->Tr0_oto_lines = dml_ceil(4.0 * st_vars->Tr0_oto / st_vars->LineTime, 1) / 4.0; - st_vars->dst_y_prefetch_oto = st_vars->Tvm_oto_lines + 2 * st_vars->Tr0_oto_lines + st_vars->Lsw_oto; + Tvm_oto_lines = dml_ceil(4.0 * Tvm_oto / LineTime, 1) / 4.0; + Tr0_oto_lines = dml_ceil(4.0 * Tr0_oto / LineTime, 1) / 4.0; + dst_y_prefetch_oto = Tvm_oto_lines + 2 * Tr0_oto_lines + Lsw_oto; - st_vars->dst_y_prefetch_equ = VStartup - (*TSetup + dml_max(TWait + TCalc, *Tdmdl)) / st_vars->LineTime - + dst_y_prefetch_equ = VStartup - (*TSetup + dml_max(TWait + TCalc, *Tdmdl)) / LineTime - (*DSTYAfterScaler + (double) *DSTXAfterScaler / (double) myPipe->HTotal); #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: HTotal = %d\n", __func__, myPipe->HTotal); - dml_print("DML::%s: min_Lsw = %f\n", __func__, st_vars->min_Lsw); + dml_print("DML::%s: min_Lsw = %f\n", __func__, min_Lsw); dml_print("DML::%s: *Tno_bw = %f\n", __func__, *Tno_bw); dml_print("DML::%s: UrgentExtraLatency = %f\n", __func__, UrgentExtraLatency); - dml_print("DML::%s: trip_to_mem = %f\n", __func__, st_vars->trip_to_mem); + dml_print("DML::%s: trip_to_mem = %f\n", __func__, trip_to_mem); dml_print("DML::%s: BytePerPixelY = %d\n", __func__, myPipe->BytePerPixelY); dml_print("DML::%s: PrefetchSourceLinesY = %f\n", __func__, PrefetchSourceLinesY); dml_print("DML::%s: swath_width_luma_ub = %d\n", __func__, swath_width_luma_ub); dml_print("DML::%s: BytePerPixelC = %d\n", __func__, myPipe->BytePerPixelC); dml_print("DML::%s: PrefetchSourceLinesC = %f\n", __func__, PrefetchSourceLinesC); dml_print("DML::%s: swath_width_chroma_ub = %d\n", __func__, swath_width_chroma_ub); - dml_print("DML::%s: prefetch_sw_bytes = %f\n", __func__, st_vars->prefetch_sw_bytes); - dml_print("DML::%s: bytes_pp = %f\n", __func__, st_vars->bytes_pp); + dml_print("DML::%s: prefetch_sw_bytes = %f\n", __func__, prefetch_sw_bytes); + dml_print("DML::%s: bytes_pp = %f\n", __func__, bytes_pp); dml_print("DML::%s: PDEAndMetaPTEBytesFrame = %d\n", __func__, PDEAndMetaPTEBytesFrame); dml_print("DML::%s: MetaRowByte = %d\n", __func__, MetaRowByte); dml_print("DML::%s: PixelPTEBytesPerRow = %d\n", __func__, PixelPTEBytesPerRow); dml_print("DML::%s: HostVMInefficiencyFactor = %f\n", __func__, HostVMInefficiencyFactor); - dml_print("DML::%s: Tvm_trips = %f\n", __func__, st_vars->Tvm_trips); - dml_print("DML::%s: Tr0_trips = %f\n", __func__, st_vars->Tr0_trips); - dml_print("DML::%s: prefetch_bw_oto = %f\n", __func__, st_vars->prefetch_bw_oto); - dml_print("DML::%s: Tr0_oto = %f\n", __func__, st_vars->Tr0_oto); - dml_print("DML::%s: Tvm_oto = %f\n", __func__, st_vars->Tvm_oto); - dml_print("DML::%s: Tvm_oto_lines = %f\n", __func__, st_vars->Tvm_oto_lines); - dml_print("DML::%s: Tr0_oto_lines = %f\n", __func__, st_vars->Tr0_oto_lines); - dml_print("DML::%s: Lsw_oto = %f\n", __func__, st_vars->Lsw_oto); - dml_print("DML::%s: dst_y_prefetch_oto = %f\n", __func__, st_vars->dst_y_prefetch_oto); - dml_print("DML::%s: dst_y_prefetch_equ = %f\n", __func__, st_vars->dst_y_prefetch_equ); + dml_print("DML::%s: Tvm_trips = %f\n", __func__, Tvm_trips); + dml_print("DML::%s: Tr0_trips = %f\n", __func__, Tr0_trips); + dml_print("DML::%s: prefetch_bw_oto = %f\n", __func__, prefetch_bw_oto); + dml_print("DML::%s: Tr0_oto = %f\n", __func__, Tr0_oto); + dml_print("DML::%s: Tvm_oto = %f\n", __func__, Tvm_oto); + dml_print("DML::%s: Tvm_oto_lines = %f\n", __func__, Tvm_oto_lines); + dml_print("DML::%s: Tr0_oto_lines = %f\n", __func__, Tr0_oto_lines); + dml_print("DML::%s: Lsw_oto = %f\n", __func__, Lsw_oto); + dml_print("DML::%s: dst_y_prefetch_oto = %f\n", __func__, dst_y_prefetch_oto); + dml_print("DML::%s: dst_y_prefetch_equ = %f\n", __func__, dst_y_prefetch_equ); #endif - st_vars->dst_y_prefetch_equ = dml_floor(4.0 * (st_vars->dst_y_prefetch_equ + 0.125), 1) / 4.0; - st_vars->Tpre_rounded = st_vars->dst_y_prefetch_equ * st_vars->LineTime; + dst_y_prefetch_equ = dml_floor(4.0 * (dst_y_prefetch_equ + 0.125), 1) / 4.0; + Tpre_rounded = dst_y_prefetch_equ * LineTime; #ifdef __DML_VBA_DEBUG__ - dml_print("DML::%s: dst_y_prefetch_equ: %f (after round)\n", __func__, st_vars->dst_y_prefetch_equ); - dml_print("DML::%s: LineTime: %f\n", __func__, st_vars->LineTime); + dml_print("DML::%s: dst_y_prefetch_equ: %f (after round)\n", __func__, dst_y_prefetch_equ); + dml_print("DML::%s: LineTime: %f\n", __func__, LineTime); dml_print("DML::%s: VStartup: %d\n", __func__, VStartup); dml_print("DML::%s: Tvstartup: %fus - time between vstartup and first pixel of active\n", - __func__, VStartup * st_vars->LineTime); + __func__, VStartup * LineTime); dml_print("DML::%s: TSetup: %fus - time from vstartup to vready\n", __func__, *TSetup); dml_print("DML::%s: TCalc: %fus - time for calculations in dchub starting at vready\n", __func__, TCalc); - dml_print("DML::%s: Tdmbf: %fus - time for dmd transfer from dchub to dio output buffer\n", __func__, st_vars->Tdmbf); - dml_print("DML::%s: Tdmec: %fus - time dio takes to transfer dmd\n", __func__, st_vars->Tdmec); + dml_print("DML::%s: Tdmbf: %fus - time for dmd transfer from dchub to dio output buffer\n", __func__, Tdmbf); + dml_print("DML::%s: Tdmec: %fus - time dio takes to transfer dmd\n", __func__, Tdmec); dml_print("DML::%s: Tdmdl_vm: %fus - time for vm stages of dmd\n", __func__, *Tdmdl_vm); dml_print("DML::%s: Tdmdl: %fus - time for fabric to become ready and fetch dmd\n", __func__, *Tdmdl); dml_print("DML::%s: DSTYAfterScaler: %d lines - number of lines of pipeline and buffer delay after scaler\n", __func__, *DSTYAfterScaler); #endif - st_vars->dep_bytes = dml_max(PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor, + dep_bytes = dml_max(PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor, MetaRowByte + PixelPTEBytesPerRow * HostVMInefficiencyFactor); - if (st_vars->prefetch_sw_bytes < st_vars->dep_bytes) - st_vars->prefetch_sw_bytes = 2 * st_vars->dep_bytes; + if (prefetch_sw_bytes < dep_bytes) + prefetch_sw_bytes = 2 * dep_bytes; *PrefetchBandwidth = 0; *DestinationLinesToRequestVMInVBlank = 0; @@ -3665,61 +3691,61 @@ bool dml32_CalculatePrefetchSchedule( *VRatioPrefetchY = 0; *VRatioPrefetchC = 0; *RequiredPrefetchPixDataBWLuma = 0; - if (st_vars->dst_y_prefetch_equ > 1) { + if (dst_y_prefetch_equ > 1) { double PrefetchBandwidth1; double PrefetchBandwidth2; double PrefetchBandwidth3; double PrefetchBandwidth4; - if (st_vars->Tpre_rounded - *Tno_bw > 0) { + if (Tpre_rounded - *Tno_bw > 0) { PrefetchBandwidth1 = (PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor + 2 * MetaRowByte + 2 * PixelPTEBytesPerRow * HostVMInefficiencyFactor - + st_vars->prefetch_sw_bytes) / (st_vars->Tpre_rounded - *Tno_bw); - st_vars->Tsw_est1 = st_vars->prefetch_sw_bytes / PrefetchBandwidth1; + + prefetch_sw_bytes) / (Tpre_rounded - *Tno_bw); + Tsw_est1 = prefetch_sw_bytes / PrefetchBandwidth1; } else PrefetchBandwidth1 = 0; - if (VStartup == MaxVStartup && (st_vars->Tsw_est1 / st_vars->LineTime < st_vars->min_Lsw) - && st_vars->Tpre_rounded - st_vars->min_Lsw * st_vars->LineTime - 0.75 * st_vars->LineTime - *Tno_bw > 0) { + if (VStartup == MaxVStartup && (Tsw_est1 / LineTime < min_Lsw) + && Tpre_rounded - min_Lsw * LineTime - 0.75 * LineTime - *Tno_bw > 0) { PrefetchBandwidth1 = (PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor + 2 * MetaRowByte + 2 * PixelPTEBytesPerRow * HostVMInefficiencyFactor) - / (st_vars->Tpre_rounded - st_vars->min_Lsw * st_vars->LineTime - 0.75 * st_vars->LineTime - *Tno_bw); + / (Tpre_rounded - min_Lsw * LineTime - 0.75 * LineTime - *Tno_bw); } - if (st_vars->Tpre_rounded - *Tno_bw - 2 * st_vars->Tr0_trips_rounded > 0) - PrefetchBandwidth2 = (PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor + st_vars->prefetch_sw_bytes) / - (st_vars->Tpre_rounded - *Tno_bw - 2 * st_vars->Tr0_trips_rounded); + if (Tpre_rounded - *Tno_bw - 2 * Tr0_trips_rounded > 0) + PrefetchBandwidth2 = (PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor + prefetch_sw_bytes) / + (Tpre_rounded - *Tno_bw - 2 * Tr0_trips_rounded); else PrefetchBandwidth2 = 0; - if (st_vars->Tpre_rounded - st_vars->Tvm_trips_rounded > 0) { + if (Tpre_rounded - Tvm_trips_rounded > 0) { PrefetchBandwidth3 = (2 * MetaRowByte + 2 * PixelPTEBytesPerRow * HostVMInefficiencyFactor - + st_vars->prefetch_sw_bytes) / (st_vars->Tpre_rounded - st_vars->Tvm_trips_rounded); - st_vars->Tsw_est3 = st_vars->prefetch_sw_bytes / PrefetchBandwidth3; + + prefetch_sw_bytes) / (Tpre_rounded - Tvm_trips_rounded); + Tsw_est3 = prefetch_sw_bytes / PrefetchBandwidth3; } else PrefetchBandwidth3 = 0; if (VStartup == MaxVStartup && - (st_vars->Tsw_est3 / st_vars->LineTime < st_vars->min_Lsw) && st_vars->Tpre_rounded - st_vars->min_Lsw * st_vars->LineTime - 0.75 * - st_vars->LineTime - st_vars->Tvm_trips_rounded > 0) { + (Tsw_est3 / LineTime < min_Lsw) && Tpre_rounded - min_Lsw * LineTime - 0.75 * + LineTime - Tvm_trips_rounded > 0) { PrefetchBandwidth3 = (2 * MetaRowByte + 2 * PixelPTEBytesPerRow * HostVMInefficiencyFactor) - / (st_vars->Tpre_rounded - st_vars->min_Lsw * st_vars->LineTime - 0.75 * st_vars->LineTime - st_vars->Tvm_trips_rounded); + / (Tpre_rounded - min_Lsw * LineTime - 0.75 * LineTime - Tvm_trips_rounded); } - if (st_vars->Tpre_rounded - st_vars->Tvm_trips_rounded - 2 * st_vars->Tr0_trips_rounded > 0) { - PrefetchBandwidth4 = st_vars->prefetch_sw_bytes / - (st_vars->Tpre_rounded - st_vars->Tvm_trips_rounded - 2 * st_vars->Tr0_trips_rounded); + if (Tpre_rounded - Tvm_trips_rounded - 2 * Tr0_trips_rounded > 0) { + PrefetchBandwidth4 = prefetch_sw_bytes / + (Tpre_rounded - Tvm_trips_rounded - 2 * Tr0_trips_rounded); } else { PrefetchBandwidth4 = 0; } #ifdef __DML_VBA_DEBUG__ - dml_print("DML::%s: Tpre_rounded: %f\n", __func__, st_vars->Tpre_rounded); + dml_print("DML::%s: Tpre_rounded: %f\n", __func__, Tpre_rounded); dml_print("DML::%s: Tno_bw: %f\n", __func__, *Tno_bw); - dml_print("DML::%s: Tvm_trips_rounded: %f\n", __func__, st_vars->Tvm_trips_rounded); - dml_print("DML::%s: Tsw_est1: %f\n", __func__, st_vars->Tsw_est1); - dml_print("DML::%s: Tsw_est3: %f\n", __func__, st_vars->Tsw_est3); + dml_print("DML::%s: Tvm_trips_rounded: %f\n", __func__, Tvm_trips_rounded); + dml_print("DML::%s: Tsw_est1: %f\n", __func__, Tsw_est1); + dml_print("DML::%s: Tsw_est3: %f\n", __func__, Tsw_est3); dml_print("DML::%s: PrefetchBandwidth1: %f\n", __func__, PrefetchBandwidth1); dml_print("DML::%s: PrefetchBandwidth2: %f\n", __func__, PrefetchBandwidth2); dml_print("DML::%s: PrefetchBandwidth3: %f\n", __func__, PrefetchBandwidth3); @@ -3732,9 +3758,9 @@ bool dml32_CalculatePrefetchSchedule( if (PrefetchBandwidth1 > 0) { if (*Tno_bw + PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor / PrefetchBandwidth1 - >= st_vars->Tvm_trips_rounded + >= Tvm_trips_rounded && (MetaRowByte + PixelPTEBytesPerRow * HostVMInefficiencyFactor) - / PrefetchBandwidth1 >= st_vars->Tr0_trips_rounded) { + / PrefetchBandwidth1 >= Tr0_trips_rounded) { Case1OK = true; } else { Case1OK = false; @@ -3745,9 +3771,9 @@ bool dml32_CalculatePrefetchSchedule( if (PrefetchBandwidth2 > 0) { if (*Tno_bw + PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor / PrefetchBandwidth2 - >= st_vars->Tvm_trips_rounded + >= Tvm_trips_rounded && (MetaRowByte + PixelPTEBytesPerRow * HostVMInefficiencyFactor) - / PrefetchBandwidth2 < st_vars->Tr0_trips_rounded) { + / PrefetchBandwidth2 < Tr0_trips_rounded) { Case2OK = true; } else { Case2OK = false; @@ -3758,9 +3784,9 @@ bool dml32_CalculatePrefetchSchedule( if (PrefetchBandwidth3 > 0) { if (*Tno_bw + PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor / PrefetchBandwidth3 < - st_vars->Tvm_trips_rounded && (MetaRowByte + PixelPTEBytesPerRow * + Tvm_trips_rounded && (MetaRowByte + PixelPTEBytesPerRow * HostVMInefficiencyFactor) / PrefetchBandwidth3 >= - st_vars->Tr0_trips_rounded) { + Tr0_trips_rounded) { Case3OK = true; } else { Case3OK = false; @@ -3770,80 +3796,80 @@ bool dml32_CalculatePrefetchSchedule( } if (Case1OK) - st_vars->prefetch_bw_equ = PrefetchBandwidth1; + prefetch_bw_equ = PrefetchBandwidth1; else if (Case2OK) - st_vars->prefetch_bw_equ = PrefetchBandwidth2; + prefetch_bw_equ = PrefetchBandwidth2; else if (Case3OK) - st_vars->prefetch_bw_equ = PrefetchBandwidth3; + prefetch_bw_equ = PrefetchBandwidth3; else - st_vars->prefetch_bw_equ = PrefetchBandwidth4; + prefetch_bw_equ = PrefetchBandwidth4; #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: Case1OK: %d\n", __func__, Case1OK); dml_print("DML::%s: Case2OK: %d\n", __func__, Case2OK); dml_print("DML::%s: Case3OK: %d\n", __func__, Case3OK); - dml_print("DML::%s: prefetch_bw_equ: %f\n", __func__, st_vars->prefetch_bw_equ); + dml_print("DML::%s: prefetch_bw_equ: %f\n", __func__, prefetch_bw_equ); #endif - if (st_vars->prefetch_bw_equ > 0) { + if (prefetch_bw_equ > 0) { if (GPUVMEnable == true) { - st_vars->Tvm_equ = dml_max3(*Tno_bw + PDEAndMetaPTEBytesFrame * - HostVMInefficiencyFactor / st_vars->prefetch_bw_equ, - st_vars->Tvm_trips, st_vars->LineTime / 4); + Tvm_equ = dml_max3(*Tno_bw + PDEAndMetaPTEBytesFrame * + HostVMInefficiencyFactor / prefetch_bw_equ, + Tvm_trips, LineTime / 4); } else { - st_vars->Tvm_equ = st_vars->LineTime / 4; + Tvm_equ = LineTime / 4; } if ((GPUVMEnable == true || myPipe->DCCEnable == true)) { - st_vars->Tr0_equ = dml_max4((MetaRowByte + PixelPTEBytesPerRow * - HostVMInefficiencyFactor) / st_vars->prefetch_bw_equ, st_vars->Tr0_trips, - (st_vars->LineTime - st_vars->Tvm_equ) / 2, st_vars->LineTime / 4); + Tr0_equ = dml_max4((MetaRowByte + PixelPTEBytesPerRow * + HostVMInefficiencyFactor) / prefetch_bw_equ, Tr0_trips, + (LineTime - Tvm_equ) / 2, LineTime / 4); } else { - st_vars->Tr0_equ = (st_vars->LineTime - st_vars->Tvm_equ) / 2; + Tr0_equ = (LineTime - Tvm_equ) / 2; } } else { - st_vars->Tvm_equ = 0; - st_vars->Tr0_equ = 0; + Tvm_equ = 0; + Tr0_equ = 0; #ifdef __DML_VBA_DEBUG__ dml_print("DML: prefetch_bw_equ equals 0! %s:%d\n", __FILE__, __LINE__); #endif } } - if (st_vars->dst_y_prefetch_oto < st_vars->dst_y_prefetch_equ) { - *DestinationLinesForPrefetch = st_vars->dst_y_prefetch_oto; - st_vars->TimeForFetchingMetaPTE = st_vars->Tvm_oto; - st_vars->TimeForFetchingRowInVBlank = st_vars->Tr0_oto; - *PrefetchBandwidth = st_vars->prefetch_bw_oto; + if (dst_y_prefetch_oto < dst_y_prefetch_equ) { + *DestinationLinesForPrefetch = dst_y_prefetch_oto; + TimeForFetchingMetaPTE = Tvm_oto; + TimeForFetchingRowInVBlank = Tr0_oto; + *PrefetchBandwidth = prefetch_bw_oto; } else { - *DestinationLinesForPrefetch = st_vars->dst_y_prefetch_equ; - st_vars->TimeForFetchingMetaPTE = st_vars->Tvm_equ; - st_vars->TimeForFetchingRowInVBlank = st_vars->Tr0_equ; - *PrefetchBandwidth = st_vars->prefetch_bw_equ; + *DestinationLinesForPrefetch = dst_y_prefetch_equ; + TimeForFetchingMetaPTE = Tvm_equ; + TimeForFetchingRowInVBlank = Tr0_equ; + *PrefetchBandwidth = prefetch_bw_equ; } - *DestinationLinesToRequestVMInVBlank = dml_ceil(4.0 * st_vars->TimeForFetchingMetaPTE / st_vars->LineTime, 1.0) / 4.0; + *DestinationLinesToRequestVMInVBlank = dml_ceil(4.0 * TimeForFetchingMetaPTE / LineTime, 1.0) / 4.0; *DestinationLinesToRequestRowInVBlank = - dml_ceil(4.0 * st_vars->TimeForFetchingRowInVBlank / st_vars->LineTime, 1.0) / 4.0; + dml_ceil(4.0 * TimeForFetchingRowInVBlank / LineTime, 1.0) / 4.0; - st_vars->LinesToRequestPrefetchPixelData = *DestinationLinesForPrefetch - + LinesToRequestPrefetchPixelData = *DestinationLinesForPrefetch - *DestinationLinesToRequestVMInVBlank - 2 * *DestinationLinesToRequestRowInVBlank; #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: DestinationLinesForPrefetch = %f\n", __func__, *DestinationLinesForPrefetch); dml_print("DML::%s: DestinationLinesToRequestVMInVBlank = %f\n", __func__, *DestinationLinesToRequestVMInVBlank); - dml_print("DML::%s: TimeForFetchingRowInVBlank = %f\n", __func__, st_vars->TimeForFetchingRowInVBlank); - dml_print("DML::%s: LineTime = %f\n", __func__, st_vars->LineTime); + dml_print("DML::%s: TimeForFetchingRowInVBlank = %f\n", __func__, TimeForFetchingRowInVBlank); + dml_print("DML::%s: LineTime = %f\n", __func__, LineTime); dml_print("DML::%s: DestinationLinesToRequestRowInVBlank = %f\n", __func__, *DestinationLinesToRequestRowInVBlank); dml_print("DML::%s: PrefetchSourceLinesY = %f\n", __func__, PrefetchSourceLinesY); - dml_print("DML::%s: LinesToRequestPrefetchPixelData = %f\n", __func__, st_vars->LinesToRequestPrefetchPixelData); + dml_print("DML::%s: LinesToRequestPrefetchPixelData = %f\n", __func__, LinesToRequestPrefetchPixelData); #endif - if (st_vars->LinesToRequestPrefetchPixelData >= 1 && st_vars->prefetch_bw_equ > 0) { - *VRatioPrefetchY = (double) PrefetchSourceLinesY / st_vars->LinesToRequestPrefetchPixelData; + if (LinesToRequestPrefetchPixelData >= 1 && prefetch_bw_equ > 0) { + *VRatioPrefetchY = (double) PrefetchSourceLinesY / LinesToRequestPrefetchPixelData; *VRatioPrefetchY = dml_max(*VRatioPrefetchY, 1.0); #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: VRatioPrefetchY = %f\n", __func__, *VRatioPrefetchY); @@ -3851,12 +3877,12 @@ bool dml32_CalculatePrefetchSchedule( dml_print("DML::%s: VInitPreFillY = %d\n", __func__, VInitPreFillY); #endif if ((SwathHeightY > 4) && (VInitPreFillY > 3)) { - if (st_vars->LinesToRequestPrefetchPixelData > (VInitPreFillY - 3.0) / 2.0) { + if (LinesToRequestPrefetchPixelData > (VInitPreFillY - 3.0) / 2.0) { *VRatioPrefetchY = dml_max((double) PrefetchSourceLinesY / - st_vars->LinesToRequestPrefetchPixelData, + LinesToRequestPrefetchPixelData, (double) MaxNumSwathY * SwathHeightY / - (st_vars->LinesToRequestPrefetchPixelData - + (LinesToRequestPrefetchPixelData - (VInitPreFillY - 3.0) / 2.0)); *VRatioPrefetchY = dml_max(*VRatioPrefetchY, 1.0); } else { @@ -3870,7 +3896,7 @@ bool dml32_CalculatePrefetchSchedule( #endif } - *VRatioPrefetchC = (double) PrefetchSourceLinesC / st_vars->LinesToRequestPrefetchPixelData; + *VRatioPrefetchC = (double) PrefetchSourceLinesC / LinesToRequestPrefetchPixelData; *VRatioPrefetchC = dml_max(*VRatioPrefetchC, 1.0); #ifdef __DML_VBA_DEBUG__ @@ -3879,11 +3905,11 @@ bool dml32_CalculatePrefetchSchedule( dml_print("DML::%s: VInitPreFillC = %d\n", __func__, VInitPreFillC); #endif if ((SwathHeightC > 4)) { - if (st_vars->LinesToRequestPrefetchPixelData > (VInitPreFillC - 3.0) / 2.0) { + if (LinesToRequestPrefetchPixelData > (VInitPreFillC - 3.0) / 2.0) { *VRatioPrefetchC = dml_max(*VRatioPrefetchC, (double) MaxNumSwathC * SwathHeightC / - (st_vars->LinesToRequestPrefetchPixelData - + (LinesToRequestPrefetchPixelData - (VInitPreFillC - 3.0) / 2.0)); *VRatioPrefetchC = dml_max(*VRatioPrefetchC, 1.0); } else { @@ -3898,25 +3924,25 @@ bool dml32_CalculatePrefetchSchedule( } *RequiredPrefetchPixDataBWLuma = (double) PrefetchSourceLinesY - / st_vars->LinesToRequestPrefetchPixelData * myPipe->BytePerPixelY * swath_width_luma_ub - / st_vars->LineTime; + / LinesToRequestPrefetchPixelData * myPipe->BytePerPixelY * swath_width_luma_ub + / LineTime; #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: BytePerPixelY = %d\n", __func__, myPipe->BytePerPixelY); dml_print("DML::%s: swath_width_luma_ub = %d\n", __func__, swath_width_luma_ub); - dml_print("DML::%s: LineTime = %f\n", __func__, st_vars->LineTime); + dml_print("DML::%s: LineTime = %f\n", __func__, LineTime); dml_print("DML::%s: RequiredPrefetchPixDataBWLuma = %f\n", __func__, *RequiredPrefetchPixDataBWLuma); #endif *RequiredPrefetchPixDataBWChroma = (double) PrefetchSourceLinesC / - st_vars->LinesToRequestPrefetchPixelData + LinesToRequestPrefetchPixelData * myPipe->BytePerPixelC - * swath_width_chroma_ub / st_vars->LineTime; + * swath_width_chroma_ub / LineTime; } else { MyError = true; #ifdef __DML_VBA_DEBUG__ dml_print("DML:%s: MyErr set. LinesToRequestPrefetchPixelData: %f, should be > 0\n", - __func__, st_vars->LinesToRequestPrefetchPixelData); + __func__, LinesToRequestPrefetchPixelData); #endif *VRatioPrefetchY = 0; *VRatioPrefetchC = 0; @@ -3925,15 +3951,15 @@ bool dml32_CalculatePrefetchSchedule( } #ifdef __DML_VBA_DEBUG__ dml_print("DML: Tpre: %fus - sum of time to request meta pte, 2 x data pte + meta data, swaths\n", - (double)st_vars->LinesToRequestPrefetchPixelData * st_vars->LineTime + - 2.0*st_vars->TimeForFetchingRowInVBlank + st_vars->TimeForFetchingMetaPTE); - dml_print("DML: Tvm: %fus - time to fetch page tables for meta surface\n", st_vars->TimeForFetchingMetaPTE); + (double)LinesToRequestPrefetchPixelData * LineTime + + 2.0*TimeForFetchingRowInVBlank + TimeForFetchingMetaPTE); + dml_print("DML: Tvm: %fus - time to fetch page tables for meta surface\n", TimeForFetchingMetaPTE); dml_print("DML: To: %fus - time for propagation from scaler to optc\n", - (*DSTYAfterScaler + ((double) (*DSTXAfterScaler) / (double) myPipe->HTotal)) * st_vars->LineTime); + (*DSTYAfterScaler + ((double) (*DSTXAfterScaler) / (double) myPipe->HTotal)) * LineTime); dml_print("DML: Tvstartup - TSetup - Tcalc - Twait - Tpre - To > 0\n"); - dml_print("DML: Tslack(pre): %fus - time left over in schedule\n", VStartup * st_vars->LineTime - - st_vars->TimeForFetchingMetaPTE - 2*st_vars->TimeForFetchingRowInVBlank - (*DSTYAfterScaler + - ((double) (*DSTXAfterScaler) / (double) myPipe->HTotal)) * st_vars->LineTime - TWait - TCalc - *TSetup); + dml_print("DML: Tslack(pre): %fus - time left over in schedule\n", VStartup * LineTime - + TimeForFetchingMetaPTE - 2*TimeForFetchingRowInVBlank - (*DSTYAfterScaler + + ((double) (*DSTXAfterScaler) / (double) myPipe->HTotal)) * LineTime - TWait - TCalc - *TSetup); dml_print("DML: row_bytes = dpte_row_bytes (per_pipe) = PixelPTEBytesPerRow = : %d\n", PixelPTEBytesPerRow); #endif @@ -3941,7 +3967,7 @@ bool dml32_CalculatePrefetchSchedule( MyError = true; #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: MyErr set, dst_y_prefetch_equ = %f (should be > 1)\n", - __func__, st_vars->dst_y_prefetch_equ); + __func__, dst_y_prefetch_equ); #endif } @@ -3957,10 +3983,10 @@ bool dml32_CalculatePrefetchSchedule( dml_print("DML::%s: HostVMInefficiencyFactor = %f\n", __func__, HostVMInefficiencyFactor); dml_print("DML::%s: DestinationLinesToRequestVMInVBlank = %f\n", __func__, *DestinationLinesToRequestVMInVBlank); - dml_print("DML::%s: LineTime = %f\n", __func__, st_vars->LineTime); + dml_print("DML::%s: LineTime = %f\n", __func__, LineTime); #endif prefetch_vm_bw = PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor / - (*DestinationLinesToRequestVMInVBlank * st_vars->LineTime); + (*DestinationLinesToRequestVMInVBlank * LineTime); #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: prefetch_vm_bw = %f\n", __func__, prefetch_vm_bw); #endif @@ -3977,7 +4003,7 @@ bool dml32_CalculatePrefetchSchedule( prefetch_row_bw = 0; } else if (*DestinationLinesToRequestRowInVBlank > 0) { prefetch_row_bw = (MetaRowByte + PixelPTEBytesPerRow * HostVMInefficiencyFactor) / - (*DestinationLinesToRequestRowInVBlank * st_vars->LineTime); + (*DestinationLinesToRequestRowInVBlank * LineTime); #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: MetaRowByte = %d\n", __func__, MetaRowByte); @@ -4000,12 +4026,12 @@ bool dml32_CalculatePrefetchSchedule( if (MyError) { *PrefetchBandwidth = 0; - st_vars->TimeForFetchingMetaPTE = 0; - st_vars->TimeForFetchingRowInVBlank = 0; + TimeForFetchingMetaPTE = 0; + TimeForFetchingRowInVBlank = 0; *DestinationLinesToRequestVMInVBlank = 0; *DestinationLinesToRequestRowInVBlank = 0; *DestinationLinesForPrefetch = 0; - st_vars->LinesToRequestPrefetchPixelData = 0; + LinesToRequestPrefetchPixelData = 0; *VRatioPrefetchY = 0; *VRatioPrefetchC = 0; *RequiredPrefetchPixDataBWLuma = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h index 37a314ce284b2..ecd4f1e7d1f79 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h @@ -715,7 +715,6 @@ double dml32_CalculateExtraLatency( unsigned int HostVMMaxNonCachedPageTableLevels); bool dml32_CalculatePrefetchSchedule( - struct dml32_CalculatePrefetchSchedule *st_vars, double HostVMInefficiencyFactor, DmlPipe *myPipe, unsigned int DSCDelay, diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 8460aefe7b6d8..42e4e4c5e656e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -247,43 +247,6 @@ struct dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport { unsigned int LBLatencyHidingSourceLinesC[DC__NUM_DPP__MAX]; }; -struct dml32_CalculatePrefetchSchedule { - unsigned int DPPCycles, DISPCLKCycles; - double DSTTotalPixelsAfterScaler; - double LineTime; - double dst_y_prefetch_equ; - double prefetch_bw_oto; - double Tvm_oto; - double Tr0_oto; - double Tvm_oto_lines; - double Tr0_oto_lines; - double dst_y_prefetch_oto; - double TimeForFetchingMetaPTE; - double TimeForFetchingRowInVBlank; - double LinesToRequestPrefetchPixelData; - unsigned int HostVMDynamicLevelsTrips; - double trip_to_mem; - double Tvm_trips; - double Tr0_trips; - double Tvm_trips_rounded; - double Tr0_trips_rounded; - double Lsw_oto; - double Tpre_rounded; - double prefetch_bw_equ; - double Tvm_equ; - double Tr0_equ; - double Tdmbf; - double Tdmec; - double Tdmsks; - double prefetch_sw_bytes; - double bytes_pp; - double dep_bytes; - unsigned int max_vratio_pre; - double min_Lsw; - double Tsw_est1; - double Tsw_est3; -}; - struct DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation { unsigned int dummy_integer_array[2][DC__NUM_DPP__MAX]; double dummy_single_array[2][DC__NUM_DPP__MAX]; @@ -358,7 +321,6 @@ struct dummy_vars { struct dml32_CalculateSwathAndDETConfiguration dml32_CalculateSwathAndDETConfiguration; struct dml32_CalculateVMRowAndSwath dml32_CalculateVMRowAndSwath; struct dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport; - struct dml32_CalculatePrefetchSchedule dml32_CalculatePrefetchSchedule; }; struct vba_vars_st { From 0ee7cc803ae52b60f268fdf2eba79b9fc1162747 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Wed, 27 Jul 2022 17:55:21 -0400 Subject: [PATCH 087/427] Revert "drm/amd/display: reduce stack for dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport" This reverts commit 3c3abac60117cfd09460980d9a14c253b37f7b00. This commit was a part of a patchset responsible for reducing the stack size. However, after some other changes, this commit becomes unnecessary, so we are reverting it here. Cc: Aurabindo Pillai Reported-by: Stephen Rothwell Reviewed-by: Alex Deucher Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- .../dc/dml/dcn32/display_mode_vba_32.c | 2 - .../dc/dml/dcn32/display_mode_vba_util_32.c | 187 ++++++++++-------- .../dc/dml/dcn32/display_mode_vba_util_32.h | 1 - .../drm/amd/display/dc/dml/display_mode_vba.h | 34 ---- 4 files changed, 104 insertions(+), 120 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index 04f1eefdabe80..55f351d5b610a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -1165,7 +1165,6 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.mmSOCParameters.SMNLatency = mode_lib->vba.SMNLatency; dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( - &v->dummy_vars.dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport, mode_lib->vba.USRRetrainingRequiredFinal, mode_lib->vba.UsesMALLForPStateChange, mode_lib->vba.PrefetchModePerState[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb], @@ -3563,7 +3562,6 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l { dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( - &v->dummy_vars.dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport, mode_lib->vba.USRRetrainingRequiredFinal, mode_lib->vba.UsesMALLForPStateChange, mode_lib->vba.PrefetchModePerState[i][j], diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c index 54dde0ea424ae..c0dab2b2c446d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c @@ -4185,7 +4185,6 @@ void dml32_CalculateFlipSchedule( } // CalculateFlipSchedule void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( - struct dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport *st_vars, bool USRRetrainingRequiredFinal, enum dm_use_mall_for_pstate_change_mode UseMALLForPStateChange[], unsigned int PrefetchMode, @@ -4247,15 +4246,37 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( double ActiveDRAMClockChangeLatencyMargin[]) { unsigned int i, j, k; - - st_vars->SurfaceWithMinActiveFCLKChangeMargin = 0; - st_vars->DRAMClockChangeSupportNumber = 0; - st_vars->DRAMClockChangeMethod = 0; - st_vars->FoundFirstSurfaceWithMinActiveFCLKChangeMargin = false; - st_vars->MinActiveFCLKChangeMargin = 0.; - st_vars->SecondMinActiveFCLKChangeMarginOneDisplayInVBLank = 0.; - st_vars->TotalPixelBW = 0.0; - st_vars->TotalActiveWriteback = 0; + unsigned int SurfaceWithMinActiveFCLKChangeMargin = 0; + unsigned int DRAMClockChangeSupportNumber = 0; + unsigned int LastSurfaceWithoutMargin; + unsigned int DRAMClockChangeMethod = 0; + bool FoundFirstSurfaceWithMinActiveFCLKChangeMargin = false; + double MinActiveFCLKChangeMargin = 0.; + double SecondMinActiveFCLKChangeMarginOneDisplayInVBLank = 0.; + double ActiveClockChangeLatencyHidingY; + double ActiveClockChangeLatencyHidingC; + double ActiveClockChangeLatencyHiding; + double EffectiveDETBufferSizeY; + double ActiveFCLKChangeLatencyMargin[DC__NUM_DPP__MAX]; + double USRRetrainingLatencyMargin[DC__NUM_DPP__MAX]; + double TotalPixelBW = 0.0; + bool SynchronizedSurfaces[DC__NUM_DPP__MAX][DC__NUM_DPP__MAX]; + double EffectiveLBLatencyHidingY; + double EffectiveLBLatencyHidingC; + double LinesInDETY[DC__NUM_DPP__MAX]; + double LinesInDETC[DC__NUM_DPP__MAX]; + unsigned int LinesInDETYRoundedDownToSwath[DC__NUM_DPP__MAX]; + unsigned int LinesInDETCRoundedDownToSwath[DC__NUM_DPP__MAX]; + double FullDETBufferingTimeY; + double FullDETBufferingTimeC; + double WritebackDRAMClockChangeLatencyMargin; + double WritebackFCLKChangeLatencyMargin; + double WritebackLatencyHiding; + bool SameTimingForFCLKChange; + + unsigned int TotalActiveWriteback = 0; + unsigned int LBLatencyHidingSourceLinesY[DC__NUM_DPP__MAX]; + unsigned int LBLatencyHidingSourceLinesC[DC__NUM_DPP__MAX]; Watermark->UrgentWatermark = mmSOCParameters.UrgentLatency + mmSOCParameters.ExtraLatency; Watermark->USRRetrainingWatermark = mmSOCParameters.UrgentLatency + mmSOCParameters.ExtraLatency @@ -4287,13 +4308,13 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( #endif - st_vars->TotalActiveWriteback = 0; + TotalActiveWriteback = 0; for (k = 0; k < NumberOfActiveSurfaces; ++k) { if (WritebackEnable[k] == true) - st_vars->TotalActiveWriteback = st_vars->TotalActiveWriteback + 1; + TotalActiveWriteback = TotalActiveWriteback + 1; } - if (st_vars->TotalActiveWriteback <= 1) { + if (TotalActiveWriteback <= 1) { Watermark->WritebackUrgentWatermark = mmSOCParameters.WritebackLatency; } else { Watermark->WritebackUrgentWatermark = mmSOCParameters.WritebackLatency @@ -4303,7 +4324,7 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( Watermark->WritebackUrgentWatermark = Watermark->WritebackUrgentWatermark + mmSOCParameters.USRRetrainingLatency; - if (st_vars->TotalActiveWriteback <= 1) { + if (TotalActiveWriteback <= 1) { Watermark->WritebackDRAMClockChangeWatermark = mmSOCParameters.DRAMClockChangeLatency + mmSOCParameters.WritebackLatency; Watermark->WritebackFCLKChangeWatermark = mmSOCParameters.FCLKChangeLatency @@ -4333,14 +4354,14 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( #endif for (k = 0; k < NumberOfActiveSurfaces; ++k) { - st_vars->TotalPixelBW = st_vars->TotalPixelBW + DPPPerSurface[k] * (SwathWidthY[k] * BytePerPixelDETY[k] * VRatio[k] + + TotalPixelBW = TotalPixelBW + DPPPerSurface[k] * (SwathWidthY[k] * BytePerPixelDETY[k] * VRatio[k] + SwathWidthC[k] * BytePerPixelDETC[k] * VRatioChroma[k]) / (HTotal[k] / PixelClock[k]); } for (k = 0; k < NumberOfActiveSurfaces; ++k) { - st_vars->LBLatencyHidingSourceLinesY[k] = dml_min((double) MaxLineBufferLines, dml_floor(LineBufferSize / LBBitPerPixel[k] / (SwathWidthY[k] / dml_max(HRatio[k], 1.0)), 1)) - (VTaps[k] - 1); - st_vars->LBLatencyHidingSourceLinesC[k] = dml_min((double) MaxLineBufferLines, dml_floor(LineBufferSize / LBBitPerPixel[k] / (SwathWidthC[k] / dml_max(HRatioChroma[k], 1.0)), 1)) - (VTapsChroma[k] - 1); + LBLatencyHidingSourceLinesY[k] = dml_min((double) MaxLineBufferLines, dml_floor(LineBufferSize / LBBitPerPixel[k] / (SwathWidthY[k] / dml_max(HRatio[k], 1.0)), 1)) - (VTaps[k] - 1); + LBLatencyHidingSourceLinesC[k] = dml_min((double) MaxLineBufferLines, dml_floor(LineBufferSize / LBBitPerPixel[k] / (SwathWidthC[k] / dml_max(HRatioChroma[k], 1.0)), 1)) - (VTapsChroma[k] - 1); #ifdef __DML_VBA_DEBUG__ @@ -4351,72 +4372,72 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( dml_print("DML::%s: k=%d, VTaps = %d\n", __func__, k, VTaps[k]); #endif - st_vars->EffectiveLBLatencyHidingY = st_vars->LBLatencyHidingSourceLinesY[k] / VRatio[k] * (HTotal[k] / PixelClock[k]); - st_vars->EffectiveLBLatencyHidingC = st_vars->LBLatencyHidingSourceLinesC[k] / VRatioChroma[k] * (HTotal[k] / PixelClock[k]); - st_vars->EffectiveDETBufferSizeY = DETBufferSizeY[k]; + EffectiveLBLatencyHidingY = LBLatencyHidingSourceLinesY[k] / VRatio[k] * (HTotal[k] / PixelClock[k]); + EffectiveLBLatencyHidingC = LBLatencyHidingSourceLinesC[k] / VRatioChroma[k] * (HTotal[k] / PixelClock[k]); + EffectiveDETBufferSizeY = DETBufferSizeY[k]; if (UnboundedRequestEnabled) { - st_vars->EffectiveDETBufferSizeY = st_vars->EffectiveDETBufferSizeY + EffectiveDETBufferSizeY = EffectiveDETBufferSizeY + CompressedBufferSizeInkByte * 1024 * (SwathWidthY[k] * BytePerPixelDETY[k] * VRatio[k]) - / (HTotal[k] / PixelClock[k]) / st_vars->TotalPixelBW; + / (HTotal[k] / PixelClock[k]) / TotalPixelBW; } - st_vars->LinesInDETY[k] = (double) st_vars->EffectiveDETBufferSizeY / BytePerPixelDETY[k] / SwathWidthY[k]; - st_vars->LinesInDETYRoundedDownToSwath[k] = dml_floor(st_vars->LinesInDETY[k], SwathHeightY[k]); - st_vars->FullDETBufferingTimeY = st_vars->LinesInDETYRoundedDownToSwath[k] * (HTotal[k] / PixelClock[k]) / VRatio[k]; + LinesInDETY[k] = (double) EffectiveDETBufferSizeY / BytePerPixelDETY[k] / SwathWidthY[k]; + LinesInDETYRoundedDownToSwath[k] = dml_floor(LinesInDETY[k], SwathHeightY[k]); + FullDETBufferingTimeY = LinesInDETYRoundedDownToSwath[k] * (HTotal[k] / PixelClock[k]) / VRatio[k]; - st_vars->ActiveClockChangeLatencyHidingY = st_vars->EffectiveLBLatencyHidingY + st_vars->FullDETBufferingTimeY + ActiveClockChangeLatencyHidingY = EffectiveLBLatencyHidingY + FullDETBufferingTimeY - (DSTXAfterScaler[k] / HTotal[k] + DSTYAfterScaler[k]) * HTotal[k] / PixelClock[k]; if (NumberOfActiveSurfaces > 1) { - st_vars->ActiveClockChangeLatencyHidingY = st_vars->ActiveClockChangeLatencyHidingY + ActiveClockChangeLatencyHidingY = ActiveClockChangeLatencyHidingY - (1 - 1 / NumberOfActiveSurfaces) * SwathHeightY[k] * HTotal[k] / PixelClock[k] / VRatio[k]; } if (BytePerPixelDETC[k] > 0) { - st_vars->LinesInDETC[k] = DETBufferSizeC[k] / BytePerPixelDETC[k] / SwathWidthC[k]; - st_vars->LinesInDETCRoundedDownToSwath[k] = dml_floor(st_vars->LinesInDETC[k], SwathHeightC[k]); - st_vars->FullDETBufferingTimeC = st_vars->LinesInDETCRoundedDownToSwath[k] * (HTotal[k] / PixelClock[k]) + LinesInDETC[k] = DETBufferSizeC[k] / BytePerPixelDETC[k] / SwathWidthC[k]; + LinesInDETCRoundedDownToSwath[k] = dml_floor(LinesInDETC[k], SwathHeightC[k]); + FullDETBufferingTimeC = LinesInDETCRoundedDownToSwath[k] * (HTotal[k] / PixelClock[k]) / VRatioChroma[k]; - st_vars->ActiveClockChangeLatencyHidingC = st_vars->EffectiveLBLatencyHidingC + st_vars->FullDETBufferingTimeC + ActiveClockChangeLatencyHidingC = EffectiveLBLatencyHidingC + FullDETBufferingTimeC - (DSTXAfterScaler[k] / HTotal[k] + DSTYAfterScaler[k]) * HTotal[k] / PixelClock[k]; if (NumberOfActiveSurfaces > 1) { - st_vars->ActiveClockChangeLatencyHidingC = st_vars->ActiveClockChangeLatencyHidingC + ActiveClockChangeLatencyHidingC = ActiveClockChangeLatencyHidingC - (1 - 1 / NumberOfActiveSurfaces) * SwathHeightC[k] * HTotal[k] / PixelClock[k] / VRatioChroma[k]; } - st_vars->ActiveClockChangeLatencyHiding = dml_min(st_vars->ActiveClockChangeLatencyHidingY, - st_vars->ActiveClockChangeLatencyHidingC); + ActiveClockChangeLatencyHiding = dml_min(ActiveClockChangeLatencyHidingY, + ActiveClockChangeLatencyHidingC); } else { - st_vars->ActiveClockChangeLatencyHiding = st_vars->ActiveClockChangeLatencyHidingY; + ActiveClockChangeLatencyHiding = ActiveClockChangeLatencyHidingY; } - ActiveDRAMClockChangeLatencyMargin[k] = st_vars->ActiveClockChangeLatencyHiding - Watermark->UrgentWatermark + ActiveDRAMClockChangeLatencyMargin[k] = ActiveClockChangeLatencyHiding - Watermark->UrgentWatermark - Watermark->DRAMClockChangeWatermark; - st_vars->ActiveFCLKChangeLatencyMargin[k] = st_vars->ActiveClockChangeLatencyHiding - Watermark->UrgentWatermark + ActiveFCLKChangeLatencyMargin[k] = ActiveClockChangeLatencyHiding - Watermark->UrgentWatermark - Watermark->FCLKChangeWatermark; - st_vars->USRRetrainingLatencyMargin[k] = st_vars->ActiveClockChangeLatencyHiding - Watermark->USRRetrainingWatermark; + USRRetrainingLatencyMargin[k] = ActiveClockChangeLatencyHiding - Watermark->USRRetrainingWatermark; if (WritebackEnable[k]) { - st_vars->WritebackLatencyHiding = WritebackInterfaceBufferSize * 1024 + WritebackLatencyHiding = WritebackInterfaceBufferSize * 1024 / (WritebackDestinationWidth[k] * WritebackDestinationHeight[k] / (WritebackSourceHeight[k] * HTotal[k] / PixelClock[k]) * 4); if (WritebackPixelFormat[k] == dm_444_64) - st_vars->WritebackLatencyHiding = st_vars->WritebackLatencyHiding / 2; + WritebackLatencyHiding = WritebackLatencyHiding / 2; - st_vars->WritebackDRAMClockChangeLatencyMargin = st_vars->WritebackLatencyHiding + WritebackDRAMClockChangeLatencyMargin = WritebackLatencyHiding - Watermark->WritebackDRAMClockChangeWatermark; - st_vars->WritebackFCLKChangeLatencyMargin = st_vars->WritebackLatencyHiding + WritebackFCLKChangeLatencyMargin = WritebackLatencyHiding - Watermark->WritebackFCLKChangeWatermark; ActiveDRAMClockChangeLatencyMargin[k] = dml_min(ActiveDRAMClockChangeLatencyMargin[k], - st_vars->WritebackFCLKChangeLatencyMargin); - st_vars->ActiveFCLKChangeLatencyMargin[k] = dml_min(st_vars->ActiveFCLKChangeLatencyMargin[k], - st_vars->WritebackDRAMClockChangeLatencyMargin); + WritebackFCLKChangeLatencyMargin); + ActiveFCLKChangeLatencyMargin[k] = dml_min(ActiveFCLKChangeLatencyMargin[k], + WritebackDRAMClockChangeLatencyMargin); } MaxActiveDRAMClockChangeLatencySupported[k] = (UseMALLForPStateChange[k] == dm_use_mall_pstate_change_phantom_pipe) ? @@ -4435,41 +4456,41 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( HTotal[i] == HTotal[j] && VTotal[i] == VTotal[j] && VActive[i] == VActive[j]) || (SynchronizeDRRDisplaysForUCLKPStateChangeFinal && (DRRDisplay[i] || DRRDisplay[j]))) { - st_vars->SynchronizedSurfaces[i][j] = true; + SynchronizedSurfaces[i][j] = true; } else { - st_vars->SynchronizedSurfaces[i][j] = false; + SynchronizedSurfaces[i][j] = false; } } } for (k = 0; k < NumberOfActiveSurfaces; ++k) { if ((UseMALLForPStateChange[k] != dm_use_mall_pstate_change_phantom_pipe) && - (!st_vars->FoundFirstSurfaceWithMinActiveFCLKChangeMargin || - st_vars->ActiveFCLKChangeLatencyMargin[k] < st_vars->MinActiveFCLKChangeMargin)) { - st_vars->FoundFirstSurfaceWithMinActiveFCLKChangeMargin = true; - st_vars->MinActiveFCLKChangeMargin = st_vars->ActiveFCLKChangeLatencyMargin[k]; - st_vars->SurfaceWithMinActiveFCLKChangeMargin = k; + (!FoundFirstSurfaceWithMinActiveFCLKChangeMargin || + ActiveFCLKChangeLatencyMargin[k] < MinActiveFCLKChangeMargin)) { + FoundFirstSurfaceWithMinActiveFCLKChangeMargin = true; + MinActiveFCLKChangeMargin = ActiveFCLKChangeLatencyMargin[k]; + SurfaceWithMinActiveFCLKChangeMargin = k; } } - *MinActiveFCLKChangeLatencySupported = st_vars->MinActiveFCLKChangeMargin + mmSOCParameters.FCLKChangeLatency; + *MinActiveFCLKChangeLatencySupported = MinActiveFCLKChangeMargin + mmSOCParameters.FCLKChangeLatency; - st_vars->SameTimingForFCLKChange = true; + SameTimingForFCLKChange = true; for (k = 0; k < NumberOfActiveSurfaces; ++k) { - if (!st_vars->SynchronizedSurfaces[k][st_vars->SurfaceWithMinActiveFCLKChangeMargin]) { + if (!SynchronizedSurfaces[k][SurfaceWithMinActiveFCLKChangeMargin]) { if ((UseMALLForPStateChange[k] != dm_use_mall_pstate_change_phantom_pipe) && - (st_vars->SameTimingForFCLKChange || - st_vars->ActiveFCLKChangeLatencyMargin[k] < - st_vars->SecondMinActiveFCLKChangeMarginOneDisplayInVBLank)) { - st_vars->SecondMinActiveFCLKChangeMarginOneDisplayInVBLank = st_vars->ActiveFCLKChangeLatencyMargin[k]; + (SameTimingForFCLKChange || + ActiveFCLKChangeLatencyMargin[k] < + SecondMinActiveFCLKChangeMarginOneDisplayInVBLank)) { + SecondMinActiveFCLKChangeMarginOneDisplayInVBLank = ActiveFCLKChangeLatencyMargin[k]; } - st_vars->SameTimingForFCLKChange = false; + SameTimingForFCLKChange = false; } } - if (st_vars->MinActiveFCLKChangeMargin > 0) { + if (MinActiveFCLKChangeMargin > 0) { *FCLKChangeSupport = dm_fclock_change_vactive; - } else if ((st_vars->SameTimingForFCLKChange || st_vars->SecondMinActiveFCLKChangeMarginOneDisplayInVBLank > 0) && + } else if ((SameTimingForFCLKChange || SecondMinActiveFCLKChangeMarginOneDisplayInVBLank > 0) && (PrefetchMode <= 1)) { *FCLKChangeSupport = dm_fclock_change_vblank; } else { @@ -4479,7 +4500,7 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( *USRRetrainingSupport = true; for (k = 0; k < NumberOfActiveSurfaces; ++k) { if ((UseMALLForPStateChange[k] != dm_use_mall_pstate_change_phantom_pipe) && - (st_vars->USRRetrainingLatencyMargin[k] < 0)) { + (USRRetrainingLatencyMargin[k] < 0)) { *USRRetrainingSupport = false; } } @@ -4490,42 +4511,42 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( UseMALLForPStateChange[k] != dm_use_mall_pstate_change_phantom_pipe && ActiveDRAMClockChangeLatencyMargin[k] < 0) { if (PrefetchMode > 0) { - st_vars->DRAMClockChangeSupportNumber = 2; - } else if (st_vars->DRAMClockChangeSupportNumber == 0) { - st_vars->DRAMClockChangeSupportNumber = 1; - st_vars->LastSurfaceWithoutMargin = k; - } else if (st_vars->DRAMClockChangeSupportNumber == 1 && - !st_vars->SynchronizedSurfaces[st_vars->LastSurfaceWithoutMargin][k]) { - st_vars->DRAMClockChangeSupportNumber = 2; + DRAMClockChangeSupportNumber = 2; + } else if (DRAMClockChangeSupportNumber == 0) { + DRAMClockChangeSupportNumber = 1; + LastSurfaceWithoutMargin = k; + } else if (DRAMClockChangeSupportNumber == 1 && + !SynchronizedSurfaces[LastSurfaceWithoutMargin][k]) { + DRAMClockChangeSupportNumber = 2; } } } for (k = 0; k < NumberOfActiveSurfaces; ++k) { if (UseMALLForPStateChange[k] == dm_use_mall_pstate_change_full_frame) - st_vars->DRAMClockChangeMethod = 1; + DRAMClockChangeMethod = 1; else if (UseMALLForPStateChange[k] == dm_use_mall_pstate_change_sub_viewport) - st_vars->DRAMClockChangeMethod = 2; + DRAMClockChangeMethod = 2; } - if (st_vars->DRAMClockChangeMethod == 0) { - if (st_vars->DRAMClockChangeSupportNumber == 0) + if (DRAMClockChangeMethod == 0) { + if (DRAMClockChangeSupportNumber == 0) *DRAMClockChangeSupport = dm_dram_clock_change_vactive; - else if (st_vars->DRAMClockChangeSupportNumber == 1) + else if (DRAMClockChangeSupportNumber == 1) *DRAMClockChangeSupport = dm_dram_clock_change_vblank; else *DRAMClockChangeSupport = dm_dram_clock_change_unsupported; - } else if (st_vars->DRAMClockChangeMethod == 1) { - if (st_vars->DRAMClockChangeSupportNumber == 0) + } else if (DRAMClockChangeMethod == 1) { + if (DRAMClockChangeSupportNumber == 0) *DRAMClockChangeSupport = dm_dram_clock_change_vactive_w_mall_full_frame; - else if (st_vars->DRAMClockChangeSupportNumber == 1) + else if (DRAMClockChangeSupportNumber == 1) *DRAMClockChangeSupport = dm_dram_clock_change_vblank_w_mall_full_frame; else *DRAMClockChangeSupport = dm_dram_clock_change_unsupported; } else { - if (st_vars->DRAMClockChangeSupportNumber == 0) + if (DRAMClockChangeSupportNumber == 0) *DRAMClockChangeSupport = dm_dram_clock_change_vactive_w_mall_sub_vp; - else if (st_vars->DRAMClockChangeSupportNumber == 1) + else if (DRAMClockChangeSupportNumber == 1) *DRAMClockChangeSupport = dm_dram_clock_change_vblank_w_mall_sub_vp; else *DRAMClockChangeSupport = dm_dram_clock_change_unsupported; @@ -4539,7 +4560,7 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( dst_y_pstate = dml_ceil((mmSOCParameters.DRAMClockChangeLatency + mmSOCParameters.UrgentLatency) / (HTotal[k] / PixelClock[k]), 1); src_y_pstate_l = dml_ceil(dst_y_pstate * VRatio[k], SwathHeightY[k]); - src_y_ahead_l = dml_floor(DETBufferSizeY[k] / BytePerPixelDETY[k] / SwathWidthY[k], SwathHeightY[k]) + st_vars->LBLatencyHidingSourceLinesY[k]; + src_y_ahead_l = dml_floor(DETBufferSizeY[k] / BytePerPixelDETY[k] / SwathWidthY[k], SwathHeightY[k]) + LBLatencyHidingSourceLinesY[k]; sub_vp_lines_l = src_y_pstate_l + src_y_ahead_l + meta_row_height[k]; #ifdef __DML_VBA_DEBUG__ @@ -4547,7 +4568,7 @@ dml_print("DML::%s: k=%d, DETBufferSizeY = %d\n", __func__, k, DET dml_print("DML::%s: k=%d, BytePerPixelDETY = %f\n", __func__, k, BytePerPixelDETY[k]); dml_print("DML::%s: k=%d, SwathWidthY = %d\n", __func__, k, SwathWidthY[k]); dml_print("DML::%s: k=%d, SwathHeightY = %d\n", __func__, k, SwathHeightY[k]); -dml_print("DML::%s: k=%d, LBLatencyHidingSourceLinesY = %d\n", __func__, k, st_vars->LBLatencyHidingSourceLinesY[k]); +dml_print("DML::%s: k=%d, LBLatencyHidingSourceLinesY = %d\n", __func__, k, LBLatencyHidingSourceLinesY[k]); dml_print("DML::%s: k=%d, dst_y_pstate = %d\n", __func__, k, dst_y_pstate); dml_print("DML::%s: k=%d, src_y_pstate_l = %d\n", __func__, k, src_y_pstate_l); dml_print("DML::%s: k=%d, src_y_ahead_l = %d\n", __func__, k, src_y_ahead_l); @@ -4558,7 +4579,7 @@ dml_print("DML::%s: k=%d, sub_vp_lines_l = %d\n", __func__, k, sub_vp_lines_l if (BytePerPixelDETC[k] > 0) { src_y_pstate_c = dml_ceil(dst_y_pstate * VRatioChroma[k], SwathHeightC[k]); - src_y_ahead_c = dml_floor(DETBufferSizeC[k] / BytePerPixelDETC[k] / SwathWidthC[k], SwathHeightC[k]) + st_vars->LBLatencyHidingSourceLinesC[k]; + src_y_ahead_c = dml_floor(DETBufferSizeC[k] / BytePerPixelDETC[k] / SwathWidthC[k], SwathHeightC[k]) + LBLatencyHidingSourceLinesC[k]; sub_vp_lines_c = src_y_pstate_c + src_y_ahead_c + meta_row_height_chroma[k]; SubViewportLinesNeededInMALL[k] = dml_max(sub_vp_lines_l, sub_vp_lines_c); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h index ecd4f1e7d1f79..974006e5ecb73 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h @@ -810,7 +810,6 @@ void dml32_CalculateFlipSchedule( bool *ImmediateFlipSupportedForPipe); void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( - struct dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport *st_vars, bool USRRetrainingRequiredFinal, enum dm_use_mall_for_pstate_change_mode UseMALLForPStateChange[], unsigned int PrefetchMode, diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 42e4e4c5e656e..b326184cfa4a2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -214,39 +214,6 @@ struct dml32_CalculateVMRowAndSwath { bool one_row_per_frame_fits_in_buffer[DC__NUM_DPP__MAX]; }; -struct dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport { - unsigned int SurfaceWithMinActiveFCLKChangeMargin; - unsigned int DRAMClockChangeSupportNumber; - unsigned int LastSurfaceWithoutMargin; - unsigned int DRAMClockChangeMethod; - bool FoundFirstSurfaceWithMinActiveFCLKChangeMargin; - double MinActiveFCLKChangeMargin; - double SecondMinActiveFCLKChangeMarginOneDisplayInVBLank; - double ActiveClockChangeLatencyHidingY; - double ActiveClockChangeLatencyHidingC; - double ActiveClockChangeLatencyHiding; - double EffectiveDETBufferSizeY; - double ActiveFCLKChangeLatencyMargin[DC__NUM_DPP__MAX]; - double USRRetrainingLatencyMargin[DC__NUM_DPP__MAX]; - double TotalPixelBW; - bool SynchronizedSurfaces[DC__NUM_DPP__MAX][DC__NUM_DPP__MAX]; - double EffectiveLBLatencyHidingY; - double EffectiveLBLatencyHidingC; - double LinesInDETY[DC__NUM_DPP__MAX]; - double LinesInDETC[DC__NUM_DPP__MAX]; - unsigned int LinesInDETYRoundedDownToSwath[DC__NUM_DPP__MAX]; - unsigned int LinesInDETCRoundedDownToSwath[DC__NUM_DPP__MAX]; - double FullDETBufferingTimeY; - double FullDETBufferingTimeC; - double WritebackDRAMClockChangeLatencyMargin; - double WritebackFCLKChangeLatencyMargin; - double WritebackLatencyHiding; - bool SameTimingForFCLKChange; - unsigned int TotalActiveWriteback; - unsigned int LBLatencyHidingSourceLinesY[DC__NUM_DPP__MAX]; - unsigned int LBLatencyHidingSourceLinesC[DC__NUM_DPP__MAX]; -}; - struct DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation { unsigned int dummy_integer_array[2][DC__NUM_DPP__MAX]; double dummy_single_array[2][DC__NUM_DPP__MAX]; @@ -320,7 +287,6 @@ struct dummy_vars { struct dml32_ModeSupportAndSystemConfigurationFull dml32_ModeSupportAndSystemConfigurationFull; struct dml32_CalculateSwathAndDETConfiguration dml32_CalculateSwathAndDETConfiguration; struct dml32_CalculateVMRowAndSwath dml32_CalculateVMRowAndSwath; - struct dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport; }; struct vba_vars_st { From 968d40986f004b463f057fce612996556b753c9e Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Wed, 27 Jul 2022 17:55:33 -0400 Subject: [PATCH 088/427] Revert "drm/amd/display: reduce stack for dml32_CalculateVMRowAndSwath" This reverts commit c3b3f9ba25e6cbe59673505fbc5fff6c4cda0ef7. This commit was a part of a patchset responsible for reducing the stack size. However, after some other changes, this commit becomes unnecessary, so we are reverting it here. Cc: Aurabindo Pillai Reported-by: Stephen Rothwell Reviewed-by: Alex Deucher Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- .../dc/dml/dcn32/display_mode_vba_32.c | 2 - .../dc/dml/dcn32/display_mode_vba_util_32.c | 110 ++++++++++-------- .../dc/dml/dcn32/display_mode_vba_util_32.h | 1 - .../drm/amd/display/dc/dml/display_mode_vba.h | 19 --- 4 files changed, 62 insertions(+), 70 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index 55f351d5b610a..3cfd3cc4d60cc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -461,7 +461,6 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman { dml32_CalculateVMRowAndSwath( - &v->dummy_vars.dml32_CalculateVMRowAndSwath, mode_lib->vba.NumberOfActiveSurfaces, v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.SurfaceParameters, v->SurfaceSizeInMALL, @@ -2746,7 +2745,6 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l { dml32_CalculateVMRowAndSwath( - &v->dummy_vars.dml32_CalculateVMRowAndSwath, mode_lib->vba.NumberOfActiveSurfaces, v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.SurfParameters, mode_lib->vba.SurfaceSizeInMALL, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c index c0dab2b2c446d..f9adfd7371dc0 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c @@ -1867,7 +1867,6 @@ void dml32_CalculateSurfaceSizeInMall( } // CalculateSurfaceSizeInMall void dml32_CalculateVMRowAndSwath( - struct dml32_CalculateVMRowAndSwath *st_vars, unsigned int NumberOfActiveSurfaces, DmlPipe myPipe[], unsigned int SurfaceSizeInMALL[], @@ -1933,6 +1932,21 @@ void dml32_CalculateVMRowAndSwath( unsigned int BIGK_FRAGMENT_SIZE[]) { unsigned int k; + unsigned int PTEBufferSizeInRequestsForLuma[DC__NUM_DPP__MAX]; + unsigned int PTEBufferSizeInRequestsForChroma[DC__NUM_DPP__MAX]; + unsigned int PDEAndMetaPTEBytesFrameY; + unsigned int PDEAndMetaPTEBytesFrameC; + unsigned int MetaRowByteY[DC__NUM_DPP__MAX]; + unsigned int MetaRowByteC[DC__NUM_DPP__MAX]; + unsigned int PixelPTEBytesPerRowY[DC__NUM_DPP__MAX]; + unsigned int PixelPTEBytesPerRowC[DC__NUM_DPP__MAX]; + unsigned int PixelPTEBytesPerRowY_one_row_per_frame[DC__NUM_DPP__MAX]; + unsigned int PixelPTEBytesPerRowC_one_row_per_frame[DC__NUM_DPP__MAX]; + unsigned int dpte_row_width_luma_ub_one_row_per_frame[DC__NUM_DPP__MAX]; + unsigned int dpte_row_height_luma_one_row_per_frame[DC__NUM_DPP__MAX]; + unsigned int dpte_row_width_chroma_ub_one_row_per_frame[DC__NUM_DPP__MAX]; + unsigned int dpte_row_height_chroma_one_row_per_frame[DC__NUM_DPP__MAX]; + bool one_row_per_frame_fits_in_buffer[DC__NUM_DPP__MAX]; for (k = 0; k < NumberOfActiveSurfaces; ++k) { if (HostVMEnable == true) { @@ -1954,15 +1968,15 @@ void dml32_CalculateVMRowAndSwath( myPipe[k].SourcePixelFormat == dm_rgbe_alpha) { if ((myPipe[k].SourcePixelFormat == dm_420_10 || myPipe[k].SourcePixelFormat == dm_420_12) && !IsVertical(myPipe[k].SourceRotation)) { - st_vars->PTEBufferSizeInRequestsForLuma[k] = + PTEBufferSizeInRequestsForLuma[k] = (PTEBufferSizeInRequestsLuma + PTEBufferSizeInRequestsChroma) / 2; - st_vars->PTEBufferSizeInRequestsForChroma[k] = st_vars->PTEBufferSizeInRequestsForLuma[k]; + PTEBufferSizeInRequestsForChroma[k] = PTEBufferSizeInRequestsForLuma[k]; } else { - st_vars->PTEBufferSizeInRequestsForLuma[k] = PTEBufferSizeInRequestsLuma; - st_vars->PTEBufferSizeInRequestsForChroma[k] = PTEBufferSizeInRequestsChroma; + PTEBufferSizeInRequestsForLuma[k] = PTEBufferSizeInRequestsLuma; + PTEBufferSizeInRequestsForChroma[k] = PTEBufferSizeInRequestsChroma; } - st_vars->PDEAndMetaPTEBytesFrameC = dml32_CalculateVMAndRowBytes( + PDEAndMetaPTEBytesFrameC = dml32_CalculateVMAndRowBytes( myPipe[k].ViewportStationary, myPipe[k].DCCEnable, myPipe[k].DPPPerSurface, @@ -1982,21 +1996,21 @@ void dml32_CalculateVMRowAndSwath( GPUVMMaxPageTableLevels, GPUVMMinPageSizeKBytes[k], HostVMMinPageSize, - st_vars->PTEBufferSizeInRequestsForChroma[k], + PTEBufferSizeInRequestsForChroma[k], myPipe[k].PitchC, myPipe[k].DCCMetaPitchC, myPipe[k].BlockWidthC, myPipe[k].BlockHeightC, /* Output */ - &st_vars->MetaRowByteC[k], - &st_vars->PixelPTEBytesPerRowC[k], + &MetaRowByteC[k], + &PixelPTEBytesPerRowC[k], &dpte_row_width_chroma_ub[k], &dpte_row_height_chroma[k], &dpte_row_height_linear_chroma[k], - &st_vars->PixelPTEBytesPerRowC_one_row_per_frame[k], - &st_vars->dpte_row_width_chroma_ub_one_row_per_frame[k], - &st_vars->dpte_row_height_chroma_one_row_per_frame[k], + &PixelPTEBytesPerRowC_one_row_per_frame[k], + &dpte_row_width_chroma_ub_one_row_per_frame[k], + &dpte_row_height_chroma_one_row_per_frame[k], &meta_req_width_chroma[k], &meta_req_height_chroma[k], &meta_row_width_chroma[k], @@ -2024,19 +2038,19 @@ void dml32_CalculateVMRowAndSwath( &VInitPreFillC[k], &MaxNumSwathC[k]); } else { - st_vars->PTEBufferSizeInRequestsForLuma[k] = PTEBufferSizeInRequestsLuma + PTEBufferSizeInRequestsChroma; - st_vars->PTEBufferSizeInRequestsForChroma[k] = 0; - st_vars->PixelPTEBytesPerRowC[k] = 0; - st_vars->PDEAndMetaPTEBytesFrameC = 0; - st_vars->MetaRowByteC[k] = 0; + PTEBufferSizeInRequestsForLuma[k] = PTEBufferSizeInRequestsLuma + PTEBufferSizeInRequestsChroma; + PTEBufferSizeInRequestsForChroma[k] = 0; + PixelPTEBytesPerRowC[k] = 0; + PDEAndMetaPTEBytesFrameC = 0; + MetaRowByteC[k] = 0; MaxNumSwathC[k] = 0; PrefetchSourceLinesC[k] = 0; - st_vars->dpte_row_height_chroma_one_row_per_frame[k] = 0; - st_vars->dpte_row_width_chroma_ub_one_row_per_frame[k] = 0; - st_vars->PixelPTEBytesPerRowC_one_row_per_frame[k] = 0; + dpte_row_height_chroma_one_row_per_frame[k] = 0; + dpte_row_width_chroma_ub_one_row_per_frame[k] = 0; + PixelPTEBytesPerRowC_one_row_per_frame[k] = 0; } - st_vars->PDEAndMetaPTEBytesFrameY = dml32_CalculateVMAndRowBytes( + PDEAndMetaPTEBytesFrameY = dml32_CalculateVMAndRowBytes( myPipe[k].ViewportStationary, myPipe[k].DCCEnable, myPipe[k].DPPPerSurface, @@ -2056,21 +2070,21 @@ void dml32_CalculateVMRowAndSwath( GPUVMMaxPageTableLevels, GPUVMMinPageSizeKBytes[k], HostVMMinPageSize, - st_vars->PTEBufferSizeInRequestsForLuma[k], + PTEBufferSizeInRequestsForLuma[k], myPipe[k].PitchY, myPipe[k].DCCMetaPitchY, myPipe[k].BlockWidthY, myPipe[k].BlockHeightY, /* Output */ - &st_vars->MetaRowByteY[k], - &st_vars->PixelPTEBytesPerRowY[k], + &MetaRowByteY[k], + &PixelPTEBytesPerRowY[k], &dpte_row_width_luma_ub[k], &dpte_row_height_luma[k], &dpte_row_height_linear_luma[k], - &st_vars->PixelPTEBytesPerRowY_one_row_per_frame[k], - &st_vars->dpte_row_width_luma_ub_one_row_per_frame[k], - &st_vars->dpte_row_height_luma_one_row_per_frame[k], + &PixelPTEBytesPerRowY_one_row_per_frame[k], + &dpte_row_width_luma_ub_one_row_per_frame[k], + &dpte_row_height_luma_one_row_per_frame[k], &meta_req_width[k], &meta_req_height[k], &meta_row_width[k], @@ -2098,19 +2112,19 @@ void dml32_CalculateVMRowAndSwath( &VInitPreFillY[k], &MaxNumSwathY[k]); - PDEAndMetaPTEBytesFrame[k] = st_vars->PDEAndMetaPTEBytesFrameY + st_vars->PDEAndMetaPTEBytesFrameC; - MetaRowByte[k] = st_vars->MetaRowByteY[k] + st_vars->MetaRowByteC[k]; + PDEAndMetaPTEBytesFrame[k] = PDEAndMetaPTEBytesFrameY + PDEAndMetaPTEBytesFrameC; + MetaRowByte[k] = MetaRowByteY[k] + MetaRowByteC[k]; - if (st_vars->PixelPTEBytesPerRowY[k] <= 64 * st_vars->PTEBufferSizeInRequestsForLuma[k] && - st_vars->PixelPTEBytesPerRowC[k] <= 64 * st_vars->PTEBufferSizeInRequestsForChroma[k]) { + if (PixelPTEBytesPerRowY[k] <= 64 * PTEBufferSizeInRequestsForLuma[k] && + PixelPTEBytesPerRowC[k] <= 64 * PTEBufferSizeInRequestsForChroma[k]) { PTEBufferSizeNotExceeded[k] = true; } else { PTEBufferSizeNotExceeded[k] = false; } - st_vars->one_row_per_frame_fits_in_buffer[k] = (st_vars->PixelPTEBytesPerRowY_one_row_per_frame[k] <= 64 * 2 * - st_vars->PTEBufferSizeInRequestsForLuma[k] && - st_vars->PixelPTEBytesPerRowC_one_row_per_frame[k] <= 64 * 2 * st_vars->PTEBufferSizeInRequestsForChroma[k]); + one_row_per_frame_fits_in_buffer[k] = (PixelPTEBytesPerRowY_one_row_per_frame[k] <= 64 * 2 * + PTEBufferSizeInRequestsForLuma[k] && + PixelPTEBytesPerRowC_one_row_per_frame[k] <= 64 * 2 * PTEBufferSizeInRequestsForChroma[k]); } dml32_CalculateMALLUseForStaticScreen( @@ -2118,7 +2132,7 @@ void dml32_CalculateVMRowAndSwath( MALLAllocatedForDCN, UseMALLForStaticScreen, // mode SurfaceSizeInMALL, - st_vars->one_row_per_frame_fits_in_buffer, + one_row_per_frame_fits_in_buffer, /* Output */ UsesMALLForStaticScreen); // boolen @@ -2144,13 +2158,13 @@ void dml32_CalculateVMRowAndSwath( !(UseMALLForPStateChange[k] == dm_use_mall_pstate_change_full_frame); if (use_one_row_for_frame[k]) { - dpte_row_height_luma[k] = st_vars->dpte_row_height_luma_one_row_per_frame[k]; - dpte_row_width_luma_ub[k] = st_vars->dpte_row_width_luma_ub_one_row_per_frame[k]; - st_vars->PixelPTEBytesPerRowY[k] = st_vars->PixelPTEBytesPerRowY_one_row_per_frame[k]; - dpte_row_height_chroma[k] = st_vars->dpte_row_height_chroma_one_row_per_frame[k]; - dpte_row_width_chroma_ub[k] = st_vars->dpte_row_width_chroma_ub_one_row_per_frame[k]; - st_vars->PixelPTEBytesPerRowC[k] = st_vars->PixelPTEBytesPerRowC_one_row_per_frame[k]; - PTEBufferSizeNotExceeded[k] = st_vars->one_row_per_frame_fits_in_buffer[k]; + dpte_row_height_luma[k] = dpte_row_height_luma_one_row_per_frame[k]; + dpte_row_width_luma_ub[k] = dpte_row_width_luma_ub_one_row_per_frame[k]; + PixelPTEBytesPerRowY[k] = PixelPTEBytesPerRowY_one_row_per_frame[k]; + dpte_row_height_chroma[k] = dpte_row_height_chroma_one_row_per_frame[k]; + dpte_row_width_chroma_ub[k] = dpte_row_width_chroma_ub_one_row_per_frame[k]; + PixelPTEBytesPerRowC[k] = PixelPTEBytesPerRowC_one_row_per_frame[k]; + PTEBufferSizeNotExceeded[k] = one_row_per_frame_fits_in_buffer[k]; } if (MetaRowByte[k] <= DCCMetaBufferSizeBytes) @@ -2158,7 +2172,7 @@ void dml32_CalculateVMRowAndSwath( else DCCMetaBufferSizeNotExceeded[k] = false; - PixelPTEBytesPerRow[k] = st_vars->PixelPTEBytesPerRowY[k] + st_vars->PixelPTEBytesPerRowC[k]; + PixelPTEBytesPerRow[k] = PixelPTEBytesPerRowY[k] + PixelPTEBytesPerRowC[k]; if (use_one_row_for_frame[k]) PixelPTEBytesPerRow[k] = PixelPTEBytesPerRow[k] / 2; @@ -2169,11 +2183,11 @@ void dml32_CalculateVMRowAndSwath( myPipe[k].VRatioChroma, myPipe[k].DCCEnable, myPipe[k].HTotal / myPipe[k].PixelClock, - st_vars->MetaRowByteY[k], st_vars->MetaRowByteC[k], + MetaRowByteY[k], MetaRowByteC[k], meta_row_height[k], meta_row_height_chroma[k], - st_vars->PixelPTEBytesPerRowY[k], - st_vars->PixelPTEBytesPerRowC[k], + PixelPTEBytesPerRowY[k], + PixelPTEBytesPerRowC[k], dpte_row_height_luma[k], dpte_row_height_chroma[k], @@ -2189,12 +2203,12 @@ void dml32_CalculateVMRowAndSwath( dml_print("DML::%s: k=%d, dpte_row_height_luma = %d\n", __func__, k, dpte_row_height_luma[k]); dml_print("DML::%s: k=%d, dpte_row_width_luma_ub = %d\n", __func__, k, dpte_row_width_luma_ub[k]); - dml_print("DML::%s: k=%d, PixelPTEBytesPerRowY = %d\n", __func__, k, st_vars->PixelPTEBytesPerRowY[k]); + dml_print("DML::%s: k=%d, PixelPTEBytesPerRowY = %d\n", __func__, k, PixelPTEBytesPerRowY[k]); dml_print("DML::%s: k=%d, dpte_row_height_chroma = %d\n", __func__, k, dpte_row_height_chroma[k]); dml_print("DML::%s: k=%d, dpte_row_width_chroma_ub = %d\n", __func__, k, dpte_row_width_chroma_ub[k]); - dml_print("DML::%s: k=%d, PixelPTEBytesPerRowC = %d\n", __func__, k, st_vars->PixelPTEBytesPerRowC[k]); + dml_print("DML::%s: k=%d, PixelPTEBytesPerRowC = %d\n", __func__, k, PixelPTEBytesPerRowC[k]); dml_print("DML::%s: k=%d, PixelPTEBytesPerRow = %d\n", __func__, k, PixelPTEBytesPerRow[k]); dml_print("DML::%s: k=%d, PTEBufferSizeNotExceeded = %d\n", __func__, k, PTEBufferSizeNotExceeded[k]); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h index 974006e5ecb73..158cfa2af1af3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h @@ -362,7 +362,6 @@ void dml32_CalculateSurfaceSizeInMall( bool *ExceededMALLSize); void dml32_CalculateVMRowAndSwath( - struct dml32_CalculateVMRowAndSwath *st_vars, unsigned int NumberOfActiveSurfaces, DmlPipe myPipe[], unsigned int SurfaceSizeInMALL[], diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index b326184cfa4a2..6cf814c2cc8de 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -196,24 +196,6 @@ struct dml32_CalculateSwathAndDETConfiguration { unsigned int DETBufferSizeInKByteForSwathCalculation; }; -struct dml32_CalculateVMRowAndSwath { - unsigned int PTEBufferSizeInRequestsForLuma[DC__NUM_DPP__MAX]; - unsigned int PTEBufferSizeInRequestsForChroma[DC__NUM_DPP__MAX]; - unsigned int PDEAndMetaPTEBytesFrameY; - unsigned int PDEAndMetaPTEBytesFrameC; - unsigned int MetaRowByteY[DC__NUM_DPP__MAX]; - unsigned int MetaRowByteC[DC__NUM_DPP__MAX]; - unsigned int PixelPTEBytesPerRowY[DC__NUM_DPP__MAX]; - unsigned int PixelPTEBytesPerRowC[DC__NUM_DPP__MAX]; - unsigned int PixelPTEBytesPerRowY_one_row_per_frame[DC__NUM_DPP__MAX]; - unsigned int PixelPTEBytesPerRowC_one_row_per_frame[DC__NUM_DPP__MAX]; - unsigned int dpte_row_width_luma_ub_one_row_per_frame[DC__NUM_DPP__MAX]; - unsigned int dpte_row_height_luma_one_row_per_frame[DC__NUM_DPP__MAX]; - unsigned int dpte_row_width_chroma_ub_one_row_per_frame[DC__NUM_DPP__MAX]; - unsigned int dpte_row_height_chroma_one_row_per_frame[DC__NUM_DPP__MAX]; - bool one_row_per_frame_fits_in_buffer[DC__NUM_DPP__MAX]; -}; - struct DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation { unsigned int dummy_integer_array[2][DC__NUM_DPP__MAX]; double dummy_single_array[2][DC__NUM_DPP__MAX]; @@ -286,7 +268,6 @@ struct dummy_vars { DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation; struct dml32_ModeSupportAndSystemConfigurationFull dml32_ModeSupportAndSystemConfigurationFull; struct dml32_CalculateSwathAndDETConfiguration dml32_CalculateSwathAndDETConfiguration; - struct dml32_CalculateVMRowAndSwath dml32_CalculateVMRowAndSwath; }; struct vba_vars_st { From 5822b8acb869caac72c3ddf149d463177aa28fd4 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Wed, 27 Jul 2022 17:55:45 -0400 Subject: [PATCH 089/427] Revert "drm/amd/display: reduce stack for dml32_CalculateSwathAndDETConfiguration" This reverts commit bac4b41d917a1d999308bb1e779f8c3b39c19f67. This commit was a part of a patchset responsible for reducing the stack size. However, after some other changes, this commit becomes unnecessary, so we are reverting it here. Cc: Aurabindo Pillai Reported-by: Stephen Rothwell Reviewed-by: Alex Deucher Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- .../dc/dml/dcn32/display_mode_vba_32.c | 3 - .../dc/dml/dcn32/display_mode_vba_util_32.c | 121 +++++++++--------- .../dc/dml/dcn32/display_mode_vba_util_32.h | 2 - .../drm/amd/display/dc/dml/display_mode_vba.h | 15 --- 4 files changed, 64 insertions(+), 77 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index 3cfd3cc4d60cc..cb2025771646b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -221,7 +221,6 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman // VBA_DELTA // Calculate DET size, swath height dml32_CalculateSwathAndDETConfiguration( - &v->dummy_vars.dml32_CalculateSwathAndDETConfiguration, mode_lib->vba.DETSizeOverride, mode_lib->vba.UsesMALLForPStateChange, mode_lib->vba.ConfigReturnBufferSizeInKByte, @@ -1948,7 +1947,6 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } dml32_CalculateSwathAndDETConfiguration( - &v->dummy_vars.dml32_CalculateSwathAndDETConfiguration, mode_lib->vba.DETSizeOverride, mode_lib->vba.UsesMALLForPStateChange, mode_lib->vba.ConfigReturnBufferSizeInKByte, @@ -2545,7 +2543,6 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } dml32_CalculateSwathAndDETConfiguration( - &v->dummy_vars.dml32_CalculateSwathAndDETConfiguration, mode_lib->vba.DETSizeOverride, mode_lib->vba.UsesMALLForPStateChange, mode_lib->vba.ConfigReturnBufferSizeInKByte, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c index f9adfd7371dc0..05fc14a47fba9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c @@ -391,7 +391,6 @@ void dml32_CalculateBytePerPixelAndBlockSizes( } // CalculateBytePerPixelAndBlockSizes void dml32_CalculateSwathAndDETConfiguration( - struct dml32_CalculateSwathAndDETConfiguration *st_vars, unsigned int DETSizeOverride[], enum dm_use_mall_for_pstate_change_mode UseMALLForPStateChange[], unsigned int ConfigReturnBufferSizeInKByte, @@ -456,10 +455,18 @@ void dml32_CalculateSwathAndDETConfiguration( bool ViewportSizeSupportPerSurface[], bool *ViewportSizeSupport) { + unsigned int MaximumSwathHeightY[DC__NUM_DPP__MAX]; + unsigned int MaximumSwathHeightC[DC__NUM_DPP__MAX]; + unsigned int RoundedUpMaxSwathSizeBytesY[DC__NUM_DPP__MAX]; + unsigned int RoundedUpMaxSwathSizeBytesC[DC__NUM_DPP__MAX]; + unsigned int RoundedUpSwathSizeBytesY; + unsigned int RoundedUpSwathSizeBytesC; + double SwathWidthdoubleDPP[DC__NUM_DPP__MAX]; + double SwathWidthdoubleDPPChroma[DC__NUM_DPP__MAX]; unsigned int k; - - st_vars->TotalActiveDPP = 0; - st_vars->NoChromaSurfaces = true; + unsigned int TotalActiveDPP = 0; + bool NoChromaSurfaces = true; + unsigned int DETBufferSizeInKByteForSwathCalculation; #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: ForceSingleDPP = %d\n", __func__, ForceSingleDPP); @@ -494,43 +501,43 @@ void dml32_CalculateSwathAndDETConfiguration( DPPPerSurface, /* Output */ - st_vars->SwathWidthdoubleDPP, - st_vars->SwathWidthdoubleDPPChroma, + SwathWidthdoubleDPP, + SwathWidthdoubleDPPChroma, SwathWidth, SwathWidthChroma, - st_vars->MaximumSwathHeightY, - st_vars->MaximumSwathHeightC, + MaximumSwathHeightY, + MaximumSwathHeightC, swath_width_luma_ub, swath_width_chroma_ub); for (k = 0; k < NumberOfActiveSurfaces; ++k) { - st_vars->RoundedUpMaxSwathSizeBytesY[k] = swath_width_luma_ub[k] * BytePerPixDETY[k] * st_vars->MaximumSwathHeightY[k]; - st_vars->RoundedUpMaxSwathSizeBytesC[k] = swath_width_chroma_ub[k] * BytePerPixDETC[k] * st_vars->MaximumSwathHeightC[k]; + RoundedUpMaxSwathSizeBytesY[k] = swath_width_luma_ub[k] * BytePerPixDETY[k] * MaximumSwathHeightY[k]; + RoundedUpMaxSwathSizeBytesC[k] = swath_width_chroma_ub[k] * BytePerPixDETC[k] * MaximumSwathHeightC[k]; #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: k=%0d DPPPerSurface = %d\n", __func__, k, DPPPerSurface[k]); dml_print("DML::%s: k=%0d swath_width_luma_ub = %d\n", __func__, k, swath_width_luma_ub[k]); dml_print("DML::%s: k=%0d BytePerPixDETY = %f\n", __func__, k, BytePerPixDETY[k]); - dml_print("DML::%s: k=%0d MaximumSwathHeightY = %d\n", __func__, k, st_vars->MaximumSwathHeightY[k]); + dml_print("DML::%s: k=%0d MaximumSwathHeightY = %d\n", __func__, k, MaximumSwathHeightY[k]); dml_print("DML::%s: k=%0d RoundedUpMaxSwathSizeBytesY = %d\n", __func__, k, - st_vars->RoundedUpMaxSwathSizeBytesY[k]); + RoundedUpMaxSwathSizeBytesY[k]); dml_print("DML::%s: k=%0d swath_width_chroma_ub = %d\n", __func__, k, swath_width_chroma_ub[k]); dml_print("DML::%s: k=%0d BytePerPixDETC = %f\n", __func__, k, BytePerPixDETC[k]); - dml_print("DML::%s: k=%0d MaximumSwathHeightC = %d\n", __func__, k, st_vars->MaximumSwathHeightC[k]); + dml_print("DML::%s: k=%0d MaximumSwathHeightC = %d\n", __func__, k, MaximumSwathHeightC[k]); dml_print("DML::%s: k=%0d RoundedUpMaxSwathSizeBytesC = %d\n", __func__, k, - st_vars->RoundedUpMaxSwathSizeBytesC[k]); + RoundedUpMaxSwathSizeBytesC[k]); #endif if (SourcePixelFormat[k] == dm_420_10) { - st_vars->RoundedUpMaxSwathSizeBytesY[k] = dml_ceil((unsigned int) st_vars->RoundedUpMaxSwathSizeBytesY[k], 256); - st_vars->RoundedUpMaxSwathSizeBytesC[k] = dml_ceil((unsigned int) st_vars->RoundedUpMaxSwathSizeBytesC[k], 256); + RoundedUpMaxSwathSizeBytesY[k] = dml_ceil((unsigned int) RoundedUpMaxSwathSizeBytesY[k], 256); + RoundedUpMaxSwathSizeBytesC[k] = dml_ceil((unsigned int) RoundedUpMaxSwathSizeBytesC[k], 256); } } for (k = 0; k < NumberOfActiveSurfaces; ++k) { - st_vars->TotalActiveDPP = st_vars->TotalActiveDPP + (ForceSingleDPP ? 1 : DPPPerSurface[k]); + TotalActiveDPP = TotalActiveDPP + (ForceSingleDPP ? 1 : DPPPerSurface[k]); if (SourcePixelFormat[k] == dm_420_8 || SourcePixelFormat[k] == dm_420_10 || SourcePixelFormat[k] == dm_420_12 || SourcePixelFormat[k] == dm_rgbe_alpha) { - st_vars->NoChromaSurfaces = false; + NoChromaSurfaces = false; } } @@ -540,10 +547,10 @@ void dml32_CalculateSwathAndDETConfiguration( // if unbounded req is enabled, program reserved space such that the ROB will not hold more than 8 swaths worth of data // - assume worst-case compression rate of 4. [ROB size - 8 * swath_size / max_compression ratio] // - assume for "narrow" vp case in which the ROB can fit 8 swaths, the DET should be big enough to do full size req - *CompBufReservedSpaceNeedAdjustment = ((int) ROBSizeKBytes - (int) *CompBufReservedSpaceKBytes) > (int) (st_vars->RoundedUpMaxSwathSizeBytesY[0]/512); + *CompBufReservedSpaceNeedAdjustment = ((int) ROBSizeKBytes - (int) *CompBufReservedSpaceKBytes) > (int) (RoundedUpMaxSwathSizeBytesY[0]/512); if (*CompBufReservedSpaceNeedAdjustment == 1) { - *CompBufReservedSpaceKBytes = ROBSizeKBytes - st_vars->RoundedUpMaxSwathSizeBytesY[0]/512; + *CompBufReservedSpaceKBytes = ROBSizeKBytes - RoundedUpMaxSwathSizeBytesY[0]/512; } #ifdef __DML_VBA_DEBUG__ @@ -551,7 +558,7 @@ void dml32_CalculateSwathAndDETConfiguration( dml_print("DML::%s: CompBufReservedSpaceNeedAdjustment = %d\n", __func__, *CompBufReservedSpaceNeedAdjustment); #endif - *UnboundedRequestEnabled = dml32_UnboundedRequest(UseUnboundedRequestingFinal, st_vars->TotalActiveDPP, st_vars->NoChromaSurfaces, Output[0], SurfaceTiling[0], *CompBufReservedSpaceNeedAdjustment, DisableUnboundRequestIfCompBufReservedSpaceNeedAdjustment); + *UnboundedRequestEnabled = dml32_UnboundedRequest(UseUnboundedRequestingFinal, TotalActiveDPP, NoChromaSurfaces, Output[0], SurfaceTiling[0], *CompBufReservedSpaceNeedAdjustment, DisableUnboundRequestIfCompBufReservedSpaceNeedAdjustment); dml32_CalculateDETBufferSize(DETSizeOverride, UseMALLForPStateChange, @@ -566,8 +573,8 @@ void dml32_CalculateSwathAndDETConfiguration( SourcePixelFormat, ReadBandwidthLuma, ReadBandwidthChroma, - st_vars->RoundedUpMaxSwathSizeBytesY, - st_vars->RoundedUpMaxSwathSizeBytesC, + RoundedUpMaxSwathSizeBytesY, + RoundedUpMaxSwathSizeBytesC, DPPPerSurface, /* Output */ @@ -575,7 +582,7 @@ void dml32_CalculateSwathAndDETConfiguration( CompressedBufferSizeInkByte); #ifdef __DML_VBA_DEBUG__ - dml_print("DML::%s: TotalActiveDPP = %d\n", __func__, st_vars->TotalActiveDPP); + dml_print("DML::%s: TotalActiveDPP = %d\n", __func__, TotalActiveDPP); dml_print("DML::%s: nomDETInKByte = %d\n", __func__, nomDETInKByte); dml_print("DML::%s: ConfigReturnBufferSizeInKByte = %d\n", __func__, ConfigReturnBufferSizeInKByte); dml_print("DML::%s: UseUnboundedRequestingFinal = %d\n", __func__, UseUnboundedRequestingFinal); @@ -586,42 +593,42 @@ void dml32_CalculateSwathAndDETConfiguration( *ViewportSizeSupport = true; for (k = 0; k < NumberOfActiveSurfaces; ++k) { - st_vars->DETBufferSizeInKByteForSwathCalculation = (UseMALLForPStateChange[k] == + DETBufferSizeInKByteForSwathCalculation = (UseMALLForPStateChange[k] == dm_use_mall_pstate_change_phantom_pipe ? 1024 : DETBufferSizeInKByte[k]); #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: k=%0d DETBufferSizeInKByteForSwathCalculation = %d\n", __func__, k, - st_vars->DETBufferSizeInKByteForSwathCalculation); + DETBufferSizeInKByteForSwathCalculation); #endif - if (st_vars->RoundedUpMaxSwathSizeBytesY[k] + st_vars->RoundedUpMaxSwathSizeBytesC[k] <= - st_vars->DETBufferSizeInKByteForSwathCalculation * 1024 / 2) { - SwathHeightY[k] = st_vars->MaximumSwathHeightY[k]; - SwathHeightC[k] = st_vars->MaximumSwathHeightC[k]; - st_vars->RoundedUpSwathSizeBytesY = st_vars->RoundedUpMaxSwathSizeBytesY[k]; - st_vars->RoundedUpSwathSizeBytesC = st_vars->RoundedUpMaxSwathSizeBytesC[k]; - } else if (st_vars->RoundedUpMaxSwathSizeBytesY[k] >= 1.5 * st_vars->RoundedUpMaxSwathSizeBytesC[k] && - st_vars->RoundedUpMaxSwathSizeBytesY[k] / 2 + st_vars->RoundedUpMaxSwathSizeBytesC[k] <= - st_vars->DETBufferSizeInKByteForSwathCalculation * 1024 / 2) { - SwathHeightY[k] = st_vars->MaximumSwathHeightY[k] / 2; - SwathHeightC[k] = st_vars->MaximumSwathHeightC[k]; - st_vars->RoundedUpSwathSizeBytesY = st_vars->RoundedUpMaxSwathSizeBytesY[k] / 2; - st_vars->RoundedUpSwathSizeBytesC = st_vars->RoundedUpMaxSwathSizeBytesC[k]; - } else if (st_vars->RoundedUpMaxSwathSizeBytesY[k] < 1.5 * st_vars->RoundedUpMaxSwathSizeBytesC[k] && - st_vars->RoundedUpMaxSwathSizeBytesY[k] + st_vars->RoundedUpMaxSwathSizeBytesC[k] / 2 <= - st_vars->DETBufferSizeInKByteForSwathCalculation * 1024 / 2) { - SwathHeightY[k] = st_vars->MaximumSwathHeightY[k]; - SwathHeightC[k] = st_vars->MaximumSwathHeightC[k] / 2; - st_vars->RoundedUpSwathSizeBytesY = st_vars->RoundedUpMaxSwathSizeBytesY[k]; - st_vars->RoundedUpSwathSizeBytesC = st_vars->RoundedUpMaxSwathSizeBytesC[k] / 2; + if (RoundedUpMaxSwathSizeBytesY[k] + RoundedUpMaxSwathSizeBytesC[k] <= + DETBufferSizeInKByteForSwathCalculation * 1024 / 2) { + SwathHeightY[k] = MaximumSwathHeightY[k]; + SwathHeightC[k] = MaximumSwathHeightC[k]; + RoundedUpSwathSizeBytesY = RoundedUpMaxSwathSizeBytesY[k]; + RoundedUpSwathSizeBytesC = RoundedUpMaxSwathSizeBytesC[k]; + } else if (RoundedUpMaxSwathSizeBytesY[k] >= 1.5 * RoundedUpMaxSwathSizeBytesC[k] && + RoundedUpMaxSwathSizeBytesY[k] / 2 + RoundedUpMaxSwathSizeBytesC[k] <= + DETBufferSizeInKByteForSwathCalculation * 1024 / 2) { + SwathHeightY[k] = MaximumSwathHeightY[k] / 2; + SwathHeightC[k] = MaximumSwathHeightC[k]; + RoundedUpSwathSizeBytesY = RoundedUpMaxSwathSizeBytesY[k] / 2; + RoundedUpSwathSizeBytesC = RoundedUpMaxSwathSizeBytesC[k]; + } else if (RoundedUpMaxSwathSizeBytesY[k] < 1.5 * RoundedUpMaxSwathSizeBytesC[k] && + RoundedUpMaxSwathSizeBytesY[k] + RoundedUpMaxSwathSizeBytesC[k] / 2 <= + DETBufferSizeInKByteForSwathCalculation * 1024 / 2) { + SwathHeightY[k] = MaximumSwathHeightY[k]; + SwathHeightC[k] = MaximumSwathHeightC[k] / 2; + RoundedUpSwathSizeBytesY = RoundedUpMaxSwathSizeBytesY[k]; + RoundedUpSwathSizeBytesC = RoundedUpMaxSwathSizeBytesC[k] / 2; } else { - SwathHeightY[k] = st_vars->MaximumSwathHeightY[k] / 2; - SwathHeightC[k] = st_vars->MaximumSwathHeightC[k] / 2; - st_vars->RoundedUpSwathSizeBytesY = st_vars->RoundedUpMaxSwathSizeBytesY[k] / 2; - st_vars->RoundedUpSwathSizeBytesC = st_vars->RoundedUpMaxSwathSizeBytesC[k] / 2; + SwathHeightY[k] = MaximumSwathHeightY[k] / 2; + SwathHeightC[k] = MaximumSwathHeightC[k] / 2; + RoundedUpSwathSizeBytesY = RoundedUpMaxSwathSizeBytesY[k] / 2; + RoundedUpSwathSizeBytesC = RoundedUpMaxSwathSizeBytesC[k] / 2; } - if ((st_vars->RoundedUpMaxSwathSizeBytesY[k] / 2 + st_vars->RoundedUpMaxSwathSizeBytesC[k] / 2 > - st_vars->DETBufferSizeInKByteForSwathCalculation * 1024 / 2) + if ((RoundedUpMaxSwathSizeBytesY[k] / 2 + RoundedUpMaxSwathSizeBytesC[k] / 2 > + DETBufferSizeInKByteForSwathCalculation * 1024 / 2) || SwathWidth[k] > MaximumSwathWidthLuma[k] || (SwathHeightC[k] > 0 && SwathWidthChroma[k] > MaximumSwathWidthChroma[k])) { *ViewportSizeSupport = false; @@ -636,7 +643,7 @@ void dml32_CalculateSwathAndDETConfiguration( #endif DETBufferSizeY[k] = DETBufferSizeInKByte[k] * 1024; DETBufferSizeC[k] = 0; - } else if (st_vars->RoundedUpSwathSizeBytesY <= 1.5 * st_vars->RoundedUpSwathSizeBytesC) { + } else if (RoundedUpSwathSizeBytesY <= 1.5 * RoundedUpSwathSizeBytesC) { #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: k=%0d Half DET for plane0, half for plane1\n", __func__, k); #endif @@ -654,11 +661,11 @@ void dml32_CalculateSwathAndDETConfiguration( dml_print("DML::%s: k=%0d SwathHeightY = %d\n", __func__, k, SwathHeightY[k]); dml_print("DML::%s: k=%0d SwathHeightC = %d\n", __func__, k, SwathHeightC[k]); dml_print("DML::%s: k=%0d RoundedUpMaxSwathSizeBytesY = %d\n", __func__, - k, st_vars->RoundedUpMaxSwathSizeBytesY[k]); + k, RoundedUpMaxSwathSizeBytesY[k]); dml_print("DML::%s: k=%0d RoundedUpMaxSwathSizeBytesC = %d\n", __func__, - k, st_vars->RoundedUpMaxSwathSizeBytesC[k]); - dml_print("DML::%s: k=%0d RoundedUpSwathSizeBytesY = %d\n", __func__, k, st_vars->RoundedUpSwathSizeBytesY); - dml_print("DML::%s: k=%0d RoundedUpSwathSizeBytesC = %d\n", __func__, k, st_vars->RoundedUpSwathSizeBytesC); + k, RoundedUpMaxSwathSizeBytesC[k]); + dml_print("DML::%s: k=%0d RoundedUpSwathSizeBytesY = %d\n", __func__, k, RoundedUpSwathSizeBytesY); + dml_print("DML::%s: k=%0d RoundedUpSwathSizeBytesC = %d\n", __func__, k, RoundedUpSwathSizeBytesC); dml_print("DML::%s: k=%0d DETBufferSizeInKByte = %d\n", __func__, k, DETBufferSizeInKByte[k]); dml_print("DML::%s: k=%0d DETBufferSizeY = %d\n", __func__, k, DETBufferSizeY[k]); dml_print("DML::%s: k=%0d DETBufferSizeC = %d\n", __func__, k, DETBufferSizeC[k]); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h index 158cfa2af1af3..d293856ba906b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h @@ -30,7 +30,6 @@ #include "os_types.h" #include "../dc_features.h" #include "../display_mode_structs.h" -#include "dml/display_mode_vba.h" unsigned int dml32_dscceComputeDelay( unsigned int bpc, @@ -82,7 +81,6 @@ void dml32_CalculateSinglePipeDPPCLKAndSCLThroughput( double *DPPCLKUsingSingleDPP); void dml32_CalculateSwathAndDETConfiguration( - struct dml32_CalculateSwathAndDETConfiguration *st_vars, unsigned int DETSizeOverride[], enum dm_use_mall_for_pstate_change_mode UseMALLForPStateChange[], unsigned int ConfigReturnBufferSizeInKByte, diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 6cf814c2cc8de..492aec634b685 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -182,20 +182,6 @@ void Calculate256BBlockSizes( unsigned int *BlockWidth256BytesY, unsigned int *BlockWidth256BytesC); -struct dml32_CalculateSwathAndDETConfiguration { - unsigned int MaximumSwathHeightY[DC__NUM_DPP__MAX]; - unsigned int MaximumSwathHeightC[DC__NUM_DPP__MAX]; - unsigned int RoundedUpMaxSwathSizeBytesY[DC__NUM_DPP__MAX]; - unsigned int RoundedUpMaxSwathSizeBytesC[DC__NUM_DPP__MAX]; - unsigned int RoundedUpSwathSizeBytesY; - unsigned int RoundedUpSwathSizeBytesC; - double SwathWidthdoubleDPP[DC__NUM_DPP__MAX]; - double SwathWidthdoubleDPPChroma[DC__NUM_DPP__MAX]; - unsigned int TotalActiveDPP; - bool NoChromaSurfaces; - unsigned int DETBufferSizeInKByteForSwathCalculation; -}; - struct DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation { unsigned int dummy_integer_array[2][DC__NUM_DPP__MAX]; double dummy_single_array[2][DC__NUM_DPP__MAX]; @@ -267,7 +253,6 @@ struct dummy_vars { struct DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation; struct dml32_ModeSupportAndSystemConfigurationFull dml32_ModeSupportAndSystemConfigurationFull; - struct dml32_CalculateSwathAndDETConfiguration dml32_CalculateSwathAndDETConfiguration; }; struct vba_vars_st { From 41ead3e0cdc03d64b7da2dcb1fd70ebb7164228b Mon Sep 17 00:00:00 2001 From: Magali Lemes Date: Tue, 2 Aug 2022 09:04:06 -0300 Subject: [PATCH 090/427] drm/amd/display: remove DML Makefile duplicate lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are two identical CFLAGS entries for "display_mode_vba_20.o", so remove one of them. Also, as there's already an entry for "display_mode_lib.o" CFLAGS, regardless of CONFIG_DRM_AMD_DC_DCN being defined or not, remove the one entry between CONFIG_DRM_AMD_DC_DCN ifdef guards. Signed-off-by: Magali Lemes Reviewed-by: André Almeida Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 359f6e9a1da04..41bb6c3cc2d8b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -61,7 +61,6 @@ CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn10/dcn10_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/dcn20_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20v2.o := $(dml_ccflags) @@ -82,7 +81,6 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn301/dcn301_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn302/dcn302_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn303/dcn303_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o := $(dml_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calcs.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_auto.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_math.o := $(dml_ccflags) -Wno-tautological-compare From c83b9d60299317a2c15550dd506c864cd01a3e5e Mon Sep 17 00:00:00 2001 From: Magali Lemes Date: Fri, 29 Jul 2022 22:06:58 -0300 Subject: [PATCH 091/427] drm/amd/display: make variables static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As "dcn3_1_soc", "dcn3_15_soc", and "dcn3_16_soc" are not used outside of their corresponding "dcn3*_fpu.c", make them static and remove their extern declaration. Fixes: 26f4712aedbd ("drm/amd/display: move FPU related code from dcn31 to dml/dcn31 folder") Fixes: fa896297b31b ("drm/amd/display: move FPU related code from dcn315 to dml/dcn31 folder") Fixes: 3f8951cc123f ("drm/amd/display: move FPU related code from dcn316 to dml/dcn31 folder") Signed-off-by: Magali Lemes Reviewed-by: Rodrigo Siqueira Reviewed-by: Maíra Canal Reviewed-by: Melissa Wen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h | 1 - drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h | 1 - drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h | 1 - drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c | 6 +++--- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h index 41f8ec99da6b3..901436591ed45 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h @@ -32,7 +32,6 @@ container_of(pool, struct dcn31_resource_pool, base) extern struct _vcs_dpi_ip_params_st dcn3_1_ip; -extern struct _vcs_dpi_soc_bounding_box_st dcn3_1_soc; struct dcn31_resource_pool { struct resource_pool base; diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h index 39929fa67a510..22849eaa6f243 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h @@ -32,7 +32,6 @@ container_of(pool, struct dcn315_resource_pool, base) extern struct _vcs_dpi_ip_params_st dcn3_15_ip; -extern struct _vcs_dpi_ip_params_st dcn3_15_soc; struct dcn315_resource_pool { struct resource_pool base; diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h index 0dc5a6c13ae7d..aba6d634131b4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h @@ -32,7 +32,6 @@ container_of(pool, struct dcn316_resource_pool, base) extern struct _vcs_dpi_ip_params_st dcn3_16_ip; -extern struct _vcs_dpi_ip_params_st dcn3_16_soc; struct dcn316_resource_pool { struct resource_pool base; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c index e36cfa5985ea9..5664653ba5ac1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c @@ -114,7 +114,7 @@ struct _vcs_dpi_ip_params_st dcn3_1_ip = { .dcc_supported = true, }; -struct _vcs_dpi_soc_bounding_box_st dcn3_1_soc = { +static struct _vcs_dpi_soc_bounding_box_st dcn3_1_soc = { /*TODO: correct dispclk/dppclk voltage level determination*/ .clock_limits = { { @@ -259,7 +259,7 @@ struct _vcs_dpi_ip_params_st dcn3_15_ip = { .dcc_supported = true, }; -struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = { +static struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = { .sr_exit_time_us = 9.0, .sr_enter_plus_exit_time_us = 11.0, .sr_exit_z8_time_us = 50.0, @@ -355,7 +355,7 @@ struct _vcs_dpi_ip_params_st dcn3_16_ip = { .dcc_supported = true, }; -struct _vcs_dpi_soc_bounding_box_st dcn3_16_soc = { +static struct _vcs_dpi_soc_bounding_box_st dcn3_16_soc = { /*TODO: correct dispclk/dppclk voltage level determination*/ .clock_limits = { { From f59966779deac642541c3f7d772a3bf5972727ed Mon Sep 17 00:00:00 2001 From: Magali Lemes Date: Fri, 29 Jul 2022 22:07:00 -0300 Subject: [PATCH 092/427] drm/amd/display: remove header from source file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since "rn_clk_mgr.h" needs ‘struct clk_mgr_internal’ which is declared in "clk_mgr_internal.h", include "clk_mgr_internal.h" in "rn_clk_mgr.h" instead of in its source file. Because of the change above, change the order of '#include "rn_clk_mgr.h"', so that the necessary structs are visible to dcn20_clk_mgr.h. Signed-off-by: Magali Lemes Reviewed-by: Rodrigo Siqueira Reviewed-by: Maíra Canal Reviewed-by: Melissa Wen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 3 +-- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index 0202dc682682b..ca6dfd2d7561f 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -24,10 +24,9 @@ */ #include "dccg.h" -#include "clk_mgr_internal.h" +#include "rn_clk_mgr.h" #include "dcn20/dcn20_clk_mgr.h" -#include "rn_clk_mgr.h" #include "dml/dcn20/dcn20_fpu.h" #include "dce100/dce_clk_mgr.h" diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.h index 2e088c5171b28..f1319957e400a 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.h @@ -28,6 +28,7 @@ #include "clk_mgr.h" #include "dm_pp_smu.h" +#include "clk_mgr_internal.h" extern struct wm_table ddr4_wm_table_gs; extern struct wm_table lpddr4_wm_table_gs; From aec208eecfb833b05597bbc28696fb1ab62f732c Mon Sep 17 00:00:00 2001 From: Daniel Phillips Date: Mon, 25 Jul 2022 08:48:00 -0700 Subject: [PATCH 093/427] drm/amdgpu: Remove rounding from vram allocation path Rounding up allocations in the allocation path caused test regressions, so now just round in the availability path. Signed-off-by: Daniel Phillips Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index a699134a1e8cf..2d2ef633c5618 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -40,10 +40,10 @@ #define AMDGPU_USERPTR_RESTORE_DELAY_MS 1 /* - * Align VRAM allocations to 2MB to avoid fragmentation caused by 4K allocations in the tail 2MB + * Align VRAM availability to 2MB to avoid fragmentation caused by 4K allocations in the tail 2MB * BO chunk */ -#define VRAM_ALLOCATION_ALIGN (1 << 21) +#define VRAM_AVAILABLITY_ALIGN (1 << 21) /* Impose limit on how much memory KFD can use */ static struct { @@ -149,7 +149,7 @@ int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev, * to avoid fragmentation caused by 4K allocations in the tail * 2M BO chunk. */ - vram_needed = ALIGN(size, VRAM_ALLOCATION_ALIGN); + vram_needed = size; } else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) { system_mem_needed = size; } else if (!(alloc_flag & @@ -204,7 +204,7 @@ void amdgpu_amdkfd_unreserve_mem_limit(struct amdgpu_device *adev, WARN_ONCE(!adev, "adev reference can't be null when alloc mem flags vram is set"); if (adev) - adev->kfd.vram_used -= ALIGN(size, VRAM_ALLOCATION_ALIGN); + adev->kfd.vram_used -= size; } else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) { kfd_mem_limit.system_mem_used -= size; } else if (!(alloc_flag & @@ -1608,7 +1608,6 @@ size_t amdgpu_amdkfd_get_available_memory(struct amdgpu_device *adev) uint64_t reserved_for_pt = ESTIMATE_PT_SIZE(amdgpu_amdkfd_total_mem_size); size_t available; - spin_lock(&kfd_mem_limit.mem_limit_lock); available = adev->gmc.real_vram_size - adev->kfd.vram_used @@ -1616,7 +1615,7 @@ size_t amdgpu_amdkfd_get_available_memory(struct amdgpu_device *adev) - reserved_for_pt; spin_unlock(&kfd_mem_limit.mem_limit_lock); - return ALIGN_DOWN(available, VRAM_ALLOCATION_ALIGN); + return ALIGN_DOWN(available, VRAM_AVAILABLITY_ALIGN); } int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( From 1ac354beecfd58e769fb5373d6b2ac87bce9e1e4 Mon Sep 17 00:00:00 2001 From: Daniel Phillips Date: Thu, 28 Jul 2022 20:05:08 -0700 Subject: [PATCH 094/427] drm/amdgpu: Pessimistic availability based on rounded up allocations Separately accumulate a statistic of rounded up allocations to use to report availability, with a view to increasing the likelihood a buffer object can be successfully allocated at exactly the size reported by the availability API. Signed-off-by: Daniel Phillips Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index 3c09dcc0986ee..647220a8762dc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -96,6 +96,7 @@ struct amdgpu_amdkfd_fence { struct amdgpu_kfd_dev { struct kfd_dev *dev; uint64_t vram_used; + uint64_t vram_used_aligned; bool init_complete; struct work_struct reset_work; }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 2d2ef633c5618..cbd593f7d553f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -182,8 +182,10 @@ int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev, */ WARN_ONCE(vram_needed && !adev, "adev reference can't be null when vram is used"); - if (adev) + if (adev) { adev->kfd.vram_used += vram_needed; + adev->kfd.vram_used_aligned += ALIGN(vram_needed, VRAM_AVAILABLITY_ALIGN); + } kfd_mem_limit.system_mem_used += system_mem_needed; kfd_mem_limit.ttm_mem_used += ttm_mem_needed; @@ -203,8 +205,10 @@ void amdgpu_amdkfd_unreserve_mem_limit(struct amdgpu_device *adev, } else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { WARN_ONCE(!adev, "adev reference can't be null when alloc mem flags vram is set"); - if (adev) + if (adev) { adev->kfd.vram_used -= size; + adev->kfd.vram_used_aligned -= ALIGN(size, VRAM_AVAILABLITY_ALIGN); + } } else if (alloc_flag & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) { kfd_mem_limit.system_mem_used -= size; } else if (!(alloc_flag & @@ -1610,7 +1614,7 @@ size_t amdgpu_amdkfd_get_available_memory(struct amdgpu_device *adev) size_t available; spin_lock(&kfd_mem_limit.mem_limit_lock); available = adev->gmc.real_vram_size - - adev->kfd.vram_used + - adev->kfd.vram_used_aligned - atomic64_read(&adev->vram_pin_size) - reserved_for_pt; spin_unlock(&kfd_mem_limit.mem_limit_lock); From 4a0a2cf4c03ba49a4c2596c49c7daa719917d509 Mon Sep 17 00:00:00 2001 From: Likun Gao Date: Wed, 3 Aug 2022 12:16:35 +0800 Subject: [PATCH 095/427] drm/amdgpu: change vram width algorithm for vram_info v3_0 Update the vram width algorithm for vram_info v3_0 to align with the changes of latest IFWI. Signed-off-by: Likun Gao Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 5.19.x --- drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index fd8f3731758ed..b81b77a9efa61 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -314,7 +314,7 @@ amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev, mem_channel_number = vram_info->v30.channel_num; mem_channel_width = vram_info->v30.channel_width; if (vram_width) - *vram_width = mem_channel_number * mem_channel_width; + *vram_width = mem_channel_number * (1 << mem_channel_width); break; default: return -EINVAL; From b2f6c73561fbccee404b441a5c2d0b4fefaae817 Mon Sep 17 00:00:00 2001 From: Magali Lemes Date: Fri, 29 Jul 2022 22:07:02 -0300 Subject: [PATCH 096/427] drm/amd/display: include missing headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing headers to solve the following warnings from sparse: drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn20/dcn20_fpu.c:656:17: warning: symbol 'ddr4_wm_table_gs' was not declared. Should it be static? drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn20/dcn20_fpu.c:693:17: warning: symbol 'lpddr4_wm_table_gs' was not declared. Should it be static? drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn20/dcn20_fpu.c:730:17: warning: symbol 'lpddr4_wm_table_with_disabled_ppt' was not declared. Should it be static? drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn20/dcn20_fpu.c:767:17: warning: symbol 'ddr4_wm_table_rn' was not declared. Should it be static? drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn20/dcn20_fpu.c:804:17: warning: symbol 'ddr4_1R_wm_table_rn' was not declared. Should it be static? drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn20/dcn20_fpu.c:841:17: warning: symbol 'lpddr4_wm_table_rn' was not declared. Should it be static? drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn301/dcn301_fpu.c:217:17: warning: symbol 'ddr4_wm_table' was not declared. Should it be static? drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn301/dcn301_fpu.c:254:17: warning: symbol 'lpddr5_wm_table' was not declared. Should it be static? drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn31/dcn31_fpu.c:53:30: warning: symbol 'dcn3_1_ip' was not declared. Should it be static? drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn31/dcn31_fpu.c:197:30: warning: symbol 'dcn3_15_ip' was not declared. Should it be static? drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn31/dcn31_fpu.c:293:30: warning: symbol 'dcn3_16_ip' was not declared. Should it be static? Fixes: 1a3408259bfd ("drm/amd/display: move FPU code on dcn21 clk_mgr") Fixes: 5085e0361f5a ("drm/amd/display: move FPU code from dcn301 clk mgr to DML folder") Fixes: 26f4712aedbd ("drm/amd/display: move FPU related code from dcn31 to dml/dcn31 folder") Fixes: fa896297b31b ("drm/amd/display: move FPU related code from dcn315 to dml/dcn31 folder") Fixes: 3f8951cc123f ("drm/amd/display: move FPU related code from dcn316 to dml/dcn31 folder") Signed-off-by: Magali Lemes Reviewed-by: Rodrigo Siqueira Reviewed-by: Maíra Canal Reviewed-by: Melissa Wen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 1 + drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c | 1 + drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c | 3 +++ 3 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c index ca44df4fca747..d34e0f1314d91 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c @@ -30,6 +30,7 @@ #include "dchubbub.h" #include "dcn20/dcn20_resource.h" #include "dcn21/dcn21_resource.h" +#include "clk_mgr/dcn21/rn_clk_mgr.h" #include "dcn20_fpu.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c index 7ef66e511ec8e..d211cf6d234c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c @@ -26,6 +26,7 @@ #include "clk_mgr.h" #include "dcn20/dcn20_resource.h" #include "dcn301/dcn301_resource.h" +#include "clk_mgr/dcn301/vg_clk_mgr.h" #include "dml/dcn20/dcn20_fpu.h" #include "dcn301_fpu.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c index 5664653ba5ac1..149a1b17cdf3f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c @@ -25,6 +25,9 @@ #include "resource.h" #include "clk_mgr.h" +#include "dcn31/dcn31_resource.h" +#include "dcn315/dcn315_resource.h" +#include "dcn316/dcn316_resource.h" #include "dml/dcn20/dcn20_fpu.h" #include "dcn31_fpu.h" From 0a83bb35d8a6ff3d18c2772afe616780c23293a6 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Wed, 3 Aug 2022 16:54:24 +0530 Subject: [PATCH 097/427] drm/amdgpu: Avoid another list of reset devices A list of devices to be reset is already created in amdgpu_device_gpu_recover function. Creating another list with the same nodes is incorrect and not supported in list_head. Instead, pass the device list as part of reset context. Fixes: 9e08564727fc (drm/amdgpu: Refactor mode2 reset logic for v13.0.2) Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/aldebaran.c | 45 +++++++--------------- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 + drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h | 1 + 3 files changed, 17 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/aldebaran.c b/drivers/gpu/drm/amd/amdgpu/aldebaran.c index c6cc493a54866..2b97b8a96fb49 100644 --- a/drivers/gpu/drm/amd/amdgpu/aldebaran.c +++ b/drivers/gpu/drm/amd/amdgpu/aldebaran.c @@ -148,30 +148,22 @@ aldebaran_mode2_perform_reset(struct amdgpu_reset_control *reset_ctl, struct amdgpu_reset_context *reset_context) { struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle; + struct list_head *reset_device_list = reset_context->reset_device_list; struct amdgpu_device *tmp_adev = NULL; - struct list_head reset_device_list; int r = 0; dev_dbg(adev->dev, "aldebaran perform hw reset\n"); + + if (reset_device_list == NULL) + return -EINVAL; + if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2) && reset_context->hive == NULL) { /* Wrong context, return error */ return -EINVAL; } - INIT_LIST_HEAD(&reset_device_list); - if (reset_context->hive) { - list_for_each_entry (tmp_adev, - &reset_context->hive->device_list, - gmc.xgmi.head) - list_add_tail(&tmp_adev->reset_list, - &reset_device_list); - } else { - list_add_tail(&reset_context->reset_req_dev->reset_list, - &reset_device_list); - } - - list_for_each_entry (tmp_adev, &reset_device_list, reset_list) { + list_for_each_entry(tmp_adev, reset_device_list, reset_list) { mutex_lock(&tmp_adev->reset_cntl->reset_lock); tmp_adev->reset_cntl->active_reset = AMD_RESET_METHOD_MODE2; } @@ -179,7 +171,7 @@ aldebaran_mode2_perform_reset(struct amdgpu_reset_control *reset_ctl, * Mode2 reset doesn't need any sync between nodes in XGMI hive, instead launch * them together so that they can be completed asynchronously on multiple nodes */ - list_for_each_entry (tmp_adev, &reset_device_list, reset_list) { + list_for_each_entry(tmp_adev, reset_device_list, reset_list) { /* For XGMI run all resets in parallel to speed up the process */ if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) { if (!queue_work(system_unbound_wq, @@ -197,7 +189,7 @@ aldebaran_mode2_perform_reset(struct amdgpu_reset_control *reset_ctl, /* For XGMI wait for all resets to complete before proceed */ if (!r) { - list_for_each_entry (tmp_adev, &reset_device_list, reset_list) { + list_for_each_entry(tmp_adev, reset_device_list, reset_list) { if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) { flush_work(&tmp_adev->reset_cntl->reset_work); r = tmp_adev->asic_reset_res; @@ -207,7 +199,7 @@ aldebaran_mode2_perform_reset(struct amdgpu_reset_control *reset_ctl, } } - list_for_each_entry (tmp_adev, &reset_device_list, reset_list) { + list_for_each_entry(tmp_adev, reset_device_list, reset_list) { mutex_unlock(&tmp_adev->reset_cntl->reset_lock); tmp_adev->reset_cntl->active_reset = AMD_RESET_METHOD_NONE; } @@ -339,10 +331,13 @@ static int aldebaran_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl, struct amdgpu_reset_context *reset_context) { + struct list_head *reset_device_list = reset_context->reset_device_list; struct amdgpu_device *tmp_adev = NULL; - struct list_head reset_device_list; int r; + if (reset_device_list == NULL) + return -EINVAL; + if (reset_context->reset_req_dev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2) && reset_context->hive == NULL) { @@ -350,19 +345,7 @@ aldebaran_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl, return -EINVAL; } - INIT_LIST_HEAD(&reset_device_list); - if (reset_context->hive) { - list_for_each_entry (tmp_adev, - &reset_context->hive->device_list, - gmc.xgmi.head) - list_add_tail(&tmp_adev->reset_list, - &reset_device_list); - } else { - list_add_tail(&reset_context->reset_req_dev->reset_list, - &reset_device_list); - } - - list_for_each_entry (tmp_adev, &reset_device_list, reset_list) { + list_for_each_entry(tmp_adev, reset_device_list, reset_list) { dev_info(tmp_adev->dev, "GPU reset succeeded, trying to resume\n"); r = aldebaran_mode2_restore_ip(tmp_adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index c4a6fe3070b6e..e8a0b19b73985 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4742,6 +4742,8 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle, tmp_adev = list_first_entry(device_list_handle, struct amdgpu_device, reset_list); amdgpu_reset_reg_dumps(tmp_adev); + + reset_context->reset_device_list = device_list_handle; r = amdgpu_reset_perform_reset(tmp_adev, reset_context); /* If reset handler not implemented, continue; otherwise return */ if (r == -ENOSYS) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h index 9e55a5d7a8253..ffda1560c6481 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h @@ -37,6 +37,7 @@ struct amdgpu_reset_context { struct amdgpu_device *reset_req_dev; struct amdgpu_job *job; struct amdgpu_hive_info *hive; + struct list_head *reset_device_list; unsigned long flags; }; From 616699d77b3813c24bf46090e722da227bd56cbf Mon Sep 17 00:00:00 2001 From: Ma Jun Date: Mon, 1 Aug 2022 09:52:47 +0800 Subject: [PATCH 098/427] drm/amdgpu: Remove redundant reference of header file Remove redundant reference of header file dev_printk.h Signed-off-by: Ma Jun Reviewed-by: Guchun Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/psp_v13_0.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c index 63b2d32545ccd..e8e0004bbb7aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c @@ -20,7 +20,6 @@ * OTHER DEALINGS IN THE SOFTWARE. * */ -#include #include #include "amdgpu.h" #include "amdgpu_psp.h" From 08ebadfcd8c8c1cc7a14a7581db8331147b85fbb Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Thu, 4 Aug 2022 16:44:56 +0800 Subject: [PATCH 099/427] drm/amd/display: change family id name for DCN314 GC version is 11.0.1 rather than 11.0.2 Signed-off-by: Yifan Zhang Reviewed-by: Roman Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 4 ++-- drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 4 ++-- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 2 +- drivers/gpu/drm/amd/display/include/dal_asic_id.h | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index 8cd25b2ea0dca..7e95232e93fe8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -660,7 +660,7 @@ static int get_plane_modifiers(struct amdgpu_device *adev, unsigned int plane_ty add_gfx10_1_modifiers(adev, mods, &size, &capacity); break; case AMDGPU_FAMILY_GC_11_0_0: - case AMDGPU_FAMILY_GC_11_0_2: + case AMDGPU_FAMILY_GC_11_0_1: add_gfx11_modifiers(adev, mods, &size, &capacity); break; } @@ -1412,7 +1412,7 @@ static bool dm_plane_format_mod_supported(struct drm_plane *plane, } break; case AMDGPU_FAMILY_GC_11_0_0: - case AMDGPU_FAMILY_GC_11_0_2: + case AMDGPU_FAMILY_GC_11_0_1: switch (AMD_FMT_MOD_GET(TILE, modifier)) { case AMD_FMT_MOD_TILE_GFX11_256K_R_X: case AMD_FMT_MOD_TILE_GFX9_64K_R_X: diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c index 4c76091fd1f21..f276abb63bcd7 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c @@ -337,7 +337,7 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p break; } - case AMDGPU_FAMILY_GC_11_0_2: { + case AMDGPU_FAMILY_GC_11_0_1: { struct clk_mgr_dcn314 *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); if (clk_mgr == NULL) { @@ -397,7 +397,7 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base) dcn32_clk_mgr_destroy(clk_mgr); break; - case AMDGPU_FAMILY_GC_11_0_2: + case AMDGPU_FAMILY_GC_11_0_1: dcn314_clk_mgr_destroy(clk_mgr); break; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e42f44fc1c08d..5d84adb6ea524 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -4292,7 +4292,7 @@ bool dc_is_dmub_outbox_supported(struct dc *dc) !dc->debug.dpia_debug.bits.disable_dpia) return true; - if (dc->ctx->asic_id.chip_family == AMDGPU_FAMILY_GC_11_0_2 && + if (dc->ctx->asic_id.chip_family == AMDGPU_FAMILY_GC_11_0_1 && !dc->debug.dpia_debug.bits.disable_dpia) return true; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 9e51338441d07..66d2ae7aacf5e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3372,7 +3372,7 @@ bool dc_link_setup_psr(struct dc_link *link, switch(link->ctx->asic_id.chip_family) { case FAMILY_YELLOW_CARP: case AMDGPU_FAMILY_GC_10_3_6: - case AMDGPU_FAMILY_GC_11_0_2: + case AMDGPU_FAMILY_GC_11_0_1: if(!dc->debug.disable_z10) psr_context->psr_level.bits.SKIP_CRTC_DISABLE = false; break; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ffc0f1c0ea93b..7dbab15bfa68f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -169,7 +169,7 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) if (ASICREV_IS_GC_11_0_2(asic_id.hw_internal_rev)) dc_version = DCN_VERSION_3_21; break; - case AMDGPU_FAMILY_GC_11_0_2: + case AMDGPU_FAMILY_GC_11_0_1: dc_version = DCN_VERSION_3_14; break; default: diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index 468a893ff7854..aedff18aff563 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -2153,7 +2153,7 @@ static bool dcn31_resource_construct( pool->base.usb4_dpia_count = 4; } - if (dc->ctx->asic_id.chip_family == AMDGPU_FAMILY_GC_11_0_2) + if (dc->ctx->asic_id.chip_family == AMDGPU_FAMILY_GC_11_0_1) pool->base.usb4_dpia_count = 4; /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index ab06c7fc74524..e054f3494087f 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -244,7 +244,7 @@ enum { #define ASICREV_IS_GC_10_3_7(eChipRev) ((eChipRev >= GC_10_3_7_A0) && (eChipRev < GC_10_3_7_UNKNOWN)) #define AMDGPU_FAMILY_GC_11_0_0 145 -#define AMDGPU_FAMILY_GC_11_0_2 148 +#define AMDGPU_FAMILY_GC_11_0_1 148 #define GC_11_0_0_A0 0x1 #define GC_11_0_2_A0 0x10 #define GC_11_UNKNOWN 0xFF From 8df436d5ccdf7f441becb8e8156c8ca9c4276e8c Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Fri, 29 Jul 2022 15:05:58 +0800 Subject: [PATCH 100/427] drm/amdgpu: add GFX Clock Gating support for GC IP v11.0.1 Add below GFX Clock Gating supports: 1. GFX Coarse Grain Clock Gating(CGCG) 2. GFX Coarse grain light sleep/deep sleep(CGLS) 3. GFX Medium Grain Clock Gating(MGCG) 4. GFX Fine Grain Clock Gating(FGCG) 5. Repeater Fine Grain Clock Gating 6. Perfmon Clock Gating Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc21.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 52816de5e17bf..b700c6cb14b48 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -586,6 +586,12 @@ static int soc21_common_early_init(void *handle) break; case IP_VERSION(11, 0, 1): adev->cg_flags = + AMD_CG_SUPPORT_GFX_CGCG | + AMD_CG_SUPPORT_GFX_CGLS | + AMD_CG_SUPPORT_GFX_MGCG | + AMD_CG_SUPPORT_GFX_FGCG | + AMD_CG_SUPPORT_REPEATER_FGCG | + AMD_CG_SUPPORT_GFX_PERF_CLK | AMD_CG_SUPPORT_VCN_MGCG | AMD_CG_SUPPORT_JPEG_MGCG; adev->pg_flags = From fb1a140b7bd19c474a41fb2df8a845e8eba328fa Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Fri, 29 Jul 2022 15:37:06 +0800 Subject: [PATCH 101/427] drm/amdgpu: enable GFX Clock Gating control for GC IP v11.0.1 Enable GFX CG gate/ungate control. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 6fd71cb10e54a..e03618803a1c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -5310,6 +5310,7 @@ static int gfx_v11_0_set_clockgating_state(void *handle, switch (adev->ip_versions[GC_HWIP][0]) { case IP_VERSION(11, 0, 0): + case IP_VERSION(11, 0, 1): case IP_VERSION(11, 0, 2): gfx_v11_0_update_gfx_clock_gating(adev, state == AMD_CG_STATE_GATE); From 64234eabb8f38ac2bf77dd23140887d81acaabe2 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Fri, 5 Aug 2022 15:16:16 +0800 Subject: [PATCH 102/427] drm/amdgpu/pm: update smu driver interface header for SMU IP v13.0.4 Update the SmuMetrics_t defination and SMU driver interface version. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Signed-off-by: Alex Deucher --- .../drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h index 76f695a1d0658..ae2d337158f3b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h @@ -27,7 +27,7 @@ // *** IMPORTANT *** // SMU TEAM: Always increment the interface version if // any structure is changed in this file -#define PMFW_DRIVER_IF_VERSION 4 +#define PMFW_DRIVER_IF_VERSION 5 typedef struct { int32_t value; @@ -197,6 +197,8 @@ typedef struct { uint16_t SkinTemp; uint16_t DeviceState; + uint16_t CurTemp; //[centi-Celsius] + uint16_t spare2; } SmuMetrics_t; typedef struct { From 1ff77beac87682c22f99e5cf32614909c65b4a36 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Fri, 5 Aug 2022 15:31:37 +0800 Subject: [PATCH 103/427] drm/amdgpu/pm: remove EnableGfxOff message for SMU IP v13.0.4 The EnableGfxOff message is dropped from the new PMFW ppsmc interface. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Signed-off-by: Alex Deucher --- .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c index 82d3718d83244..64665e8a86e4d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c @@ -71,7 +71,6 @@ static struct cmn2asic_msg_mapping smu_v13_0_4_message_map[SMU_MSG_MAX_COUNT] = MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1), MSG_MAP(GetSmuVersion, PPSMC_MSG_GetPmfwVersion, 1), MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1), - MSG_MAP(EnableGfxOff, PPSMC_MSG_EnableGfxOff, 1), MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 1), MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 1), MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 1), @@ -226,18 +225,6 @@ static int smu_v13_0_4_system_features_control(struct smu_context *smu, bool en) return ret; } -static int smu_v13_0_4_post_smu_init(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - int ret = 0; - - /* allow message will be sent after enable message */ - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_EnableGfxOff, NULL); - if (ret) - dev_err(adev->dev, "Failed to Enable GfxOff!\n"); - return ret; -} - static ssize_t smu_v13_0_4_get_gpu_metrics(struct smu_context *smu, void **table) { @@ -1026,7 +1013,6 @@ static const struct pptable_funcs smu_v13_0_4_ppt_funcs = { .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_driver_table_location = smu_v13_0_set_driver_table_location, .gfx_off_control = smu_v13_0_gfx_off_control, - .post_init = smu_v13_0_4_post_smu_init, .mode2_reset = smu_v13_0_4_mode2_reset, .get_dpm_ultimate_freq = smu_v13_0_4_get_dpm_ultimate_freq, .od_edit_dpm_table = smu_v13_0_od_edit_dpm_table, From 89390c4982b77c159e3b8a0be4a04552ef0971a0 Mon Sep 17 00:00:00 2001 From: Daniel Miess Date: Tue, 19 Jul 2022 14:07:41 -0400 Subject: [PATCH 104/427] drm/amd/display: Use pixels per container logic for DCN314 DCCG dividers [Why] DP DSC YCbCr422 not working because dcn314_calculate_dccg_k1_k2_values does not account for two pixels per container [How] Replace the contents of dcn314_calculate_dccg_k1_k2_values with the code from the function dcn32_calculate_dccg_k1_k2_values Reviewed-by: Charlene Liu Acked-by: Tom Chung Signed-off-by: Daniel Miess Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c index 755c715ad8dce..452f4a9bf251c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c @@ -343,7 +343,10 @@ unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsig { struct dc_stream_state *stream = pipe_ctx->stream; unsigned int odm_combine_factor = 0; + struct dc *dc = pipe_ctx->stream->ctx->dc; + bool two_pix_per_container = false; + two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing); odm_combine_factor = get_odm_config(pipe_ctx, NULL); if (is_dp_128b_132b_signal(pipe_ctx)) { @@ -355,16 +358,13 @@ unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsig else *k2_div = PIXEL_RATE_DIV_BY_4; } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) { - if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { + if (two_pix_per_container) { *k1_div = PIXEL_RATE_DIV_BY_1; *k2_div = PIXEL_RATE_DIV_BY_2; - } else if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) { - *k1_div = PIXEL_RATE_DIV_BY_2; - *k2_div = PIXEL_RATE_DIV_BY_2; } else { - if (odm_combine_factor == 1) - *k2_div = PIXEL_RATE_DIV_BY_4; - else if (odm_combine_factor == 2) + *k1_div = PIXEL_RATE_DIV_BY_1; + *k2_div = PIXEL_RATE_DIV_BY_4; + if ((odm_combine_factor == 2) || dc->debug.enable_dp_dig_pixel_rate_div_policy) *k2_div = PIXEL_RATE_DIV_BY_2; } } From 4c3861f587400db00801810eb8034c7b480e21dd Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 19 Jul 2022 16:28:50 -0400 Subject: [PATCH 105/427] drm/amd/display: Create FPU files for DCN314 DCN314 has multiple references to FPU operations inside the resource files, and we need to move those codes to the DML folder. This commit creates the dcn314_fpu files and moves the bounding box operation to this file. Reviewed-by: Nicholas Kazlauskas Acked-by: Tom Chung Signed-off-by: Rodrigo Siqueira Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn314/dcn314_resource.c | 235 +--------------- .../amd/display/dc/dcn314/dcn314_resource.h | 3 + drivers/gpu/drm/amd/display/dc/dml/Makefile | 2 + .../amd/display/dc/dml/dcn314/dcn314_fpu.c | 266 ++++++++++++++++++ .../amd/display/dc/dml/dcn314/dcn314_fpu.h | 37 +++ 5 files changed, 312 insertions(+), 231 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.h diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c index 63861cdfb09f2..376488198363e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c @@ -70,6 +70,7 @@ #include "dce110/dce110_resource.h" #include "dml/display_mode_vba.h" #include "dml/dcn31/dcn31_fpu.h" +#include "dml/dcn314/dcn314_fpu.h" #include "dcn314/dcn314_dccg.h" #include "dcn10/dcn10_resource.h" #include "dcn31/dcn31_panel_cntl.h" @@ -132,155 +133,6 @@ static const struct IP_BASE DCN_BASE = { { { { 0x00000012, 0x000000C0, 0x000034C #define DC_LOGGER_INIT(logger) -#define DCN3_14_DEFAULT_DET_SIZE 384 -#define DCN3_14_MAX_DET_SIZE 384 -#define DCN3_14_MIN_COMPBUF_SIZE_KB 128 -#define DCN3_14_CRB_SEGMENT_SIZE_KB 64 -struct _vcs_dpi_ip_params_st dcn3_14_ip = { - .VBlankNomDefaultUS = 668, - .gpuvm_enable = 1, - .gpuvm_max_page_table_levels = 1, - .hostvm_enable = 1, - .hostvm_max_page_table_levels = 2, - .rob_buffer_size_kbytes = 64, - .det_buffer_size_kbytes = DCN3_14_DEFAULT_DET_SIZE, - .config_return_buffer_size_in_kbytes = 1792, - .compressed_buffer_segment_size_in_kbytes = 64, - .meta_fifo_size_in_kentries = 32, - .zero_size_buffer_entries = 512, - .compbuf_reserved_space_64b = 256, - .compbuf_reserved_space_zs = 64, - .dpp_output_buffer_pixels = 2560, - .opp_output_buffer_lines = 1, - .pixel_chunk_size_kbytes = 8, - .meta_chunk_size_kbytes = 2, - .min_meta_chunk_size_bytes = 256, - .writeback_chunk_size_kbytes = 8, - .ptoi_supported = false, - .num_dsc = 4, - .maximum_dsc_bits_per_component = 10, - .dsc422_native_support = false, - .is_line_buffer_bpp_fixed = true, - .line_buffer_fixed_bpp = 48, - .line_buffer_size_bits = 789504, - .max_line_buffer_lines = 12, - .writeback_interface_buffer_size_kbytes = 90, - .max_num_dpp = 4, - .max_num_otg = 4, - .max_num_hdmi_frl_outputs = 1, - .max_num_wb = 1, - .max_dchub_pscl_bw_pix_per_clk = 4, - .max_pscl_lb_bw_pix_per_clk = 2, - .max_lb_vscl_bw_pix_per_clk = 4, - .max_vscl_hscl_bw_pix_per_clk = 4, - .max_hscl_ratio = 6, - .max_vscl_ratio = 6, - .max_hscl_taps = 8, - .max_vscl_taps = 8, - .dpte_buffer_size_in_pte_reqs_luma = 64, - .dpte_buffer_size_in_pte_reqs_chroma = 34, - .dispclk_ramp_margin_percent = 1, - .max_inter_dcn_tile_repeaters = 8, - .cursor_buffer_size = 16, - .cursor_chunk_size = 2, - .writeback_line_buffer_buffer_size = 0, - .writeback_min_hscl_ratio = 1, - .writeback_min_vscl_ratio = 1, - .writeback_max_hscl_ratio = 1, - .writeback_max_vscl_ratio = 1, - .writeback_max_hscl_taps = 1, - .writeback_max_vscl_taps = 1, - .dppclk_delay_subtotal = 46, - .dppclk_delay_scl = 50, - .dppclk_delay_scl_lb_only = 16, - .dppclk_delay_cnvc_formatter = 27, - .dppclk_delay_cnvc_cursor = 6, - .dispclk_delay_subtotal = 119, - .dynamic_metadata_vm_enabled = false, - .odm_combine_4to1_supported = false, - .dcc_supported = true, -}; - -struct _vcs_dpi_soc_bounding_box_st dcn3_14_soc = { - /*TODO: correct dispclk/dppclk voltage level determination*/ - .clock_limits = { - { - .state = 0, - .dispclk_mhz = 1200.0, - .dppclk_mhz = 1200.0, - .phyclk_mhz = 600.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 186.0, - .dtbclk_mhz = 625.0, - }, - { - .state = 1, - .dispclk_mhz = 1200.0, - .dppclk_mhz = 1200.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 209.0, - .dtbclk_mhz = 625.0, - }, - { - .state = 2, - .dispclk_mhz = 1200.0, - .dppclk_mhz = 1200.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 209.0, - .dtbclk_mhz = 625.0, - }, - { - .state = 3, - .dispclk_mhz = 1200.0, - .dppclk_mhz = 1200.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 371.0, - .dtbclk_mhz = 625.0, - }, - { - .state = 4, - .dispclk_mhz = 1200.0, - .dppclk_mhz = 1200.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 417.0, - .dtbclk_mhz = 625.0, - }, - }, - .num_states = 5, - .sr_exit_time_us = 9.0, - .sr_enter_plus_exit_time_us = 11.0, - .sr_exit_z8_time_us = 442.0, - .sr_enter_plus_exit_z8_time_us = 560.0, - .writeback_latency_us = 12.0, - .dram_channel_width_bytes = 4, - .round_trip_ping_latency_dcfclk_cycles = 106, - .urgent_latency_pixel_data_only_us = 4.0, - .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, - .urgent_latency_vm_data_only_us = 4.0, - .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, - .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, - .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, - .pct_ideal_sdp_bw_after_urgent = 80.0, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 65.0, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 60.0, - .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 30.0, - .max_avg_sdp_bw_use_normal_percent = 60.0, - .max_avg_dram_bw_use_normal_percent = 60.0, - .fabric_datapath_to_dcn_data_return_bytes = 32, - .return_bus_width_bytes = 64, - .downspread_percent = 0.38, - .dcn_downspread_percent = 0.5, - .gpuvm_min_page_size_bytes = 4096, - .hostvm_min_page_size_bytes = 4096, - .do_urgent_latency_adjustment = false, - .urgent_latency_adjustment_fabric_clock_component_us = 0, - .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, -}; - enum dcn31_clk_src_array_id { DCN31_CLK_SRC_PLL0, DCN31_CLK_SRC_PLL1, @@ -1906,88 +1758,9 @@ static struct dc_cap_funcs cap_funcs = { static void dcn314_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) { - struct clk_limit_table *clk_table = &bw_params->clk_table; - struct _vcs_dpi_voltage_scaling_st *clock_tmp = dcn3_14_soc._clock_tmp; - unsigned int i, closest_clk_lvl; - int max_dispclk_mhz = 0, max_dppclk_mhz = 0; - int j; - - // Default clock levels are used for diags, which may lead to overclocking. - if (!IS_DIAG_DC(dc->ctx->dce_environment)) { - - dcn3_14_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator; - dcn3_14_ip.max_num_dpp = dc->res_pool->pipe_count; - - if (bw_params->num_channels > 0) - dcn3_14_soc.num_chans = bw_params->num_channels; - - ASSERT(dcn3_14_soc.num_chans); - ASSERT(clk_table->num_entries); - - /* Prepass to find max clocks independent of voltage level. */ - for (i = 0; i < clk_table->num_entries; ++i) { - if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz) - max_dispclk_mhz = clk_table->entries[i].dispclk_mhz; - if (clk_table->entries[i].dppclk_mhz > max_dppclk_mhz) - max_dppclk_mhz = clk_table->entries[i].dppclk_mhz; - } - - for (i = 0; i < clk_table->num_entries; i++) { - /* loop backwards*/ - for (closest_clk_lvl = 0, j = dcn3_14_soc.num_states - 1; j >= 0; j--) { - if ((unsigned int) dcn3_14_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) { - closest_clk_lvl = j; - break; - } - } - if (clk_table->num_entries == 1) { - /*smu gives one DPM level, let's take the highest one*/ - closest_clk_lvl = dcn3_14_soc.num_states - 1; - } - - clock_tmp[i].state = i; - - /* Clocks dependent on voltage level. */ - clock_tmp[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; - if (clk_table->num_entries == 1 && - clock_tmp[i].dcfclk_mhz < dcn3_14_soc.clock_limits[closest_clk_lvl].dcfclk_mhz) { - /*SMU fix not released yet*/ - clock_tmp[i].dcfclk_mhz = dcn3_14_soc.clock_limits[closest_clk_lvl].dcfclk_mhz; - } - clock_tmp[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; - clock_tmp[i].socclk_mhz = clk_table->entries[i].socclk_mhz; - - if (clk_table->entries[i].memclk_mhz && clk_table->entries[i].wck_ratio) - clock_tmp[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2 * clk_table->entries[i].wck_ratio; - - /* Clocks independent of voltage level. */ - clock_tmp[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz : - dcn3_14_soc.clock_limits[closest_clk_lvl].dispclk_mhz; - - clock_tmp[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz : - dcn3_14_soc.clock_limits[closest_clk_lvl].dppclk_mhz; - - clock_tmp[i].dram_bw_per_chan_gbps = dcn3_14_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; - clock_tmp[i].dscclk_mhz = dcn3_14_soc.clock_limits[closest_clk_lvl].dscclk_mhz; - clock_tmp[i].dtbclk_mhz = dcn3_14_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; - clock_tmp[i].phyclk_d18_mhz = dcn3_14_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; - clock_tmp[i].phyclk_mhz = dcn3_14_soc.clock_limits[closest_clk_lvl].phyclk_mhz; - } - for (i = 0; i < clk_table->num_entries; i++) - dcn3_14_soc.clock_limits[i] = clock_tmp[i]; - if (clk_table->num_entries) - dcn3_14_soc.num_states = clk_table->num_entries; - } - - if (max_dispclk_mhz) { - dcn3_14_soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; - dc->dml.soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; - } - - if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - dml_init_instance(&dc->dml, &dcn3_14_soc, &dcn3_14_ip, DML_PROJECT_DCN31); - else - dml_init_instance(&dc->dml, &dcn3_14_soc, &dcn3_14_ip, DML_PROJECT_DCN31_FPGA); + DC_FP_START(); + dcn314_update_bw_bounding_box_fpu(dc, bw_params); + DC_FP_END(); } static struct resource_funcs dcn314_res_pool_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.h b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.h index c41108847ce08..0dd3153aa5c17 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.h @@ -29,6 +29,9 @@ #include "core_types.h" +extern struct _vcs_dpi_ip_params_st dcn3_14_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn3_14_soc; + #define TO_DCN314_RES_POOL(pool)\ container_of(pool, struct dcn314_resource_pool, base) diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 41bb6c3cc2d8b..86a3b5bfd699b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -70,6 +70,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) $(fram CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) $(frame_warn_flag) CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml/dcn314/dcn314_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/dcn30_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn32/dcn32_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn32/display_mode_vba_32.o := $(dml_ccflags) $(frame_warn_flag) @@ -129,6 +130,7 @@ DML += dcn321/dcn321_fpu.o DML += dcn301/dcn301_fpu.o DML += dcn302/dcn302_fpu.o DML += dcn303/dcn303_fpu.o +DML += dcn314/dcn314_fpu.o DML += dsc/rc_calc_fpu.o DML += calcs/dcn_calcs.o calcs/dcn_calc_math.o calcs/dcn_calc_auto.o endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c new file mode 100644 index 0000000000000..340c3ca223454 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "clk_mgr.h" +#include "resource.h" +#include "dcn314_fpu.h" +#include "dml/display_mode_vba.h" + +struct _vcs_dpi_ip_params_st dcn3_14_ip = { + .VBlankNomDefaultUS = 668, + .gpuvm_enable = 1, + .gpuvm_max_page_table_levels = 1, + .hostvm_enable = 1, + .hostvm_max_page_table_levels = 2, + .rob_buffer_size_kbytes = 64, + .det_buffer_size_kbytes = DCN3_14_DEFAULT_DET_SIZE, + .config_return_buffer_size_in_kbytes = 1792, + .compressed_buffer_segment_size_in_kbytes = 64, + .meta_fifo_size_in_kentries = 32, + .zero_size_buffer_entries = 512, + .compbuf_reserved_space_64b = 256, + .compbuf_reserved_space_zs = 64, + .dpp_output_buffer_pixels = 2560, + .opp_output_buffer_lines = 1, + .pixel_chunk_size_kbytes = 8, + .meta_chunk_size_kbytes = 2, + .min_meta_chunk_size_bytes = 256, + .writeback_chunk_size_kbytes = 8, + .ptoi_supported = false, + .num_dsc = 4, + .maximum_dsc_bits_per_component = 10, + .dsc422_native_support = false, + .is_line_buffer_bpp_fixed = true, + .line_buffer_fixed_bpp = 48, + .line_buffer_size_bits = 789504, + .max_line_buffer_lines = 12, + .writeback_interface_buffer_size_kbytes = 90, + .max_num_dpp = 4, + .max_num_otg = 4, + .max_num_hdmi_frl_outputs = 1, + .max_num_wb = 1, + .max_dchub_pscl_bw_pix_per_clk = 4, + .max_pscl_lb_bw_pix_per_clk = 2, + .max_lb_vscl_bw_pix_per_clk = 4, + .max_vscl_hscl_bw_pix_per_clk = 4, + .max_hscl_ratio = 6, + .max_vscl_ratio = 6, + .max_hscl_taps = 8, + .max_vscl_taps = 8, + .dpte_buffer_size_in_pte_reqs_luma = 64, + .dpte_buffer_size_in_pte_reqs_chroma = 34, + .dispclk_ramp_margin_percent = 1, + .max_inter_dcn_tile_repeaters = 8, + .cursor_buffer_size = 16, + .cursor_chunk_size = 2, + .writeback_line_buffer_buffer_size = 0, + .writeback_min_hscl_ratio = 1, + .writeback_min_vscl_ratio = 1, + .writeback_max_hscl_ratio = 1, + .writeback_max_vscl_ratio = 1, + .writeback_max_hscl_taps = 1, + .writeback_max_vscl_taps = 1, + .dppclk_delay_subtotal = 46, + .dppclk_delay_scl = 50, + .dppclk_delay_scl_lb_only = 16, + .dppclk_delay_cnvc_formatter = 27, + .dppclk_delay_cnvc_cursor = 6, + .dispclk_delay_subtotal = 119, + .dynamic_metadata_vm_enabled = false, + .odm_combine_4to1_supported = false, + .dcc_supported = true, +}; + +struct _vcs_dpi_soc_bounding_box_st dcn3_14_soc = { + /*TODO: correct dispclk/dppclk voltage level determination*/ + .clock_limits = { + { + .state = 0, + .dispclk_mhz = 1200.0, + .dppclk_mhz = 1200.0, + .phyclk_mhz = 600.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 186.0, + .dtbclk_mhz = 625.0, + }, + { + .state = 1, + .dispclk_mhz = 1200.0, + .dppclk_mhz = 1200.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 209.0, + .dtbclk_mhz = 625.0, + }, + { + .state = 2, + .dispclk_mhz = 1200.0, + .dppclk_mhz = 1200.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 209.0, + .dtbclk_mhz = 625.0, + }, + { + .state = 3, + .dispclk_mhz = 1200.0, + .dppclk_mhz = 1200.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 371.0, + .dtbclk_mhz = 625.0, + }, + { + .state = 4, + .dispclk_mhz = 1200.0, + .dppclk_mhz = 1200.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 417.0, + .dtbclk_mhz = 625.0, + }, + }, + .num_states = 5, + .sr_exit_time_us = 9.0, + .sr_enter_plus_exit_time_us = 11.0, + .sr_exit_z8_time_us = 442.0, + .sr_enter_plus_exit_z8_time_us = 560.0, + .writeback_latency_us = 12.0, + .dram_channel_width_bytes = 4, + .round_trip_ping_latency_dcfclk_cycles = 106, + .urgent_latency_pixel_data_only_us = 4.0, + .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, + .urgent_latency_vm_data_only_us = 4.0, + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, + .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, + .pct_ideal_sdp_bw_after_urgent = 80.0, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 65.0, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 60.0, + .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 30.0, + .max_avg_sdp_bw_use_normal_percent = 60.0, + .max_avg_dram_bw_use_normal_percent = 60.0, + .fabric_datapath_to_dcn_data_return_bytes = 32, + .return_bus_width_bytes = 64, + .downspread_percent = 0.38, + .dcn_downspread_percent = 0.5, + .gpuvm_min_page_size_bytes = 4096, + .hostvm_min_page_size_bytes = 4096, + .do_urgent_latency_adjustment = false, + .urgent_latency_adjustment_fabric_clock_component_us = 0, + .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, +}; + + +void dcn314_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params) +{ + struct clk_limit_table *clk_table = &bw_params->clk_table; + struct _vcs_dpi_voltage_scaling_st *clock_limits = + dcn3_14_soc.clock_limits; + unsigned int i, closest_clk_lvl; + int max_dispclk_mhz = 0, max_dppclk_mhz = 0; + int j; + + dc_assert_fp_enabled(); + + // Default clock levels are used for diags, which may lead to overclocking. + if (!IS_DIAG_DC(dc->ctx->dce_environment)) { + + dcn3_14_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator; + dcn3_14_ip.max_num_dpp = dc->res_pool->pipe_count; + + if (bw_params->num_channels > 0) + dcn3_14_soc.num_chans = bw_params->num_channels; + + ASSERT(dcn3_14_soc.num_chans); + ASSERT(clk_table->num_entries); + + /* Prepass to find max clocks independent of voltage level. */ + for (i = 0; i < clk_table->num_entries; ++i) { + if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz) + max_dispclk_mhz = clk_table->entries[i].dispclk_mhz; + if (clk_table->entries[i].dppclk_mhz > max_dppclk_mhz) + max_dppclk_mhz = clk_table->entries[i].dppclk_mhz; + } + + for (i = 0; i < clk_table->num_entries; i++) { + /* loop backwards*/ + for (closest_clk_lvl = 0, j = dcn3_14_soc.num_states - 1; j >= 0; j--) { + if ((unsigned int) dcn3_14_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) { + closest_clk_lvl = j; + break; + } + } + if (clk_table->num_entries == 1) { + /*smu gives one DPM level, let's take the highest one*/ + closest_clk_lvl = dcn3_14_soc.num_states - 1; + } + + clock_limits[i].state = i; + + /* Clocks dependent on voltage level. */ + clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; + if (clk_table->num_entries == 1 && + clock_limits[i].dcfclk_mhz < dcn3_14_soc.clock_limits[closest_clk_lvl].dcfclk_mhz) { + /*SMU fix not released yet*/ + clock_limits[i].dcfclk_mhz = dcn3_14_soc.clock_limits[closest_clk_lvl].dcfclk_mhz; + } + clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; + clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz; + + if (clk_table->entries[i].memclk_mhz && clk_table->entries[i].wck_ratio) + clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2 * clk_table->entries[i].wck_ratio; + + /* Clocks independent of voltage level. */ + clock_limits[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz : + dcn3_14_soc.clock_limits[closest_clk_lvl].dispclk_mhz; + + clock_limits[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz : + dcn3_14_soc.clock_limits[closest_clk_lvl].dppclk_mhz; + + clock_limits[i].dram_bw_per_chan_gbps = dcn3_14_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; + clock_limits[i].dscclk_mhz = dcn3_14_soc.clock_limits[closest_clk_lvl].dscclk_mhz; + clock_limits[i].dtbclk_mhz = dcn3_14_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; + clock_limits[i].phyclk_d18_mhz = dcn3_14_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; + clock_limits[i].phyclk_mhz = dcn3_14_soc.clock_limits[closest_clk_lvl].phyclk_mhz; + } + for (i = 0; i < clk_table->num_entries; i++) + dcn3_14_soc.clock_limits[i] = clock_limits[i]; + if (clk_table->num_entries) { + dcn3_14_soc.num_states = clk_table->num_entries; + } + } + + if (max_dispclk_mhz) { + dcn3_14_soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; + dc->dml.soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; + } + + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) + dml_init_instance(&dc->dml, &dcn3_14_soc, &dcn3_14_ip, DML_PROJECT_DCN31); + else + dml_init_instance(&dc->dml, &dcn3_14_soc, &dcn3_14_ip, DML_PROJECT_DCN31_FPGA); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.h new file mode 100644 index 0000000000000..79466d4f41851 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DCN314_FPU_H__ +#define __DCN314_FPU_H__ + +#define DCN3_14_DEFAULT_DET_SIZE 384 +#define DCN3_14_MAX_DET_SIZE 384 +#define DCN3_14_MIN_COMPBUF_SIZE_KB 128 +#define DCN3_14_CRB_SEGMENT_SIZE_KB 64 + +void dcn314_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params); + +#endif From 67c79599eea167dd5e08314b8c26f2dfa717753a Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 19 Jul 2022 16:57:23 -0400 Subject: [PATCH 106/427] drm/amd/display: Move populate dml pipes from DCN314 to dml The function responsible for populating DML pipes has some FPU operations, and for this reason, it must be moved to the dml folder. This commit moves such function from resource to the fpu file under the dml folder. Reviewed-by: Nicholas Kazlauskas Acked-by: Tom Chung Signed-off-by: Rodrigo Siqueira Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn314/dcn314_resource.c | 101 +--------------- .../amd/display/dc/dml/dcn314/dcn314_fpu.c | 110 ++++++++++++++++++ .../amd/display/dc/dml/dcn314/dcn314_fpu.h | 3 + 3 files changed, 117 insertions(+), 97 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c index 376488198363e..1f095f05d9865 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c @@ -1645,109 +1645,16 @@ static struct clock_source *dcn31_clock_source_create( return NULL; } -static bool is_dual_plane(enum surface_pixel_format format) -{ - return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA; -} - static int dcn314_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, bool fast_validate) { - int i, pipe_cnt; - struct resource_context *res_ctx = &context->res_ctx; - struct pipe_ctx *pipe; - bool upscaled = false; - - dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); - - for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { - struct dc_crtc_timing *timing; - - if (!res_ctx->pipe_ctx[i].stream) - continue; - pipe = &res_ctx->pipe_ctx[i]; - timing = &pipe->stream->timing; - - if (dc_extended_blank_supported(dc) && pipe->stream->adjust.v_total_max == pipe->stream->adjust.v_total_min - && pipe->stream->adjust.v_total_min > timing->v_total) - pipes[pipe_cnt].pipe.dest.vtotal = pipe->stream->adjust.v_total_min; - - if (pipe->plane_state && - (pipe->plane_state->src_rect.height < pipe->plane_state->dst_rect.height || - pipe->plane_state->src_rect.width < pipe->plane_state->dst_rect.width)) - upscaled = true; - - /* - * Immediate flip can be set dynamically after enabling the plane. - * We need to require support for immediate flip or underflow can be - * intermittently experienced depending on peak b/w requirements. - */ - pipes[pipe_cnt].pipe.src.immediate_flip = true; - - pipes[pipe_cnt].pipe.src.unbounded_req_mode = false; - pipes[pipe_cnt].pipe.src.hostvm = dc->res_pool->hubbub->riommu_active; - pipes[pipe_cnt].pipe.src.gpuvm = true; - pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_luma = 0; - pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_chroma = 0; - pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; - pipes[pipe_cnt].pipe.src.dcc_rate = 3; - pipes[pipe_cnt].dout.dsc_input_bpc = 0; - - if (pipes[pipe_cnt].dout.dsc_enable) { - switch (timing->display_color_depth) { - case COLOR_DEPTH_888: - pipes[pipe_cnt].dout.dsc_input_bpc = 8; - break; - case COLOR_DEPTH_101010: - pipes[pipe_cnt].dout.dsc_input_bpc = 10; - break; - case COLOR_DEPTH_121212: - pipes[pipe_cnt].dout.dsc_input_bpc = 12; - break; - default: - ASSERT(0); - break; - } - } - - pipe_cnt++; - } - context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_14_DEFAULT_DET_SIZE; - - dc->config.enable_4to1MPC = false; - if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) { - if (is_dual_plane(pipe->plane_state->format) - && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) { - dc->config.enable_4to1MPC = true; - } else if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) { - /* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */ - context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; - pipes[0].pipe.src.unbounded_req_mode = true; - } - } else if (context->stream_count >= dc->debug.crb_alloc_policy_min_disp_count - && dc->debug.crb_alloc_policy > DET_SIZE_DEFAULT) { - context->bw_ctx.dml.ip.det_buffer_size_kbytes = dc->debug.crb_alloc_policy * 64; - } else if (context->stream_count >= 3 && upscaled) { - context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; - } - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - if (!pipe->stream) - continue; + int pipe_cnt; - if (pipe->stream->signal == SIGNAL_TYPE_EDP && dc->debug.seamless_boot_odm_combine && - pipe->stream->apply_seamless_boot_optimization) { - - if (pipe->stream->apply_boot_odm_mode == dm_odm_combine_policy_2to1) { - context->bw_ctx.dml.vba.ODMCombinePolicy = dm_odm_combine_policy_2to1; - break; - } - } - } + DC_FP_START(); + pipe_cnt = dcn314_populate_dml_pipes_from_context_fpu(dc, context, pipes, fast_validate); + DC_FP_END(); return pipe_cnt; } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c index 340c3ca223454..d52a16d280e98 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c @@ -26,7 +26,9 @@ #include "clk_mgr.h" #include "resource.h" +#include "dcn31/dcn31_hubbub.h" #include "dcn314_fpu.h" +#include "dml/dcn20/dcn20_fpu.h" #include "dml/display_mode_vba.h" struct _vcs_dpi_ip_params_st dcn3_14_ip = { @@ -264,3 +266,111 @@ void dcn314_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p else dml_init_instance(&dc->dml, &dcn3_14_soc, &dcn3_14_ip, DML_PROJECT_DCN31_FPGA); } + +static bool is_dual_plane(enum surface_pixel_format format) +{ + return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA; +} + +int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate) +{ + int i, pipe_cnt; + struct resource_context *res_ctx = &context->res_ctx; + struct pipe_ctx *pipe; + bool upscaled = false; + + dc_assert_fp_enabled(); + + dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + + for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { + struct dc_crtc_timing *timing; + + if (!res_ctx->pipe_ctx[i].stream) + continue; + pipe = &res_ctx->pipe_ctx[i]; + timing = &pipe->stream->timing; + + if (dc_extended_blank_supported(dc) && pipe->stream->adjust.v_total_max == pipe->stream->adjust.v_total_min + && pipe->stream->adjust.v_total_min > timing->v_total) + pipes[pipe_cnt].pipe.dest.vtotal = pipe->stream->adjust.v_total_min; + + if (pipe->plane_state && + (pipe->plane_state->src_rect.height < pipe->plane_state->dst_rect.height || + pipe->plane_state->src_rect.width < pipe->plane_state->dst_rect.width)) + upscaled = true; + + /* + * Immediate flip can be set dynamically after enabling the plane. + * We need to require support for immediate flip or underflow can be + * intermittently experienced depending on peak b/w requirements. + */ + pipes[pipe_cnt].pipe.src.immediate_flip = true; + + pipes[pipe_cnt].pipe.src.unbounded_req_mode = false; + pipes[pipe_cnt].pipe.src.hostvm = dc->res_pool->hubbub->riommu_active; + pipes[pipe_cnt].pipe.src.gpuvm = true; + pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_luma = 0; + pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_chroma = 0; + pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; + pipes[pipe_cnt].pipe.src.dcc_rate = 3; + pipes[pipe_cnt].dout.dsc_input_bpc = 0; + + if (pipes[pipe_cnt].dout.dsc_enable) { + switch (timing->display_color_depth) { + case COLOR_DEPTH_888: + pipes[pipe_cnt].dout.dsc_input_bpc = 8; + break; + case COLOR_DEPTH_101010: + pipes[pipe_cnt].dout.dsc_input_bpc = 10; + break; + case COLOR_DEPTH_121212: + pipes[pipe_cnt].dout.dsc_input_bpc = 12; + break; + default: + ASSERT(0); + break; + } + } + + pipe_cnt++; + } + context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_14_DEFAULT_DET_SIZE; + + dc->config.enable_4to1MPC = false; + if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) { + if (is_dual_plane(pipe->plane_state->format) + && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) { + dc->config.enable_4to1MPC = true; + } else if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) { + /* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */ + context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; + pipes[0].pipe.src.unbounded_req_mode = true; + } + } else if (context->stream_count >= dc->debug.crb_alloc_policy_min_disp_count + && dc->debug.crb_alloc_policy > DET_SIZE_DEFAULT) { + context->bw_ctx.dml.ip.det_buffer_size_kbytes = dc->debug.crb_alloc_policy * 64; + } else if (context->stream_count >= 3 && upscaled) { + context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (!pipe->stream) + continue; + + if (pipe->stream->signal == SIGNAL_TYPE_EDP && dc->debug.seamless_boot_odm_combine && + pipe->stream->apply_seamless_boot_optimization) { + + if (pipe->stream->apply_boot_odm_mode == dm_odm_combine_policy_2to1) { + context->bw_ctx.dml.vba.ODMCombinePolicy = dm_odm_combine_policy_2to1; + break; + } + } + } + + return pipe_cnt; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.h index 79466d4f41851..d32c5bb99f4c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.h @@ -33,5 +33,8 @@ #define DCN3_14_CRB_SEGMENT_SIZE_KB 64 void dcn314_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params); +int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate); #endif From 0af167f92838f34e594e49a6c8cbaca45548e030 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 19 Jul 2022 17:02:56 -0400 Subject: [PATCH 107/427] drm/amd/display: Drop FPU flags from Makefile At this point, we isolate the FPU code associated with DCN314 under the DML folder. This commit drops the FPU flags from the Makefile. Reviewed-by: Nicholas Kazlauskas Acked-by: Tom Chung Signed-off-by: Rodrigo Siqueira Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn314/Makefile | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/Makefile b/drivers/gpu/drm/amd/display/dc/dcn314/Makefile index e3b5a95e03b19..702c28c2560eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn314/Makefile @@ -13,31 +13,6 @@ DCN314 = dcn314_resource.o dcn314_hwseq.o dcn314_init.o \ dcn314_dio_stream_encoder.o dcn314_dccg.o dcn314_optc.o -ifdef CONFIG_X86 -CFLAGS_$(AMDDALPATH)/dc/dcn314/dcn314_resource.o := -mhard-float -msse -endif - -ifdef CONFIG_PPC64 -CFLAGS_$(AMDDALPATH)/dc/dcn314/dcn314_resource.o := -mhard-float -maltivec -endif - -ifdef CONFIG_CC_IS_GCC -ifeq ($(call cc-ifversion, -lt, 0701, y), y) -IS_OLD_GCC = 1 -endif -endif - -ifdef CONFIG_X86 -ifdef IS_OLD_GCC -# Stack alignment mismatch, proceed with caution. -# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3 -# (8B stack alignment). -CFLAGS_$(AMDDALPATH)/dc/dcn314/dcn314_resource.o += -mpreferred-stack-boundary=4 -else -CFLAGS_$(AMDDALPATH)/dc/dcn314/dcn314_resource.o += -msse2 -endif -endif - AMD_DAL_DCN314 = $(addprefix $(AMDDALPATH)/dc/dcn314/,$(DCN314)) AMD_DISPLAY_FILES += $(AMD_DAL_DCN314) From 2de09ce41f484cbcc65e518905dae73da67ad35c Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Fri, 15 Jul 2022 14:59:26 -0400 Subject: [PATCH 108/427] drm/amd/display: fix CAB allocation for multiple displays [Why & How] When multiple displays are used, the underlying framebuffers could be two separate framebuffers, or a single large framebuffer. Fix the calculation logic for CAB to account for large framebuffer. Current logic assumes that any FB that the plane points to are independent. When a single FB is used on the system, this does 2 times allocation. Add a check to prevent duplicate allocation by checking if the base addresses are the same, and then ensuring that the if we allocate using the pitch, whole of the other fbs will be accounted for in the first allocation. Reviewed-by: Alvin Lee Acked-by: Tom Chung Signed-off-by: Aurabindo Pillai Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c index d38341f68b172..5ba503d807288 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c @@ -250,6 +250,7 @@ static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *c uint32_t total_lines = 0; uint32_t lines_per_way = 0; uint32_t num_ways = 0; + uint32_t prev_addr_low = 0; for (i = 0; i < ctx->stream_count; i++) { stream = ctx->streams[i]; @@ -267,10 +268,20 @@ static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *c plane = ctx->stream_status[i].plane_states[j]; // Calculate total surface size - surface_size = plane->plane_size.surface_pitch * + if (prev_addr_low != plane->address.grph.addr.u.low_part) { + /* if plane address are different from prev FB, then userspace allocated separate FBs*/ + surface_size += plane->plane_size.surface_pitch * plane->plane_size.surface_size.height * (plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4); + prev_addr_low = plane->address.grph.addr.u.low_part; + } else { + /* We have the same fb for all the planes. + * Xorg always creates one giant fb that holds all surfaces, + * so allocating it once is sufficient. + * */ + continue; + } // Convert surface size + starting address to number of cache lines required // (alignment accounted for) cache_lines_used += dcn32_cache_lines_for_surface(dc, surface_size, From 0cd34ce82b0a9ce503d35a51bff47ba3b6715557 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Wed, 20 Jul 2022 13:16:59 -0400 Subject: [PATCH 109/427] drm/amd/display: Add a variable to update FCLK latency [Description] Add a variable to update FCLK latency Reviewed-by: Martin Leung Acked-by: Tom Chung Signed-off-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 7 +++++++ drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c | 7 +++++++ 3 files changed, 15 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 8e1e40083ec83..d73e68c2fd511 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -609,6 +609,7 @@ struct dc_bounding_box_overrides { int percent_of_ideal_drambw; int dram_clock_change_latency_ns; int dummy_clock_change_latency_ns; + int fclk_clock_change_latency_ns; /* This forces a hard min on the DCFCLK we use * for DML. Unlike the debug option for forcing * DCFCLK, this override affects watermark calculations diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 66453546e24fe..f8023cfe79f89 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -2098,6 +2098,13 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa dc->bb_overrides.dram_clock_change_latency_ns / 1000.0; } + if ((int)(dcn3_2_soc.fclk_change_latency_us * 1000) + != dc->bb_overrides.fclk_clock_change_latency_ns + && dc->bb_overrides.fclk_clock_change_latency_ns) { + dcn3_2_soc.fclk_change_latency_us = + dc->bb_overrides.fclk_clock_change_latency_ns / 1000; + } + if ((int)(dcn3_2_soc.dummy_pstate_latency_us * 1000) != dc->bb_overrides.dummy_clock_change_latency_ns && dc->bb_overrides.dummy_clock_change_latency_ns) { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c index 84b4b00f29cbd..c87091683b5dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c @@ -498,6 +498,13 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p dc->bb_overrides.dram_clock_change_latency_ns / 1000.0; } + if ((int)(dcn3_21_soc.fclk_change_latency_us * 1000) + != dc->bb_overrides.fclk_clock_change_latency_ns + && dc->bb_overrides.fclk_clock_change_latency_ns) { + dcn3_21_soc.fclk_change_latency_us = + dc->bb_overrides.fclk_clock_change_latency_ns / 1000; + } + if ((int)(dcn3_21_soc.dummy_pstate_latency_us * 1000) != dc->bb_overrides.dummy_clock_change_latency_ns && dc->bb_overrides.dummy_clock_change_latency_ns) { From 9bd110ab06e93fd01938dedd8b6015940418f0fb Mon Sep 17 00:00:00 2001 From: Daniel Miess Date: Tue, 19 Jul 2022 11:43:28 -0400 Subject: [PATCH 110/427] drm/amd/display: Fix TMDS 4K@60Hz YCbCr420 corruption issue [Why] DIG_FIFO_OUTPUT_PIXEL_MODE not being set for dcn314 resulting in incorrect timing for YCbCr4:2:0 [How] Copy the implementation of set_pixels_per_cycle from dcn32 over to dcn314 Reviewed-by: Nicholas Kazlauskas Acked-by: Tom Chung Signed-off-by: Daniel Miess Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn314/dcn314_hwseq.c | 28 +++++++++++++++++++ .../drm/amd/display/dc/dcn314/dcn314_hwseq.h | 4 +++ .../drm/amd/display/dc/dcn314/dcn314_init.c | 2 ++ 3 files changed, 34 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c index 452f4a9bf251c..39931d48f3851 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c @@ -374,3 +374,31 @@ unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsig return odm_combine_factor; } + +void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx) +{ + uint32_t pix_per_cycle = 1; + uint32_t odm_combine_factor = 1; + + if (!pipe_ctx || !pipe_ctx->stream || !pipe_ctx->stream_res.stream_enc) + return; + + odm_combine_factor = get_odm_config(pipe_ctx, NULL); + if (optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing) || odm_combine_factor > 1 + || dcn314_is_dp_dig_pixel_rate_div_policy(pipe_ctx)) + pix_per_cycle = 2; + + if (pipe_ctx->stream_res.stream_enc->funcs->set_input_mode) + pipe_ctx->stream_res.stream_enc->funcs->set_input_mode(pipe_ctx->stream_res.stream_enc, + pix_per_cycle); +} + +bool dcn314_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx) +{ + struct dc *dc = pipe_ctx->stream->ctx->dc; + + if (dc_is_dp_signal(pipe_ctx->stream->signal) && !is_dp_128b_132b_signal(pipe_ctx) && + dc->debug.enable_dp_dig_pixel_rate_div_policy) + return true; + return false; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h index be0f5e4d48e13..d014580592aca 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h @@ -39,4 +39,8 @@ void dcn314_enable_power_gating_plane(struct dce_hwseq *hws, bool enable); unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div); +void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx); + +bool dcn314_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx); + #endif /* __DC_HWSS_DCN314_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c index b9debeb081fdf..fcf67eb3478f0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c @@ -145,6 +145,8 @@ static const struct hwseq_private_funcs dcn314_private_funcs = { .set_shaper_3dlut = dcn20_set_shaper_3dlut, .setup_hpo_hw_control = dcn31_setup_hpo_hw_control, .calculate_dccg_k1_k2_values = dcn314_calculate_dccg_k1_k2_values, + .set_pixels_per_cycle = dcn314_set_pixels_per_cycle, + .is_dp_dig_pixel_rate_div_policy = dcn314_is_dp_dig_pixel_rate_div_policy, }; void dcn314_hw_sequencer_construct(struct dc *dc) From 9c580e8f6cd6524d4e2c3490c440110526f7ddd6 Mon Sep 17 00:00:00 2001 From: Chiawen Huang Date: Thu, 21 Jul 2022 21:57:05 +0800 Subject: [PATCH 111/427] drm/amd/display: Device flash garbage before get in OS [Why] Enabling stream with tg lock makes config settings pending causing the garbage until tg unlock. [How] Keep the original lock mechanism The driver doesn't lock tg if plane_state is null. Reviewed-by: Anthony Koo Acked-by: Tom Chung Signed-off-by: Chiawen Huang Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index bed783747f169..5b5d952b2b8cd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -110,6 +110,7 @@ void dcn10_lock_all_pipes(struct dc *dc, */ if (pipe_ctx->top_pipe || !pipe_ctx->stream || + !pipe_ctx->plane_state || !tg->funcs->is_tg_enabled(tg)) continue; From 615fc50207fa27453ba7f5fa1abd60a01a498136 Mon Sep 17 00:00:00 2001 From: Josip Pavic Date: Thu, 21 Jul 2022 15:33:00 -0400 Subject: [PATCH 112/427] drm/amd/display: Avoid MPC infinite loop [Why] In some cases MPC tree bottom pipe ends up point to itself. This causes iterating from top to bottom to hang the system in an infinite loop. [How] When looping to next MPC bottom pipe, check that the pointer is not same as current to avoid infinite loop. Reviewed-by: Jun Lei Acked-by: Tom Chung Signed-off-by: Josip Pavic Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 6 ++++++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 769974375b4b3..8e9384094f6d6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -131,6 +131,12 @@ struct mpcc *mpc1_get_mpcc_for_dpp(struct mpc_tree *tree, int dpp_id) while (tmp_mpcc != NULL) { if (tmp_mpcc->dpp_id == dpp_id) return tmp_mpcc; + + /* avoid circular linked list */ + ASSERT(tmp_mpcc != tmp_mpcc->mpcc_bot); + if (tmp_mpcc == tmp_mpcc->mpcc_bot) + break; + tmp_mpcc = tmp_mpcc->mpcc_bot; } return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c index 3d307dd58e9af..116f67a0b989d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c @@ -531,6 +531,12 @@ static struct mpcc *mpc2_get_mpcc_for_dpp(struct mpc_tree *tree, int dpp_id) while (tmp_mpcc != NULL) { if (tmp_mpcc->dpp_id == 0xf || tmp_mpcc->dpp_id == dpp_id) return tmp_mpcc; + + /* avoid circular linked list */ + ASSERT(tmp_mpcc != tmp_mpcc->mpcc_bot); + if (tmp_mpcc == tmp_mpcc->mpcc_bot) + break; + tmp_mpcc = tmp_mpcc->mpcc_bot; } return NULL; From 0591183699fceeafb4c4141072d47775de83ecfb Mon Sep 17 00:00:00 2001 From: Leo Ma Date: Fri, 22 Jul 2022 13:42:58 -0400 Subject: [PATCH 113/427] drm/amd/display: Fix HDMI VSIF V3 incorrect issue [Why] Reported from customer the checksum in AMD VSIF V3 is incorrect and causing blank screen issue. [How] Fix the packet length issue on AMD HDMI VSIF V3. Reviewed-by: Anthony Koo Acked-by: Tom Chung Signed-off-by: Leo Ma Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/modules/freesync/freesync.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index da09ba7589f73..0f39ab9dc5b41 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -613,10 +613,6 @@ static void build_vrr_infopacket_data_v1(const struct mod_vrr_params *vrr, * Note: We should never go above the field rate of the mode timing set. */ infopacket->sb[8] = (unsigned char)((vrr->max_refresh_in_uhz + 500000) / 1000000); - - /* FreeSync HDR */ - infopacket->sb[9] = 0; - infopacket->sb[10] = 0; } static void build_vrr_infopacket_data_v3(const struct mod_vrr_params *vrr, @@ -684,10 +680,6 @@ static void build_vrr_infopacket_data_v3(const struct mod_vrr_params *vrr, /* PB16 : Reserved bits 7:1, FixedRate bit 0 */ infopacket->sb[16] = (vrr->state == VRR_STATE_ACTIVE_FIXED) ? 1 : 0; - - //FreeSync HDR - infopacket->sb[9] = 0; - infopacket->sb[10] = 0; } static void build_vrr_infopacket_fs2_data(enum color_transfer_func app_tf, @@ -772,8 +764,7 @@ static void build_vrr_infopacket_header_v2(enum signal_type signal, /* HB2 = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x09] */ infopacket->hb2 = 0x09; - *payload_size = 0x0A; - + *payload_size = 0x09; } else if (dc_is_dp_signal(signal)) { /* HEADER */ @@ -822,9 +813,9 @@ static void build_vrr_infopacket_header_v3(enum signal_type signal, infopacket->hb1 = version; /* HB2 = [Bits 7:5 = 0] [Bits 4:0 = Length] */ - *payload_size = 0x10; - infopacket->hb2 = *payload_size - 1; //-1 for checksum + infopacket->hb2 = 0x10; + *payload_size = 0x10; } else if (dc_is_dp_signal(signal)) { /* HEADER */ From 86678d46272021c88638881c63d427dd10d665d6 Mon Sep 17 00:00:00 2001 From: David Galiffi Date: Wed, 20 Jul 2022 17:54:05 -0400 Subject: [PATCH 114/427] drm/amd/display: Allow alternate prefetch modes in DML for DCN32 [Why] Driver is restricting voltage levels if system cannot switch in vblank. [How] Change allow_for_pstate_or_stutter_in_vblank_final from dm_prefetch_support_uclk_fclk_and_stutter to dm_prefetch_support_uclk_fclk_and_stutter_if_possible. Add support for a new registry property, DalDMLDisallowAlternatePrefetchModes, for easier debugging. Reviewed-by: Alvin Lee Reviewed-by: Jun Lei Acked-by: Tom Chung Signed-off-by: David Galiffi Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 34 +++++++++++++------ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d73e68c2fd511..ede8519cf7908 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -752,6 +752,7 @@ struct dc_debug_options { uint32_t mst_start_top_delay; uint8_t psr_power_use_phy_fsm; enum dml_hostvm_override_opts dml_hostvm_override; + bool dml_disallow_alternate_prefetch_modes; bool use_legacy_soc_bb_mechanism; bool exit_idle_opt_for_cursor_updates; bool enable_single_display_2to1_odm_policy; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index f8023cfe79f89..49b8738b0318f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -983,9 +983,15 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, * DML favors voltage over p-state, but we're more interested in * supporting p-state over voltage. We can't support p-state in * prefetch mode > 0 so try capping the prefetch mode to start. + * Override present for testing. */ - context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final = + if (dc->debug.dml_disallow_alternate_prefetch_modes) + context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final = dm_prefetch_support_uclk_fclk_and_stutter; + else + context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final = + dm_prefetch_support_uclk_fclk_and_stutter_if_possible; + *vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, *pipe_cnt); /* This may adjust vlevel and maxMpcComb */ if (*vlevel < context->bw_ctx.dml.soc.num_states) @@ -1014,7 +1020,9 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, * will not allow for switch in VBLANK. The DRR display must have it's VBLANK stretched * enough to support MCLK switching. */ - if (*vlevel == context->bw_ctx.dml.soc.num_states) { + if (*vlevel == context->bw_ctx.dml.soc.num_states && + context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final == + dm_prefetch_support_uclk_fclk_and_stutter) { context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final = dm_prefetch_support_stutter; /* There are params (such as FabricClock) that need to be recalculated @@ -1344,7 +1352,8 @@ bool dcn32_internal_validate_bw(struct dc *dc, int split[MAX_PIPES] = { 0 }; bool merge[MAX_PIPES] = { false }; bool newly_split[MAX_PIPES] = { false }; - int pipe_cnt, i, pipe_idx, vlevel; + int pipe_cnt, i, pipe_idx; + int vlevel = context->bw_ctx.dml.soc.num_states; struct vba_vars_st *vba = &context->bw_ctx.dml.vba; dc_assert_fp_enabled(); @@ -1373,17 +1382,22 @@ bool dcn32_internal_validate_bw(struct dc *dc, DC_FP_END(); } - if (fast_validate || vlevel == context->bw_ctx.dml.soc.num_states || - vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported) { + if (fast_validate || + dc->debug.dml_disallow_alternate_prefetch_modes && + (vlevel == context->bw_ctx.dml.soc.num_states || + vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported)) { /* - * If mode is unsupported or there's still no p-state support then - * fall back to favoring voltage. + * If dml_disallow_alternate_prefetch_modes is false, then we have already + * tried alternate prefetch modes during full validation. + * + * If mode is unsupported or there is no p-state support, then + * fall back to favouring voltage. * - * If Prefetch mode 0 failed for this config, or passed with Max UCLK, try if - * supported with Prefetch mode 1 (dm_prefetch_support_fclk_and_stutter == 2) + * If Prefetch mode 0 failed for this config, or passed with Max UCLK, then try + * to support with Prefetch mode 1 (dm_prefetch_support_fclk_and_stutter == 2) */ context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final = - dm_prefetch_support_fclk_and_stutter; + dm_prefetch_support_fclk_and_stutter; vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); From dd07556324ece81f0d2be756508903d53e331e9e Mon Sep 17 00:00:00 2001 From: David Galiffi Date: Fri, 22 Jul 2022 16:03:13 -0400 Subject: [PATCH 115/427] drm/amd/display: Fix Compile-time Warning Fixed bracketing around condition statement. Reviewed-by: Alvin Lee Reviewed-by: Jun Lei Acked-by: Tom Chung Signed-off-by: David Galiffi Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 49b8738b0318f..79959254d57cc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -1383,9 +1383,9 @@ bool dcn32_internal_validate_bw(struct dc *dc, } if (fast_validate || - dc->debug.dml_disallow_alternate_prefetch_modes && + (dc->debug.dml_disallow_alternate_prefetch_modes && (vlevel == context->bw_ctx.dml.soc.num_states || - vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported)) { + vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported))) { /* * If dml_disallow_alternate_prefetch_modes is false, then we have already * tried alternate prefetch modes during full validation. From 6396679a1f2db0c63721b841f1a5617d6282a4b1 Mon Sep 17 00:00:00 2001 From: Duncan Ma Date: Mon, 25 Jul 2022 15:26:39 -0400 Subject: [PATCH 116/427] drm/amd/display: Fix VPG instancing for dcn314 HPO [Why] An issue during VPG indexing offset generation causing to use the incorrect VPG. HW team placed VPG instances 5 at end of list, making it VPG 9 in register headers. [How] Correct VPG instance for HPO encoders. Reviewed-by: Charlene Liu Acked-by: Tom Chung Signed-off-by: Duncan Ma Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c index 1f095f05d9865..85f32206a7662 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c @@ -1254,7 +1254,7 @@ static struct stream_encoder *dcn314_stream_encoder_create( int afmt_inst; /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ - if (eng_id <= ENGINE_ID_DIGF) { + if (eng_id < ENGINE_ID_DIGF) { vpg_inst = eng_id; afmt_inst = eng_id; } else @@ -1299,7 +1299,8 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( * VPG[8] -> HPO_DP[2] * VPG[9] -> HPO_DP[3] */ - vpg_inst = hpo_dp_inst + 6; + //Uses offset index 5-8, but actually maps to vpg_inst 6-9 + vpg_inst = hpo_dp_inst + 5; /* Mapping of APG register blocks to HPO DP block instance: * APG[0] -> HPO_DP[0] From 89b008222c2bf21e50219725caed31590edfd9d1 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Tue, 26 Jul 2022 13:13:27 -0400 Subject: [PATCH 117/427] drm/amd/display: Check correct bounds for stream encoder instances for DCN303 [Why & How] eng_id for DCN303 cannot be more than 1, since we have only two instances of stream encoders. Check the correct boundary condition for engine ID for DCN303 prevent the potential out of bounds access. Fixes: cd6d421e3d1a ("drm/amd/display: Initial DC support for Beige Goby") Reported-by: Dan Carpenter Cc: stable@vger.kernel.org Reviewed-by: Chris Park Reviewed-by: Rodrigo Siqueira Acked-by: Tom Chung Signed-off-by: Aurabindo Pillai Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c index 0a67f8a5656de..d97076648acba 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c @@ -372,7 +372,7 @@ static struct stream_encoder *dcn303_stream_encoder_create(enum engine_id eng_id int afmt_inst; /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ - if (eng_id <= ENGINE_ID_DIGE) { + if (eng_id <= ENGINE_ID_DIGB) { vpg_inst = eng_id; afmt_inst = eng_id; } else From f173c7405224002fc32b64cf1679c4d888c493eb Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Tue, 26 Jul 2022 14:12:29 -0400 Subject: [PATCH 118/427] drm/amd/display: Enable SubVP by default on DCN32 & DCN321 [Why&How] Set the debug options to enable SubVP feature Reviewed-by: Alvin Lee Acked-by: Tom Chung Signed-off-by: Aurabindo Pillai Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index 9a26d24b579f7..74e95a61c13ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -867,7 +867,7 @@ static const struct dc_debug_options debug_defaults_drv = { } }, .use_max_lb = true, - .force_disable_subvp = true, + .force_disable_subvp = false, .exit_idle_opt_for_cursor_updates = true, .enable_single_display_2to1_odm_policy = true, .enable_dp_dig_pixel_rate_div_policy = 1, diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c index 8157e40d2c7ef..db419b2118d3b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c @@ -868,7 +868,7 @@ static const struct dc_debug_options debug_defaults_drv = { } }, .use_max_lb = true, - .force_disable_subvp = true, + .force_disable_subvp = false, .exit_idle_opt_for_cursor_updates = true, .enable_single_display_2to1_odm_policy = true, .enable_dp_dig_pixel_rate_div_policy = 1, From 2051160546826cf312f15bde534038582b90f844 Mon Sep 17 00:00:00 2001 From: Duncan Ma Date: Wed, 27 Jul 2022 15:44:43 -0400 Subject: [PATCH 119/427] drm/amd/display: Correct DTBCLK for dcn314 [Why] DTBCLK clocks reset after clocks are initialized and bounding box values are also incorrect. [How] Use dcn31 init clock function programming sequence and correct bounding box values for dcn314 Reviewed-by: Nicholas Kazlauskas Reviewed-by: Jun Lei Acked-by: Tom Chung Signed-off-by: Duncan Ma Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c | 12 +----------- .../amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.h | 2 +- .../gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c | 10 +++++----- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c index ee99974b3b62b..7af19823a29db 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c @@ -307,16 +307,6 @@ static void dcn314_enable_pme_wa(struct clk_mgr *clk_mgr_base) dcn314_smu_enable_pme_wa(clk_mgr); } -void dcn314_init_clocks(struct clk_mgr *clk_mgr) -{ - memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks)); - // Assumption is that boot state always supports pstate - clk_mgr->clks.p_state_change_support = true; - clk_mgr->clks.prev_p_state_change_support = true; - clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN; - clk_mgr->clks.zstate_support = DCN_ZSTATE_SUPPORT_UNKNOWN; -} - bool dcn314_are_clock_states_equal(struct dc_clocks *a, struct dc_clocks *b) { @@ -641,7 +631,7 @@ static struct clk_mgr_funcs dcn314_funcs = { .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz, .update_clocks = dcn314_update_clocks, - .init_clocks = dcn314_init_clocks, + .init_clocks = dcn31_init_clocks, .enable_pme_wa = dcn314_enable_pme_wa, .are_clock_states_equal = dcn314_are_clock_states_equal, .notify_wm_ranges = dcn314_notify_wm_ranges diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.h index c695a4498c50f..171f84340eb2f 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.h @@ -42,7 +42,7 @@ struct clk_mgr_dcn314 { bool dcn314_are_clock_states_equal(struct dc_clocks *a, struct dc_clocks *b); -void dcn314_init_clocks(struct clk_mgr *clk_mgr); + void dcn314_update_clocks(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool safe_to_lower); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c index d52a16d280e98..c80307a6af1bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c @@ -106,7 +106,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_14_soc = { .phyclk_mhz = 600.0, .phyclk_d18_mhz = 667.0, .dscclk_mhz = 186.0, - .dtbclk_mhz = 625.0, + .dtbclk_mhz = 600.0, }, { .state = 1, @@ -115,7 +115,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_14_soc = { .phyclk_mhz = 810.0, .phyclk_d18_mhz = 667.0, .dscclk_mhz = 209.0, - .dtbclk_mhz = 625.0, + .dtbclk_mhz = 600.0, }, { .state = 2, @@ -124,7 +124,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_14_soc = { .phyclk_mhz = 810.0, .phyclk_d18_mhz = 667.0, .dscclk_mhz = 209.0, - .dtbclk_mhz = 625.0, + .dtbclk_mhz = 600.0, }, { .state = 3, @@ -133,7 +133,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_14_soc = { .phyclk_mhz = 810.0, .phyclk_d18_mhz = 667.0, .dscclk_mhz = 371.0, - .dtbclk_mhz = 625.0, + .dtbclk_mhz = 600.0, }, { .state = 4, @@ -142,7 +142,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_14_soc = { .phyclk_mhz = 810.0, .phyclk_d18_mhz = 667.0, .dscclk_mhz = 417.0, - .dtbclk_mhz = 625.0, + .dtbclk_mhz = 600.0, }, }, .num_states = 5, From 764a1e6e0272f377f145fc84b547d61e12724233 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Tue, 26 Jul 2022 19:00:23 -0400 Subject: [PATCH 120/427] drm/amd/display: Revert "attempt to fix the logic in commit_planes_for_stream()" [Description] Reverts commit "attempt to fix the logic in commit_planes_for_stream()" since it caused a regression. Reviewed-by: Martin Leung Acked-by: Tom Chung Signed-off-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 27 +++++++++++------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5d84adb6ea524..ce8910ad27835 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3229,7 +3229,7 @@ static void commit_planes_for_stream(struct dc *dc, odm_pipe->ttu_regs.min_ttu_vblank = MAX_TTU; } - if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) { + if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) if (top_pipe_to_program && top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) { if (should_use_dmub_lock(stream->link)) { @@ -3247,7 +3247,6 @@ static void commit_planes_for_stream(struct dc *dc, top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable( top_pipe_to_program->stream_res.tg); } - } if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) { if (dc->hwss.subvp_pipe_control_lock) @@ -3466,7 +3465,7 @@ static void commit_planes_for_stream(struct dc *dc, dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); } - if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) { + if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) if (top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) { top_pipe_to_program->stream_res.tg->funcs->wait_for_state( top_pipe_to_program->stream_res.tg, @@ -3493,21 +3492,19 @@ static void commit_planes_for_stream(struct dc *dc, top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_disable( top_pipe_to_program->stream_res.tg); } - } - if (update_type != UPDATE_TYPE_FAST) { + if (update_type != UPDATE_TYPE_FAST) dc->hwss.post_unlock_program_front_end(dc, context); - /* Since phantom pipe programming is moved to post_unlock_program_front_end, - * move the SubVP lock to after the phantom pipes have been setup - */ - if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) { - if (dc->hwss.subvp_pipe_control_lock) - dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use); - } else { - if (dc->hwss.subvp_pipe_control_lock) - dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, top_pipe_to_program, subvp_prev_use); - } + /* Since phantom pipe programming is moved to post_unlock_program_front_end, + * move the SubVP lock to after the phantom pipes have been setup + */ + if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) { + if (dc->hwss.subvp_pipe_control_lock) + dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use); + } else { + if (dc->hwss.subvp_pipe_control_lock) + dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, top_pipe_to_program, subvp_prev_use); } // Fire manual trigger only when bottom plane is flipped From 84ef99c728079dfd21d6bc70b4c3e4af20602b3c Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 28 Jul 2022 09:51:05 -0400 Subject: [PATCH 121/427] drm/amd/display: For stereo keep "FLIP_ANY_FRAME" [Description] Observed in stereomode that programming FLIP_LEFT_EYE can cause hangs. Keep FLIP_ANY_FRAME in stereo mode so the surface flip can take place before left or right eye Reviewed-by: Martin Leung Acked-by: Tom Chung Signed-off-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c index 6a4dcafb9bba5..dc3e8df706b34 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c @@ -86,7 +86,7 @@ bool hubp3_program_surface_flip_and_addr( VMID, address->vmid); if (address->type == PLN_ADDR_TYPE_GRPH_STEREO) { - REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0x1); + REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0); REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x1); } else { From f0068dd0effd5972046b69b23f99c43251e82d0e Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 28 Jul 2022 10:02:25 -0400 Subject: [PATCH 122/427] drm/amd/display: Don't try to enter MALL SS if stereo3d [Description] MALL not supported with stereo3D according to DCN doc. Reviewed-by: Jun Lei Acked-by: Tom Chung Signed-off-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn32/dcn32_hwseq.c | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c index 5ba503d807288..4aecbf2304463 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c @@ -331,7 +331,9 @@ static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *c bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable) { union dmub_rb_cmd cmd; - uint8_t ways; + uint8_t ways, i, j; + bool stereo_in_use = false; + struct dc_plane_state *plane = NULL; if (!dc->ctx->dmub_srv) return false; @@ -360,7 +362,23 @@ bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable) * and configure HUBP's to fetch from MALL */ ways = dcn32_calculate_cab_allocation(dc, dc->current_state); - if (ways <= dc->caps.cache_num_ways) { + + /* MALL not supported with Stereo3D. If any plane is using stereo, + * don't try to enter MALL. + */ + for (i = 0; i < dc->current_state->stream_count; i++) { + for (j = 0; j < dc->current_state->stream_status[i].plane_count; j++) { + plane = dc->current_state->stream_status[i].plane_states[j]; + + if (plane->address.type == PLN_ADDR_TYPE_GRPH_STEREO) { + stereo_in_use = true; + break; + } + } + if (stereo_in_use) + break; + } + if (ways <= dc->caps.cache_num_ways && !stereo_in_use) { memset(&cmd, 0, sizeof(cmd)); cmd.cab.header.type = DMUB_CMD__CAB_FOR_SS; cmd.cab.header.sub_type = DMUB_CMD__CAB_DCN_SS_FIT_IN_CAB; @@ -694,9 +712,11 @@ void dcn32_update_mall_sel(struct dc *dc, struct dc_state *context) if (pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { hubp->funcs->hubp_update_mall_sel(hubp, 1, false); } else { + // MALL not supported with Stereo3D hubp->funcs->hubp_update_mall_sel(hubp, num_ways <= dc->caps.cache_num_ways && - pipe->stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED ? 2 : 0, + pipe->stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED && + pipe->plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO ? 2 : 0, cache_cursor); } } From b2a93490201300a749ad261b5c5d05cb50179c44 Mon Sep 17 00:00:00 2001 From: Fudong Wang Date: Wed, 27 Jul 2022 12:01:29 +0800 Subject: [PATCH 123/427] drm/amd/display: clear optc underflow before turn off odm clock [Why] After ODM clock off, optc underflow bit will be kept there always and clear not work. We need to clear that before clock off. [How] Clear that if have when clock off. Reviewed-by: Alvin Lee Acked-by: Tom Chung Signed-off-by: Fudong Wang Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c index e1a9a45b03b65..3fc300cd1ce95 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c @@ -465,6 +465,11 @@ void optc1_enable_optc_clock(struct timing_generator *optc, bool enable) OTG_CLOCK_ON, 1, 1, 1000); } else { + + //last chance to clear underflow, otherwise, it will always there due to clock is off. + if (optc->funcs->is_optc_underflow_occurred(optc) == true) + optc->funcs->clear_optc_underflow(optc); + REG_UPDATE_2(OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, 0, OTG_CLOCK_EN, 0); From 30456ffa65469d1d2e5e1da05017e6728d24c11c Mon Sep 17 00:00:00 2001 From: Meenakshikumar Somasundaram Date: Mon, 11 Jul 2022 18:37:41 -0400 Subject: [PATCH 124/427] drm/amd/display: Fix TDR eDP and USB4 display light up issue [Why] After TDR recovery, eDP and USB4 display does not light up. Because dmub outbox notifications are not enabled after dmub reload and link encoder assignments for the streams are not cleared before dc state reset. [How] - Dmub outbox notification is enabled after tdr recovery by issuing inbox command to dmub. - Link encoders for the streams are unassigned before dc state reset. Reviewed-by: Jimmy Kizito Reviewed-by: Jun Lei Acked-by: Tom Chung Signed-off-by: Meenakshikumar Somasundaram Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 1 + drivers/gpu/drm/amd/display/dc/dc_link.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ce8910ad27835..663be10b292be 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -4337,6 +4337,7 @@ void dc_enable_dmub_outbox(struct dc *dc) struct dc_context *dc_ctx = dc->ctx; dmub_enable_outbox_notification(dc_ctx->dmub_srv); + DC_LOG_DC("%s: dmub outbox notifications enabled\n", __func__); } /** diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index a0af0f6afeef8..9544abf75e846 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -344,6 +344,7 @@ enum dc_detect_reason { DETECT_REASON_HPDRX, DETECT_REASON_FALLBACK, DETECT_REASON_RETRAIN, + DETECT_REASON_TDR, }; bool dc_link_detect(struct dc_link *dc_link, enum dc_detect_reason reason); From 9f5171ce733a694bd0211952687704c7a5bf32b9 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 21 Jul 2022 10:23:41 -0400 Subject: [PATCH 125/427] drm/amd/display: Add 16 lines margin for SubVP [Description] SUBVP_START_LINE must be aligned to 2 swaths, so add 16 lines of margin so the start line can be adjusted by up to 16 lines for alignment purposes in FW. Reviewed-by: Jun Lei Acked-by: Tom Chung Signed-off-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 5 ++++- 6 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ede8519cf7908..ef8a7cebf8277 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -213,6 +213,7 @@ struct dc_caps { uint32_t cache_num_ways; uint16_t subvp_fw_processing_delay_us; uint16_t subvp_prefetch_end_to_mall_start_us; + uint8_t subvp_swath_height_margin_lines; // subvp start line must be aligned to 2 x swath height uint16_t subvp_pstate_allow_width_us; uint16_t subvp_vertical_int_margin_us; bool seamless_odm; diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 2d61c2a91cee2..c8059c28ac494 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -275,8 +275,7 @@ void dc_dmub_srv_set_drr_manual_trigger_cmd(struct dc *dc, uint32_t tg_inst) union dmub_rb_cmd cmd = { 0 }; cmd.drr_update.header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH; - // TODO: Uncomment once FW headers are promoted - //cmd.drr_update.header.sub_type = DMUB_CMD__FAMS_SET_MANUAL_TRIGGER; + cmd.drr_update.header.sub_type = DMUB_CMD__FAMS_SET_MANUAL_TRIGGER; cmd.drr_update.dmub_optc_state_req.tg_inst = tg_inst; cmd.drr_update.header.payload_bytes = sizeof(cmd.drr_update) - sizeof(cmd.drr_update.header); @@ -612,6 +611,7 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc, main_timing->v_total - main_timing->v_front_porch - main_timing->v_addressable; pipe_data->pipe_config.subvp_data.mall_region_lines = phantom_timing->v_addressable; pipe_data->pipe_config.subvp_data.main_pipe_index = subvp_pipe->pipe_idx; + pipe_data->pipe_config.subvp_data.is_drr = subvp_pipe->stream->ignore_msa_timing_param; // Prefetch lines is equal to VACTIVE + BP + VSYNC pipe_data->pipe_config.subvp_data.prefetch_lines = diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c index eff1f4e17689c..1fad7b48bd5be 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c @@ -281,7 +281,7 @@ static struct timing_generator_funcs dcn32_tg_funcs = { .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, .enable_optc_clock = optc1_enable_optc_clock, - .set_drr = optc31_set_drr, // TODO: Update to optc32_set_drr once FW headers are promoted + .set_drr = optc32_set_drr, .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, .set_vtotal_min_max = optc3_set_vtotal_min_max, .set_static_screen_control = optc1_set_static_screen_control, diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index 74e95a61c13ea..8b887b552f2c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -2051,6 +2051,7 @@ static bool dcn32_resource_construct( dc->caps.max_cab_allocation_bytes = 67108864; // 64MB = 1024 * 1024 * 64 dc->caps.subvp_fw_processing_delay_us = 15; dc->caps.subvp_prefetch_end_to_mall_start_us = 15; + dc->caps.subvp_swath_height_margin_lines = 16; dc->caps.subvp_pstate_allow_width_us = 20; dc->caps.subvp_vertical_int_margin_us = 30; diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c index db419b2118d3b..e9db5f8b6fdcc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c @@ -1662,6 +1662,7 @@ static bool dcn321_resource_construct( dc->caps.max_cab_allocation_bytes = 33554432; // 32MB = 1024 * 1024 * 32 dc->caps.subvp_fw_processing_delay_us = 15; dc->caps.subvp_prefetch_end_to_mall_start_us = 15; + dc->caps.subvp_swath_height_margin_lines = 16; dc->caps.subvp_pstate_allow_width_us = 20; dc->caps.max_slave_planes = 1; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 79959254d57cc..3316c4a649011 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -473,8 +473,11 @@ void dcn32_set_phantom_stream_timing(struct dc *dc, // DML calculation for MALL region doesn't take into account FW delay // and required pstate allow width for multi-display cases + /* Add 16 lines margin to the MALL REGION because SUB_VP_START_LINE must be aligned + * to 2 swaths (i.e. 16 lines) + */ phantom_vactive = get_subviewport_lines_needed_in_mall(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx) + - pstate_width_fw_delay_lines; + pstate_width_fw_delay_lines + dc->caps.subvp_swath_height_margin_lines; // For backporch of phantom pipe, use vstartup of the main pipe phantom_bp = get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); From 8da536d5e114ad1da6028c7505f048ded2e421c6 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Mon, 25 Jul 2022 01:54:00 -0400 Subject: [PATCH 126/427] drm/amd/display: 3.2.197 This version brings along following fixes: - Move fpu file to dml folder - Fix CAB allocation for multiple displays - Add a variable to update FCLK - Fix TMDS 4K@60Hz YCbCr420 corruption issue - Fix MPC tree infinite loop in some case - Fix HDMI VSIF V3 blank screen issue - Add some documentation to the code - Allow alternate prefetch modes in DML for DCN32 - Fix VPG instancing for dcn314 HPO - Check correct bounds for stream encoder instances for DCN303 - Enable SubVP by default on DCN32 & DCN321 - Fix DTBCLK not correct for dcn314 - Fix Compile-time warning - Fix the stereo mode hang issue - Fix display light up issue Acked-by: Tom Chung Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ef8a7cebf8277..2de45aaad7f75 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.196" +#define DC_VER "3.2.197" #define MAX_SURFACES 3 #define MAX_PLANES 6 From 352e683b72e79dbd46cbde528eb91e228e88267a Mon Sep 17 00:00:00 2001 From: Joseph Greathouse Date: Thu, 4 Aug 2022 09:54:57 -0500 Subject: [PATCH 127/427] drm/amdgpu: Enable translate_further to extend UTCL2 reach MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable translate_further on Arcturus and Aldebaran server chips in order to increase the UTCL2 reach from 8 GiB to 64 GiB, which is more in line with the amount of framebuffer DRAM in the devices. Signed-off-by: Joseph Greathouse Acked-by: Felix Kuehling Acked-by: Kent Russell Acked-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 22761a3bb8181..ab89d91975ab0 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1624,12 +1624,15 @@ static int gmc_v9_0_sw_init(void *handle) amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 47); else amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48); + if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2)) + adev->gmc.translate_further = adev->vm_manager.num_level > 1; break; case IP_VERSION(9, 4, 1): adev->num_vmhubs = 3; /* Keep the vm size same with Vega20 */ amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48); + adev->gmc.translate_further = adev->vm_manager.num_level > 1; break; default: break; From b7ffeb4a1b5bce1a7495636d21f1704bd7ff01d3 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 28 Jul 2022 17:44:44 +0800 Subject: [PATCH 128/427] drm/amd/pm: add 3715 softpptable support for SMU13.0.0 Add support for 3715 softpptable. Signed-off-by: Evan Quan Reviewed-by: Hawking Zhang Reviewed-by: Feifei Xu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index e8fe84f806d17..6f39e69dead9a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -229,6 +229,7 @@ int smu_v13_0_init_pptable_microcode(struct smu_context *smu) /* * Temporary solution for SMU V13.0.0 with SCPM enabled: * - use 36831 signed pptable when pp_table_id is 3683 + * - use 37151 signed pptable when pp_table_id is 3715 * - use 36641 signed pptable when pp_table_id is 3664 or 0 * TODO: drop these when the pptable carried in vbios is ready. */ @@ -241,6 +242,9 @@ int smu_v13_0_init_pptable_microcode(struct smu_context *smu) case 3683: pptable_id = 36831; break; + case 3715: + pptable_id = 37151; + break; default: dev_err(adev->dev, "Unsupported pptable id %d\n", pptable_id); return -EINVAL; @@ -478,7 +482,7 @@ int smu_v13_0_setup_pptable(struct smu_context *smu) /* * Temporary solution for SMU V13.0.0 with SCPM disabled: - * - use 3664 or 3683 on request + * - use 3664, 3683 or 3715 on request * - use 3664 when pptable_id is 0 * TODO: drop these when the pptable carried in vbios is ready. */ @@ -489,6 +493,7 @@ int smu_v13_0_setup_pptable(struct smu_context *smu) break; case 3664: case 3683: + case 3715: break; default: dev_err(adev->dev, "Unsupported pptable id %d\n", pptable_id); From 4e64b529c5b04e7944b41de554ee686ecab00744 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Tue, 9 Aug 2022 10:13:54 +0800 Subject: [PATCH 129/427] drm/amd/pm: skip pptable override for smu_v13_0_7 skip pptable override for smu_v13_0_7 secure boards only. Signed-off-by: Kenneth Feng Reviewed-by: Feifei Xu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index 6f39e69dead9a..fc5772352cfb0 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -212,6 +212,9 @@ int smu_v13_0_init_pptable_microcode(struct smu_context *smu) if (!adev->scpm_enabled) return 0; + if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 7)) + return 0; + /* override pptable_id from driver parameter */ if (amdgpu_smu_pptable_id >= 0) { pptable_id = amdgpu_smu_pptable_id; @@ -219,13 +222,6 @@ int smu_v13_0_init_pptable_microcode(struct smu_context *smu) } else { pptable_id = smu->smu_table.boot_values.pp_table_id; - if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 7) && - pptable_id == 3667) - pptable_id = 36671; - - if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 7) && - pptable_id == 3688) - pptable_id = 36881; /* * Temporary solution for SMU V13.0.0 with SCPM enabled: * - use 36831 signed pptable when pp_table_id is 3683 From c4c10a68e82b8a03df234ee744acabcc648df270 Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Wed, 20 Apr 2022 09:37:56 -0400 Subject: [PATCH 130/427] drm/amdgpu: Avoid direct cast to amdgpu_ttm_tt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For typesafety, use container_of() instead of implicit cast from struct ttm_tt to struct amdgpu_ttm_tt. Reviewed-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 34 +++++++++++++------------ 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 3b4c19412625d..134575a3893c5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -637,6 +637,8 @@ struct amdgpu_ttm_tt { #endif }; +#define ttm_to_amdgpu_ttm_tt(ptr) container_of(ptr, struct amdgpu_ttm_tt, ttm) + #ifdef CONFIG_DRM_AMDGPU_USERPTR /* * amdgpu_ttm_tt_get_user_pages - get device accessible pages that back user @@ -648,7 +650,7 @@ struct amdgpu_ttm_tt { int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo, struct page **pages) { struct ttm_tt *ttm = bo->tbo.ttm; - struct amdgpu_ttm_tt *gtt = (void *)ttm; + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm); unsigned long start = gtt->userptr; struct vm_area_struct *vma; struct mm_struct *mm; @@ -702,7 +704,7 @@ int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo, struct page **pages) */ bool amdgpu_ttm_tt_get_user_pages_done(struct ttm_tt *ttm) { - struct amdgpu_ttm_tt *gtt = (void *)ttm; + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm); bool r = false; if (!gtt || !gtt->userptr) @@ -751,7 +753,7 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_device *bdev, struct ttm_tt *ttm) { struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); - struct amdgpu_ttm_tt *gtt = (void *)ttm; + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm); int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY); enum dma_data_direction direction = write ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE; @@ -788,7 +790,7 @@ static void amdgpu_ttm_tt_unpin_userptr(struct ttm_device *bdev, struct ttm_tt *ttm) { struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); - struct amdgpu_ttm_tt *gtt = (void *)ttm; + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm); int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY); enum dma_data_direction direction = write ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE; @@ -822,7 +824,7 @@ static void amdgpu_ttm_gart_bind(struct amdgpu_device *adev, { struct amdgpu_bo *abo = ttm_to_amdgpu_bo(tbo); struct ttm_tt *ttm = tbo->ttm; - struct amdgpu_ttm_tt *gtt = (void *)ttm; + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm); if (amdgpu_bo_encrypted(abo)) flags |= AMDGPU_PTE_TMZ; @@ -860,7 +862,7 @@ static int amdgpu_ttm_backend_bind(struct ttm_device *bdev, struct ttm_resource *bo_mem) { struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); - struct amdgpu_ttm_tt *gtt = (void*)ttm; + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm); uint64_t flags; int r; @@ -927,7 +929,7 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct ttm_operation_ctx ctx = { false, false }; - struct amdgpu_ttm_tt *gtt = (void *)bo->ttm; + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(bo->ttm); struct ttm_placement placement; struct ttm_place placements; struct ttm_resource *tmp; @@ -998,7 +1000,7 @@ static void amdgpu_ttm_backend_unbind(struct ttm_device *bdev, struct ttm_tt *ttm) { struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); - struct amdgpu_ttm_tt *gtt = (void *)ttm; + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm); /* if the pages have userptr pinning then clear that first */ if (gtt->userptr) { @@ -1025,7 +1027,7 @@ static void amdgpu_ttm_backend_unbind(struct ttm_device *bdev, static void amdgpu_ttm_backend_destroy(struct ttm_device *bdev, struct ttm_tt *ttm) { - struct amdgpu_ttm_tt *gtt = (void *)ttm; + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm); if (gtt->usertask) put_task_struct(gtt->usertask); @@ -1079,7 +1081,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_device *bdev, struct ttm_operation_ctx *ctx) { struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); - struct amdgpu_ttm_tt *gtt = (void *)ttm; + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm); pgoff_t i; int ret; @@ -1113,7 +1115,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_device *bdev, static void amdgpu_ttm_tt_unpopulate(struct ttm_device *bdev, struct ttm_tt *ttm) { - struct amdgpu_ttm_tt *gtt = (void *)ttm; + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm); struct amdgpu_device *adev; pgoff_t i; @@ -1182,7 +1184,7 @@ int amdgpu_ttm_tt_set_userptr(struct ttm_buffer_object *bo, /* Set TTM_TT_FLAG_EXTERNAL before populate but after create. */ bo->ttm->page_flags |= TTM_TT_FLAG_EXTERNAL; - gtt = (void *)bo->ttm; + gtt = ttm_to_amdgpu_ttm_tt(bo->ttm); gtt->userptr = addr; gtt->userflags = flags; @@ -1199,7 +1201,7 @@ int amdgpu_ttm_tt_set_userptr(struct ttm_buffer_object *bo, */ struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm) { - struct amdgpu_ttm_tt *gtt = (void *)ttm; + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm); if (gtt == NULL) return NULL; @@ -1218,7 +1220,7 @@ struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm) bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, unsigned long end, unsigned long *userptr) { - struct amdgpu_ttm_tt *gtt = (void *)ttm; + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm); unsigned long size; if (gtt == NULL || !gtt->userptr) @@ -1241,7 +1243,7 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, */ bool amdgpu_ttm_tt_is_userptr(struct ttm_tt *ttm) { - struct amdgpu_ttm_tt *gtt = (void *)ttm; + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm); if (gtt == NULL || !gtt->userptr) return false; @@ -1254,7 +1256,7 @@ bool amdgpu_ttm_tt_is_userptr(struct ttm_tt *ttm) */ bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm) { - struct amdgpu_ttm_tt *gtt = (void *)ttm; + struct amdgpu_ttm_tt *gtt = ttm_to_amdgpu_ttm_tt(ttm); if (gtt == NULL) return false; From bea9a56afbc4b5a41ea579b8b0dc5e189b439504 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Thu, 4 Aug 2022 18:19:38 -0400 Subject: [PATCH 131/427] drm/amdkfd: Handle restart of kfd_ioctl_wait_events When kfd_ioctl_wait_events needs to restart due to a signal, we need to update the timeout to account for the time already elapsed. We also need to undo auto_reset of events that have signaled already, so that the restarted ioctl will be able to count those signals again. This fixes infinite hangs when kfd_ioctl_wait_events is interrupted by a signal. Signed-off-by: Felix Kuehling Reviewed-and-tested-by: Xiaogang Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_events.c | 24 ++++++++++++------------ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 2b3d8bc8f0aae..dc774ddf34456 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -874,7 +874,7 @@ static int kfd_ioctl_wait_events(struct file *filp, struct kfd_process *p, err = kfd_wait_on_events(p, args->num_events, (void __user *)args->events_ptr, (args->wait_for_all != 0), - args->timeout, &args->wait_result); + &args->timeout, &args->wait_result); return err; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c index 3942a56c28bbb..83e3ce9f60491 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c @@ -894,7 +894,8 @@ static long user_timeout_to_jiffies(uint32_t user_timeout_ms) return msecs_to_jiffies(user_timeout_ms) + 1; } -static void free_waiters(uint32_t num_events, struct kfd_event_waiter *waiters) +static void free_waiters(uint32_t num_events, struct kfd_event_waiter *waiters, + bool undo_auto_reset) { uint32_t i; @@ -903,6 +904,9 @@ static void free_waiters(uint32_t num_events, struct kfd_event_waiter *waiters) spin_lock(&waiters[i].event->lock); remove_wait_queue(&waiters[i].event->wq, &waiters[i].wait); + if (undo_auto_reset && waiters[i].activated && + waiters[i].event && waiters[i].event->auto_reset) + set_event(waiters[i].event); spin_unlock(&waiters[i].event->lock); } @@ -911,7 +915,7 @@ static void free_waiters(uint32_t num_events, struct kfd_event_waiter *waiters) int kfd_wait_on_events(struct kfd_process *p, uint32_t num_events, void __user *data, - bool all, uint32_t user_timeout_ms, + bool all, uint32_t *user_timeout_ms, uint32_t *wait_result) { struct kfd_event_data __user *events = @@ -920,7 +924,7 @@ int kfd_wait_on_events(struct kfd_process *p, int ret = 0; struct kfd_event_waiter *event_waiters = NULL; - long timeout = user_timeout_to_jiffies(user_timeout_ms); + long timeout = user_timeout_to_jiffies(*user_timeout_ms); event_waiters = alloc_event_waiters(num_events); if (!event_waiters) { @@ -970,15 +974,11 @@ int kfd_wait_on_events(struct kfd_process *p, } if (signal_pending(current)) { - /* - * This is wrong when a nonzero, non-infinite timeout - * is specified. We need to use - * ERESTARTSYS_RESTARTBLOCK, but struct restart_block - * contains a union with data for each user and it's - * in generic kernel code that I don't want to - * touch yet. - */ ret = -ERESTARTSYS; + if (*user_timeout_ms != KFD_EVENT_TIMEOUT_IMMEDIATE && + *user_timeout_ms != KFD_EVENT_TIMEOUT_INFINITE) + *user_timeout_ms = jiffies_to_msecs( + max(0l, timeout-1)); break; } @@ -1019,7 +1019,7 @@ int kfd_wait_on_events(struct kfd_process *p, event_waiters, events); out_unlock: - free_waiters(num_events, event_waiters); + free_waiters(num_events, event_waiters, ret == -ERESTARTSYS); mutex_unlock(&p->event_mutex); out: if (ret) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index d03a3b9c9c5d6..bf610e3b683bb 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1317,7 +1317,7 @@ void kfd_event_free_process(struct kfd_process *p); int kfd_event_mmap(struct kfd_process *process, struct vm_area_struct *vma); int kfd_wait_on_events(struct kfd_process *p, uint32_t num_events, void __user *data, - bool all, uint32_t user_timeout_ms, + bool all, uint32_t *user_timeout_ms, uint32_t *wait_result); void kfd_signal_event_interrupt(u32 pasid, uint32_t partial_id, uint32_t valid_id_bits); From cb9c7ab1b3ddc2702379dd9639df0c2230453c2e Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Fri, 29 Jul 2022 18:37:27 +0800 Subject: [PATCH 132/427] drm/amdgpu: enable GFX Power Gating for GC IP v11.0.1 Enable GFX Power Gating control for GC IP v11.0.1. Signed-off-by: Tim Huang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index e03618803a1c2..158d87e6805d1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -53,6 +53,7 @@ #define GFX11_MEC_HPD_SIZE 2048 #define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L +#define RLC_PG_DELAY_3_DEFAULT_GC_11_0_1 0x1388 #define regCGTT_WD_CLK_CTRL 0x5086 #define regCGTT_WD_CLK_CTRL_BASE_IDX 1 @@ -5279,6 +5280,38 @@ static const struct amdgpu_rlc_funcs gfx_v11_0_rlc_funcs = { .update_spm_vmid = gfx_v11_0_update_spm_vmid, }; +static void gfx_v11_cntl_power_gating(struct amdgpu_device *adev, bool enable) +{ + u32 data = RREG32_SOC15(GC, 0, regRLC_PG_CNTL); + + if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) + data |= RLC_PG_CNTL__GFX_POWER_GATING_ENABLE_MASK; + else + data &= ~RLC_PG_CNTL__GFX_POWER_GATING_ENABLE_MASK; + + WREG32_SOC15(GC, 0, regRLC_PG_CNTL, data); + + // Program RLC_PG_DELAY3 for CGPG hysteresis + if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) { + switch (adev->ip_versions[GC_HWIP][0]) { + case IP_VERSION(11, 0, 1): + WREG32_SOC15(GC, 0, regRLC_PG_DELAY_3, RLC_PG_DELAY_3_DEFAULT_GC_11_0_1); + break; + default: + break; + } + } +} + +static void gfx_v11_cntl_pg(struct amdgpu_device *adev, bool enable) +{ + amdgpu_gfx_rlc_enter_safe_mode(adev); + + gfx_v11_cntl_power_gating(adev, enable); + + amdgpu_gfx_rlc_exit_safe_mode(adev); +} + static int gfx_v11_0_set_powergating_state(void *handle, enum amd_powergating_state state) { @@ -5293,6 +5326,11 @@ static int gfx_v11_0_set_powergating_state(void *handle, case IP_VERSION(11, 0, 2): amdgpu_gfx_off_ctrl(adev, enable); break; + case IP_VERSION(11, 0, 1): + gfx_v11_cntl_pg(adev, enable); + /* TODO: Enable this when GFXOFF is ready */ + // amdgpu_gfx_off_ctrl(adev, enable); + break; default: break; } From dc0a096bcc1d659ae93f836099c6b0312d2ccaaf Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Fri, 29 Jul 2022 15:25:57 +0800 Subject: [PATCH 133/427] drm/amdgpu: add GFX Power Gating support for GC IP v11.0.1 Add AMD_PG_SUPPORT_GFX_PG support. Signed-off-by: Tim Huang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc21.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index b700c6cb14b48..bbbf760f8ad2b 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -595,6 +595,7 @@ static int soc21_common_early_init(void *handle) AMD_CG_SUPPORT_VCN_MGCG | AMD_CG_SUPPORT_JPEG_MGCG; adev->pg_flags = + AMD_PG_SUPPORT_GFX_PG | AMD_PG_SUPPORT_JPEG; adev->external_rev_id = adev->rev_id + 0x1; break; From 5afb76522a0af0513b6dc01f84128a73206b051b Mon Sep 17 00:00:00 2001 From: Zhen Ni Date: Wed, 3 Aug 2022 17:19:58 +0800 Subject: [PATCH 134/427] drm/amd/pm: Fix a potential gpu_metrics_table memory leak Memory is allocated for gpu_metrics_table in smu_v13_0_4_init_smc_tables(), but not freed in smu_v13_0_4_fini_smc_tables(). This may cause memory leaks, fix it. Reviewed-by: Evan Quan Signed-off-by: Zhen Ni Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c index 64665e8a86e4d..97e1d55dcaad5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c @@ -198,6 +198,9 @@ static int smu_v13_0_4_fini_smc_tables(struct smu_context *smu) kfree(smu_table->watermarks_table); smu_table->watermarks_table = NULL; + kfree(smu_table->gpu_metrics_table); + smu_table->gpu_metrics_table = NULL; + return 0; } From 541d54e40f1672dea6514ad64d54d61ed952648e Mon Sep 17 00:00:00 2001 From: Zhen Ni Date: Wed, 3 Aug 2022 17:19:59 +0800 Subject: [PATCH 135/427] drm/amd/pm: Fix a potential gpu_metrics_table memory leak Memory is allocated for gpu_metrics_table in smu_v13_0_5_init_smc_tables(), but not freed in smu_v13_0_5_fini_smc_tables(). This may cause memory leaks, fix it. Reviewed-by: Evan Quan Signed-off-by: Zhen Ni Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c index 47360ef5c1758..66445964efbd1 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c @@ -176,6 +176,9 @@ static int smu_v13_0_5_fini_smc_tables(struct smu_context *smu) kfree(smu_table->watermarks_table); smu_table->watermarks_table = NULL; + kfree(smu_table->gpu_metrics_table); + smu_table->gpu_metrics_table = NULL; + return 0; } From acc96ae0d12783e9781428b17e34fd662a904f0a Mon Sep 17 00:00:00 2001 From: Melissa Wen Date: Thu, 4 Aug 2022 15:13:49 -0100 Subject: [PATCH 136/427] drm/amd/display: set panel orientation before drm_dev_register To set the panel orientation property with quirk, we need the mode size provided by EDID. This info is available after EDID is read by dc_link_detect() and updated by amdgpu_dm_update_connector_after_detect(). The detection happens at driver load in amdgpu_dm_initialize_drm_device() and, therefore, we can get modes and set panel orientation before drm_dev_register() to avoid DRM warns on creating the connector property after device registration: [ 2.563969] ------------[ cut here ]------------ [ 2.563971] WARNING: CPU: 6 PID: 325 at drivers/gpu/drm/drm_mode_object.c:45 drm_mode_object_add+0x72/0x80 [drm] [ 2.563997] Modules linked in: btusb btrtl btbcm btintel btmtk bluetooth rfkill ecdh_generic ecc usbhid crc16 amdgpu(+) drm_ttm_helper ttm agpgart gpu_sched i2c_algo_bit drm_display_helper drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm serio_raw sdhci_pci atkbd libps2 cqhci vivaldi_fmap ccp sdhci i8042 crct10dif_pclmul crc32_pclmul hid_multitouch ghash_clmulni_intel aesni_intel crypto_simd cryptd wdat_wdt mmc_core cec xhci_pci sp5100_tco rng_core xhci_pci_renesas serio 8250_dw i2c_hid_acpi i2c_hid btrfs blake2b_generic libcrc32c crc32c_generic crc32c_intel xor raid6_pq dm_mirror dm_region_hash dm_log dm_mod pkcs8_key_parser crypto_user [ 2.564032] CPU: 6 PID: 325 Comm: systemd-udevd Not tainted 5.18.0-amd-staging-drm-next+ #67 [ 2.564034] Hardware name: Valve Jupiter/Jupiter, BIOS F7A0105 03/21/2022 [ 2.564036] RIP: 0010:drm_mode_object_add+0x72/0x80 [drm] [ 2.564053] Code: f0 89 c3 85 c0 78 07 89 45 00 44 89 65 04 4c 89 ef e8 e2 99 04 f1 31 c0 85 db 0f 4e c3 5b 5d 41 5c 41 5d c3 80 7f 50 00 74 ac <0f> 0b eb a8 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 41 54 4c [ 2.564055] RSP: 0018:ffffb2e880413860 EFLAGS: 00010202 [ 2.564056] RAX: ffffffffc0ba1440 RBX: ffff99508a860010 RCX: 0000000000000001 [ 2.564057] RDX: 00000000b0b0b0b0 RSI: ffff99508c050110 RDI: ffff99508a860010 [ 2.564058] RBP: ffff99508c050110 R08: 0000000000000020 R09: ffff99508c292c20 [ 2.564059] R10: 0000000000000000 R11: ffff99508c0507d8 R12: 00000000b0b0b0b0 [ 2.564060] R13: 0000000000000004 R14: ffffffffc068a4b6 R15: ffffffffc068a47f [ 2.564061] FS: 00007fc69b5f1a40(0000) GS:ffff9953aff80000(0000) knlGS:0000000000000000 [ 2.564063] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 2.564063] CR2: 00007f9506804000 CR3: 0000000107f92000 CR4: 0000000000350ee0 [ 2.564065] Call Trace: [ 2.564068] [ 2.564070] drm_property_create+0xc9/0x170 [drm] [ 2.564088] drm_property_create_enum+0x1f/0x70 [drm] [ 2.564105] drm_connector_set_panel_orientation_with_quirk+0x96/0xc0 [drm] [ 2.564123] get_modes+0x4fb/0x530 [amdgpu] [ 2.564378] drm_helper_probe_single_connector_modes+0x1ad/0x850 [drm_kms_helper] [ 2.564390] drm_client_modeset_probe+0x229/0x1400 [drm] [ 2.564411] ? xas_store+0x52/0x5e0 [ 2.564416] ? kmem_cache_alloc_trace+0x177/0x2c0 [ 2.564420] __drm_fb_helper_initial_config_and_unlock+0x44/0x4e0 [drm_kms_helper] [ 2.564430] drm_fbdev_client_hotplug+0x173/0x210 [drm_kms_helper] [ 2.564438] drm_fbdev_generic_setup+0xa5/0x166 [drm_kms_helper] [ 2.564446] amdgpu_pci_probe+0x35e/0x370 [amdgpu] [ 2.564621] local_pci_probe+0x45/0x80 [ 2.564625] ? pci_match_device+0xd7/0x130 [ 2.564627] pci_device_probe+0xbf/0x220 [ 2.564629] ? sysfs_do_create_link_sd+0x69/0xd0 [ 2.564633] really_probe+0x19c/0x380 [ 2.564637] __driver_probe_device+0xfe/0x180 [ 2.564639] driver_probe_device+0x1e/0x90 [ 2.564641] __driver_attach+0xc0/0x1c0 [ 2.564643] ? __device_attach_driver+0xe0/0xe0 [ 2.564644] ? __device_attach_driver+0xe0/0xe0 [ 2.564646] bus_for_each_dev+0x78/0xc0 [ 2.564648] bus_add_driver+0x149/0x1e0 [ 2.564650] driver_register+0x8f/0xe0 [ 2.564652] ? 0xffffffffc1023000 [ 2.564654] do_one_initcall+0x44/0x200 [ 2.564657] ? kmem_cache_alloc_trace+0x177/0x2c0 [ 2.564659] do_init_module+0x4c/0x250 [ 2.564663] __do_sys_init_module+0x12e/0x1b0 [ 2.564666] do_syscall_64+0x3b/0x90 [ 2.564670] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 2.564673] RIP: 0033:0x7fc69bff232e [ 2.564674] Code: 48 8b 0d 45 0b 0c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 49 89 ca b8 af 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 12 0b 0c 00 f7 d8 64 89 01 48 [ 2.564676] RSP: 002b:00007ffe872ba3e8 EFLAGS: 00000246 ORIG_RAX: 00000000000000af [ 2.564677] RAX: ffffffffffffffda RBX: 000055873f797820 RCX: 00007fc69bff232e [ 2.564678] RDX: 000055873f7bf390 RSI: 0000000001155e81 RDI: 00007fc699e4d010 [ 2.564679] RBP: 00007fc699e4d010 R08: 000055873f7bfe20 R09: 0000000001155e90 [ 2.564680] R10: 000000055873f7bf R11: 0000000000000246 R12: 000055873f7bf390 [ 2.564681] R13: 000000000000000d R14: 000055873f7c4cb0 R15: 000055873f797820 [ 2.564683] [ 2.564683] ---[ end trace 0000000000000000 ]--- [ 2.564696] ------------[ cut here ]------------ [ 2.564696] WARNING: CPU: 6 PID: 325 at drivers/gpu/drm/drm_mode_object.c:242 drm_object_attach_property+0x52/0x80 [drm] [ 2.564717] Modules linked in: btusb btrtl btbcm btintel btmtk bluetooth rfkill ecdh_generic ecc usbhid crc16 amdgpu(+) drm_ttm_helper ttm agpgart gpu_sched i2c_algo_bit drm_display_helper drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm serio_raw sdhci_pci atkbd libps2 cqhci vivaldi_fmap ccp sdhci i8042 crct10dif_pclmul crc32_pclmul hid_multitouch ghash_clmulni_intel aesni_intel crypto_simd cryptd wdat_wdt mmc_core cec xhci_pci sp5100_tco rng_core xhci_pci_renesas serio 8250_dw i2c_hid_acpi i2c_hid btrfs blake2b_generic libcrc32c crc32c_generic crc32c_intel xor raid6_pq dm_mirror dm_region_hash dm_log dm_mod pkcs8_key_parser crypto_user [ 2.564738] CPU: 6 PID: 325 Comm: systemd-udevd Tainted: G W 5.18.0-amd-staging-drm-next+ #67 [ 2.564740] Hardware name: Valve Jupiter/Jupiter, BIOS F7A0105 03/21/2022 [ 2.564741] RIP: 0010:drm_object_attach_property+0x52/0x80 [drm] [ 2.564759] Code: 2d 83 f8 18 74 33 48 89 74 c1 08 48 8b 4f 08 48 89 94 c1 c8 00 00 00 48 8b 47 08 83 00 01 c3 4d 85 d2 75 dd 83 7f 58 01 75 d7 <0f> 0b eb d3 41 80 78 50 00 74 cc 0f 0b eb c8 44 89 ce 48 c7 c7 28 [ 2.564760] RSP: 0018:ffffb2e8804138d8 EFLAGS: 00010246 [ 2.564761] RAX: 0000000000000010 RBX: ffff99508c1a2000 RCX: ffff99508c1a2180 [ 2.564762] RDX: 0000000000000003 RSI: ffff99508c050100 RDI: ffff99508c1a2040 [ 2.564763] RBP: 00000000ffffffff R08: ffff99508a860010 R09: 00000000c0c0c0c0 [ 2.564763] R10: 0000000000000000 R11: 0000000000000020 R12: ffff99508a860010 [ 2.564764] R13: ffff995088733008 R14: ffff99508c1a2000 R15: ffffffffc068a47f [ 2.564765] FS: 00007fc69b5f1a40(0000) GS:ffff9953aff80000(0000) knlGS:0000000000000000 [ 2.564766] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 2.564767] CR2: 00007f9506804000 CR3: 0000000107f92000 CR4: 0000000000350ee0 [ 2.564768] Call Trace: [ 2.564769] [ 2.564770] drm_connector_set_panel_orientation_with_quirk+0x4a/0xc0 [drm] [ 2.564789] get_modes+0x4fb/0x530 [amdgpu] [ 2.565024] drm_helper_probe_single_connector_modes+0x1ad/0x850 [drm_kms_helper] [ 2.565036] drm_client_modeset_probe+0x229/0x1400 [drm] [ 2.565056] ? xas_store+0x52/0x5e0 [ 2.565060] ? kmem_cache_alloc_trace+0x177/0x2c0 [ 2.565062] __drm_fb_helper_initial_config_and_unlock+0x44/0x4e0 [drm_kms_helper] [ 2.565072] drm_fbdev_client_hotplug+0x173/0x210 [drm_kms_helper] [ 2.565080] drm_fbdev_generic_setup+0xa5/0x166 [drm_kms_helper] [ 2.565088] amdgpu_pci_probe+0x35e/0x370 [amdgpu] [ 2.565261] local_pci_probe+0x45/0x80 [ 2.565263] ? pci_match_device+0xd7/0x130 [ 2.565265] pci_device_probe+0xbf/0x220 [ 2.565267] ? sysfs_do_create_link_sd+0x69/0xd0 [ 2.565268] really_probe+0x19c/0x380 [ 2.565270] __driver_probe_device+0xfe/0x180 [ 2.565272] driver_probe_device+0x1e/0x90 [ 2.565274] __driver_attach+0xc0/0x1c0 [ 2.565276] ? __device_attach_driver+0xe0/0xe0 [ 2.565278] ? __device_attach_driver+0xe0/0xe0 [ 2.565279] bus_for_each_dev+0x78/0xc0 [ 2.565281] bus_add_driver+0x149/0x1e0 [ 2.565283] driver_register+0x8f/0xe0 [ 2.565285] ? 0xffffffffc1023000 [ 2.565286] do_one_initcall+0x44/0x200 [ 2.565288] ? kmem_cache_alloc_trace+0x177/0x2c0 [ 2.565290] do_init_module+0x4c/0x250 [ 2.565291] __do_sys_init_module+0x12e/0x1b0 [ 2.565294] do_syscall_64+0x3b/0x90 [ 2.565296] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 2.565297] RIP: 0033:0x7fc69bff232e [ 2.565298] Code: 48 8b 0d 45 0b 0c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 49 89 ca b8 af 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 12 0b 0c 00 f7 d8 64 89 01 48 [ 2.565299] RSP: 002b:00007ffe872ba3e8 EFLAGS: 00000246 ORIG_RAX: 00000000000000af [ 2.565301] RAX: ffffffffffffffda RBX: 000055873f797820 RCX: 00007fc69bff232e [ 2.565302] RDX: 000055873f7bf390 RSI: 0000000001155e81 RDI: 00007fc699e4d010 [ 2.565303] RBP: 00007fc699e4d010 R08: 000055873f7bfe20 R09: 0000000001155e90 [ 2.565303] R10: 000000055873f7bf R11: 0000000000000246 R12: 000055873f7bf390 [ 2.565304] R13: 000000000000000d R14: 000055873f7c4cb0 R15: 000055873f797820 [ 2.565306] [ 2.565307] ---[ end trace 0000000000000000 ]--- -- v2: - call amdgpu_dm_connector_get_modes() instead of ddc_get_modes() (Harry) Fixes: d77de7880e0e0 ("amd/display: enable panel orientation quirks") Acked-by: Hans de Goede Signed-off-by: Melissa Wen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8660d93cc4055..08906c7778b48 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4135,6 +4135,7 @@ static void register_backlight_device(struct amdgpu_display_manager *dm, } } +static void amdgpu_set_panel_orientation(struct drm_connector *connector); /* * In this architecture, the association @@ -4326,6 +4327,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) adev_to_drm(adev)->vblank_disable_immediate = false; } } + amdgpu_set_panel_orientation(&aconnector->base); } /* Software is initialized. Now we can register interrupt handlers. */ @@ -6684,6 +6686,10 @@ static void amdgpu_set_panel_orientation(struct drm_connector *connector) connector->connector_type != DRM_MODE_CONNECTOR_LVDS) return; + mutex_lock(&connector->dev->mode_config.mutex); + amdgpu_dm_connector_get_modes(connector); + mutex_unlock(&connector->dev->mode_config.mutex); + encoder = amdgpu_dm_connector_to_encoder(connector); if (!encoder) return; @@ -6728,8 +6734,6 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, * restored here. */ amdgpu_dm_update_freesync_caps(connector, edid); - - amdgpu_set_panel_orientation(connector); } else { amdgpu_dm_connector->num_modes = 0; } From a6250bdb6c4677ee77d699b338e077b900f94c0c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 9 Aug 2022 11:44:05 -0400 Subject: [PATCH 137/427] drm/amdgpu: Only disable prefer_shadow on hawaii We changed it for all asics due to a hibernation regression on hawaii, but the workaround breaks suspend on a polaris12. Just disable it for hawaii. Link: https://bugzilla.kernel.org/show_bug.cgi?id=216119 Fixes: 3a4b1cc28fbd ("drm/amdgpu/display: disable prefer_shadow for generic fb helpers") Reviewed-and-tested-by: Mario Limonciello Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 3 +-- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 3 +-- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 3 +-- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 3 +-- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 7 +++++-- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 +++++-- 6 files changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c index 108e8e8a1a367..576849e952964 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c @@ -496,8 +496,7 @@ static int amdgpu_vkms_sw_init(void *handle) adev_to_drm(adev)->mode_config.max_height = YRES_MAX; adev_to_drm(adev)->mode_config.preferred_depth = 24; - /* disable prefer shadow for now due to hibernation issues */ - adev_to_drm(adev)->mode_config.prefer_shadow = 0; + adev_to_drm(adev)->mode_config.prefer_shadow = 1; adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 9c964cd3b5d4e..288fce7dc0ed1 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -2796,8 +2796,7 @@ static int dce_v10_0_sw_init(void *handle) adev_to_drm(adev)->mode_config.max_height = 16384; adev_to_drm(adev)->mode_config.preferred_depth = 24; - /* disable prefer shadow for now due to hibernation issues */ - adev_to_drm(adev)->mode_config.prefer_shadow = 0; + adev_to_drm(adev)->mode_config.prefer_shadow = 1; adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index e0ad9f27dc3f9..cbe5250b31cb4 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -2914,8 +2914,7 @@ static int dce_v11_0_sw_init(void *handle) adev_to_drm(adev)->mode_config.max_height = 16384; adev_to_drm(adev)->mode_config.preferred_depth = 24; - /* disable prefer shadow for now due to hibernation issues */ - adev_to_drm(adev)->mode_config.prefer_shadow = 0; + adev_to_drm(adev)->mode_config.prefer_shadow = 1; adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index 77f5e998a1202..b1c44fab074f3 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -2673,8 +2673,7 @@ static int dce_v6_0_sw_init(void *handle) adev_to_drm(adev)->mode_config.max_width = 16384; adev_to_drm(adev)->mode_config.max_height = 16384; adev_to_drm(adev)->mode_config.preferred_depth = 24; - /* disable prefer shadow for now due to hibernation issues */ - adev_to_drm(adev)->mode_config.prefer_shadow = 0; + adev_to_drm(adev)->mode_config.prefer_shadow = 1; adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true; adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 802e5c753271c..a22b45c927922 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -2693,8 +2693,11 @@ static int dce_v8_0_sw_init(void *handle) adev_to_drm(adev)->mode_config.max_height = 16384; adev_to_drm(adev)->mode_config.preferred_depth = 24; - /* disable prefer shadow for now due to hibernation issues */ - adev_to_drm(adev)->mode_config.prefer_shadow = 0; + if (adev->asic_type == CHIP_HAWAII) + /* disable prefer shadow for now due to hibernation issues */ + adev_to_drm(adev)->mode_config.prefer_shadow = 0; + else + adev_to_drm(adev)->mode_config.prefer_shadow = 1; adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 08906c7778b48..5140d9c2bf3b4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3825,8 +3825,11 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) adev_to_drm(adev)->mode_config.max_height = 16384; adev_to_drm(adev)->mode_config.preferred_depth = 24; - /* disable prefer shadow for now due to hibernation issues */ - adev_to_drm(adev)->mode_config.prefer_shadow = 0; + if (adev->asic_type == CHIP_HAWAII) + /* disable prefer shadow for now due to hibernation issues */ + adev_to_drm(adev)->mode_config.prefer_shadow = 0; + else + adev_to_drm(adev)->mode_config.prefer_shadow = 1; /* indicates support for immediate flip */ adev_to_drm(adev)->mode_config.async_page_flip = true; From ad2feebd71ff80532dff75756d1103f056358614 Mon Sep 17 00:00:00 2001 From: Sebin Sebastian Date: Sat, 30 Jul 2022 09:16:58 +0530 Subject: [PATCH 138/427] drm/amdgpu: double free error and freeing uninitialized null pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a double free and an uninitialized pointer read error. Both tmp and new are pointing at same address and both are freed which leads to double free. Adding a check to verify if new and tmp are free in the error_free label fixes the double free issue. new is not initialized to null which also leads to a free on an uninitialized pointer. Reviewed-by: André Almeida Suggested by: S. Amaranath Signed-off-by: Sebin Sebastian Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index e2eec985adb3a..cb00c7d6f50be 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -1705,7 +1705,7 @@ static ssize_t amdgpu_reset_dump_register_list_write(struct file *f, { struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; char reg_offset[11]; - uint32_t *new, *tmp = NULL; + uint32_t *new = NULL, *tmp = NULL; int ret, i = 0, len = 0; do { @@ -1747,7 +1747,8 @@ static ssize_t amdgpu_reset_dump_register_list_write(struct file *f, ret = size; error_free: - kfree(tmp); + if (tmp != new) + kfree(tmp); kfree(new); return ret; } From 2bba782002c5dab6ca8d608b778b386fb912adff Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 1 Aug 2022 14:54:19 +0200 Subject: [PATCH 139/427] drm/bridge: lvds-codec: Fix error checking of drm_of_lvds_get_data_mapping() The drm_of_lvds_get_data_mapping() returns either negative value on error or MEDIA_BUS_FMT_* otherwise. The check for 'ret' would also catch the positive case of MEDIA_BUS_FMT_* and lead to probe failure every time 'data-mapping' DT property is specified. Fixes: 7c4dd0a266527 ("drm: of: Add drm_of_lvds_get_data_mapping") Signed-off-by: Marek Vasut Cc: Laurent Pinchart Cc: Sam Ravnborg To: dri-devel@lists.freedesktop.org Reviewed-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20220801125419.167562-1-marex@denx.de --- drivers/gpu/drm/bridge/lvds-codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/lvds-codec.c b/drivers/gpu/drm/bridge/lvds-codec.c index 702ea803a743c..39e7004de7200 100644 --- a/drivers/gpu/drm/bridge/lvds-codec.c +++ b/drivers/gpu/drm/bridge/lvds-codec.c @@ -180,7 +180,7 @@ static int lvds_codec_probe(struct platform_device *pdev) of_node_put(bus_node); if (ret == -ENODEV) { dev_warn(dev, "missing 'data-mapping' DT property\n"); - } else if (ret) { + } else if (ret < 0) { dev_err(dev, "invalid 'data-mapping' DT property\n"); return ret; } else { From fe54833dc8d97ef387e86f7c80537d51c503ca75 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 8 Aug 2022 21:56:48 +0900 Subject: [PATCH 140/427] ksmbd: return STATUS_BAD_NETWORK_NAME error status if share is not configured If share is not configured in smb.conf, smb2 tree connect should return STATUS_BAD_NETWORK_NAME instead of STATUS_BAD_NETWORK_PATH. Signed-off-by: Namjae Jeon Reviewed-by: Hyunchul Lee Signed-off-by: Steve French --- fs/ksmbd/mgmt/tree_connect.c | 2 +- fs/ksmbd/smb2pdu.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/ksmbd/mgmt/tree_connect.c b/fs/ksmbd/mgmt/tree_connect.c index b35ea6a6abc53..dd262daa2c4a5 100644 --- a/fs/ksmbd/mgmt/tree_connect.c +++ b/fs/ksmbd/mgmt/tree_connect.c @@ -19,7 +19,7 @@ struct ksmbd_tree_conn_status ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, char *share_name) { - struct ksmbd_tree_conn_status status = {-EINVAL, NULL}; + struct ksmbd_tree_conn_status status = {-ENOENT, NULL}; struct ksmbd_tree_connect_response *resp = NULL; struct ksmbd_share_config *sc; struct ksmbd_tree_connect *tree_conn = NULL; diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 9751cc92c111b..1f9a2cda0c58f 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -1944,8 +1944,9 @@ int smb2_tree_connect(struct ksmbd_work *work) rsp->hdr.Status = STATUS_SUCCESS; rc = 0; break; + case -ENOENT: case KSMBD_TREE_CONN_STATUS_NO_SHARE: - rsp->hdr.Status = STATUS_BAD_NETWORK_PATH; + rsp->hdr.Status = STATUS_BAD_NETWORK_NAME; break; case -ENOMEM: case KSMBD_TREE_CONN_STATUS_NOMEM: From 4963d74f8a6cc0eafd71d9ffc13e3a11ff1dd160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atte=20Heikkil=C3=A4?= Date: Tue, 9 Aug 2022 01:02:14 +0300 Subject: [PATCH 141/427] ksmbd: request update to stale share config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ksmbd_share_config_get() retrieves the cached share config as long as there is at least one connection to the share. This is an issue when the user space utilities are used to update share configs. In that case there is a need to inform ksmbd that it should not use the cached share config for a new connection to the share. With these changes the tree connection flag KSMBD_TREE_CONN_FLAG_UPDATE indicates this. When this flag is set, ksmbd removes the share config from the shares hash table meaning that ksmbd_share_config_get() ends up requesting a share config from user space. Signed-off-by: Atte Heikkilä Acked-by: Namjae Jeon Signed-off-by: Steve French --- fs/ksmbd/ksmbd_netlink.h | 2 ++ fs/ksmbd/mgmt/share_config.c | 6 +++++- fs/ksmbd/mgmt/share_config.h | 1 + fs/ksmbd/mgmt/tree_connect.c | 14 ++++++++++++++ fs/ksmbd/smb2pdu.c | 1 + 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/fs/ksmbd/ksmbd_netlink.h b/fs/ksmbd/ksmbd_netlink.h index 52aa0adeb9519..e0cbcfa98c7eb 100644 --- a/fs/ksmbd/ksmbd_netlink.h +++ b/fs/ksmbd/ksmbd_netlink.h @@ -349,6 +349,7 @@ enum KSMBD_TREE_CONN_STATUS { #define KSMBD_SHARE_FLAG_STREAMS BIT(11) #define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS BIT(12) #define KSMBD_SHARE_FLAG_ACL_XATTR BIT(13) +#define KSMBD_SHARE_FLAG_UPDATE BIT(14) /* * Tree connect request flags. @@ -364,6 +365,7 @@ enum KSMBD_TREE_CONN_STATUS { #define KSMBD_TREE_CONN_FLAG_READ_ONLY BIT(1) #define KSMBD_TREE_CONN_FLAG_WRITABLE BIT(2) #define KSMBD_TREE_CONN_FLAG_ADMIN_ACCOUNT BIT(3) +#define KSMBD_TREE_CONN_FLAG_UPDATE BIT(4) /* * RPC over IPC. diff --git a/fs/ksmbd/mgmt/share_config.c b/fs/ksmbd/mgmt/share_config.c index 70655af93b440..c9bca1c2c8349 100644 --- a/fs/ksmbd/mgmt/share_config.c +++ b/fs/ksmbd/mgmt/share_config.c @@ -51,12 +51,16 @@ static void kill_share(struct ksmbd_share_config *share) kfree(share); } -void __ksmbd_share_config_put(struct ksmbd_share_config *share) +void ksmbd_share_config_del(struct ksmbd_share_config *share) { down_write(&shares_table_lock); hash_del(&share->hlist); up_write(&shares_table_lock); +} +void __ksmbd_share_config_put(struct ksmbd_share_config *share) +{ + ksmbd_share_config_del(share); kill_share(share); } diff --git a/fs/ksmbd/mgmt/share_config.h b/fs/ksmbd/mgmt/share_config.h index 28bf3511763f4..902f2cb1963a9 100644 --- a/fs/ksmbd/mgmt/share_config.h +++ b/fs/ksmbd/mgmt/share_config.h @@ -64,6 +64,7 @@ static inline int test_share_config_flag(struct ksmbd_share_config *share, return share->flags & flag; } +void ksmbd_share_config_del(struct ksmbd_share_config *share); void __ksmbd_share_config_put(struct ksmbd_share_config *share); static inline void ksmbd_share_config_put(struct ksmbd_share_config *share) diff --git a/fs/ksmbd/mgmt/tree_connect.c b/fs/ksmbd/mgmt/tree_connect.c index dd262daa2c4a5..97ab7987df6eb 100644 --- a/fs/ksmbd/mgmt/tree_connect.c +++ b/fs/ksmbd/mgmt/tree_connect.c @@ -57,6 +57,20 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, goto out_error; tree_conn->flags = resp->connection_flags; + if (test_tree_conn_flag(tree_conn, KSMBD_TREE_CONN_FLAG_UPDATE)) { + struct ksmbd_share_config *new_sc; + + ksmbd_share_config_del(sc); + new_sc = ksmbd_share_config_get(share_name); + if (!new_sc) { + pr_err("Failed to update stale share config\n"); + status.ret = -ESTALE; + goto out_error; + } + ksmbd_share_config_put(sc); + sc = new_sc; + } + tree_conn->user = sess->user; tree_conn->share_conf = sc; status.tree_conn = tree_conn; diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 1f9a2cda0c58f..b5c36657ecfdd 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -1944,6 +1944,7 @@ int smb2_tree_connect(struct ksmbd_work *work) rsp->hdr.Status = STATUS_SUCCESS; rc = 0; break; + case -ESTALE: case -ENOENT: case KSMBD_TREE_CONN_STATUS_NO_SHARE: rsp->hdr.Status = STATUS_BAD_NETWORK_NAME; From a664375da76c6da8f83dc7997e43c568e1eb9a6a Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 9 Aug 2022 15:16:32 +0200 Subject: [PATCH 142/427] netfilter: nf_ct_sane: remove pseudo skb linearization For historical reason this code performs pseudo linearization of skbs via skb_header_pointer and a global 64k buffer. With arrival of BIG TCP, packets generated by TCP stack can exceed 64kb. Rewrite this to only extract the needed header data. This also allows to get rid of the locking. Fixes: 7c4e983c4f3c ("net: allow gso_max_size to exceed 65536") Fixes: 0fe79f28bfaf ("net: allow gro_max_size to exceed 65536") Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_sane.c | 68 ++++++++++++++----------------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c index fcb33b1d5456d..13dc421fc4f52 100644 --- a/net/netfilter/nf_conntrack_sane.c +++ b/net/netfilter/nf_conntrack_sane.c @@ -34,10 +34,6 @@ MODULE_AUTHOR("Michal Schmidt "); MODULE_DESCRIPTION("SANE connection tracking helper"); MODULE_ALIAS_NFCT_HELPER(HELPER_NAME); -static char *sane_buffer; - -static DEFINE_SPINLOCK(nf_sane_lock); - #define MAX_PORTS 8 static u_int16_t ports[MAX_PORTS]; static unsigned int ports_c; @@ -67,14 +63,16 @@ static int help(struct sk_buff *skb, unsigned int dataoff, datalen; const struct tcphdr *th; struct tcphdr _tcph; - void *sb_ptr; int ret = NF_ACCEPT; int dir = CTINFO2DIR(ctinfo); struct nf_ct_sane_master *ct_sane_info = nfct_help_data(ct); struct nf_conntrack_expect *exp; struct nf_conntrack_tuple *tuple; - struct sane_request *req; struct sane_reply_net_start *reply; + union { + struct sane_request req; + struct sane_reply_net_start repl; + } buf; /* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED && @@ -92,59 +90,62 @@ static int help(struct sk_buff *skb, return NF_ACCEPT; datalen = skb->len - dataoff; - - spin_lock_bh(&nf_sane_lock); - sb_ptr = skb_header_pointer(skb, dataoff, datalen, sane_buffer); - if (!sb_ptr) { - spin_unlock_bh(&nf_sane_lock); - return NF_ACCEPT; - } - if (dir == IP_CT_DIR_ORIGINAL) { + const struct sane_request *req; + if (datalen != sizeof(struct sane_request)) - goto out; + return NF_ACCEPT; + + req = skb_header_pointer(skb, dataoff, datalen, &buf.req); + if (!req) + return NF_ACCEPT; - req = sb_ptr; if (req->RPC_code != htonl(SANE_NET_START)) { /* Not an interesting command */ - ct_sane_info->state = SANE_STATE_NORMAL; - goto out; + WRITE_ONCE(ct_sane_info->state, SANE_STATE_NORMAL); + return NF_ACCEPT; } /* We're interested in the next reply */ - ct_sane_info->state = SANE_STATE_START_REQUESTED; - goto out; + WRITE_ONCE(ct_sane_info->state, SANE_STATE_START_REQUESTED); + return NF_ACCEPT; } + /* IP_CT_DIR_REPLY */ + /* Is it a reply to an uninteresting command? */ - if (ct_sane_info->state != SANE_STATE_START_REQUESTED) - goto out; + if (READ_ONCE(ct_sane_info->state) != SANE_STATE_START_REQUESTED) + return NF_ACCEPT; /* It's a reply to SANE_NET_START. */ - ct_sane_info->state = SANE_STATE_NORMAL; + WRITE_ONCE(ct_sane_info->state, SANE_STATE_NORMAL); if (datalen < sizeof(struct sane_reply_net_start)) { pr_debug("NET_START reply too short\n"); - goto out; + return NF_ACCEPT; } - reply = sb_ptr; + datalen = sizeof(struct sane_reply_net_start); + + reply = skb_header_pointer(skb, dataoff, datalen, &buf.repl); + if (!reply) + return NF_ACCEPT; + if (reply->status != htonl(SANE_STATUS_SUCCESS)) { /* saned refused the command */ pr_debug("unsuccessful SANE_STATUS = %u\n", ntohl(reply->status)); - goto out; + return NF_ACCEPT; } /* Invalid saned reply? Ignore it. */ if (reply->zero != 0) - goto out; + return NF_ACCEPT; exp = nf_ct_expect_alloc(ct); if (exp == NULL) { nf_ct_helper_log(skb, ct, "cannot alloc expectation"); - ret = NF_DROP; - goto out; + return NF_DROP; } tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; @@ -162,9 +163,6 @@ static int help(struct sk_buff *skb, } nf_ct_expect_put(exp); - -out: - spin_unlock_bh(&nf_sane_lock); return ret; } @@ -178,7 +176,6 @@ static const struct nf_conntrack_expect_policy sane_exp_policy = { static void __exit nf_conntrack_sane_fini(void) { nf_conntrack_helpers_unregister(sane, ports_c * 2); - kfree(sane_buffer); } static int __init nf_conntrack_sane_init(void) @@ -187,10 +184,6 @@ static int __init nf_conntrack_sane_init(void) NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_sane_master)); - sane_buffer = kmalloc(65536, GFP_KERNEL); - if (!sane_buffer) - return -ENOMEM; - if (ports_c == 0) ports[ports_c++] = SANE_PORT; @@ -210,7 +203,6 @@ static int __init nf_conntrack_sane_init(void) ret = nf_conntrack_helpers_register(sane, ports_c * 2); if (ret < 0) { pr_err("failed to register helpers\n"); - kfree(sane_buffer); return ret; } From f3e124c36f70d5ffcdd4e8bdbe7bb28a98a715c0 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 9 Aug 2022 15:16:33 +0200 Subject: [PATCH 143/427] netfilter: nf_ct_h323: cap packet size at 64k With BIG TCP, packets generated by tcp stack may exceed 64kb. Cap datalen at 64kb. The internal message format uses 16bit fields, so no embedded message can exceed 64k size. Multiple h323 messages in a single superpacket may now result in a message to get treated as incomplete/truncated, but thats better than scribbling past h323_buffer. Another alternative suitable for net tree would be a switch to skb_linearize(). Fixes: 7c4e983c4f3c ("net: allow gso_max_size to exceed 65536") Fixes: 0fe79f28bfaf ("net: allow gro_max_size to exceed 65536") Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_h323_main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index bb76305bb7ff9..5a9bce24f3c3d 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -34,6 +34,8 @@ #include #include +#define H323_MAX_SIZE 65535 + /* Parameters */ static unsigned int default_rrq_ttl __read_mostly = 300; module_param(default_rrq_ttl, uint, 0600); @@ -86,6 +88,9 @@ static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff, if (tcpdatalen <= 0) /* No TCP data */ goto clear_out; + if (tcpdatalen > H323_MAX_SIZE) + tcpdatalen = H323_MAX_SIZE; + if (*data == NULL) { /* first TPKT */ /* Get first TPKT pointer */ tpkt = skb_header_pointer(skb, tcpdataoff, tcpdatalen, @@ -1169,6 +1174,9 @@ static unsigned char *get_udp_data(struct sk_buff *skb, unsigned int protoff, if (dataoff >= skb->len) return NULL; *datalen = skb->len - dataoff; + if (*datalen > H323_MAX_SIZE) + *datalen = H323_MAX_SIZE; + return skb_header_pointer(skb, dataoff, *datalen, h323_buffer); } @@ -1770,7 +1778,7 @@ static int __init nf_conntrack_h323_init(void) NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_h323_master)); - h323_buffer = kmalloc(65536, GFP_KERNEL); + h323_buffer = kmalloc(H323_MAX_SIZE + 1, GFP_KERNEL); if (!h323_buffer) return -ENOMEM; ret = h323_helper_init(); From c783a29c7e5934eabac2b760571489ad83bf4fd1 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 9 Aug 2022 15:16:34 +0200 Subject: [PATCH 144/427] netfilter: nf_ct_ftp: prefer skb_linearize This uses a pseudo-linearization scheme with a 64k global buffer, but BIG TCP arrival means IPv6 TCP stack can generate skbs that exceed this size. Use skb_linearize. It should be possible to rewrite this to properly deal with segmented skbs (i.e., only do small chunk-wise accesses), but this is going to be a lot more intrusive than this because every helper function needs to get the sk_buff instead of a pointer to a raw data buffer. In practice, provided we're really looking at FTP control channel packets, there should never be a case where we deal with huge packets. Fixes: 7c4e983c4f3c ("net: allow gso_max_size to exceed 65536") Fixes: 0fe79f28bfaf ("net: allow gro_max_size to exceed 65536") Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_ftp.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index a414274338cff..0d9332e9cf71a 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -34,11 +34,6 @@ MODULE_DESCRIPTION("ftp connection tracking helper"); MODULE_ALIAS("ip_conntrack_ftp"); MODULE_ALIAS_NFCT_HELPER(HELPER_NAME); -/* This is slow, but it's simple. --RR */ -static char *ftp_buffer; - -static DEFINE_SPINLOCK(nf_ftp_lock); - #define MAX_PORTS 8 static u_int16_t ports[MAX_PORTS]; static unsigned int ports_c; @@ -398,6 +393,9 @@ static int help(struct sk_buff *skb, return NF_ACCEPT; } + if (unlikely(skb_linearize(skb))) + return NF_DROP; + th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); if (th == NULL) return NF_ACCEPT; @@ -411,12 +409,8 @@ static int help(struct sk_buff *skb, } datalen = skb->len - dataoff; - spin_lock_bh(&nf_ftp_lock); - fb_ptr = skb_header_pointer(skb, dataoff, datalen, ftp_buffer); - if (!fb_ptr) { - spin_unlock_bh(&nf_ftp_lock); - return NF_ACCEPT; - } + spin_lock_bh(&ct->lock); + fb_ptr = skb->data + dataoff; ends_in_nl = (fb_ptr[datalen - 1] == '\n'); seq = ntohl(th->seq) + datalen; @@ -544,7 +538,7 @@ static int help(struct sk_buff *skb, if (ends_in_nl) update_nl_seq(ct, seq, ct_ftp_info, dir, skb); out: - spin_unlock_bh(&nf_ftp_lock); + spin_unlock_bh(&ct->lock); return ret; } @@ -571,7 +565,6 @@ static const struct nf_conntrack_expect_policy ftp_exp_policy = { static void __exit nf_conntrack_ftp_fini(void) { nf_conntrack_helpers_unregister(ftp, ports_c * 2); - kfree(ftp_buffer); } static int __init nf_conntrack_ftp_init(void) @@ -580,10 +573,6 @@ static int __init nf_conntrack_ftp_init(void) NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_ftp_master)); - ftp_buffer = kmalloc(65536, GFP_KERNEL); - if (!ftp_buffer) - return -ENOMEM; - if (ports_c == 0) ports[ports_c++] = FTP_PORT; @@ -603,7 +592,6 @@ static int __init nf_conntrack_ftp_init(void) ret = nf_conntrack_helpers_register(ftp, ports_c * 2); if (ret < 0) { pr_err("failed to register helpers\n"); - kfree(ftp_buffer); return ret; } From 976bf59c69cd2e2c17f0ab20a14c0e700cba0f15 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 9 Aug 2022 15:16:35 +0200 Subject: [PATCH 145/427] netfilter: nf_ct_irc: cap packet search space to 4k This uses a pseudo-linearization scheme with a 64k global buffer, but BIG TCP arrival means IPv6 TCP stack can generate skbs that exceed this size. In practice, IRC commands are not expected to exceed 512 bytes, plus this is interactive protocol, so we should not see large packets in practice. Given most IRC connections nowadays use TLS so this helper could also be removed in the near future. Fixes: 7c4e983c4f3c ("net: allow gso_max_size to exceed 65536") Fixes: 0fe79f28bfaf ("net: allow gro_max_size to exceed 65536") Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_irc.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index 08ee4e760a3d2..1796c456ac98b 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c @@ -39,6 +39,7 @@ unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb, EXPORT_SYMBOL_GPL(nf_nat_irc_hook); #define HELPER_NAME "irc" +#define MAX_SEARCH_SIZE 4095 MODULE_AUTHOR("Harald Welte "); MODULE_DESCRIPTION("IRC (DCC) connection tracking helper"); @@ -121,6 +122,7 @@ static int help(struct sk_buff *skb, unsigned int protoff, int i, ret = NF_ACCEPT; char *addr_beg_p, *addr_end_p; typeof(nf_nat_irc_hook) nf_nat_irc; + unsigned int datalen; /* If packet is coming from IRC server */ if (dir == IP_CT_DIR_REPLY) @@ -140,8 +142,12 @@ static int help(struct sk_buff *skb, unsigned int protoff, if (dataoff >= skb->len) return NF_ACCEPT; + datalen = skb->len - dataoff; + if (datalen > MAX_SEARCH_SIZE) + datalen = MAX_SEARCH_SIZE; + spin_lock_bh(&irc_buffer_lock); - ib_ptr = skb_header_pointer(skb, dataoff, skb->len - dataoff, + ib_ptr = skb_header_pointer(skb, dataoff, datalen, irc_buffer); if (!ib_ptr) { spin_unlock_bh(&irc_buffer_lock); @@ -149,7 +155,7 @@ static int help(struct sk_buff *skb, unsigned int protoff, } data = ib_ptr; - data_limit = ib_ptr + skb->len - dataoff; + data_limit = ib_ptr + datalen; /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24 * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */ @@ -251,7 +257,7 @@ static int __init nf_conntrack_irc_init(void) irc_exp_policy.max_expected = max_dcc_channels; irc_exp_policy.timeout = dcc_timeout; - irc_buffer = kmalloc(65536, GFP_KERNEL); + irc_buffer = kmalloc(MAX_SEARCH_SIZE + 1, GFP_KERNEL); if (!irc_buffer) return -ENOMEM; From 7fe05e125d5f730bd2d0fc53985bee77b6c762f0 Mon Sep 17 00:00:00 2001 From: Benjamin Mikailenko Date: Fri, 15 Jul 2022 18:27:07 -0400 Subject: [PATCH 146/427] ice: Fix VSI rebuild WARN_ON check for VF In commit b03d519d3460 ("ice: store VF pointer instead of VF ID") WARN_ON checks were added to validate the vsi->vf pointer and catch programming errors. However, one check to vsi->vf was missed. This caused a call trace when resetting VFs. Fix ice_vsi_rebuild by encompassing VF pointer in WARN_ON check. Fixes: b03d519d3460 ("ice: store VF pointer instead of VF ID") Signed-off-by: Benjamin Mikailenko Tested-by: Marek Szlosek Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index a830f7f9aed05..0d4dbca889640 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -3181,7 +3181,7 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi) pf = vsi->back; vtype = vsi->type; - if (WARN_ON(vtype == ICE_VSI_VF) && !vsi->vf) + if (WARN_ON(vtype == ICE_VSI_VF && !vsi->vf)) return -EINVAL; ice_vsi_init_vlan_ops(vsi); From cf90b74341eecc32ceef0c136954a1668e43b1e7 Mon Sep 17 00:00:00 2001 From: Michal Jaron Date: Mon, 25 Jul 2022 10:32:43 +0200 Subject: [PATCH 147/427] ice: Fix call trace with null VSI during VF reset During stress test with attaching and detaching VF from KVM and simultaneously changing VFs spoofcheck and trust there was a call trace in ice_reset_vf that VF's VSI is null. [145237.352797] WARNING: CPU: 46 PID: 840629 at drivers/net/ethernet/intel/ice/ice_vf_lib.c:508 ice_reset_vf+0x3d6/0x410 [ice] [145237.352851] Modules linked in: ice(E) vfio_pci vfio_pci_core vfio_virqfd vfio_iommu_type1 vfio iavf dm_mod xt_CHECKSUM xt_MASQUERADE xt_conntrack ipt_REJECT nf_reject_ipv4 nft_compat nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables nfnetlink tun bridge stp llc sunrpc intel_rapl_msr intel_rapl_common sb_edac x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm iTCO_wdt iTC O_vendor_support irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel rapl ipmi_si intel_cstate ipmi_devintf joydev intel_uncore m ei_me ipmi_msghandler i2c_i801 pcspkr mei lpc_ich ioatdma i2c_smbus acpi_pad acpi_power_meter ip_tables xfs libcrc32c i2c_algo_bit drm_sh mem_helper drm_kms_helper sd_mod t10_pi crc64_rocksoft syscopyarea crc64 sysfillrect sg sysimgblt fb_sys_fops drm i40e ixgbe ahci libahci libata crc32c_intel mdio dca wmi fuse [last unloaded: ice] [145237.352917] CPU: 46 PID: 840629 Comm: kworker/46:2 Tainted: G S W I E 5.19.0-rc6+ #24 [145237.352921] Hardware name: Intel Corporation S2600WTT/S2600WTT, BIOS SE5C610.86B.01.01.0008.021120151325 02/11/2015 [145237.352923] Workqueue: ice ice_service_task [ice] [145237.352948] RIP: 0010:ice_reset_vf+0x3d6/0x410 [ice] [145237.352984] Code: 30 ec f3 cc e9 28 fd ff ff 0f b7 4b 50 48 c7 c2 48 19 9c c0 4c 89 ee 48 c7 c7 30 fe 9e c0 e8 d1 21 9d cc 31 c0 e9 a 9 fe ff ff <0f> 0b b8 ea ff ff ff e9 c1 fc ff ff 0f 0b b8 fb ff ff ff e9 91 fe [145237.352987] RSP: 0018:ffffb453e257fdb8 EFLAGS: 00010246 [145237.352990] RAX: ffff8bd0040181c0 RBX: ffff8be68db8f800 RCX: 0000000000000000 [145237.352991] RDX: 000000000000ffff RSI: 0000000000000000 RDI: ffff8be68db8f800 [145237.352993] RBP: ffff8bd0040181c0 R08: 0000000000001000 R09: ffff8bcfd520e000 [145237.352995] R10: 0000000000000000 R11: 00008417b5ab0bc0 R12: 0000000000000005 [145237.352996] R13: ffff8bcee061c0d0 R14: ffff8bd004019640 R15: 0000000000000000 [145237.352998] FS: 0000000000000000(0000) GS:ffff8be5dfb00000(0000) knlGS:0000000000000000 [145237.353000] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [145237.353002] CR2: 00007fd81f651d68 CR3: 0000001a0fe10001 CR4: 00000000001726e0 [145237.353003] Call Trace: [145237.353008] [145237.353011] ice_process_vflr_event+0x8d/0xb0 [ice] [145237.353049] ice_service_task+0x79f/0xef0 [ice] [145237.353074] process_one_work+0x1c8/0x390 [145237.353081] ? process_one_work+0x390/0x390 [145237.353084] worker_thread+0x30/0x360 [145237.353087] ? process_one_work+0x390/0x390 [145237.353090] kthread+0xe8/0x110 [145237.353094] ? kthread_complete_and_exit+0x20/0x20 [145237.353097] ret_from_fork+0x22/0x30 [145237.353103] Remove WARN_ON() from check if VSI is null in ice_reset_vf. Add "VF is already removed\n" in dev_dbg(). This WARN_ON() is unnecessary and causes call trace, despite that call trace, driver still works. There is no need for this warn because this piece of code is responsible for disabling VF's Tx/Rx queues when VF is disabled, but when VF is already removed there is no need to do reset or disable queues. Fixes: efe41860008e ("ice: Fix memory corruption in VF driver") Signed-off-by: Michal Jaron Signed-off-by: Jedrzej Jagielski Tested-by: Marek Szlosek Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_vf_lib.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c index 8fd7c3e37f5e3..76f70fe1d9989 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c @@ -571,8 +571,10 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags) if (ice_is_vf_disabled(vf)) { vsi = ice_get_vf_vsi(vf); - if (WARN_ON(!vsi)) + if (!vsi) { + dev_dbg(dev, "VF is already removed\n"); return -EINVAL; + } ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, vf->vf_id); ice_vsi_stop_all_rx_rings(vsi); dev_dbg(dev, "VF is already disabled, there is no need for resetting it, telling VM, all is fine %d\n", From 2024439bd5ceb145eeeb428b2a59e9b905153ac3 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 11 Aug 2022 13:30:39 +0200 Subject: [PATCH 148/427] netfilter: nf_tables: fix scheduling-while-atomic splat nf_tables_check_loops() can be called from rhashtable list walk so cond_resched() cannot be used here. Fixes: 81ea01066741 ("netfilter: nf_tables: add rescheduling points during loop detection walks") Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 989c9782ecc34..d90434eadc1b1 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -9426,13 +9426,9 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx, break; } } - - cond_resched(); } list_for_each_entry(set, &ctx->table->sets, list) { - cond_resched(); - if (!nft_is_active_next(ctx->net, set)) continue; if (!(set->flags & NFT_SET_MAP) || From 0b2f3212b551a87fe936701fa0813032861a3308 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 5 Aug 2022 10:59:57 +0200 Subject: [PATCH 149/427] netfilter: nfnetlink: re-enable conntrack expectation events To avoid allocation of the conntrack extension area when possible, the default behaviour was changed to only allocate the event extension if a userspace program is subscribed to a notification group. Problem is that while 'conntrack -E' does enable the event allocation behind the scenes, 'conntrack -E expect' does not: no expectation events are delivered unless user sets "net.netfilter.nf_conntrack_events" back to 1 (always on). Fix the autodetection to also consider EXP type group. We need to track the 6 event groups (3+3, new/update/destroy for events and for expectations each) independently, else we'd disable events again if an expectation group becomes empty while there is still an active event group. Fixes: 2794cdb0b97b ("netfilter: nfnetlink: allow to detect if ctnetlink listeners exist") Reported-by: Yi Chen Signed-off-by: Florian Westphal --- include/net/netns/conntrack.h | 2 +- net/netfilter/nfnetlink.c | 83 ++++++++++++++++++++++++++++++----- 2 files changed, 72 insertions(+), 13 deletions(-) diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h index 0677cd3de0344..c396a3862e808 100644 --- a/include/net/netns/conntrack.h +++ b/include/net/netns/conntrack.h @@ -95,7 +95,7 @@ struct nf_ip_net { struct netns_ct { #ifdef CONFIG_NF_CONNTRACK_EVENTS - bool ctnetlink_has_listener; + u8 ctnetlink_has_listener; bool ecache_dwork_pending; #endif u8 sysctl_log_invalid; /* Log invalid packets */ diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index c24b1240908fd..9c44518cb70ff 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -44,6 +44,10 @@ MODULE_DESCRIPTION("Netfilter messages via netlink socket"); static unsigned int nfnetlink_pernet_id __read_mostly; +#ifdef CONFIG_NF_CONNTRACK_EVENTS +static DEFINE_SPINLOCK(nfnl_grp_active_lock); +#endif + struct nfnl_net { struct sock *nfnl; }; @@ -654,6 +658,44 @@ static void nfnetlink_rcv(struct sk_buff *skb) netlink_rcv_skb(skb, nfnetlink_rcv_msg); } +static void nfnetlink_bind_event(struct net *net, unsigned int group) +{ +#ifdef CONFIG_NF_CONNTRACK_EVENTS + int type, group_bit; + u8 v; + + /* All NFNLGRP_CONNTRACK_* group bits fit into u8. + * The other groups are not relevant and can be ignored. + */ + if (group >= 8) + return; + + type = nfnl_group2type[group]; + + switch (type) { + case NFNL_SUBSYS_CTNETLINK: + break; + case NFNL_SUBSYS_CTNETLINK_EXP: + break; + default: + return; + } + + group_bit = (1 << group); + + spin_lock(&nfnl_grp_active_lock); + v = READ_ONCE(net->ct.ctnetlink_has_listener); + if ((v & group_bit) == 0) { + v |= group_bit; + + /* read concurrently without nfnl_grp_active_lock held. */ + WRITE_ONCE(net->ct.ctnetlink_has_listener, v); + } + + spin_unlock(&nfnl_grp_active_lock); +#endif +} + static int nfnetlink_bind(struct net *net, int group) { const struct nfnetlink_subsystem *ss; @@ -670,28 +712,45 @@ static int nfnetlink_bind(struct net *net, int group) if (!ss) request_module_nowait("nfnetlink-subsys-%d", type); -#ifdef CONFIG_NF_CONNTRACK_EVENTS - if (type == NFNL_SUBSYS_CTNETLINK) { - nfnl_lock(NFNL_SUBSYS_CTNETLINK); - WRITE_ONCE(net->ct.ctnetlink_has_listener, true); - nfnl_unlock(NFNL_SUBSYS_CTNETLINK); - } -#endif + nfnetlink_bind_event(net, group); return 0; } static void nfnetlink_unbind(struct net *net, int group) { #ifdef CONFIG_NF_CONNTRACK_EVENTS + int type, group_bit; + if (group <= NFNLGRP_NONE || group > NFNLGRP_MAX) return; - if (nfnl_group2type[group] == NFNL_SUBSYS_CTNETLINK) { - nfnl_lock(NFNL_SUBSYS_CTNETLINK); - if (!nfnetlink_has_listeners(net, group)) - WRITE_ONCE(net->ct.ctnetlink_has_listener, false); - nfnl_unlock(NFNL_SUBSYS_CTNETLINK); + type = nfnl_group2type[group]; + + switch (type) { + case NFNL_SUBSYS_CTNETLINK: + break; + case NFNL_SUBSYS_CTNETLINK_EXP: + break; + default: + return; + } + + /* ctnetlink_has_listener is u8 */ + if (group >= 8) + return; + + group_bit = (1 << group); + + spin_lock(&nfnl_grp_active_lock); + if (!nfnetlink_has_listeners(net, group)) { + u8 v = READ_ONCE(net->ct.ctnetlink_has_listener); + + v &= ~group_bit; + + /* read concurrently without nfnl_grp_active_lock held. */ + WRITE_ONCE(net->ct.ctnetlink_has_listener, v); } + spin_unlock(&nfnl_grp_active_lock); #endif } From 271c5ca826e0c3c53e0eb4032f8eaedea1ee391c Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 9 Aug 2022 17:23:53 +0200 Subject: [PATCH 150/427] netfilter: nf_tables: really skip inactive sets when allocating name While looping to build the bitmap of used anonymous set names, check the current set in the iteration, instead of the one that is being created. Fixes: 37a9cc525525 ("netfilter: nf_tables: add generation mask to sets") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index d90434eadc1b1..1b9459a364ba7 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -3907,7 +3907,7 @@ static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set, list_for_each_entry(i, &ctx->table->sets, list) { int tmp; - if (!nft_is_active_next(ctx->net, set)) + if (!nft_is_active_next(ctx->net, i)) continue; if (!sscanf(i->name, name, &tmp)) continue; From 09992025dacd258c823f50e82db09d7ef06cdac4 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 11 Aug 2022 15:44:45 +0200 Subject: [PATCH 151/427] spi: meson-spicc: add local pow2 clock ops to preserve rate between messages At the end of a message, the HW gets a reset in meson_spicc_unprepare_transfer(), this resets the SPICC_CONREG register and notably the value set by the Common Clock Framework. This is problematic because: - the register value CCF can be different from the corresponding CCF cached rate - CCF is allowed to change the clock rate whenever the HW state This introduces: - local pow2 clock ops checking the HW state before allowing a clock operation - separation of legacy pow2 clock patch and new enhanced clock path - SPICC_CONREG datarate value is now value kepts across messages It has been checked that: - SPICC_CONREG datarate value is kept across messages - CCF is only allowed to change the SPICC_CONREG datarate value when busy - SPICC_CONREG datarate value is correct for each transfer This didn't appear before commit 3e0cf4d3fc29 ("spi: meson-spicc: add a linear clock divider support") because we recalculated and wrote the rate for each xfer. Fixes: 3e0cf4d3fc29 ("spi: meson-spicc: add a linear clock divider support") Reported-by: Da Xue Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20220811134445.678446-1-narmstrong@baylibre.com Signed-off-by: Mark Brown --- drivers/spi/spi-meson-spicc.c | 129 ++++++++++++++++++++++++++-------- 1 file changed, 101 insertions(+), 28 deletions(-) diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c index 0bc7daa7afc83..e4cb52e1fe261 100644 --- a/drivers/spi/spi-meson-spicc.c +++ b/drivers/spi/spi-meson-spicc.c @@ -156,6 +156,7 @@ struct meson_spicc_device { void __iomem *base; struct clk *core; struct clk *pclk; + struct clk_divider pow2_div; struct clk *clk; struct spi_message *message; struct spi_transfer *xfer; @@ -168,6 +169,8 @@ struct meson_spicc_device { unsigned long xfer_remain; }; +#define pow2_clk_to_spicc(_div) container_of(_div, struct meson_spicc_device, pow2_div) + static void meson_spicc_oen_enable(struct meson_spicc_device *spicc) { u32 conf; @@ -421,7 +424,7 @@ static int meson_spicc_prepare_message(struct spi_master *master, { struct meson_spicc_device *spicc = spi_master_get_devdata(master); struct spi_device *spi = message->spi; - u32 conf = 0; + u32 conf = readl_relaxed(spicc->base + SPICC_CONREG) & SPICC_DATARATE_MASK; /* Store current message */ spicc->message = message; @@ -458,8 +461,6 @@ static int meson_spicc_prepare_message(struct spi_master *master, /* Select CS */ conf |= FIELD_PREP(SPICC_CS_MASK, spi->chip_select); - /* Default Clock rate core/4 */ - /* Default 8bit word */ conf |= FIELD_PREP(SPICC_BITLENGTH_MASK, 8 - 1); @@ -476,12 +477,16 @@ static int meson_spicc_prepare_message(struct spi_master *master, static int meson_spicc_unprepare_transfer(struct spi_master *master) { struct meson_spicc_device *spicc = spi_master_get_devdata(master); + u32 conf = readl_relaxed(spicc->base + SPICC_CONREG) & SPICC_DATARATE_MASK; /* Disable all IRQs */ writel(0, spicc->base + SPICC_INTREG); device_reset_optional(&spicc->pdev->dev); + /* Set default configuration, keeping datarate field */ + writel_relaxed(conf, spicc->base + SPICC_CONREG); + return 0; } @@ -518,14 +523,60 @@ static void meson_spicc_cleanup(struct spi_device *spi) * Clk path for G12A series: * pclk -> pow2 fixed div -> pow2 div -> mux -> out * pclk -> enh fixed div -> enh div -> mux -> out + * + * The pow2 divider is tied to the controller HW state, and the + * divider is only valid when the controller is initialized. + * + * A set of clock ops is added to make sure we don't read/set this + * clock rate while the controller is in an unknown state. */ -static int meson_spicc_clk_init(struct meson_spicc_device *spicc) +static unsigned long meson_spicc_pow2_recalc_rate(struct clk_hw *hw, + unsigned long parent_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) + return 0; + + return clk_divider_ops.recalc_rate(hw, parent_rate); +} + +static int meson_spicc_pow2_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + 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) + return -EINVAL; + + return clk_divider_ops.determine_rate(hw, req); +} + +static int meson_spicc_pow2_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_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) + return -EINVAL; + + return clk_divider_ops.set_rate(hw, rate, parent_rate); +} + +const struct clk_ops meson_spicc_pow2_clk_ops = { + .recalc_rate = meson_spicc_pow2_recalc_rate, + .determine_rate = meson_spicc_pow2_determine_rate, + .set_rate = meson_spicc_pow2_set_rate, +}; + +static int meson_spicc_pow2_clk_init(struct meson_spicc_device *spicc) { struct device *dev = &spicc->pdev->dev; - struct clk_fixed_factor *pow2_fixed_div, *enh_fixed_div; - struct clk_divider *pow2_div, *enh_div; - struct clk_mux *mux; + struct clk_fixed_factor *pow2_fixed_div; struct clk_init_data init; struct clk *clk; struct clk_parent_data parent_data[2]; @@ -560,31 +611,45 @@ static int meson_spicc_clk_init(struct meson_spicc_device *spicc) if (WARN_ON(IS_ERR(clk))) return PTR_ERR(clk); - pow2_div = devm_kzalloc(dev, sizeof(*pow2_div), GFP_KERNEL); - if (!pow2_div) - return -ENOMEM; - snprintf(name, sizeof(name), "%s#pow2_div", dev_name(dev)); init.name = name; - init.ops = &clk_divider_ops; - init.flags = CLK_SET_RATE_PARENT; + init.ops = &meson_spicc_pow2_clk_ops; + /* + * Set NOCACHE here to make sure we read the actual HW value + * since we reset the HW after each transfer. + */ + init.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE; parent_data[0].hw = &pow2_fixed_div->hw; init.num_parents = 1; - pow2_div->shift = 16, - pow2_div->width = 3, - pow2_div->flags = CLK_DIVIDER_POWER_OF_TWO, - pow2_div->reg = spicc->base + SPICC_CONREG; - pow2_div->hw.init = &init; + spicc->pow2_div.shift = 16, + spicc->pow2_div.width = 3, + spicc->pow2_div.flags = CLK_DIVIDER_POWER_OF_TWO, + spicc->pow2_div.reg = spicc->base + SPICC_CONREG; + spicc->pow2_div.hw.init = &init; - clk = devm_clk_register(dev, &pow2_div->hw); - if (WARN_ON(IS_ERR(clk))) - return PTR_ERR(clk); + spicc->clk = devm_clk_register(dev, &spicc->pow2_div.hw); + if (WARN_ON(IS_ERR(spicc->clk))) + return PTR_ERR(spicc->clk); - if (!spicc->data->has_enhance_clk_div) { - spicc->clk = clk; - return 0; - } + return 0; +} + +static int meson_spicc_enh_clk_init(struct meson_spicc_device *spicc) +{ + struct device *dev = &spicc->pdev->dev; + struct clk_fixed_factor *enh_fixed_div; + struct clk_divider *enh_div; + struct clk_mux *mux; + struct clk_init_data init; + struct clk *clk; + struct clk_parent_data parent_data[2]; + char name[64]; + + memset(&init, 0, sizeof(init)); + memset(&parent_data, 0, sizeof(parent_data)); + + init.parent_data = parent_data; /* algorithm for enh div: rate = freq / 2 / (N + 1) */ @@ -637,7 +702,7 @@ static int meson_spicc_clk_init(struct meson_spicc_device *spicc) snprintf(name, sizeof(name), "%s#sel", dev_name(dev)); init.name = name; init.ops = &clk_mux_ops; - parent_data[0].hw = &pow2_div->hw; + parent_data[0].hw = &spicc->pow2_div.hw; parent_data[1].hw = &enh_div->hw; init.num_parents = 2; init.flags = CLK_SET_RATE_PARENT; @@ -754,12 +819,20 @@ static int meson_spicc_probe(struct platform_device *pdev) meson_spicc_oen_enable(spicc); - ret = meson_spicc_clk_init(spicc); + ret = meson_spicc_pow2_clk_init(spicc); if (ret) { - dev_err(&pdev->dev, "clock registration failed\n"); + dev_err(&pdev->dev, "pow2 clock registration failed\n"); goto out_clk; } + if (spicc->data->has_enhance_clk_div) { + ret = meson_spicc_enh_clk_init(spicc); + if (ret) { + dev_err(&pdev->dev, "clock registration failed\n"); + goto out_clk; + } + } + ret = devm_spi_register_master(&pdev->dev, master); if (ret) { dev_err(&pdev->dev, "spi master registration failed\n"); From 2fd92c7b8fe2cfc634613dc093d0f507c7389ea8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 11 Aug 2022 09:38:26 +0300 Subject: [PATCH 152/427] spi: dt-bindings: Drop Pratyush Yadav Emails to Pratyush Yadav bounce ("550 Invalid recipient"). Generic SPI properties should be maintained by subsystem maintainer (Mark). Add recent contributor Vaishnav Achath to the Cadence SPI bindings. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220811063826.7620-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- .../devicetree/bindings/spi/cdns,qspi-nor-peripheral-props.yaml | 2 +- Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml | 2 +- Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/cdns,qspi-nor-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/cdns,qspi-nor-peripheral-props.yaml index 553601a441a7d..510b82c177c05 100644 --- a/Documentation/devicetree/bindings/spi/cdns,qspi-nor-peripheral-props.yaml +++ b/Documentation/devicetree/bindings/spi/cdns,qspi-nor-peripheral-props.yaml @@ -10,7 +10,7 @@ description: See spi-peripheral-props.yaml for more info. maintainers: - - Pratyush Yadav + - Vaishnav Achath properties: # cdns,qspi-nor.yaml diff --git a/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml b/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml index 0a537fa3a6410..4707294d8f596 100644 --- a/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml +++ b/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Cadence Quad SPI controller maintainers: - - Pratyush Yadav + - Vaishnav Achath allOf: - $ref: spi-controller.yaml# diff --git a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml index ce048e782e804..a4abe15880053 100644 --- a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml +++ b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml @@ -16,7 +16,7 @@ description: their own separate schema that should be referenced from here. maintainers: - - Pratyush Yadav + - Mark Brown properties: reg: From 9f414eb409daf4f778f011cf8266d36896bb930b Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 10 Aug 2022 09:00:42 -0400 Subject: [PATCH 153/427] rds: add missing barrier to release_refill The functions clear_bit and set_bit do not imply a memory barrier, thus it may be possible that the waitqueue_active function (which does not take any locks) is moved before clear_bit and it could miss a wakeup event. Fix this bug by adding a memory barrier after clear_bit. Signed-off-by: Mikulas Patocka Cc: stable@vger.kernel.org Signed-off-by: David S. Miller --- net/rds/ib_recv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c index 6fdedd9dbbc28..cfbf0e129cba5 100644 --- a/net/rds/ib_recv.c +++ b/net/rds/ib_recv.c @@ -363,6 +363,7 @@ static int acquire_refill(struct rds_connection *conn) static void release_refill(struct rds_connection *conn) { clear_bit(RDS_RECV_REFILL, &conn->c_flags); + smp_mb__after_atomic(); /* We don't use wait_on_bit()/wake_up_bit() because our waking is in a * hot path and finding waiters is very rare. We don't want to walk From 86d2155e48f6ce1aacbd01667176e5b915ae275c Mon Sep 17 00:00:00 2001 From: Jilin Yuan Date: Wed, 10 Aug 2022 21:59:01 +0800 Subject: [PATCH 154/427] skfp/h: fix repeated words in comments Delete the redundant word 'the'. Signed-off-by: Jilin Yuan Signed-off-by: David S. Miller --- drivers/net/fddi/skfp/h/hwmtm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/fddi/skfp/h/hwmtm.h b/drivers/net/fddi/skfp/h/hwmtm.h index 76c4a709d73da..e97db826cdd45 100644 --- a/drivers/net/fddi/skfp/h/hwmtm.h +++ b/drivers/net/fddi/skfp/h/hwmtm.h @@ -348,7 +348,7 @@ do { \ * This macro is invoked by the OS-specific before it left the * function mac_drv_rx_complete. This macro calls mac_drv_fill_rxd * if the number of used RxDs is equal or lower than the - * the given low water mark. + * given low water mark. * * para low_water low water mark of used RxD's * From bfc48f1b0505ffcb03a6d749139b7577d6b81ae0 Mon Sep 17 00:00:00 2001 From: Xin Xiong Date: Wed, 10 Aug 2022 23:29:13 +0800 Subject: [PATCH 155/427] net/sunrpc: fix potential memory leaks in rpc_sysfs_xprt_state_change() The issue happens on some error handling paths. When the function fails to grab the object `xprt`, it simply returns 0, forgetting to decrease the reference count of another object `xps`, which is increased by rpc_sysfs_xprt_kobj_get_xprt_switch(), causing refcount leaks. Also, the function forgets to check whether `xps` is valid before using it, which may result in NULL-dereferencing issues. Fix it by adding proper error handling code when either `xprt` or `xps` is NULL. Fixes: 5b7eb78486cd ("SUNRPC: take a xprt offline using sysfs") Signed-off-by: Xin Xiong Signed-off-by: Xin Tan Signed-off-by: David S. Miller --- net/sunrpc/sysfs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c index 7330eb9a70cf8..c65c90ad626ad 100644 --- a/net/sunrpc/sysfs.c +++ b/net/sunrpc/sysfs.c @@ -291,8 +291,10 @@ static ssize_t rpc_sysfs_xprt_state_change(struct kobject *kobj, int offline = 0, online = 0, remove = 0; struct rpc_xprt_switch *xps = rpc_sysfs_xprt_kobj_get_xprt_switch(kobj); - if (!xprt) - return 0; + if (!xprt || !xps) { + count = 0; + goto out_put; + } if (!strncmp(buf, "offline", 7)) offline = 1; From 95bb633048fab742230eb2cdf20b8e2676240a54 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 11 Aug 2022 08:51:58 -0400 Subject: [PATCH 156/427] virtio_net: fix endian-ness for RSS Using native endian-ness for device supplied fields is wrong on BE platforms. Sparse warns about this. Fixes: 91f41f01d219 ("drivers/net/virtio_net: Added RSS hash report.") Cc: "Andrew Melnychenko" Signed-off-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 3b3eebad39772..d4e0a775b1ba7 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1199,7 +1199,7 @@ static void virtio_skb_set_hash(const struct virtio_net_hdr_v1_hash *hdr_hash, if (!hdr_hash || !skb) return; - switch ((int)hdr_hash->hash_report) { + switch (__le16_to_cpu(hdr_hash->hash_report)) { case VIRTIO_NET_HASH_REPORT_TCPv4: case VIRTIO_NET_HASH_REPORT_UDPv4: case VIRTIO_NET_HASH_REPORT_TCPv6: @@ -1217,7 +1217,7 @@ static void virtio_skb_set_hash(const struct virtio_net_hdr_v1_hash *hdr_hash, default: rss_hash_type = PKT_HASH_TYPE_NONE; } - skb_set_hash(skb, (unsigned int)hdr_hash->hash_value, rss_hash_type); + skb_set_hash(skb, __le32_to_cpu(hdr_hash->hash_value), rss_hash_type); } static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, From 9221b2898a5877f7e15442ccee7a4e59c6f03f0d Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Thu, 11 Aug 2022 19:52:59 +0800 Subject: [PATCH 157/427] net: ipa: Fix comment typo The double `is' is duplicated in the comment, remove one. Signed-off-by: Jason Wang Reviewed-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/ipa_reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ipa/ipa_reg.h b/drivers/net/ipa/ipa_reg.h index a5b355384d4ae..6f35438cda890 100644 --- a/drivers/net/ipa/ipa_reg.h +++ b/drivers/net/ipa/ipa_reg.h @@ -48,7 +48,7 @@ struct ipa; * * The offset of registers related to resource types is computed by a macro * that is supplied a parameter "rt". The "rt" represents a resource type, - * which is is a member of the ipa_resource_type_src enumerated type for + * which is a member of the ipa_resource_type_src enumerated type for * source endpoint resources or the ipa_resource_type_dst enumerated type * for destination endpoint resources. * From 0619d0fa6cedb32f0835e23ca774085128ccb2b8 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Thu, 11 Aug 2022 19:56:20 +0800 Subject: [PATCH 158/427] bnx2x: Fix comment typo The double `the' is duplicated in the comment, remove one. Signed-off-by: Jason Wang Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 7071604f9984c..02808513ffe45 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -13844,7 +13844,7 @@ static void bnx2x_check_kr2_wa(struct link_params *params, /* Once KR2 was disabled, wait 5 seconds before checking KR2 recovery * Since some switches tend to reinit the AN process and clear the - * the advertised BP/NP after ~2 seconds causing the KR2 to be disabled + * advertised BP/NP after ~2 seconds causing the KR2 to be disabled * and recovered many times */ if (vars->check_kr2_recovery_cnt > 0) { From 75d8620d46f00fcece574dd70ea36acfdfcf171b Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Thu, 11 Aug 2022 19:57:01 +0800 Subject: [PATCH 159/427] net: cxgb3: Fix comment typo The double `the' is duplicated in the comment, remove one. Signed-off-by: Jason Wang Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c index 84604aff53ce7..89256b8668403 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c @@ -243,7 +243,7 @@ static int cxgb_ulp_iscsi_ctl(struct adapter *adapter, unsigned int req, /* * on rx, the iscsi pdu has to be < rx page size and the - * the max rx data length programmed in TP + * max rx data length programmed in TP */ val = min(adapter->params.tp.rx_pg_size, ((t3_read_reg(adapter, A_TP_PARA_REG2)) >> From 40b4ac880e21d917da7f3752332fa57564a4c202 Mon Sep 17 00:00:00 2001 From: Li Qiong Date: Fri, 12 Aug 2022 11:09:54 +0800 Subject: [PATCH 160/427] net: lan966x: fix checking for return value of platform_get_irq_byname() The platform_get_irq_byname() returns non-zero IRQ number or negative error number. "if (irq)" always true, chang it to "if (irq > 0)" Signed-off-by: Li Qiong Signed-off-by: David S. Miller --- drivers/net/ethernet/microchip/lan966x/lan966x_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c index 1d6e3b641b2e6..d928b75f37803 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -710,7 +710,7 @@ static void lan966x_cleanup_ports(struct lan966x *lan966x) disable_irq(lan966x->xtr_irq); lan966x->xtr_irq = -ENXIO; - if (lan966x->ana_irq) { + if (lan966x->ana_irq > 0) { disable_irq(lan966x->ana_irq); lan966x->ana_irq = -ENXIO; } @@ -718,10 +718,10 @@ static void lan966x_cleanup_ports(struct lan966x *lan966x) if (lan966x->fdma) devm_free_irq(lan966x->dev, lan966x->fdma_irq, lan966x); - if (lan966x->ptp_irq) + if (lan966x->ptp_irq > 0) devm_free_irq(lan966x->dev, lan966x->ptp_irq, lan966x); - if (lan966x->ptp_ext_irq) + if (lan966x->ptp_ext_irq > 0) devm_free_irq(lan966x->dev, lan966x->ptp_ext_irq, lan966x); } @@ -1049,7 +1049,7 @@ static int lan966x_probe(struct platform_device *pdev) } lan966x->ana_irq = platform_get_irq_byname(pdev, "ana"); - if (lan966x->ana_irq) { + if (lan966x->ana_irq > 0) { err = devm_request_threaded_irq(&pdev->dev, lan966x->ana_irq, NULL, lan966x_ana_irq_handler, IRQF_ONESHOT, "ana irq", lan966x); From a9084d888fbaaed65ded56f11d052cf8b04519a5 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 1 Aug 2022 21:28:07 +0200 Subject: [PATCH 161/427] irqchip/loongson-liointc: Fix an error handling path in liointc_init() All errors lead to the error handling path, except the one dealing with "reg-names" in DT. Fix it and release some resources before returning if this test fails. Fixes: 0858ed035a85 ("irqchip/loongson-liointc: Add ACPI init support") Signed-off-by: Christophe JAILLET [maz: fix commit message] Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/1a6d74ab70712279023aa7bdbd31bd3aec103bc0.1659382063.git.christophe.jaillet@wanadoo.fr --- drivers/irqchip/irq-loongson-liointc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c index acd1a4b897df0..0da8716f8f24b 100644 --- a/drivers/irqchip/irq-loongson-liointc.c +++ b/drivers/irqchip/irq-loongson-liointc.c @@ -207,7 +207,7 @@ static int liointc_init(phys_addr_t addr, unsigned long size, int revision, "reg-names", core_reg_names[i]); if (index < 0) - return -EINVAL; + goto out_iounmap; priv->core_isr[i] = of_iomap(node, index); } From 5a2f3dc31811e93be15522d9eb13ed61460b76c8 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 12 Aug 2022 16:19:23 +0200 Subject: [PATCH 162/427] netfilter: nf_tables: validate NFTA_SET_ELEM_OBJREF based on NFT_SET_OBJECT flag If the NFTA_SET_ELEM_OBJREF netlink attribute is present and NFT_SET_OBJECT flag is set on, report EINVAL. Move existing sanity check earlier to validate that NFT_SET_OBJECT requires NFTA_SET_ELEM_OBJREF. Fixes: 8aeff920dcc9 ("netfilter: nf_tables: add stateful object reference to set elements") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 1b9459a364ba7..bcfe8120e014d 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -5894,6 +5894,15 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, return -EINVAL; } + if (set->flags & NFT_SET_OBJECT) { + if (!nla[NFTA_SET_ELEM_OBJREF] && + !(flags & NFT_SET_ELEM_INTERVAL_END)) + return -EINVAL; + } else { + if (nla[NFTA_SET_ELEM_OBJREF]) + return -EINVAL; + } + if ((flags & NFT_SET_ELEM_INTERVAL_END) && (nla[NFTA_SET_ELEM_DATA] || nla[NFTA_SET_ELEM_OBJREF] || @@ -6032,10 +6041,6 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, } if (nla[NFTA_SET_ELEM_OBJREF] != NULL) { - if (!(set->flags & NFT_SET_OBJECT)) { - err = -EINVAL; - goto err_parse_key_end; - } obj = nft_obj_lookup(ctx->net, ctx->table, nla[NFTA_SET_ELEM_OBJREF], set->objtype, genmask); From 419831617ed349992c84344dbd9e627f9e68f842 Mon Sep 17 00:00:00 2001 From: Przemyslaw Patynowski Date: Tue, 19 Jul 2022 11:16:52 +0200 Subject: [PATCH 163/427] iavf: Fix adminq error handling iavf_alloc_asq_bufs/iavf_alloc_arq_bufs allocates with dma_alloc_coherent memory for VF mailbox. Free DMA regions for both ASQ and ARQ in case error happens during configuration of ASQ/ARQ registers. Without this change it is possible to see when unloading interface: 74626.583369: dma_debug_device_change: device driver has pending DMA allocations while released from device [count=32] One of leaked entries details: [device address=0x0000000b27ff9000] [size=4096 bytes] [mapped with DMA_BIDIRECTIONAL] [mapped as coherent] Fixes: d358aa9a7a2d ("i40evf: init code and hardware support") Signed-off-by: Przemyslaw Patynowski Signed-off-by: Jedrzej Jagielski Tested-by: Marek Szlosek Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/iavf/iavf_adminq.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/iavf/iavf_adminq.c b/drivers/net/ethernet/intel/iavf/iavf_adminq.c index cd4e6a22d0f9f..9ffbd24d83cb6 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_adminq.c +++ b/drivers/net/ethernet/intel/iavf/iavf_adminq.c @@ -324,6 +324,7 @@ static enum iavf_status iavf_config_arq_regs(struct iavf_hw *hw) static enum iavf_status iavf_init_asq(struct iavf_hw *hw) { enum iavf_status ret_code = 0; + int i; if (hw->aq.asq.count > 0) { /* queue already initialized */ @@ -354,12 +355,17 @@ static enum iavf_status iavf_init_asq(struct iavf_hw *hw) /* initialize base registers */ ret_code = iavf_config_asq_regs(hw); if (ret_code) - goto init_adminq_free_rings; + goto init_free_asq_bufs; /* success! */ hw->aq.asq.count = hw->aq.num_asq_entries; goto init_adminq_exit; +init_free_asq_bufs: + for (i = 0; i < hw->aq.num_asq_entries; i++) + iavf_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]); + iavf_free_virt_mem(hw, &hw->aq.asq.dma_head); + init_adminq_free_rings: iavf_free_adminq_asq(hw); @@ -383,6 +389,7 @@ static enum iavf_status iavf_init_asq(struct iavf_hw *hw) static enum iavf_status iavf_init_arq(struct iavf_hw *hw) { enum iavf_status ret_code = 0; + int i; if (hw->aq.arq.count > 0) { /* queue already initialized */ @@ -413,12 +420,16 @@ static enum iavf_status iavf_init_arq(struct iavf_hw *hw) /* initialize base registers */ ret_code = iavf_config_arq_regs(hw); if (ret_code) - goto init_adminq_free_rings; + goto init_free_arq_bufs; /* success! */ hw->aq.arq.count = hw->aq.num_arq_entries; goto init_adminq_exit; +init_free_arq_bufs: + for (i = 0; i < hw->aq.num_arq_entries; i++) + iavf_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]); + iavf_free_virt_mem(hw, &hw->aq.arq.dma_head); init_adminq_free_rings: iavf_free_adminq_arq(hw); From 541a1af451b0cb3779e915d48d08efb17915207b Mon Sep 17 00:00:00 2001 From: Przemyslaw Patynowski Date: Tue, 19 Jul 2022 11:16:53 +0200 Subject: [PATCH 164/427] iavf: Fix NULL pointer dereference in iavf_get_link_ksettings Fix possible NULL pointer dereference, due to freeing of adapter->vf_res in iavf_init_get_resources. Previous commit introduced a regression, where receiving IAVF_ERR_ADMIN_QUEUE_NO_WORK from iavf_get_vf_config would free adapter->vf_res. However, netdev is still registered, so ethtool_ops can be called. Calling iavf_get_link_ksettings with no vf_res, will result with: [ 9385.242676] BUG: kernel NULL pointer dereference, address: 0000000000000008 [ 9385.242683] #PF: supervisor read access in kernel mode [ 9385.242686] #PF: error_code(0x0000) - not-present page [ 9385.242690] PGD 0 P4D 0 [ 9385.242696] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC PTI [ 9385.242701] CPU: 6 PID: 3217 Comm: pmdalinux Kdump: loaded Tainted: G S E 5.18.0-04958-ga54ce3703613-dirty #1 [ 9385.242708] Hardware name: Dell Inc. PowerEdge R730/0WCJNT, BIOS 2.11.0 11/02/2019 [ 9385.242710] RIP: 0010:iavf_get_link_ksettings+0x29/0xd0 [iavf] [ 9385.242745] Code: 00 0f 1f 44 00 00 b8 01 ef ff ff 48 c7 46 30 00 00 00 00 48 c7 46 38 00 00 00 00 c6 46 0b 00 66 89 46 08 48 8b 87 68 0e 00 00 40 08 80 75 50 8b 87 5c 0e 00 00 83 f8 08 74 7a 76 1d 83 f8 20 [ 9385.242749] RSP: 0018:ffffc0560ec7fbd0 EFLAGS: 00010246 [ 9385.242755] RAX: 0000000000000000 RBX: ffffc0560ec7fc08 RCX: 0000000000000000 [ 9385.242759] RDX: ffffffffc0ad4550 RSI: ffffc0560ec7fc08 RDI: ffffa0fc66674000 [ 9385.242762] RBP: 00007ffd1fb2bf50 R08: b6a2d54b892363ee R09: ffffa101dc14fb00 [ 9385.242765] R10: 0000000000000000 R11: 0000000000000004 R12: ffffa0fc66674000 [ 9385.242768] R13: 0000000000000000 R14: ffffa0fc66674000 R15: 00000000ffffffa1 [ 9385.242771] FS: 00007f93711a2980(0000) GS:ffffa0fad72c0000(0000) knlGS:0000000000000000 [ 9385.242775] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 9385.242778] CR2: 0000000000000008 CR3: 0000000a8e61c003 CR4: 00000000003706e0 [ 9385.242781] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 9385.242784] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 9385.242787] Call Trace: [ 9385.242791] [ 9385.242793] ethtool_get_settings+0x71/0x1a0 [ 9385.242814] __dev_ethtool+0x426/0x2f40 [ 9385.242823] ? slab_post_alloc_hook+0x4f/0x280 [ 9385.242836] ? kmem_cache_alloc_trace+0x15d/0x2f0 [ 9385.242841] ? dev_ethtool+0x59/0x170 [ 9385.242848] dev_ethtool+0xa7/0x170 [ 9385.242856] dev_ioctl+0xc3/0x520 [ 9385.242866] sock_do_ioctl+0xa0/0xe0 [ 9385.242877] sock_ioctl+0x22f/0x320 [ 9385.242885] __x64_sys_ioctl+0x84/0xc0 [ 9385.242896] do_syscall_64+0x3a/0x80 [ 9385.242904] entry_SYSCALL_64_after_hwframe+0x46/0xb0 [ 9385.242918] RIP: 0033:0x7f93702396db [ 9385.242923] Code: 73 01 c3 48 8b 0d ad 57 38 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 7d 57 38 00 f7 d8 64 89 01 48 [ 9385.242927] RSP: 002b:00007ffd1fb2bf18 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 [ 9385.242932] RAX: ffffffffffffffda RBX: 000055671b1d2fe0 RCX: 00007f93702396db [ 9385.242935] RDX: 00007ffd1fb2bf20 RSI: 0000000000008946 RDI: 0000000000000007 [ 9385.242937] RBP: 00007ffd1fb2bf20 R08: 0000000000000003 R09: 0030763066307330 [ 9385.242940] R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffd1fb2bf80 [ 9385.242942] R13: 0000000000000007 R14: 0000556719f6de90 R15: 00007ffd1fb2c1b0 [ 9385.242948] [ 9385.242949] Modules linked in: iavf(E) xt_CHECKSUM xt_MASQUERADE xt_conntrack ipt_REJECT nft_compat nf_nat_tftp nft_objref nf_conntrack_tftp bridge stp llc nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ip_set nf_tables rfkill nfnetlink vfat fat irdma ib_uverbs ib_core intel_rapl_msr intel_rapl_common sb_edac x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm iTCO_wdt iTCO_vendor_support ice irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel rapl i40e pcspkr intel_cstate joydev mei_me intel_uncore mxm_wmi mei ipmi_ssif lpc_ich ipmi_si acpi_power_meter xfs libcrc32c mgag200 i2c_algo_bit drm_shmem_helper drm_kms_helper sd_mod t10_pi crc64_rocksoft crc64 syscopyarea sg sysfillrect sysimgblt fb_sys_fops drm ixgbe ahci libahci libata crc32c_intel mdio dca wmi dm_mirror dm_region_hash dm_log dm_mod ipmi_devintf ipmi_msghandler fuse [ 9385.243065] [last unloaded: iavf] Dereference happens in if (ADV_LINK_SUPPORT(adapter)) statement Fixes: 209f2f9c7181 ("iavf: Add support for VIRTCHNL_VF_OFFLOAD_VLAN_V2 negotiation") Signed-off-by: Przemyslaw Patynowski Signed-off-by: Jedrzej Jagielski Tested-by: Marek Szlosek Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/iavf/iavf_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index 45d097a164adc..6aa3eff0da2c7 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -2367,7 +2367,7 @@ static void iavf_init_get_resources(struct iavf_adapter *adapter) err = iavf_get_vf_config(adapter); if (err == -EALREADY) { err = iavf_send_vf_config_msg(adapter); - goto err_alloc; + goto err; } else if (err == -EINVAL) { /* We only get -EINVAL if the device is in a very bad * state or if we've been disabled for previous bad From 31071173771e079f7bc08dacd61e0db913262fbf Mon Sep 17 00:00:00 2001 From: Przemyslaw Patynowski Date: Tue, 19 Jul 2022 11:16:54 +0200 Subject: [PATCH 165/427] iavf: Fix reset error handling Do not call iavf_close in iavf_reset_task error handling. Doing so can lead to double call of napi_disable, which can lead to deadlock there. Removing VF would lead to iavf_remove task being stuck, because it requires crit_lock, which is held by iavf_close. Call iavf_disable_vf if reset fail, so that driver will clean up remaining invalid resources. During rapid VF resets, HW can fail to setup VF mailbox. Wrong error handling can lead to iavf_remove being stuck with: [ 5218.999087] iavf 0000:82:01.0: Failed to init adminq: -53 ... [ 5267.189211] INFO: task repro.sh:11219 blocked for more than 30 seconds. [ 5267.189520] Tainted: G S E 5.18.0-04958-ga54ce3703613-dirty #1 [ 5267.189764] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 5267.190062] task:repro.sh state:D stack: 0 pid:11219 ppid: 8162 flags:0x00000000 [ 5267.190347] Call Trace: [ 5267.190647] [ 5267.190927] __schedule+0x460/0x9f0 [ 5267.191264] schedule+0x44/0xb0 [ 5267.191563] schedule_preempt_disabled+0x14/0x20 [ 5267.191890] __mutex_lock.isra.12+0x6e3/0xac0 [ 5267.192237] ? iavf_remove+0xf9/0x6c0 [iavf] [ 5267.192565] iavf_remove+0x12a/0x6c0 [iavf] [ 5267.192911] ? _raw_spin_unlock_irqrestore+0x1e/0x40 [ 5267.193285] pci_device_remove+0x36/0xb0 [ 5267.193619] device_release_driver_internal+0xc1/0x150 [ 5267.193974] pci_stop_bus_device+0x69/0x90 [ 5267.194361] pci_stop_and_remove_bus_device+0xe/0x20 [ 5267.194735] pci_iov_remove_virtfn+0xba/0x120 [ 5267.195130] sriov_disable+0x2f/0xe0 [ 5267.195506] ice_free_vfs+0x7d/0x2f0 [ice] [ 5267.196056] ? pci_get_device+0x4f/0x70 [ 5267.196496] ice_sriov_configure+0x78/0x1a0 [ice] [ 5267.196995] sriov_numvfs_store+0xfe/0x140 [ 5267.197466] kernfs_fop_write_iter+0x12e/0x1c0 [ 5267.197918] new_sync_write+0x10c/0x190 [ 5267.198404] vfs_write+0x24e/0x2d0 [ 5267.198886] ksys_write+0x5c/0xd0 [ 5267.199367] do_syscall_64+0x3a/0x80 [ 5267.199827] entry_SYSCALL_64_after_hwframe+0x46/0xb0 [ 5267.200317] RIP: 0033:0x7f5b381205c8 [ 5267.200814] RSP: 002b:00007fff8c7e8c78 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 [ 5267.201981] RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007f5b381205c8 [ 5267.202620] RDX: 0000000000000002 RSI: 00005569420ee900 RDI: 0000000000000001 [ 5267.203426] RBP: 00005569420ee900 R08: 000000000000000a R09: 00007f5b38180820 [ 5267.204327] R10: 000000000000000a R11: 0000000000000246 R12: 00007f5b383c06e0 [ 5267.205193] R13: 0000000000000002 R14: 00007f5b383bb880 R15: 0000000000000002 [ 5267.206041] [ 5267.206970] Kernel panic - not syncing: hung_task: blocked tasks [ 5267.207809] CPU: 48 PID: 551 Comm: khungtaskd Kdump: loaded Tainted: G S E 5.18.0-04958-ga54ce3703613-dirty #1 [ 5267.208726] Hardware name: Dell Inc. PowerEdge R730/0WCJNT, BIOS 2.11.0 11/02/2019 [ 5267.209623] Call Trace: [ 5267.210569] [ 5267.211480] dump_stack_lvl+0x33/0x42 [ 5267.212472] panic+0x107/0x294 [ 5267.213467] watchdog.cold.8+0xc/0xbb [ 5267.214413] ? proc_dohung_task_timeout_secs+0x30/0x30 [ 5267.215511] kthread+0xf4/0x120 [ 5267.216459] ? kthread_complete_and_exit+0x20/0x20 [ 5267.217505] ret_from_fork+0x22/0x30 [ 5267.218459] Fixes: f0db78928783 ("i40evf: use netdev variable in reset task") Signed-off-by: Przemyslaw Patynowski Signed-off-by: Jedrzej Jagielski Tested-by: Marek Szlosek Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/iavf/iavf_main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index 6aa3eff0da2c7..95d4348e75799 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -3086,12 +3086,15 @@ static void iavf_reset_task(struct work_struct *work) return; reset_err: + if (running) { + set_bit(__IAVF_VSI_DOWN, adapter->vsi.state); + iavf_free_traffic_irqs(adapter); + } + iavf_disable_vf(adapter); + mutex_unlock(&adapter->client_lock); mutex_unlock(&adapter->crit_lock); - if (running) - iavf_change_state(adapter, __IAVF_RUNNING); dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n"); - iavf_close(netdev); } /** From cbe9e51126305832cf407ee6bb556ce831488ffe Mon Sep 17 00:00:00 2001 From: Ivan Vecera Date: Mon, 8 Aug 2022 19:58:45 +0200 Subject: [PATCH 166/427] iavf: Fix deadlock in initialization Fix deadlock that occurs when iavf interface is a part of failover configuration. 1. Mutex crit_lock is taken at the beginning of iavf_watchdog_task() 2. Function iavf_init_config_adapter() is called when adapter state is __IAVF_INIT_CONFIG_ADAPTER 3. iavf_init_config_adapter() calls register_netdevice() that emits NETDEV_REGISTER event 4. Notifier function failover_event() then calls net_failover_slave_register() that calls dev_open() 5. dev_open() calls iavf_open() that tries to take crit_lock in end-less loop Stack trace: ... [ 790.251876] usleep_range_state+0x5b/0x80 [ 790.252547] iavf_open+0x37/0x1d0 [iavf] [ 790.253139] __dev_open+0xcd/0x160 [ 790.253699] dev_open+0x47/0x90 [ 790.254323] net_failover_slave_register+0x122/0x220 [net_failover] [ 790.255213] failover_slave_register.part.7+0xd2/0x180 [failover] [ 790.256050] failover_event+0x122/0x1ab [failover] [ 790.256821] notifier_call_chain+0x47/0x70 [ 790.257510] register_netdevice+0x20f/0x550 [ 790.258263] iavf_watchdog_task+0x7c8/0xea0 [iavf] [ 790.259009] process_one_work+0x1a7/0x360 [ 790.259705] worker_thread+0x30/0x390 To fix the situation we should check the current adapter state after first unsuccessful mutex_trylock() and return with -EBUSY if it is __IAVF_INIT_CONFIG_ADAPTER. Fixes: 226d528512cf ("iavf: fix locking of critical sections") Signed-off-by: Ivan Vecera Tested-by: Konrad Jankowski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/iavf/iavf_main.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index 95d4348e75799..f39440ad5c50d 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -4088,8 +4088,17 @@ static int iavf_open(struct net_device *netdev) return -EIO; } - while (!mutex_trylock(&adapter->crit_lock)) + while (!mutex_trylock(&adapter->crit_lock)) { + /* If we are in __IAVF_INIT_CONFIG_ADAPTER state the crit_lock + * is already taken and iavf_open is called from an upper + * device's notifier reacting on NETDEV_REGISTER event. + * We have to leave here to avoid dead lock. + */ + if (adapter->state == __IAVF_INIT_CONFIG_ADAPTER) + return -EBUSY; + usleep_range(500, 1000); + } if (adapter->state != __IAVF_DOWN) { err = -EBUSY; From 61d5e2a251fb20c2c5e998c3f1d52ed6d5360319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cs=C3=B3k=C3=A1s=20Bence?= Date: Thu, 11 Aug 2022 12:13:49 +0200 Subject: [PATCH 167/427] fec: Fix timer capture timing in `fec_ptp_enable_pps()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code reimplements functionality already in `fec_ptp_read()`, but misses check for FEC_QUIRK_BUG_CAPTURE. Replace with function call. Fixes: 28b5f058cf1d ("net: fec: ptp: fix convergence issue to support LinuxPTP stack") Signed-off-by: Csókás Bence Link: https://lore.kernel.org/r/20220811101348.13755-1-csokas.bence@prolan.hu Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fec_ptp.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index 7d49c28215f31..3dc3c0b626c21 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -135,11 +135,7 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable) * NSEC_PER_SEC - ts.tv_nsec. Add the remaining nanoseconds * to current timer would be next second. */ - tempval = readl(fep->hwp + FEC_ATIME_CTRL); - tempval |= FEC_T_CTRL_CAPTURE; - writel(tempval, fep->hwp + FEC_ATIME_CTRL); - - tempval = readl(fep->hwp + FEC_ATIME); + tempval = fep->cc.read(&fep->cc); /* Convert the ptp local counter to 1588 timestamp */ ns = timecounter_cyc2time(&fep->tc, tempval); ts = ns_to_timespec64(ns); From 246bbf2f977ea36aaf41f5d24370fef433250728 Mon Sep 17 00:00:00 2001 From: Sergei Antonov Date: Thu, 11 Aug 2022 10:09:39 +0300 Subject: [PATCH 168/427] net: dsa: mv88e6060: prevent crash on an unused port If the port isn't a CPU port nor a user port, 'cpu_dp' is a null pointer and a crash happened on dereferencing it in mv88e6060_setup_port(): [ 9.575872] Unable to handle kernel NULL pointer dereference at virtual address 00000014 ... [ 9.942216] mv88e6060_setup from dsa_register_switch+0x814/0xe84 [ 9.948616] dsa_register_switch from mdio_probe+0x2c/0x54 [ 9.954433] mdio_probe from really_probe.part.0+0x98/0x2a0 [ 9.960375] really_probe.part.0 from driver_probe_device+0x30/0x10c [ 9.967029] driver_probe_device from __device_attach_driver+0xb8/0x13c [ 9.973946] __device_attach_driver from bus_for_each_drv+0x90/0xe0 [ 9.980509] bus_for_each_drv from __device_attach+0x110/0x184 [ 9.986632] __device_attach from bus_probe_device+0x8c/0x94 [ 9.992577] bus_probe_device from deferred_probe_work_func+0x78/0xa8 [ 9.999311] deferred_probe_work_func from process_one_work+0x290/0x73c [ 10.006292] process_one_work from worker_thread+0x30/0x4b8 [ 10.012155] worker_thread from kthread+0xd4/0x10c [ 10.017238] kthread from ret_from_fork+0x14/0x3c Fixes: 0abfd494deef ("net: dsa: use dedicated CPU port") CC: Vivien Didelot CC: Florian Fainelli Signed-off-by: Sergei Antonov Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20220811070939.1717146-1-saproj@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/mv88e6060.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index a4c6eb9a52d0d..83dca9179aa07 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -118,6 +118,9 @@ static int mv88e6060_setup_port(struct mv88e6060_priv *priv, int p) int addr = REG_PORT(p); int ret; + if (dsa_is_unused_port(priv->ds, p)) + return 0; + /* Do not force flow control, disable Ingress and Egress * Header tagging, disable VLAN tunneling, and set the port * state to Forwarding. Additionally, if this is the CPU From 777885673122b78b2abd2f1e428730961a786ff2 Mon Sep 17 00:00:00 2001 From: Hongbin Wang Date: Thu, 11 Aug 2022 23:38:33 -0400 Subject: [PATCH 169/427] ip6_tunnel: Fix the type of functions Functions ip6_tnl_change, ip6_tnl_update and ip6_tnl0_update do always return 0, change the type of functions to void. Signed-off-by: Hongbin Wang Signed-off-by: David S. Miller --- net/ipv6/ip6_tunnel.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 3fda5634578ce..79c6a827dea9f 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1517,7 +1517,7 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) * ip6_tnl_change() updates the tunnel parameters **/ -static int +static void ip6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p) { t->parms.laddr = p->laddr; @@ -1531,29 +1531,25 @@ ip6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p) t->parms.fwmark = p->fwmark; dst_cache_reset(&t->dst_cache); ip6_tnl_link_config(t); - return 0; } -static int ip6_tnl_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p) +static void ip6_tnl_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p) { struct net *net = t->net; struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); - int err; ip6_tnl_unlink(ip6n, t); synchronize_net(); - err = ip6_tnl_change(t, p); + ip6_tnl_change(t, p); ip6_tnl_link(ip6n, t); netdev_state_change(t->dev); - return err; } -static int ip6_tnl0_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p) +static void ip6_tnl0_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p) { /* for default tnl0 device allow to change only the proto */ t->parms.proto = p->proto; netdev_state_change(t->dev); - return 0; } static void @@ -1667,9 +1663,9 @@ ip6_tnl_siocdevprivate(struct net_device *dev, struct ifreq *ifr, } else t = netdev_priv(dev); if (dev == ip6n->fb_tnl_dev) - err = ip6_tnl0_update(t, &p1); + ip6_tnl0_update(t, &p1); else - err = ip6_tnl_update(t, &p1); + ip6_tnl_update(t, &p1); } if (!IS_ERR(t)) { err = 0; @@ -2091,7 +2087,8 @@ static int ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[], } else t = netdev_priv(dev); - return ip6_tnl_update(t, &p); + ip6_tnl_update(t, &p); + return 0; } static void ip6_tnl_dellink(struct net_device *dev, struct list_head *head) From 92cb6e2e5dbaea02c2fa317f3543c8918db25e89 Mon Sep 17 00:00:00 2001 From: ZiyangZhang Date: Wed, 10 Aug 2022 13:52:12 +0800 Subject: [PATCH 170/427] ublk_drv: update iod->addr for UBLK_IO_NEED_GET_DATA If ublksrv sends UBLK_IO_NEED_GET_DATA with new allocated io buffer, we have to update iod->addr in task_work before calling io_uring_cmd_done(). Then usersapce target can handle (write)io request with the new io buffer reading from updated iod. Without this change, userspace target may touch a wrong io buffer! Signed-off-by: ZiyangZhang Reviewed-by: Ming Lei Link: https://lore.kernel.org/r/20220810055212.66417-1-ZiyangZhang@linux.alibaba.com Signed-off-by: Jens Axboe --- drivers/block/ublk_drv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 2b7d1db5c4a7b..5d8c7234639cc 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -680,6 +680,11 @@ static inline void __ublk_rq_task_work(struct request *req) * do the copy work. */ io->flags &= ~UBLK_IO_FLAG_NEED_GET_DATA; + /* update iod->addr because ublksrv may have passed a new io buffer */ + ublk_get_iod(ubq, req->tag)->addr = io->addr; + pr_devel("%s: update iod->addr: op %d, qid %d tag %d io_flags %x addr %llx\n", + __func__, io->cmd->cmd_op, ubq->q_id, req->tag, io->flags, + ublk_get_iod(ubq, req->tag)->addr); } mapped_bytes = ublk_map_io(ubq, req, io); From 8924779df820c53875abaeb10c648e9cb75b46d4 Mon Sep 17 00:00:00 2001 From: Nadav Amit Date: Sat, 13 Aug 2022 15:59:43 -0700 Subject: [PATCH 171/427] x86/kprobes: Fix JNG/JNLE emulation When kprobes emulates JNG/JNLE instructions on x86 it uses the wrong condition. For JNG (opcode: 0F 8E), according to Intel SDM, the jump is performed if (ZF == 1 or SF != OF). However the kernel emulation currently uses 'and' instead of 'or'. As a result, setting a kprobe on JNG/JNLE might cause the kernel to behave incorrectly whenever the kprobe is hit. Fix by changing the 'and' to 'or'. Fixes: 6256e668b7af ("x86/kprobes: Use int3 instead of debug trap for single-step") Signed-off-by: Nadav Amit Signed-off-by: Ingo Molnar Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20220813225943.143767-1-namit@vmware.com --- arch/x86/kernel/kprobes/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 74167dc5f55ec..4c3c27b6aea3b 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -505,7 +505,7 @@ static void kprobe_emulate_jcc(struct kprobe *p, struct pt_regs *regs) match = ((regs->flags & X86_EFLAGS_SF) >> X86_EFLAGS_SF_BIT) ^ ((regs->flags & X86_EFLAGS_OF) >> X86_EFLAGS_OF_BIT); if (p->ainsn.jcc.type >= 0xe) - match = match && (regs->flags & X86_EFLAGS_ZF); + match = match || (regs->flags & X86_EFLAGS_ZF); } __kprobe_emulate_jmp(p, regs, (match && !invert) || (!match && invert)); } From 5dd8ce24667a70bb9f7808f5eec0354bd37290c6 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 13 Aug 2022 17:22:11 -0500 Subject: [PATCH 172/427] cifs: missing directory in MAINTAINERS file The include/uapi/linux/cifs directory (not just fs/cifs and fs/smbfs_common) should be included in cifs entry in the MAINTAINERS file. Reviewed-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8a5012ba6ff98..c35bf10c520c4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5145,6 +5145,7 @@ T: git git://git.samba.org/sfrench/cifs-2.6.git F: Documentation/admin-guide/cifs/ F: fs/cifs/ F: fs/smbfs_common/ +F: include/uapi/linux/cifs COMPACTPCI HOTPLUG CORE M: Scott Murray From 8d48562a2729742f767b0fdd994d6b2a56a49c63 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Mon, 15 Aug 2022 16:55:23 +1000 Subject: [PATCH 173/427] powerpc/pci: Fix get_phb_number() locking The recent change to get_phb_number() causes a DEBUG_ATOMIC_SLEEP warning on some systems: BUG: sleeping function called from invalid context at kernel/locking/mutex.c:580 in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 1, name: swapper preempt_count: 1, expected: 0 RCU nest depth: 0, expected: 0 1 lock held by swapper/1: #0: c157efb0 (hose_spinlock){+.+.}-{2:2}, at: pcibios_alloc_controller+0x64/0x220 Preemption disabled at: [<00000000>] 0x0 CPU: 0 PID: 1 Comm: swapper Not tainted 5.19.0-yocto-standard+ #1 Call Trace: [d101dc90] [c073b264] dump_stack_lvl+0x50/0x8c (unreliable) [d101dcb0] [c0093b70] __might_resched+0x258/0x2a8 [d101dcd0] [c0d3e634] __mutex_lock+0x6c/0x6ec [d101dd50] [c0a84174] of_alias_get_id+0x50/0xf4 [d101dd80] [c002ec78] pcibios_alloc_controller+0x1b8/0x220 [d101ddd0] [c140c9dc] pmac_pci_init+0x198/0x784 [d101de50] [c140852c] discover_phbs+0x30/0x4c [d101de60] [c0007fd4] do_one_initcall+0x94/0x344 [d101ded0] [c1403b40] kernel_init_freeable+0x1a8/0x22c [d101df10] [c00086e0] kernel_init+0x34/0x160 [d101df30] [c001b334] ret_from_kernel_thread+0x5c/0x64 This is because pcibios_alloc_controller() holds hose_spinlock but of_alias_get_id() takes of_mutex which can sleep. The hose_spinlock protects the phb_bitmap, and also the hose_list, but it doesn't need to be held while get_phb_number() calls the OF routines, because those are only looking up information in the device tree. So fix it by having get_phb_number() take the hose_spinlock itself, only where required, and then dropping the lock before returning. pcibios_alloc_controller() then needs to take the lock again before the list_add() but that's safe, the order of the list is not important. Fixes: 0fe1e96fef0a ("powerpc/pci: Prefer PCI domain assignment via DT 'linux,pci-domain' and alias") Reported-by: Guenter Roeck Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20220815065550.1303620-1-mpe@ellerman.id.au --- arch/powerpc/kernel/pci-common.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index bdd3332200c55..31de91c8359c1 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -68,10 +68,6 @@ void __init set_pci_dma_ops(const struct dma_map_ops *dma_ops) pci_dma_ops = dma_ops; } -/* - * This function should run under locking protection, specifically - * hose_spinlock. - */ static int get_phb_number(struct device_node *dn) { int ret, phb_id = -1; @@ -108,15 +104,20 @@ static int get_phb_number(struct device_node *dn) if (!ret) phb_id = (int)(prop & (MAX_PHBS - 1)); + spin_lock(&hose_spinlock); + /* We need to be sure to not use the same PHB number twice. */ if ((phb_id >= 0) && !test_and_set_bit(phb_id, phb_bitmap)) - return phb_id; + goto out_unlock; /* If everything fails then fallback to dynamic PHB numbering. */ phb_id = find_first_zero_bit(phb_bitmap, MAX_PHBS); BUG_ON(phb_id >= MAX_PHBS); set_bit(phb_id, phb_bitmap); +out_unlock: + spin_unlock(&hose_spinlock); + return phb_id; } @@ -127,10 +128,13 @@ struct pci_controller *pcibios_alloc_controller(struct device_node *dev) phb = zalloc_maybe_bootmem(sizeof(struct pci_controller), GFP_KERNEL); if (phb == NULL) return NULL; - spin_lock(&hose_spinlock); + phb->global_number = get_phb_number(dev); + + spin_lock(&hose_spinlock); list_add_tail(&phb->list_node, &hose_list); spin_unlock(&hose_spinlock); + phb->dn = dev; phb->is_dynamic = slab_is_available(); #ifdef CONFIG_PPC64 From 2a29f80e155a9cf40ca8b6648bcdc8422db4c4e4 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 12 Aug 2022 02:37:02 -0500 Subject: [PATCH 174/427] dt-bindings: display: sun4i: Add D1 TCONs to conditionals When adding the D1 TCON bindings, I missed the conditional blocks that restrict the binding for TCON LCD vs TCON TV hardware. Add the D1 TCON variants to the appropriate blocks for DE2 TCON LCDs and TCON TVs. Fixes: ae5a5d26c15c ("dt-bindings: display: Add D1 display engine compatibles") Signed-off-by: Samuel Holland Acked-by: Krzysztof Kozlowski Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20220812073702.57618-1-samuel@sholland.org --- .../devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml b/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml index 4a92a4c7dcd70..f8168986a0a9e 100644 --- a/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml +++ b/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml @@ -233,6 +233,7 @@ allOf: - allwinner,sun8i-a83t-tcon-lcd - allwinner,sun8i-v3s-tcon - allwinner,sun9i-a80-tcon-lcd + - allwinner,sun20i-d1-tcon-lcd then: properties: @@ -252,6 +253,7 @@ allOf: - allwinner,sun8i-a83t-tcon-tv - allwinner,sun8i-r40-tcon-tv - allwinner,sun9i-a80-tcon-tv + - allwinner,sun20i-d1-tcon-tv then: properties: @@ -278,6 +280,7 @@ allOf: - allwinner,sun9i-a80-tcon-lcd - allwinner,sun4i-a10-tcon - allwinner,sun8i-a83t-tcon-lcd + - allwinner,sun20i-d1-tcon-lcd then: required: @@ -294,6 +297,7 @@ allOf: - allwinner,sun8i-a23-tcon - allwinner,sun8i-a33-tcon - allwinner,sun8i-a83t-tcon-lcd + - allwinner,sun20i-d1-tcon-lcd then: properties: From 82a1356a933d8443139f8886f11b63c974a09a67 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Thu, 11 Aug 2022 22:16:23 -0500 Subject: [PATCH 175/427] drm/sun4i: dsi: Prevent underflow when computing packet sizes Currently, the packet overhead is subtracted using unsigned arithmetic. With a short sync pulse, this could underflow and wrap around to near the maximal u16 value. Fix this by using signed subtraction. The call to max() will correctly handle any negative numbers that are produced. Apply the same fix to the other timings, even though those subtractions are less likely to underflow. Fixes: 133add5b5ad4 ("drm/sun4i: Add Allwinner A31 MIPI-DSI controller support") Signed-off-by: Samuel Holland Reviewed-by: Jernej Skrabec Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20220812031623.34057-1-samuel@sholland.org --- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c index b4dfa166eccdf..34234a144e87d 100644 --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c @@ -531,7 +531,7 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi, struct drm_display_mode *mode) { struct mipi_dsi_device *device = dsi->device; - unsigned int Bpp = mipi_dsi_pixel_format_to_bpp(device->format) / 8; + int Bpp = mipi_dsi_pixel_format_to_bpp(device->format) / 8; u16 hbp = 0, hfp = 0, hsa = 0, hblk = 0, vblk = 0; u32 basic_ctl = 0; size_t bytes; @@ -555,7 +555,7 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi, * (4 bytes). Its minimal size is therefore 10 bytes */ #define HSA_PACKET_OVERHEAD 10 - hsa = max((unsigned int)HSA_PACKET_OVERHEAD, + hsa = max(HSA_PACKET_OVERHEAD, (mode->hsync_end - mode->hsync_start) * Bpp - HSA_PACKET_OVERHEAD); /* @@ -564,7 +564,7 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi, * therefore 6 bytes */ #define HBP_PACKET_OVERHEAD 6 - hbp = max((unsigned int)HBP_PACKET_OVERHEAD, + hbp = max(HBP_PACKET_OVERHEAD, (mode->htotal - mode->hsync_end) * Bpp - HBP_PACKET_OVERHEAD); /* @@ -574,7 +574,7 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi, * 16 bytes */ #define HFP_PACKET_OVERHEAD 16 - hfp = max((unsigned int)HFP_PACKET_OVERHEAD, + hfp = max(HFP_PACKET_OVERHEAD, (mode->hsync_start - mode->hdisplay) * Bpp - HFP_PACKET_OVERHEAD); /* @@ -583,7 +583,7 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi, * bytes). Its minimal size is therefore 10 bytes. */ #define HBLK_PACKET_OVERHEAD 10 - hblk = max((unsigned int)HBLK_PACKET_OVERHEAD, + hblk = max(HBLK_PACKET_OVERHEAD, (mode->htotal - (mode->hsync_end - mode->hsync_start)) * Bpp - HBLK_PACKET_OVERHEAD); From 68a838b84effb7b57ba7d50b1863fc6ae35a54ce Mon Sep 17 00:00:00 2001 From: Maxim Kochetkov Date: Thu, 11 Aug 2022 12:48:40 +0300 Subject: [PATCH 176/427] net: qrtr: start MHI channel after endpoit creation MHI channel may generates event/interrupt right after enabling. It may leads to 2 race conditions issues. 1) Such event may be dropped by qcom_mhi_qrtr_dl_callback() at check: if (!qdev || mhi_res->transaction_status) return; Because dev_set_drvdata(&mhi_dev->dev, qdev) may be not performed at this moment. In this situation qrtr-ns will be unable to enumerate services in device. --------------------------------------------------------------- 2) Such event may come at the moment after dev_set_drvdata() and before qrtr_endpoint_register(). In this case kernel will panic with accessing wrong pointer at qcom_mhi_qrtr_dl_callback(): rc = qrtr_endpoint_post(&qdev->ep, mhi_res->buf_addr, mhi_res->bytes_xferd); Because endpoint is not created yet. -------------------------------------------------------------- So move mhi_prepare_for_transfer_autoqueue after endpoint creation to fix it. Fixes: a2e2cc0dbb11 ("net: qrtr: Start MHI channels during init") Signed-off-by: Maxim Kochetkov Reviewed-by: Hemant Kumar Reviewed-by: Manivannan Sadhasivam Reviewed-by: Loic Poulain Signed-off-by: David S. Miller --- net/qrtr/mhi.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/net/qrtr/mhi.c b/net/qrtr/mhi.c index 18196e1c8c2fd..9ced13c0627a7 100644 --- a/net/qrtr/mhi.c +++ b/net/qrtr/mhi.c @@ -78,11 +78,6 @@ static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev, struct qrtr_mhi_dev *qdev; int rc; - /* start channels */ - rc = mhi_prepare_for_transfer_autoqueue(mhi_dev); - if (rc) - return rc; - qdev = devm_kzalloc(&mhi_dev->dev, sizeof(*qdev), GFP_KERNEL); if (!qdev) return -ENOMEM; @@ -96,6 +91,13 @@ static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev, if (rc) return rc; + /* start channels */ + rc = mhi_prepare_for_transfer_autoqueue(mhi_dev); + if (rc) { + qrtr_endpoint_unregister(&qdev->ep); + return rc; + } + dev_dbg(qdev->dev, "Qualcomm MHI QRTR driver probed\n"); return 0; From 66ba215cb51323e4e55e38fd5f250e0fae0cbc94 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Thu, 11 Aug 2022 18:20:11 +0300 Subject: [PATCH 177/427] neigh: fix possible DoS due to net iface start/stop loop Normal processing of ARP request (usually this is Ethernet broadcast packet) coming to the host is looking like the following: * the packet comes to arp_process() call and is passed through routing procedure * the request is put into the queue using pneigh_enqueue() if corresponding ARP record is not local (common case for container records on the host) * the request is processed by timer (within 80 jiffies by default) and ARP reply is sent from the same arp_process() using NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED condition (flag is set inside pneigh_enqueue()) And here the problem comes. Linux kernel calls pneigh_queue_purge() which destroys the whole queue of ARP requests on ANY network interface start/stop event through __neigh_ifdown(). This is actually not a problem within the original world as network interface start/stop was accessible to the host 'root' only, which could do more destructive things. But the world is changed and there are Linux containers available. Here container 'root' has an access to this API and could be considered as untrusted user in the hosting (container's) world. Thus there is an attack vector to other containers on node when container's root will endlessly start/stop interfaces. We have observed similar situation on a real production node when docker container was doing such activity and thus other containers on the node become not accessible. The patch proposed doing very simple thing. It drops only packets from the same namespace in the pneigh_queue_purge() where network interface state change is detected. This is enough to prevent the problem for the whole node preserving original semantics of the code. v2: - do del_timer_sync() if queue is empty after pneigh_queue_purge() v3: - rebase to net tree Cc: "David S. Miller" Cc: Eric Dumazet Cc: Jakub Kicinski Cc: Paolo Abeni Cc: Daniel Borkmann Cc: David Ahern Cc: Yajun Deng Cc: Roopa Prabhu Cc: Christian Brauner Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Alexey Kuznetsov Cc: Alexander Mikhalitsyn Cc: Konstantin Khorenko Cc: kernel@openvz.org Cc: devel@openvz.org Investigated-by: Alexander Mikhalitsyn Signed-off-by: Denis V. Lunev Signed-off-by: David S. Miller --- net/core/neighbour.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 6a8c2596ebab9..0e38a05d5b233 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -307,14 +307,23 @@ static int neigh_del_timer(struct neighbour *n) return 0; } -static void pneigh_queue_purge(struct sk_buff_head *list) +static void pneigh_queue_purge(struct sk_buff_head *list, struct net *net) { + unsigned long flags; struct sk_buff *skb; - while ((skb = skb_dequeue(list)) != NULL) { - dev_put(skb->dev); - kfree_skb(skb); + spin_lock_irqsave(&list->lock, flags); + skb = skb_peek(list); + while (skb != NULL) { + struct sk_buff *skb_next = skb_peek_next(skb, list); + if (net == NULL || net_eq(dev_net(skb->dev), net)) { + __skb_unlink(skb, list); + dev_put(skb->dev); + kfree_skb(skb); + } + skb = skb_next; } + spin_unlock_irqrestore(&list->lock, flags); } static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev, @@ -385,9 +394,9 @@ static int __neigh_ifdown(struct neigh_table *tbl, struct net_device *dev, write_lock_bh(&tbl->lock); neigh_flush_dev(tbl, dev, skip_perm); pneigh_ifdown_and_unlock(tbl, dev); - - del_timer_sync(&tbl->proxy_timer); - pneigh_queue_purge(&tbl->proxy_queue); + pneigh_queue_purge(&tbl->proxy_queue, dev_net(dev)); + if (skb_queue_empty_lockless(&tbl->proxy_queue)) + del_timer_sync(&tbl->proxy_timer); return 0; } @@ -1787,7 +1796,7 @@ int neigh_table_clear(int index, struct neigh_table *tbl) cancel_delayed_work_sync(&tbl->managed_work); cancel_delayed_work_sync(&tbl->gc_work); del_timer_sync(&tbl->proxy_timer); - pneigh_queue_purge(&tbl->proxy_queue); + pneigh_queue_purge(&tbl->proxy_queue, NULL); neigh_ifdown(tbl, NULL); if (atomic_read(&tbl->entries)) pr_crit("neighbour leakage\n"); From 0ff4eb3d5ebbf72a7fc355e6001a0a6740662bf9 Mon Sep 17 00:00:00 2001 From: Alexander Mikhalitsyn Date: Thu, 11 Aug 2022 18:20:12 +0300 Subject: [PATCH 178/427] neighbour: make proxy_queue.qlen limit per-device Right now we have a neigh_param PROXY_QLEN which specifies maximum length of neigh_table->proxy_queue. But in fact, this limitation doesn't work well because check condition looks like: tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN) The problem is that p (struct neigh_parms) is a per-device thing, but tbl (struct neigh_table) is a system-wide global thing. It seems reasonable to make proxy_queue limit per-device based. v2: - nothing changed in this patch v3: - rebase to net tree Cc: "David S. Miller" Cc: Eric Dumazet Cc: Jakub Kicinski Cc: Paolo Abeni Cc: Daniel Borkmann Cc: David Ahern Cc: Yajun Deng Cc: Roopa Prabhu Cc: Christian Brauner Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Alexey Kuznetsov Cc: Alexander Mikhalitsyn Cc: Konstantin Khorenko Cc: kernel@openvz.org Cc: devel@openvz.org Suggested-by: Denis V. Lunev Signed-off-by: Alexander Mikhalitsyn Reviewed-by: Denis V. Lunev Signed-off-by: David S. Miller --- include/net/neighbour.h | 1 + net/core/neighbour.c | 25 ++++++++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/net/neighbour.h b/include/net/neighbour.h index 9f0bab0589d9c..3827a6b395fdb 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -83,6 +83,7 @@ struct neigh_parms { struct rcu_head rcu_head; int reachable_time; + int qlen; int data[NEIGH_VAR_DATA_MAX]; DECLARE_BITMAP(data_state, NEIGH_VAR_DATA_MAX); }; diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 0e38a05d5b233..5b669eb802708 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -316,9 +316,18 @@ static void pneigh_queue_purge(struct sk_buff_head *list, struct net *net) skb = skb_peek(list); while (skb != NULL) { struct sk_buff *skb_next = skb_peek_next(skb, list); - if (net == NULL || net_eq(dev_net(skb->dev), net)) { + struct net_device *dev = skb->dev; + if (net == NULL || net_eq(dev_net(dev), net)) { + struct in_device *in_dev; + + rcu_read_lock(); + in_dev = __in_dev_get_rcu(dev); + if (in_dev) + in_dev->arp_parms->qlen--; + rcu_read_unlock(); __skb_unlink(skb, list); - dev_put(skb->dev); + + dev_put(dev); kfree_skb(skb); } skb = skb_next; @@ -1606,8 +1615,15 @@ static void neigh_proxy_process(struct timer_list *t) if (tdif <= 0) { struct net_device *dev = skb->dev; + struct in_device *in_dev; + rcu_read_lock(); + in_dev = __in_dev_get_rcu(dev); + if (in_dev) + in_dev->arp_parms->qlen--; + rcu_read_unlock(); __skb_unlink(skb, &tbl->proxy_queue); + if (tbl->proxy_redo && netif_running(dev)) { rcu_read_lock(); tbl->proxy_redo(skb); @@ -1632,7 +1648,7 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, unsigned long sched_next = jiffies + prandom_u32_max(NEIGH_VAR(p, PROXY_DELAY)); - if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) { + if (p->qlen > NEIGH_VAR(p, PROXY_QLEN)) { kfree_skb(skb); return; } @@ -1648,6 +1664,7 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, skb_dst_drop(skb); dev_hold(skb->dev); __skb_queue_tail(&tbl->proxy_queue, skb); + p->qlen++; mod_timer(&tbl->proxy_timer, sched_next); spin_unlock(&tbl->proxy_queue.lock); } @@ -1680,6 +1697,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev, refcount_set(&p->refcnt, 1); p->reachable_time = neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME)); + p->qlen = 0; netdev_hold(dev, &p->dev_tracker, GFP_KERNEL); p->dev = dev; write_pnet(&p->net, net); @@ -1745,6 +1763,7 @@ void neigh_table_init(int index, struct neigh_table *tbl) refcount_set(&tbl->parms.refcnt, 1); tbl->parms.reachable_time = neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME)); + tbl->parms.qlen = 0; tbl->stats = alloc_percpu(struct neigh_statistics); if (!tbl->stats) From 7396ba87f1edf549284869451665c7c4e74ecd4f Mon Sep 17 00:00:00 2001 From: Xin Xiong Date: Sat, 13 Aug 2022 20:49:08 +0800 Subject: [PATCH 179/427] net: fix potential refcount leak in ndisc_router_discovery() The issue happens on specific paths in the function. After both the object `rt` and `neigh` are grabbed successfully, when `lifetime` is nonzero but the metric needs change, the function just deletes the route and set `rt` to NULL. Then, it may try grabbing `rt` and `neigh` again if above conditions hold. The function simply overwrite `neigh` if succeeds or returns if fails, without decreasing the reference count of previous `neigh`. This may result in memory leaks. Fix it by decrementing the reference count of `neigh` in place. Fixes: 6b2e04bc240f ("net: allow user to set metric on default route learned via Router Advertisement") Signed-off-by: Xin Xiong Signed-off-by: Xin Tan Signed-off-by: David S. Miller --- net/ipv6/ndisc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 98453693e4009..3a553494ff164 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1378,6 +1378,9 @@ static void ndisc_router_discovery(struct sk_buff *skb) if (!rt && lifetime) { ND_PRINTK(3, info, "RA: adding default router\n"); + if (neigh) + neigh_release(neigh); + rt = rt6_add_dflt_router(net, &ipv6_hdr(skb)->saddr, skb->dev, pref, defrtr_usr_metric); if (!rt) { From 02799571714dc5dd6948824b9d080b44a295f695 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Sun, 14 Aug 2022 11:27:58 +0000 Subject: [PATCH 180/427] net_sched: cls_route: disallow handle of 0 Follows up on: https://lore.kernel.org/all/20220809170518.164662-1-cascardo@canonical.com/ handle of 0 implies from/to of universe realm which is not very sensible. Lets see what this patch will do: $sudo tc qdisc add dev $DEV root handle 1:0 prio //lets manufacture a way to insert handle of 0 $sudo tc filter add dev $DEV parent 1:0 protocol ip prio 100 \ route to 0 from 0 classid 1:10 action ok //gets rejected... Error: handle of 0 is not valid. We have an error talking to the kernel, -1 //lets create a legit entry.. sudo tc filter add dev $DEV parent 1:0 protocol ip prio 100 route from 10 \ classid 1:10 action ok //what did the kernel insert? $sudo tc filter ls dev $DEV parent 1:0 filter protocol ip pref 100 route chain 0 filter protocol ip pref 100 route chain 0 fh 0x000a8000 flowid 1:10 from 10 action order 1: gact action pass random type none pass val 0 index 1 ref 1 bind 1 //Lets try to replace that legit entry with a handle of 0 $ sudo tc filter replace dev $DEV parent 1:0 protocol ip prio 100 \ handle 0x000a8000 route to 0 from 0 classid 1:10 action drop Error: Replacing with handle of 0 is invalid. We have an error talking to the kernel, -1 And last, lets run Cascardo's POC: $ ./poc 0 0 -22 -22 -22 Signed-off-by: Jamal Hadi Salim Acked-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/sched/cls_route.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index 3f935cbbaff66..48712bc51bda7 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c @@ -424,6 +424,11 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp, return -EINVAL; } + if (!nhandle) { + NL_SET_ERR_MSG(extack, "Replacing with handle of 0 is invalid"); + return -EINVAL; + } + h1 = to_hash(nhandle); b = rtnl_dereference(head->table[h1]); if (!b) { @@ -477,6 +482,11 @@ static int route4_change(struct net *net, struct sk_buff *in_skb, int err; bool new = true; + if (!handle) { + NL_SET_ERR_MSG(extack, "Creating with handle of 0 is invalid"); + return -EINVAL; + } + if (opt == NULL) return handle ? -EINVAL : 0; From 12e091389b29cddf26279fdf182b13b3a1583d0d Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Fri, 12 Aug 2022 17:32:00 +0200 Subject: [PATCH 181/427] mlxsw: spectrum_ptp: Fix compilation warnings In case that 'CONFIG_PTP_1588_CLOCK' is not enabled in the config file, there are implementations for the functions mlxsw_{sp,sp2}_ptp_txhdr_construct() as part of 'spectrum_ptp.h'. In this case, they should be defined as 'static' as they are not supposed to be used out of this file. Make the functions 'static', otherwise the following warnings are returned: "warning: no previous prototype for 'mlxsw_sp_ptp_txhdr_construct'" "warning: no previous prototype for 'mlxsw_sp2_ptp_txhdr_construct'" In addition, make the functions 'inline' for case that 'spectrum_ptp.h' will be included anywhere else and the functions would probably not be used, so compilation warnings about unused static will be returned. Fixes: 24157bc69f45 ("mlxsw: Send PTP packets as data packets to overcome a limitation") Reported-by: kernel test robot Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_ptp.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h index 2d1628fdefc12..a8b88230959a2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h @@ -171,10 +171,11 @@ static inline void mlxsw_sp1_get_stats(struct mlxsw_sp_port *mlxsw_sp_port, { } -int mlxsw_sp_ptp_txhdr_construct(struct mlxsw_core *mlxsw_core, - struct mlxsw_sp_port *mlxsw_sp_port, - struct sk_buff *skb, - const struct mlxsw_tx_info *tx_info) +static inline int +mlxsw_sp_ptp_txhdr_construct(struct mlxsw_core *mlxsw_core, + struct mlxsw_sp_port *mlxsw_sp_port, + struct sk_buff *skb, + const struct mlxsw_tx_info *tx_info) { return -EOPNOTSUPP; } @@ -231,10 +232,11 @@ static inline int mlxsw_sp2_ptp_get_ts_info(struct mlxsw_sp *mlxsw_sp, return mlxsw_sp_ptp_get_ts_info_noptp(info); } -int mlxsw_sp2_ptp_txhdr_construct(struct mlxsw_core *mlxsw_core, - struct mlxsw_sp_port *mlxsw_sp_port, - struct sk_buff *skb, - const struct mlxsw_tx_info *tx_info) +static inline int +mlxsw_sp2_ptp_txhdr_construct(struct mlxsw_core *mlxsw_core, + struct mlxsw_sp_port *mlxsw_sp_port, + struct sk_buff *skb, + const struct mlxsw_tx_info *tx_info) { return -EOPNOTSUPP; } From a159e986ad26d3f35c0157ac92760ba5e44e6785 Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Fri, 12 Aug 2022 17:32:01 +0200 Subject: [PATCH 182/427] mlxsw: spectrum: Clear PTP configuration after unregistering the netdevice Currently as part of removing port, PTP API is called to clear the existing configuration and set the 'rx_filter' and 'tx_type' to zero. The clearing is done before unregistering the netdevice, which means that there is a window of time in which the user can reconfigure PTP in the port, and this configuration will not be cleared. Reorder the operations, clear PTP configuration after unregistering the netdevice. Fixes: 8748642751ede ("mlxsw: spectrum: PTP: Support SIOCGHWTSTAMP, SIOCSHWTSTAMP ioctls") Signed-off-by: Amit Cohen Signed-off-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 1e240cdd9cbde..30c7b0e157218 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1897,9 +1897,9 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u16 local_port) cancel_delayed_work_sync(&mlxsw_sp_port->periodic_hw_stats.update_dw); cancel_delayed_work_sync(&mlxsw_sp_port->ptp.shaper_dw); - mlxsw_sp_port_ptp_clear(mlxsw_sp_port); mlxsw_core_port_clear(mlxsw_sp->core, local_port, mlxsw_sp); unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */ + mlxsw_sp_port_ptp_clear(mlxsw_sp_port); mlxsw_sp_port_vlan_classification_set(mlxsw_sp_port, true, true); mlxsw_sp->ports[local_port] = NULL; mlxsw_sp_port_vlan_flush(mlxsw_sp_port, true); From d72fdef21f07540c6cbb8043cc93decd2a5d35dd Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Fri, 12 Aug 2022 17:32:02 +0200 Subject: [PATCH 183/427] mlxsw: spectrum_ptp: Protect PTP configuration with a mutex Currently the functions mlxsw_sp2_ptp_{configure, deconfigure}_port() assume that they are called when RTNL is locked and they warn otherwise. The deconfigure function can be called when port is removed, for example as part of device reload, then there is no locked RTNL and the function warns [1]. To avoid such case, do not assume that RTNL protects this code, add a dedicated mutex instead. The mutex protects 'ptp_state->config' which stores the existing global configuration in hardware. Use this mutex also to protect the code which configures the hardware. Then, there will be only one configuration in any time, which will be updated in 'ptp_state' and a race will be avoided. [1]: RTNL: assertion failed at drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c (1600) WARNING: CPU: 1 PID: 1583493 at drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c:1600 mlxsw_sp2_ptp_hwtstamp_set+0x2d3/0x300 [mlxsw_spectrum] [...] CPU: 1 PID: 1583493 Comm: devlink Not tainted5.19.0-rc8-custom-127022-gb371dffda095 #789 Hardware name: Mellanox Technologies Ltd.MSN3420/VMOD0005, BIOS 5.11 01/06/2019 RIP: 0010:mlxsw_sp2_ptp_hwtstamp_set+0x2d3/0x300[mlxsw_spectrum] [...] Call Trace: mlxsw_sp_port_remove+0x7e/0x190 [mlxsw_spectrum] mlxsw_sp_fini+0xd1/0x270 [mlxsw_spectrum] mlxsw_core_bus_device_unregister+0x55/0x280 [mlxsw_core] mlxsw_devlink_core_bus_device_reload_down+0x1c/0x30[mlxsw_core] devlink_reload+0x1ee/0x230 devlink_nl_cmd_reload+0x4de/0x580 genl_family_rcv_msg_doit+0xdc/0x140 genl_rcv_msg+0xd7/0x1d0 netlink_rcv_skb+0x49/0xf0 genl_rcv+0x1f/0x30 netlink_unicast+0x22f/0x350 netlink_sendmsg+0x208/0x440 __sys_sendto+0xf0/0x140 __x64_sys_sendto+0x1b/0x20 do_syscall_64+0x35/0x80 entry_SYSCALL_64_after_hwframe+0x63/0xcd Fixes: 08ef8bc825d96 ("mlxsw: spectrum_ptp: Support SIOCGHWTSTAMP, SIOCSHWTSTAMP ioctls") Reported-by: Ido Schimmel Signed-off-by: Amit Cohen Signed-off-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_ptp.c | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c index 2e0b704b8a319..f32c83603b842 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c @@ -46,6 +46,7 @@ struct mlxsw_sp2_ptp_state { * enabled. */ struct hwtstamp_config config; + struct mutex lock; /* Protects 'config' and HW configuration. */ }; struct mlxsw_sp1_ptp_key { @@ -1374,6 +1375,7 @@ struct mlxsw_sp_ptp_state *mlxsw_sp2_ptp_init(struct mlxsw_sp *mlxsw_sp) goto err_ptp_traps_set; refcount_set(&ptp_state->ptp_port_enabled_ref, 0); + mutex_init(&ptp_state->lock); return &ptp_state->common; err_ptp_traps_set: @@ -1388,6 +1390,7 @@ void mlxsw_sp2_ptp_fini(struct mlxsw_sp_ptp_state *ptp_state_common) ptp_state = mlxsw_sp2_ptp_state(mlxsw_sp); + mutex_destroy(&ptp_state->lock); mlxsw_sp_ptp_traps_unset(mlxsw_sp); kfree(ptp_state); } @@ -1461,7 +1464,10 @@ int mlxsw_sp2_ptp_hwtstamp_get(struct mlxsw_sp_port *mlxsw_sp_port, ptp_state = mlxsw_sp2_ptp_state(mlxsw_sp_port->mlxsw_sp); + mutex_lock(&ptp_state->lock); *config = ptp_state->config; + mutex_unlock(&ptp_state->lock); + return 0; } @@ -1574,8 +1580,6 @@ static int mlxsw_sp2_ptp_configure_port(struct mlxsw_sp_port *mlxsw_sp_port, struct mlxsw_sp2_ptp_state *ptp_state; int err; - ASSERT_RTNL(); - ptp_state = mlxsw_sp2_ptp_state(mlxsw_sp_port->mlxsw_sp); if (refcount_inc_not_zero(&ptp_state->ptp_port_enabled_ref)) @@ -1597,8 +1601,6 @@ static int mlxsw_sp2_ptp_deconfigure_port(struct mlxsw_sp_port *mlxsw_sp_port, struct mlxsw_sp2_ptp_state *ptp_state; int err; - ASSERT_RTNL(); - ptp_state = mlxsw_sp2_ptp_state(mlxsw_sp_port->mlxsw_sp); if (!refcount_dec_and_test(&ptp_state->ptp_port_enabled_ref)) @@ -1618,16 +1620,20 @@ static int mlxsw_sp2_ptp_deconfigure_port(struct mlxsw_sp_port *mlxsw_sp_port, int mlxsw_sp2_ptp_hwtstamp_set(struct mlxsw_sp_port *mlxsw_sp_port, struct hwtstamp_config *config) { + struct mlxsw_sp2_ptp_state *ptp_state; enum hwtstamp_rx_filters rx_filter; struct hwtstamp_config new_config; u16 new_ing_types, new_egr_types; bool ptp_enabled; int err; + ptp_state = mlxsw_sp2_ptp_state(mlxsw_sp_port->mlxsw_sp); + mutex_lock(&ptp_state->lock); + err = mlxsw_sp2_ptp_get_message_types(config, &new_ing_types, &new_egr_types, &rx_filter); if (err) - return err; + goto err_get_message_types; new_config.flags = config->flags; new_config.tx_type = config->tx_type; @@ -1640,11 +1646,11 @@ int mlxsw_sp2_ptp_hwtstamp_set(struct mlxsw_sp_port *mlxsw_sp_port, err = mlxsw_sp2_ptp_configure_port(mlxsw_sp_port, new_ing_types, new_egr_types, new_config); if (err) - return err; + goto err_configure_port; } else if (!new_ing_types && !new_egr_types && ptp_enabled) { err = mlxsw_sp2_ptp_deconfigure_port(mlxsw_sp_port, new_config); if (err) - return err; + goto err_deconfigure_port; } mlxsw_sp_port->ptp.ing_types = new_ing_types; @@ -1652,8 +1658,15 @@ int mlxsw_sp2_ptp_hwtstamp_set(struct mlxsw_sp_port *mlxsw_sp_port, /* Notify the ioctl caller what we are actually timestamping. */ config->rx_filter = rx_filter; + mutex_unlock(&ptp_state->lock); return 0; + +err_deconfigure_port: +err_configure_port: +err_get_message_types: + mutex_unlock(&ptp_state->lock); + return err; } int mlxsw_sp2_ptp_get_ts_info(struct mlxsw_sp *mlxsw_sp, From e01885c31bef7c2c5fcb79dc192039f25e300ded Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Fri, 12 Aug 2022 17:32:03 +0200 Subject: [PATCH 184/427] mlxsw: spectrum_ptp: Forbid PTP enablement only in RX or in TX Currently mlxsw driver configures one global PTP configuration for all ports. The reason is that the switch behaves like a transparent clock between CPU port and front-panel ports. When time stamp is enabled in any port, the hardware is configured to update the correction field. The fact that the configuration of CPU port affects all the ports, makes the correction field update to be global for all ports. Otherwise, user will see odd values in the correction field, as the switch will update the correction field in the CPU port, but not in all the front-panel ports. The CPU port is relevant in both RX and TX, so to avoid problematic configuration, forbid PTP enablement only in one direction, i.e., only in RX or TX. Without the change: $ hwstamp_ctl -i swp1 -r 12 -t 0 current settings: tx_type 0 rx_filter 0 new settings: tx_type 0 rx_filter 2 $ echo $? 0 With the change: $ hwstamp_ctl -i swp1 -r 12 -t 0 current settings: tx_type 1 rx_filter 2 SIOCSHWTSTAMP failed: Invalid argument Fixes: 08ef8bc825d96 ("mlxsw: spectrum_ptp: Support SIOCGHWTSTAMP, SIOCSHWTSTAMP ioctls") Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c index f32c83603b842..7b01b9c20722a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c @@ -1529,6 +1529,9 @@ mlxsw_sp2_ptp_get_message_types(const struct hwtstamp_config *config, return -EINVAL; } + if ((ing_types && !egr_types) || (!ing_types && egr_types)) + return -EINVAL; + *p_ing_types = ing_types; *p_egr_types = egr_types; return 0; From f889a2e89ea5b4db5cf09765ee5e310be43c7b6f Mon Sep 17 00:00:00 2001 From: Russell Currey Date: Fri, 12 Aug 2022 17:16:32 +1000 Subject: [PATCH 185/427] selftests/powerpc: Add missing PMU selftests to .gitignores Some recently added selftests don't have their binaries in .gitignores, so add them. I also alphabetically sorted sampling_tests/.gitignore while I was in there. Signed-off-by: Russell Currey Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20220812071632.56095-1-ruscur@russell.cc --- .../powerpc/pmu/event_code_tests/.gitignore | 20 +++++++++++++++++++ .../powerpc/pmu/sampling_tests/.gitignore | 18 +++++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 tools/testing/selftests/powerpc/pmu/event_code_tests/.gitignore diff --git a/tools/testing/selftests/powerpc/pmu/event_code_tests/.gitignore b/tools/testing/selftests/powerpc/pmu/event_code_tests/.gitignore new file mode 100644 index 0000000000000..5710683da5255 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/event_code_tests/.gitignore @@ -0,0 +1,20 @@ +blacklisted_events_test +event_alternatives_tests_p10 +event_alternatives_tests_p9 +generic_events_valid_test +group_constraint_cache_test +group_constraint_l2l3_sel_test +group_constraint_mmcra_sample_test +group_constraint_pmc56_test +group_constraint_pmc_count_test +group_constraint_radix_scope_qual_test +group_constraint_repeat_test +group_constraint_thresh_cmp_test +group_constraint_thresh_ctl_test +group_constraint_thresh_sel_test +group_constraint_unit_test +group_pmc56_exclude_constraints_test +hw_cache_event_type_test +invalid_event_code_test +reserved_bits_mmcra_sample_elig_mode_test +reserved_bits_mmcra_thresh_ctl_test diff --git a/tools/testing/selftests/powerpc/pmu/sampling_tests/.gitignore b/tools/testing/selftests/powerpc/pmu/sampling_tests/.gitignore index 0fce5a694684b..f93b4c7c3a8ad 100644 --- a/tools/testing/selftests/powerpc/pmu/sampling_tests/.gitignore +++ b/tools/testing/selftests/powerpc/pmu/sampling_tests/.gitignore @@ -1,11 +1,21 @@ -mmcr0_exceptionbits_test +bhrb_filter_map_test +bhrb_no_crash_wo_pmu_test +intr_regs_no_crash_wo_pmu_test mmcr0_cc56run_test -mmcr0_pmccext_test -mmcr0_pmcjce_test +mmcr0_exceptionbits_test mmcr0_fc56_pmc1ce_test mmcr0_fc56_pmc56_test +mmcr0_pmccext_test +mmcr0_pmcjce_test mmcr1_comb_test -mmcr2_l2l3_test +mmcr1_sel_unit_cache_test mmcr2_fcs_fch_test +mmcr2_l2l3_test mmcr3_src_test +mmcra_bhrb_any_test +mmcra_bhrb_cond_test +mmcra_bhrb_disable_no_branch_test +mmcra_bhrb_disable_test +mmcra_bhrb_ind_call_test +mmcra_thresh_cmp_test mmcra_thresh_marked_sample_test From 98d7c5e5792b8ce3e1352196dac7f404bb1b46ec Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 26 Jul 2022 21:15:43 +0200 Subject: [PATCH 186/427] mmc: pxamci: Fix an error handling path in pxamci_probe() The commit in Fixes: has moved some code around without updating gotos to the error handling path. Update it now and release some resources if pxamci_of_init() fails. Fixes: fa3a5115469c ("mmc: pxamci: call mmc_of_parse()") Signed-off-by: Christophe JAILLET Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/6d75855ad4e2470e9ed99e0df21bc30f0c925a29.1658862932.git.christophe.jaillet@wanadoo.fr Signed-off-by: Ulf Hansson --- drivers/mmc/host/pxamci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 0db9490dc6595..37bf362a0ed56 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -648,7 +648,7 @@ static int pxamci_probe(struct platform_device *pdev) ret = pxamci_of_init(pdev, mmc); if (ret) - return ret; + goto out; host = mmc_priv(mmc); host->mmc = mmc; From b886f54c300d31c109d2e4336b22922b64e7ba7d Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 26 Jul 2022 21:15:51 +0200 Subject: [PATCH 187/427] mmc: pxamci: Fix another error handling path in pxamci_probe() The commit in Fixes: has introduced an new error handling without branching to the existing error handling path. Update it now and release some resources if pxamci_init_ocr() fails. Fixes: 61951fd6cb49 ("mmc: pxamci: let mmc core handle regulators") Signed-off-by: Christophe JAILLET Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/07a2dcebf8ede69b484103de8f9df043f158cffd.1658862932.git.christophe.jaillet@wanadoo.fr Signed-off-by: Ulf Hansson --- drivers/mmc/host/pxamci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 37bf362a0ed56..e4003f6058eb5 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -672,7 +672,7 @@ static int pxamci_probe(struct platform_device *pdev) ret = pxamci_init_ocr(host); if (ret < 0) - return ret; + goto out; mmc->caps = 0; host->cmdat = 0; From cc5d1692600613e72f32af60e27330fe0c79f4fe Mon Sep 17 00:00:00 2001 From: Wenbin Mei Date: Thu, 28 Jul 2022 16:00:48 +0800 Subject: [PATCH 188/427] mmc: mtk-sd: Clear interrupts when cqe off/disable Currently we don't clear MSDC interrupts when cqe off/disable, which led to the data complete interrupt will be reserved for the next command. If the next command with data transfer after cqe off/disable, we process the CMD ready interrupt and trigger DMA start for data, but the data complete interrupt is already exists, then SW assume that the data transfer is complete, SW will trigger DMA stop, but the data may not be transmitted yet or is transmitting, so we may encounter the following error: mtk-msdc 11230000.mmc: CMD bus busy detected. Signed-off-by: Wenbin Mei Fixes: 88bd652b3c74 ("mmc: mediatek: command queue support") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20220728080048.21336-1-wenbin.mei@mediatek.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mtk-sd.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 4ff73d1883ded..69d78604d1fc3 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -2446,6 +2446,9 @@ static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery) /* disable busy check */ sdr_clr_bits(host->base + MSDC_PATCH_BIT1, MSDC_PB1_BUSY_CHECK_SEL); + val = readl(host->base + MSDC_INT); + writel(val, host->base + MSDC_INT); + if (recovery) { sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP, 1); @@ -2932,11 +2935,14 @@ static int __maybe_unused msdc_suspend(struct device *dev) struct mmc_host *mmc = dev_get_drvdata(dev); struct msdc_host *host = mmc_priv(mmc); int ret; + u32 val; if (mmc->caps2 & MMC_CAP2_CQE) { ret = cqhci_suspend(mmc); if (ret) return ret; + val = readl(host->base + MSDC_INT); + writel(val, host->base + MSDC_INT); } /* From b3e1cf31154136da855f3cb6117c17eb0b6bcfb4 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 7 Aug 2022 08:56:38 +0200 Subject: [PATCH 189/427] mmc: meson-gx: Fix an error handling path in meson_mmc_probe() The commit in Fixes has introduced a new error handling which should goto the existing error handling path. Otherwise some resources leak. Fixes: 19c6beaa064c ("mmc: meson-gx: add device reset") Signed-off-by: Christophe JAILLET Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/be4b863bacf323521ba3a02efdc4fca9cdedd1a6.1659855351.git.christophe.jaillet@wanadoo.fr Signed-off-by: Ulf Hansson --- drivers/mmc/host/meson-gx-mmc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 2f08d442e5577..fc462995cf94a 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -1172,8 +1172,10 @@ static int meson_mmc_probe(struct platform_device *pdev) } ret = device_reset_optional(&pdev->dev); - if (ret) - return dev_err_probe(&pdev->dev, ret, "device reset failed\n"); + if (ret) { + dev_err_probe(&pdev->dev, ret, "device reset failed\n"); + goto free_host; + } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); host->regs = devm_ioremap_resource(&pdev->dev, res); From 461122b999bda2ebef2086a35d8990f9ccac5ab8 Mon Sep 17 00:00:00 2001 From: Stefan Binding Date: Mon, 15 Aug 2022 15:19:53 +0100 Subject: [PATCH 190/427] ALSA: hda/realtek: Add quirks for ASUS Zenbooks using CS35L41 These Asus Zenbook laptop use Realtek HDA codec combined with 2xCS35L41 Amplifiers using SPI. Signed-off-by: Stefan Binding Link: https://lore.kernel.org/r/20220815141953.25197-1-sbinding@opensource.cirrus.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index fd630d62b5a0a..f544761eb11b7 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9283,6 +9283,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1271, "ASUS X430UN", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1290, "ASUS X441SA", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x12a0, "ASUS X441UV", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1043, 0x12af, "ASUS UX582ZS", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x12e0, "ASUS X541SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x12f0, "ASUS X541UV", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x1313, "Asus K42JZ", ALC269VB_FIXUP_ASUS_MIC_NO_PRESENCE), @@ -9303,6 +9304,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x19e1, "ASUS UX581LV", ALC295_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), SND_PCI_QUIRK(0x1043, 0x1a30, "ASUS X705UD", ALC256_FIXUP_ASUS_MIC), + SND_PCI_QUIRK(0x1043, 0x1a8f, "ASUS UX582ZS", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x1b11, "ASUS UX431DA", ALC294_FIXUP_ASUS_COEF_1B), SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), From 7b6670b03641ac308aaa6fa2e6f964ac993b5ea3 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Mon, 20 Jun 2022 11:45:34 +0200 Subject: [PATCH 191/427] s390/hypfs: avoid error message under KVM When booting under KVM the following error messages are issued: hypfs.7f5705: The hardware system does not support hypfs hypfs.7a79f0: Initialization of hypfs failed with rc=-61 Demote the severity of first message from "error" to "info" and issue the second message only in other error cases. Signed-off-by: Juergen Gross Acked-by: Heiko Carstens Acked-by: Christian Borntraeger Link: https://lore.kernel.org/r/20220620094534.18967-1-jgross@suse.com [arch/s390/hypfs/hypfs_diag.c changed description] Signed-off-by: Alexander Gordeev --- arch/s390/hypfs/hypfs_diag.c | 2 +- arch/s390/hypfs/inode.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c index f0bc4dc3e9bf0..6511d15ace45e 100644 --- a/arch/s390/hypfs/hypfs_diag.c +++ b/arch/s390/hypfs/hypfs_diag.c @@ -437,7 +437,7 @@ __init int hypfs_diag_init(void) int rc; if (diag204_probe()) { - pr_err("The hardware system does not support hypfs\n"); + pr_info("The hardware system does not support hypfs\n"); return -ENODATA; } diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c index 5c97f48cea91d..ee919bfc81867 100644 --- a/arch/s390/hypfs/inode.c +++ b/arch/s390/hypfs/inode.c @@ -496,9 +496,9 @@ static int __init hypfs_init(void) hypfs_vm_exit(); fail_hypfs_diag_exit: hypfs_diag_exit(); + pr_err("Initialization of hypfs failed with rc=%i\n", rc); fail_dbfs_exit: hypfs_dbfs_exit(); - pr_err("Initialization of hypfs failed with rc=%i\n", rc); return rc; } device_initcall(hypfs_init) From 0fef40be5d1f8e7af3d61e8827a63c5862cd99f7 Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Fri, 15 Jul 2022 12:23:48 +0200 Subject: [PATCH 192/427] s390/ap: fix crash on older machines based on QCI info missing On older z series machines (z12 and older) there is no QCI info available. The AP code took care of this and the AP bus scan then switched to simple probing via TAPQ. With commit 283915850a44 ("s390/ap: notify drivers on config changed and scan complete callbacks") some code was introduced which silently assumed that the QCI info is always available. However, with KVM simulating an older machine (z12) the result was a kernel crash. Funnily the same crash does not happen on LPAR - maybe because NULL is a valid pointer and reading some data from address 0 also works fine. This fix now improves the code to be aware that the QCI instruction may not be available on older machines and thus the two pointers to QCI info structs may simple be NULL. However, on a machine not providing the QCI info the two callbacks to the zcrypt device drivers on_config_changed() and on_scan_complete() provide parameters which are pointers to a QCI info struct. These both callbacks are NOT served if there is no QCI info available. The only consumer of these callbacks is the vfio device driver. This driver only supports CEX4 and higher. All physical machines which are able to provide CEX4 cards have QCI support available. So there is no sense in for example fill the QCI info struct by hand with looping over cards and queues and TAPQ each APQN. Signed-off-by: Harald Freudenberger Signed-off-by: Tony Krowiak Cc: stable@vger.kernel.org Fixes: 283915850a44 ("s390/ap: notify drivers on config changed and scan complete callbacks") Signed-off-by: Alexander Gordeev --- drivers/s390/crypto/ap_bus.c | 3 +++ drivers/s390/crypto/ap_bus.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 8f1d1cf23d444..59ac98f2bd275 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -2086,6 +2086,9 @@ static inline void ap_scan_adapter(int ap) */ static bool ap_get_configuration(void) { + if (!ap_qci_info) /* QCI not supported */ + return false; + memcpy(ap_qci_info_old, ap_qci_info, sizeof(*ap_qci_info)); ap_fetch_qci_info(ap_qci_info); diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 0c40af157df23..0f17933954fb2 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -148,12 +148,16 @@ struct ap_driver { /* * Called at the start of the ap bus scan function when * the crypto config information (qci) has changed. + * This callback is not invoked if there is no AP + * QCI support available. */ void (*on_config_changed)(struct ap_config_info *new_config_info, struct ap_config_info *old_config_info); /* * Called at the end of the ap bus scan function when * the crypto config information (qci) has changed. + * This callback is not invoked if there is no AP + * QCI support available. */ void (*on_scan_complete)(struct ap_config_info *new_config_info, struct ap_config_info *old_config_info); From 88cccd908d51397f9754f89a937cd13fa59dee37 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 12 Aug 2022 16:21:28 +0200 Subject: [PATCH 193/427] netfilter: nf_tables: NFTA_SET_ELEM_KEY_END requires concat and interval flags If the NFT_SET_CONCAT|NFT_SET_INTERVAL flags are set on, then the netlink attribute NFTA_SET_ELEM_KEY_END must be specified. Otherwise, NFTA_SET_ELEM_KEY_END should not be present. For catch-all element, NFTA_SET_ELEM_KEY_END should not be present. The NFT_SET_ELEM_INTERVAL_END is never used with this set flags combination. Fixes: 7b225d0b5c6d ("netfilter: nf_tables: add NFTA_SET_ELEM_KEY_END attribute") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index bcfe8120e014d..1d14d694f6541 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -5844,6 +5844,24 @@ static void nft_setelem_remove(const struct net *net, set->ops->remove(net, set, elem); } +static bool nft_setelem_valid_key_end(const struct nft_set *set, + struct nlattr **nla, u32 flags) +{ + if ((set->flags & (NFT_SET_CONCAT | NFT_SET_INTERVAL)) == + (NFT_SET_CONCAT | NFT_SET_INTERVAL)) { + if (flags & NFT_SET_ELEM_INTERVAL_END) + return false; + if (!nla[NFTA_SET_ELEM_KEY_END] && + !(flags & NFT_SET_ELEM_CATCHALL)) + return false; + } else { + if (nla[NFTA_SET_ELEM_KEY_END]) + return false; + } + + return true; +} + static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, const struct nlattr *attr, u32 nlmsg_flags) { @@ -5903,6 +5921,9 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, return -EINVAL; } + if (!nft_setelem_valid_key_end(set, nla, flags)) + return -EINVAL; + if ((flags & NFT_SET_ELEM_INTERVAL_END) && (nla[NFTA_SET_ELEM_DATA] || nla[NFTA_SET_ELEM_OBJREF] || @@ -6333,6 +6354,9 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, if (!nla[NFTA_SET_ELEM_KEY] && !(flags & NFT_SET_ELEM_CATCHALL)) return -EINVAL; + if (!nft_setelem_valid_key_end(set, nla, flags)) + return -EINVAL; + nft_set_ext_prepare(&tmpl); if (flags != 0) { From fc0ae524b5fd2938c94d56da3f749f11eb3273d5 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 13 Aug 2022 15:22:05 +0200 Subject: [PATCH 194/427] netfilter: nf_tables: disallow NFT_SET_ELEM_CATCHALL and NFT_SET_ELEM_INTERVAL_END These flags are mutually exclusive, report EINVAL in this case. Fixes: aaa31047a6d2 ("netfilter: nftables: add catch-all set element support") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 1d14d694f6541..b1b12e083abbd 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -5198,6 +5198,9 @@ static int nft_setelem_parse_flags(const struct nft_set *set, if (!(set->flags & NFT_SET_INTERVAL) && *flags & NFT_SET_ELEM_INTERVAL_END) return -EINVAL; + if ((*flags & (NFT_SET_ELEM_INTERVAL_END | NFT_SET_ELEM_CATCHALL)) == + (NFT_SET_ELEM_INTERVAL_END | NFT_SET_ELEM_CATCHALL)) + return -EINVAL; return 0; } From 8535c239ac674f7ead0f2652932d35c52c4123b2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 8 Aug 2022 16:06:04 +0100 Subject: [PATCH 195/427] nios2: page fault et.al. are *not* restartable syscalls... make sure that ->orig_r2 is negative for everything except the syscalls. Fixes: 82ed08dd1b0e ("nios2: Exception handling") Signed-off-by: Al Viro Signed-off-by: Dinh Nguyen --- arch/nios2/include/asm/entry.h | 3 ++- arch/nios2/kernel/entry.S | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/nios2/include/asm/entry.h b/arch/nios2/include/asm/entry.h index cf37f55efbc22..bafb7b2ca59fc 100644 --- a/arch/nios2/include/asm/entry.h +++ b/arch/nios2/include/asm/entry.h @@ -50,7 +50,8 @@ stw r13, PT_R13(sp) stw r14, PT_R14(sp) stw r15, PT_R15(sp) - stw r2, PT_ORIG_R2(sp) + movi r24, -1 + stw r24, PT_ORIG_R2(sp) stw r7, PT_ORIG_R7(sp) stw ra, PT_RA(sp) diff --git a/arch/nios2/kernel/entry.S b/arch/nios2/kernel/entry.S index 0794cd7803dfe..fbd348bf103f1 100644 --- a/arch/nios2/kernel/entry.S +++ b/arch/nios2/kernel/entry.S @@ -185,6 +185,7 @@ ENTRY(handle_system_call) ldw r5, PT_R5(sp) local_restart: + stw r2, PT_ORIG_R2(sp) /* Check that the requested system call is within limits */ movui r1, __NR_syscalls bgeu r2, r1, ret_invsyscall @@ -336,9 +337,6 @@ external_interrupt: /* skip if no interrupt is pending */ beq r12, r0, ret_from_interrupt - movi r24, -1 - stw r24, PT_ORIG_R2(sp) - /* * Process an external hardware interrupt. */ From 45ec746c65097c25e77d24eae8fee0def5b6cc5d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 8 Aug 2022 16:06:46 +0100 Subject: [PATCH 196/427] nios2: don't leave NULLs in sys_call_table[] fill the gaps in there with sys_ni_syscall, as everyone does... Fixes: 82ed08dd1b0e ("nios2: Exception handling") Signed-off-by: Al Viro Signed-off-by: Dinh Nguyen --- arch/nios2/kernel/entry.S | 1 - arch/nios2/kernel/syscall_table.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/nios2/kernel/entry.S b/arch/nios2/kernel/entry.S index fbd348bf103f1..8f41ef5b03995 100644 --- a/arch/nios2/kernel/entry.S +++ b/arch/nios2/kernel/entry.S @@ -193,7 +193,6 @@ local_restart: movhi r11, %hiadj(sys_call_table) add r1, r1, r11 ldw r1, %lo(sys_call_table)(r1) - beq r1, r0, ret_invsyscall /* Check if we are being traced */ GET_THREAD_INFO r11 diff --git a/arch/nios2/kernel/syscall_table.c b/arch/nios2/kernel/syscall_table.c index 6176d63023c1d..c2875a6dd5a4a 100644 --- a/arch/nios2/kernel/syscall_table.c +++ b/arch/nios2/kernel/syscall_table.c @@ -13,5 +13,6 @@ #define __SYSCALL(nr, call) [nr] = (call), void *sys_call_table[__NR_syscalls] = { + [0 ... __NR_syscalls-1] = sys_ni_syscall, #include }; From 25ba820ef36bdbaf9884adeac69b6e1821a7df76 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 8 Aug 2022 16:07:21 +0100 Subject: [PATCH 197/427] nios2: traced syscall does need to check the syscall number all checks done before letting the tracer modify the register state are worthless... Fixes: 82ed08dd1b0e ("nios2: Exception handling") Signed-off-by: Al Viro Signed-off-by: Dinh Nguyen --- arch/nios2/kernel/entry.S | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/nios2/kernel/entry.S b/arch/nios2/kernel/entry.S index 8f41ef5b03995..fd2449031d081 100644 --- a/arch/nios2/kernel/entry.S +++ b/arch/nios2/kernel/entry.S @@ -255,9 +255,9 @@ traced_system_call: ldw r6, PT_R6(sp) ldw r7, PT_R7(sp) - /* Fetch the syscall function, we don't need to check the boundaries - * since this is already done. - */ + /* Fetch the syscall function. */ + movui r1, __NR_syscalls + bgeu r2, r1, traced_invsyscall slli r1, r2, 2 movhi r11,%hiadj(sys_call_table) add r1, r1, r11 @@ -287,6 +287,11 @@ end_translate_rc_and_ret2: RESTORE_SWITCH_STACK br ret_from_exception + /* If the syscall number was invalid return ENOSYS */ +traced_invsyscall: + movi r2, -ENOSYS + br translate_rc_and_ret2 + Luser_return: GET_THREAD_INFO r11 /* get thread_info pointer */ ldw r10, TI_FLAGS(r11) /* get thread_info->flags */ From 2d631bd58fe0ea3e3350212e23c9aba1fb606514 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 8 Aug 2022 16:08:48 +0100 Subject: [PATCH 198/427] nios2: fix syscall restart checks sys_foo() returns -512 (aka -ERESTARTSYS) => do_signal() sees 512 in r2 and 1 in r1. sys_foo() returns 512 => do_signal() sees 512 in r2 and 0 in r1. The former is restart-worthy; the latter obviously isn't. Fixes: b53e906d255d ("nios2: Signal handling support") Signed-off-by: Al Viro Signed-off-by: Dinh Nguyen --- arch/nios2/kernel/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/nios2/kernel/signal.c b/arch/nios2/kernel/signal.c index cb0b91589cf20..15e672d7150e8 100644 --- a/arch/nios2/kernel/signal.c +++ b/arch/nios2/kernel/signal.c @@ -242,7 +242,7 @@ static int do_signal(struct pt_regs *regs) /* * If we were from a system call, check for system call restarting... */ - if (regs->orig_r2 >= 0) { + if (regs->orig_r2 >= 0 && regs->r1) { continue_addr = regs->ea; restart_addr = continue_addr - 4; retval = regs->r2; From 411a76b7219555c55867466c82d70ce928d6c9e1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 8 Aug 2022 16:09:16 +0100 Subject: [PATCH 199/427] nios2: restarts apply only to the first sigframe we build... Fixes: b53e906d255d ("nios2: Signal handling support") Signed-off-by: Al Viro Signed-off-by: Dinh Nguyen --- arch/nios2/kernel/signal.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/nios2/kernel/signal.c b/arch/nios2/kernel/signal.c index 15e672d7150e8..a5b93a30c6eb2 100644 --- a/arch/nios2/kernel/signal.c +++ b/arch/nios2/kernel/signal.c @@ -264,6 +264,7 @@ static int do_signal(struct pt_regs *regs) regs->ea = restart_addr; break; } + regs->orig_r2 = -1; } if (get_signal(&ksig)) { From fd0c153daad135d0ec1a53c5dbe6936a724d6ae1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 8 Aug 2022 16:09:45 +0100 Subject: [PATCH 200/427] nios2: add force_successful_syscall_return() If we use the ancient SysV syscall ABI, we'd better have tell the kernel how to claim that a negative return value is a success. Use ->orig_r2 for that - it's inaccessible via ptrace, so it's a fair game for changes and it's normally[*] non-negative on return from syscall. Set to -1; syscall is not going to be restart-worthy by definition, so we won't interfere with that use either. [*] the only exception is rt_sigreturn(), where we skip the entire messing with r1/r2 anyway. Fixes: 82ed08dd1b0e ("nios2: Exception handling") Signed-off-by: Al Viro Signed-off-by: Dinh Nguyen --- arch/nios2/include/asm/ptrace.h | 2 ++ arch/nios2/kernel/entry.S | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/arch/nios2/include/asm/ptrace.h b/arch/nios2/include/asm/ptrace.h index 6424621448728..9da34c3022a27 100644 --- a/arch/nios2/include/asm/ptrace.h +++ b/arch/nios2/include/asm/ptrace.h @@ -74,6 +74,8 @@ extern void show_regs(struct pt_regs *); ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE)\ - 1) +#define force_successful_syscall_return() (current_pt_regs()->orig_r2 = -1) + int do_syscall_trace_enter(void); void do_syscall_trace_exit(void); #endif /* __ASSEMBLY__ */ diff --git a/arch/nios2/kernel/entry.S b/arch/nios2/kernel/entry.S index fd2449031d081..99f0a65e62347 100644 --- a/arch/nios2/kernel/entry.S +++ b/arch/nios2/kernel/entry.S @@ -213,6 +213,9 @@ local_restart: translate_rc_and_ret: movi r1, 0 bge r2, zero, 3f + ldw r1, PT_ORIG_R2(sp) + addi r1, r1, 1 + beq r1, zero, 3f sub r2, zero, r2 movi r1, 1 3: @@ -276,6 +279,9 @@ traced_system_call: translate_rc_and_ret2: movi r1, 0 bge r2, zero, 4f + ldw r1, PT_ORIG_R2(sp) + addi r1, r1, 1 + beq r1, zero, 4f sub r2, zero, r2 movi r1, 1 4: From 1b6345d4160ecd3d04bd8cd75df90c67811e8cc9 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 15 Aug 2022 17:55:07 +0200 Subject: [PATCH 201/427] netfilter: nf_tables: check NFT_SET_CONCAT flag if field_count is specified Since f3a2181e16f1 ("netfilter: nf_tables: Support for sets with multiple ranged fields"), it possible to combine intervals and concatenations. Later on, ef516e8625dd ("netfilter: nf_tables: reintroduce the NFT_SET_CONCAT flag") provides the NFT_SET_CONCAT flag for userspace to report that the set stores a concatenation. Make sure NFT_SET_CONCAT is set on if field_count is specified for consistency. Otherwise, if NFT_SET_CONCAT is specified with no field_count, bail out with EINVAL. Fixes: ef516e8625dd ("netfilter: nf_tables: reintroduce the NFT_SET_CONCAT flag") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index b1b12e083abbd..62cfb0e31c40e 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -4451,6 +4451,11 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info, err = nf_tables_set_desc_parse(&desc, nla[NFTA_SET_DESC]); if (err < 0) return err; + + if (desc.field_count > 1 && !(flags & NFT_SET_CONCAT)) + return -EINVAL; + } else if (flags & NFT_SET_CONCAT) { + return -EINVAL; } if (nla[NFTA_SET_EXPR] || nla[NFTA_SET_EXPRESSIONS]) From f1227dc7d0411ee9a9faaa1e80cfd9d6e5d6d63e Mon Sep 17 00:00:00 2001 From: Guillaume Tucker Date: Wed, 3 Aug 2022 22:13:54 +0200 Subject: [PATCH 202/427] selftests/landlock: fix broken include of linux/landlock.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Revert part of the earlier changes to fix the kselftest build when using a sub-directory from the top of the tree as this broke the landlock test build as a side-effect when building with "make -C tools/testing/selftests/landlock". Reported-by: Mickaël Salaün Fixes: a917dd94b832 ("selftests/landlock: drop deprecated headers dependency") Fixes: f2745dc0ba3d ("selftests: stop using KSFT_KHDR_INSTALL") Signed-off-by: Guillaume Tucker Signed-off-by: Shuah Khan --- tools/testing/selftests/landlock/Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/landlock/Makefile b/tools/testing/selftests/landlock/Makefile index a6959df28eb0f..02868ac3bc717 100644 --- a/tools/testing/selftests/landlock/Makefile +++ b/tools/testing/selftests/landlock/Makefile @@ -9,10 +9,13 @@ TEST_GEN_PROGS := $(src_test:.c=) TEST_GEN_PROGS_EXTENDED := true OVERRIDE_TARGETS := 1 +top_srcdir := ../../../.. include ../lib.mk +khdr_dir = $(top_srcdir)/usr/include + $(OUTPUT)/true: true.c $(LINK.c) $< $(LDLIBS) -o $@ -static -$(OUTPUT)/%_test: %_test.c ../kselftest_harness.h common.h - $(LINK.c) $< $(LDLIBS) -o $@ -lcap +$(OUTPUT)/%_test: %_test.c $(khdr_dir)/linux/landlock.h ../kselftest_harness.h common.h + $(LINK.c) $< $(LDLIBS) -o $@ -lcap -I$(khdr_dir) From a0753ef66c34c1739580219dca664eda648164b7 Mon Sep 17 00:00:00 2001 From: Liming Sun Date: Tue, 9 Aug 2022 13:37:42 -0400 Subject: [PATCH 203/427] mmc: sdhci-of-dwcmshc: Re-enable support for the BlueField-3 SoC The commit 08f3dff799d4 (mmc: sdhci-of-dwcmshc: add rockchip platform support") introduces the use of_device_get_match_data() to check for some chips. Unfortunately, it also breaks the BlueField-3 FW, which uses ACPI. To fix the problem, let's add the ACPI match data and the corresponding quirks to re-enable the support for the BlueField-3 SoC. Reviewed-by: David Woods Signed-off-by: Liming Sun Acked-by: Adrian Hunter Fixes: 08f3dff799d4 ("mmc: sdhci-of-dwcmshc: add rockchip platform support") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20220809173742.178440-1-limings@nvidia.com [Ulf: Clarified the commit message a bit] Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-dwcmshc.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index 4e904850973cd..a7343d4bc50e7 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -349,6 +349,15 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = { .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, }; +#ifdef CONFIG_ACPI +static const struct sdhci_pltfm_data sdhci_dwcmshc_bf3_pdata = { + .ops = &sdhci_dwcmshc_ops, + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | + SDHCI_QUIRK2_ACMD23_BROKEN, +}; +#endif + static const struct sdhci_pltfm_data sdhci_dwcmshc_rk35xx_pdata = { .ops = &sdhci_dwcmshc_rk35xx_ops, .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | @@ -431,7 +440,10 @@ MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids); #ifdef CONFIG_ACPI static const struct acpi_device_id sdhci_dwcmshc_acpi_ids[] = { - { .id = "MLNXBF30" }, + { + .id = "MLNXBF30", + .driver_data = (kernel_ulong_t)&sdhci_dwcmshc_bf3_pdata, + }, {} }; #endif @@ -447,7 +459,7 @@ static int dwcmshc_probe(struct platform_device *pdev) int err; u32 extra; - pltfm_data = of_device_get_match_data(&pdev->dev); + pltfm_data = device_get_match_data(&pdev->dev); if (!pltfm_data) { dev_err(&pdev->dev, "Error: No device match data found\n"); return -ENODEV; From be599244865cb788abe2c6f59ccb05d7240448e4 Mon Sep 17 00:00:00 2001 From: Sander Vanheule Date: Tue, 9 Aug 2022 19:36:33 +0200 Subject: [PATCH 204/427] cpumask: align signatures of UP implementations Between the generic version, and their uniprocessor optimised implementations, the return types of cpumask_any_and_distribute() and cpumask_any_distribute() are not identical. Change the UP versions to 'unsigned int', to match the generic versions. Suggested-by: Yury Norov Signed-off-by: Sander Vanheule Signed-off-by: Yury Norov --- include/linux/cpumask.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 0d435d0edbcb4..d8c2a40f8bebf 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -202,12 +202,13 @@ static inline unsigned int cpumask_local_spread(unsigned int i, int node) return 0; } -static inline int cpumask_any_and_distribute(const struct cpumask *src1p, - const struct cpumask *src2p) { +static inline unsigned int cpumask_any_and_distribute(const struct cpumask *src1p, + const struct cpumask *src2p) +{ return cpumask_first_and(src1p, src2p); } -static inline int cpumask_any_distribute(const struct cpumask *srcp) +static inline unsigned int cpumask_any_distribute(const struct cpumask *srcp) { return cpumask_first(srcp); } From 2248ccd80124e61c2c84a22b22409bab452e1f0c Mon Sep 17 00:00:00 2001 From: Sander Vanheule Date: Tue, 9 Aug 2022 19:36:34 +0200 Subject: [PATCH 205/427] lib/cpumask: add inline cpumask_next_wrap() for UP In the uniprocessor case, cpumask_next_wrap() can be simplified, as the number of valid argument combinations is limited: - 'start' can only be 0 - 'n' can only be -1 or 0 The only valid CPU that can then be returned, if any, will be the first one set in the provided 'mask'. For NR_CPUS == 1, include/linux/cpumask.h now provides an inline definition of cpumask_next_wrap(), which will conflict with the one provided by lib/cpumask.c. Make building of lib/cpumask.o again depend on CONFIG_SMP=y (i.e. NR_CPUS > 1) to avoid the re-definition. Suggested-by: Yury Norov Signed-off-by: Sander Vanheule Signed-off-by: Yury Norov --- include/linux/cpumask.h | 19 +++++++++++++++++++ lib/Makefile | 3 ++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index d8c2a40f8bebf..bd047864c7ac7 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -262,7 +262,26 @@ unsigned int cpumask_next_and(int n, const struct cpumask *src1p, (cpu) = cpumask_next_zero((cpu), (mask)), \ (cpu) < nr_cpu_ids;) +#if NR_CPUS == 1 +static inline +unsigned int cpumask_next_wrap(int n, const struct cpumask *mask, int start, bool wrap) +{ + cpumask_check(start); + if (n != -1) + cpumask_check(n); + + /* + * Return the first available CPU when wrapping, or when starting before cpu0, + * since there is only one valid option. + */ + if (wrap && n >= 0) + return nr_cpumask_bits; + + return cpumask_first(mask); +} +#else unsigned int __pure cpumask_next_wrap(int n, const struct cpumask *mask, int start, bool wrap); +#endif /** * for_each_cpu_wrap - iterate over every cpu in a mask, starting at a specified location diff --git a/lib/Makefile b/lib/Makefile index c952121419282..5927d7fa08063 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -34,9 +34,10 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ is_single_threaded.o plist.o decompress.o kobject_uevent.o \ earlycpio.o seq_buf.o siphash.o dec_and_lock.o \ nmi_backtrace.o win_minmax.o memcat_p.o \ - buildid.o cpumask.o + buildid.o lib-$(CONFIG_PRINTK) += dump_stack.o +lib-$(CONFIG_SMP) += cpumask.o lib-y += kobject.o klist.o obj-y += lockref.o From 61b123ffcedac72a1ac6a96d1da87d25efddcbda Mon Sep 17 00:00:00 2001 From: Sander Vanheule Date: Tue, 9 Aug 2022 19:36:35 +0200 Subject: [PATCH 206/427] lib/cpumask: drop always-true preprocessor guard Since lib/cpumask.o is only built for CONFIG_SMP=y, NR_CPUS will always be greater than 1 at compile time. This makes checking for that condition unnecesarry, so it can be dropped. Signed-off-by: Sander Vanheule Signed-off-by: Yury Norov --- lib/cpumask.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/cpumask.c b/lib/cpumask.c index 8baeb37e23d34..f0ae119be8c41 100644 --- a/lib/cpumask.c +++ b/lib/cpumask.c @@ -109,7 +109,6 @@ void __init free_bootmem_cpumask_var(cpumask_var_t mask) } #endif -#if NR_CPUS > 1 /** * cpumask_local_spread - select the i'th cpu with local numa cpu's first * @i: index number @@ -197,4 +196,3 @@ unsigned int cpumask_any_distribute(const struct cpumask *srcp) return next; } EXPORT_SYMBOL(cpumask_any_distribute); -#endif /* NR_CPUS */ From d3122bf9aa4c974f5e2c0112f799757b3a2779da Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Fri, 12 Aug 2022 02:29:53 +0900 Subject: [PATCH 207/427] ata: libata-eh: Add missing command name Add the missing command name for ATA_CMD_NCQ_NON_DATA to ata_get_cmd_name(). Fixes: 661ce1f0c4a6 ("libata/libsas: Define ATA_CMD_NCQ_NON_DATA") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal Reviewed-by: Hannes Reinecke --- drivers/ata/libata-eh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index ef4508d72c023..7c128c89b4546 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2122,6 +2122,7 @@ const char *ata_get_cmd_name(u8 command) { ATA_CMD_WRITE_QUEUED_FUA_EXT, "WRITE DMA QUEUED FUA EXT" }, { ATA_CMD_FPDMA_READ, "READ FPDMA QUEUED" }, { ATA_CMD_FPDMA_WRITE, "WRITE FPDMA QUEUED" }, + { ATA_CMD_NCQ_NON_DATA, "NCQ NON-DATA" }, { ATA_CMD_FPDMA_SEND, "SEND FPDMA QUEUED" }, { ATA_CMD_FPDMA_RECV, "RECEIVE FPDMA QUEUED" }, { ATA_CMD_PIO_READ, "READ SECTOR(S)" }, From c90b31eaf9e77269d3803ed9223a2e0168b519ac Mon Sep 17 00:00:00 2001 From: Hyunchul Lee Date: Fri, 12 Aug 2022 11:11:32 +0900 Subject: [PATCH 208/427] ksmbd: remove unnecessary generic_fillattr in smb2_open Remove unnecessary generic_fillattr to fix wrong AllocationSize of SMB2_CREATE response, And Move the call of ksmbd_vfs_getattr above the place where stat is needed because of truncate. This patch fixes wrong AllocationSize of SMB2_CREATE response. Because ext4 updates inode->i_blocks only when disk space is allocated, generic_fillattr does not set stat.blocks properly for delayed allocation. But ext4 returns the blocks that include the delayed allocation blocks when getattr is called. The issue can be reproduced with commands below: touch ${FILENAME} xfs_io -c "pwrite -S 0xAB 0 40k" ${FILENAME} xfs_io -c "stat" ${FILENAME} 40KB are written, but the count of blocks is 8. Signed-off-by: Hyunchul Lee Acked-by: Namjae Jeon Signed-off-by: Steve French --- fs/ksmbd/smb2pdu.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index b5c36657ecfdd..a136d5e4943ba 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -3044,12 +3044,6 @@ int smb2_open(struct ksmbd_work *work) list_add(&fp->node, &fp->f_ci->m_fp_list); write_unlock(&fp->f_ci->m_lock); - rc = ksmbd_vfs_getattr(&path, &stat); - if (rc) { - generic_fillattr(user_ns, d_inode(path.dentry), &stat); - rc = 0; - } - /* Check delete pending among previous fp before oplock break */ if (ksmbd_inode_pending_delete(fp)) { rc = -EBUSY; @@ -3136,6 +3130,10 @@ int smb2_open(struct ksmbd_work *work) } } + rc = ksmbd_vfs_getattr(&path, &stat); + if (rc) + goto err_out; + if (stat.result_mask & STATX_BTIME) fp->create_time = ksmbd_UnixTimeToNT(stat.btime); else @@ -3151,9 +3149,6 @@ int smb2_open(struct ksmbd_work *work) memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE); - generic_fillattr(user_ns, file_inode(fp->filp), - &stat); - rsp->StructureSize = cpu_to_le16(89); rcu_read_lock(); opinfo = rcu_dereference(fp->f_opinfo); From 17661ecf6a64eb11ae7f1108fe88686388b2acd5 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Sun, 14 Aug 2022 22:40:25 +0900 Subject: [PATCH 209/427] ksmbd: don't remove dos attribute xattr on O_TRUNC open When smb client open file in ksmbd share with O_TRUNC, dos attribute xattr is removed as well as data in file. This cause the FSCTL_SET_SPARSE request from the client fails because ksmbd can't update the dos attribute after setting ATTR_SPARSE_FILE. And this patch fix xfstests generic/469 test also. Signed-off-by: Namjae Jeon Reviewed-by: Hyunchul Lee Signed-off-by: Steve French --- fs/ksmbd/smb2pdu.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index a136d5e4943ba..19412ac701a65 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -2330,15 +2330,15 @@ static int smb2_remove_smb_xattrs(struct path *path) name += strlen(name) + 1) { ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name)); - if (strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) && - strncmp(&name[XATTR_USER_PREFIX_LEN], DOS_ATTRIBUTE_PREFIX, - DOS_ATTRIBUTE_PREFIX_LEN) && - strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX, STREAM_PREFIX_LEN)) - continue; - - err = ksmbd_vfs_remove_xattr(user_ns, path->dentry, name); - if (err) - ksmbd_debug(SMB, "remove xattr failed : %s\n", name); + if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) && + !strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX, + STREAM_PREFIX_LEN)) { + err = ksmbd_vfs_remove_xattr(user_ns, path->dentry, + name); + if (err) + ksmbd_debug(SMB, "remove xattr failed : %s\n", + name); + } } out: kvfree(xattr_list); From 3a12df22a8f68954a4ba48435c06b3d1791c87c4 Mon Sep 17 00:00:00 2001 From: Sergei Antonov Date: Fri, 12 Aug 2022 20:13:39 +0300 Subject: [PATCH 210/427] net: moxa: pass pdev instead of ndev to DMA functions dma_map_single() calls fail in moxart_mac_setup_desc_ring() and moxart_mac_start_xmit() which leads to an incessant output of this: [ 16.043925] moxart-ethernet 92000000.mac eth0: DMA mapping error [ 16.050957] moxart-ethernet 92000000.mac eth0: DMA mapping error [ 16.058229] moxart-ethernet 92000000.mac eth0: DMA mapping error Passing pdev to DMA is a common approach among net drivers. Fixes: 6c821bd9edc9 ("net: Add MOXA ART SoCs ethernet driver") Signed-off-by: Sergei Antonov Suggested-by: Andrew Lunn Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20220812171339.2271788-1-saproj@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/moxa/moxart_ether.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c index a3214a762e4b3..f11f1cb92025f 100644 --- a/drivers/net/ethernet/moxa/moxart_ether.c +++ b/drivers/net/ethernet/moxa/moxart_ether.c @@ -77,7 +77,7 @@ static void moxart_mac_free_memory(struct net_device *ndev) int i; for (i = 0; i < RX_DESC_NUM; i++) - dma_unmap_single(&ndev->dev, priv->rx_mapping[i], + dma_unmap_single(&priv->pdev->dev, priv->rx_mapping[i], priv->rx_buf_size, DMA_FROM_DEVICE); if (priv->tx_desc_base) @@ -147,11 +147,11 @@ static void moxart_mac_setup_desc_ring(struct net_device *ndev) desc + RX_REG_OFFSET_DESC1); priv->rx_buf[i] = priv->rx_buf_base + priv->rx_buf_size * i; - priv->rx_mapping[i] = dma_map_single(&ndev->dev, + priv->rx_mapping[i] = dma_map_single(&priv->pdev->dev, priv->rx_buf[i], priv->rx_buf_size, DMA_FROM_DEVICE); - if (dma_mapping_error(&ndev->dev, priv->rx_mapping[i])) + if (dma_mapping_error(&priv->pdev->dev, priv->rx_mapping[i])) netdev_err(ndev, "DMA mapping error\n"); moxart_desc_write(priv->rx_mapping[i], @@ -240,7 +240,7 @@ static int moxart_rx_poll(struct napi_struct *napi, int budget) if (len > RX_BUF_SIZE) len = RX_BUF_SIZE; - dma_sync_single_for_cpu(&ndev->dev, + dma_sync_single_for_cpu(&priv->pdev->dev, priv->rx_mapping[rx_head], priv->rx_buf_size, DMA_FROM_DEVICE); skb = netdev_alloc_skb_ip_align(ndev, len); @@ -294,7 +294,7 @@ static void moxart_tx_finished(struct net_device *ndev) unsigned int tx_tail = priv->tx_tail; while (tx_tail != tx_head) { - dma_unmap_single(&ndev->dev, priv->tx_mapping[tx_tail], + dma_unmap_single(&priv->pdev->dev, priv->tx_mapping[tx_tail], priv->tx_len[tx_tail], DMA_TO_DEVICE); ndev->stats.tx_packets++; @@ -358,9 +358,9 @@ static netdev_tx_t moxart_mac_start_xmit(struct sk_buff *skb, len = skb->len > TX_BUF_SIZE ? TX_BUF_SIZE : skb->len; - priv->tx_mapping[tx_head] = dma_map_single(&ndev->dev, skb->data, + priv->tx_mapping[tx_head] = dma_map_single(&priv->pdev->dev, skb->data, len, DMA_TO_DEVICE); - if (dma_mapping_error(&ndev->dev, priv->tx_mapping[tx_head])) { + if (dma_mapping_error(&priv->pdev->dev, priv->tx_mapping[tx_head])) { netdev_err(ndev, "DMA mapping error\n"); goto out_unlock; } @@ -379,7 +379,7 @@ static netdev_tx_t moxart_mac_start_xmit(struct sk_buff *skb, len = ETH_ZLEN; } - dma_sync_single_for_device(&ndev->dev, priv->tx_mapping[tx_head], + dma_sync_single_for_device(&priv->pdev->dev, priv->tx_mapping[tx_head], priv->tx_buf_size, DMA_TO_DEVICE); txdes1 = TX_DESC1_LTS | TX_DESC1_FTS | (len & TX_DESC1_BUF_SIZE_MASK); @@ -493,7 +493,7 @@ static int moxart_mac_probe(struct platform_device *pdev) priv->tx_buf_size = TX_BUF_SIZE; priv->rx_buf_size = RX_BUF_SIZE; - priv->tx_desc_base = dma_alloc_coherent(&pdev->dev, TX_REG_DESC_SIZE * + priv->tx_desc_base = dma_alloc_coherent(p_dev, TX_REG_DESC_SIZE * TX_DESC_NUM, &priv->tx_base, GFP_DMA | GFP_KERNEL); if (!priv->tx_desc_base) { @@ -501,7 +501,7 @@ static int moxart_mac_probe(struct platform_device *pdev) goto init_fail; } - priv->rx_desc_base = dma_alloc_coherent(&pdev->dev, RX_REG_DESC_SIZE * + priv->rx_desc_base = dma_alloc_coherent(p_dev, RX_REG_DESC_SIZE * RX_DESC_NUM, &priv->rx_base, GFP_DMA | GFP_KERNEL); if (!priv->rx_desc_base) { From 5b22f62724a0a09e00d301abf5b57b0c12be8a16 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Mon, 15 Aug 2022 10:46:29 +0800 Subject: [PATCH 211/427] net: rtnetlink: fix module reference count leak issue in rtnetlink_rcv_msg When bulk delete command is received in the rtnetlink_rcv_msg function, if bulk delete is not supported, module_put is not called to release the reference counting. As a result, module reference count is leaked. Fixes: a6cec0bcd342 ("net: rtnetlink: add bulk delete support flag") Signed-off-by: Zhengchao Shao Acked-by: Nikolay Aleksandrov Link: https://lore.kernel.org/r/20220815024629.240367-1-shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski --- net/core/rtnetlink.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index ac45328607f77..4b5b15c684ed6 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -6070,6 +6070,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, if (kind == RTNL_KIND_DEL && (nlh->nlmsg_flags & NLM_F_BULK) && !(flags & RTNL_FLAG_BULK_DEL_SUPPORTED)) { NL_SET_ERR_MSG(extack, "Bulk delete is not supported"); + module_put(owner); goto err_unlock; } From 063604265f967e90901996a1b173fe6df582d350 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Mon, 15 Aug 2022 13:42:00 +0100 Subject: [PATCH 212/427] io_uring/net: use right helpers for async recycle We have a helper that checks for whether a request contains anything in ->async_data or not, namely req_has_async_data(). It's better to use it as it might have some extra considerations. Fixes: 43e0bbbd0b0e3 ("io_uring: add netmsg cache") Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/b7414da4e7c3c32c31fc02dfd1355af4ccf4ca5f.1660566179.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- io_uring/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/io_uring/net.c b/io_uring/net.c index 6d71748e2c5af..2129562bfd9f3 100644 --- a/io_uring/net.c +++ b/io_uring/net.c @@ -116,7 +116,7 @@ static void io_netmsg_recycle(struct io_kiocb *req, unsigned int issue_flags) { struct io_async_msghdr *hdr = req->async_data; - if (!hdr || issue_flags & IO_URING_F_UNLOCKED) + if (!req_has_async_data(req) || issue_flags & IO_URING_F_UNLOCKED) return; /* Let normal cleanup path reap it if we fail adding to the cache */ From 86dc8f23bb1b68262ca5db890ec7177b2d074640 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Mon, 15 Aug 2022 13:42:01 +0100 Subject: [PATCH 213/427] io_uring/net: improve zc addr import error handling We may account memory to a memcg of a request that didn't even got to the network layer. It's not a bug as it'll be routinely cleaned up on flush, but it might be confusing for the userspace. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/b8aae61f4c3ddc4da97c1da876bb73871f352d50.1660566179.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- io_uring/net.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/io_uring/net.c b/io_uring/net.c index 2129562bfd9f3..f7cbd716817fe 100644 --- a/io_uring/net.c +++ b/io_uring/net.c @@ -977,6 +977,14 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags) msg.msg_controllen = 0; msg.msg_namelen = 0; + if (zc->addr) { + ret = move_addr_to_kernel(zc->addr, zc->addr_len, &address); + if (unlikely(ret < 0)) + return ret; + msg.msg_name = (struct sockaddr *)&address; + msg.msg_namelen = zc->addr_len; + } + if (zc->flags & IORING_RECVSEND_FIXED_BUF) { ret = io_import_fixed(WRITE, &msg.msg_iter, req->imu, (u64)(uintptr_t)zc->buf, zc->len); @@ -992,14 +1000,6 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags) return ret; } - if (zc->addr) { - ret = move_addr_to_kernel(zc->addr, zc->addr_len, &address); - if (unlikely(ret < 0)) - return ret; - msg.msg_name = (struct sockaddr *)&address; - msg.msg_namelen = zc->addr_len; - } - msg_flags = zc->msg_flags | MSG_ZEROCOPY; if (issue_flags & IO_URING_F_NONBLOCK) msg_flags |= MSG_DONTWAIT; From 5993000dc6b31b927403cee65fbc5f9f070fa3e4 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Mon, 15 Aug 2022 13:42:02 +0100 Subject: [PATCH 214/427] io_uring/notif: raise limit on notification slots 1024 notification slots is rather an arbitrary value, raise it up, everything is accounted to memcg. Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/eb78a0a5f2fa5941f8e845cdae5fb399bf7ba0be.1660566179.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- io_uring/notif.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/io_uring/notif.h b/io_uring/notif.h index 65f0b42f25550..80f6445e0c2ba 100644 --- a/io_uring/notif.h +++ b/io_uring/notif.h @@ -8,7 +8,7 @@ #include "rsrc.h" #define IO_NOTIF_SPLICE_BATCH 32 -#define IORING_MAX_NOTIF_SLOTS (1U << 10) +#define IORING_MAX_NOTIF_SLOTS (1U << 15) struct io_notif_data { struct file *file; From 2e9ca760c289e1f992eb2cd053e217db7934ab0a Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 16 Aug 2022 01:36:27 -0400 Subject: [PATCH 215/427] virtio_net: Revert "virtio_net: set the default max ring size by find_vqs()" This reverts commit 762faee5a2678559d3dc09d95f8f2c54cd0466a7. This has been reported to trip up guests on GCP (Google Cloud). The reason is that virtio_find_vqs_ctx_size is broken on legacy devices. We can in theory fix virtio_find_vqs_ctx_size but in fact the patch itself has several other issues: - It treats unknown speed as < 10G - It leaves userspace no way to find out the ring size set by hypervisor - It tests speed when link is down - It ignores the virtio spec advice: Both \field{speed} and \field{duplex} can change, thus the driver is expected to re-read these values after receiving a configuration change notification. - It is not clear the performance impact has been tested properly Revert the patch for now. Reported-by: Andres Freund Link: https://lore.kernel.org/r/20220814212610.GA3690074%40roeck-us.net Link: https://lore.kernel.org/r/20220815070203.plwjx7b3cyugpdt7%40awork3.anarazel.de Link: https://lore.kernel.org/r/3df6bb82-1951-455d-a768-e9e1513eb667%40www.fastmail.com Link: https://lore.kernel.org/r/FCDC5DDE-3CDD-4B8A-916F-CA7D87B547CE%40anarazel.de Fixes: 762faee5a267 ("virtio_net: set the default max ring size by find_vqs()") Cc: Xuan Zhuo Cc: Jason Wang Signed-off-by: Michael S. Tsirkin Tested-by: Andres Freund Tested-by: Guenter Roeck Message-Id: <20220816053602.173815-2-mst@redhat.com> --- drivers/net/virtio_net.c | 42 ++++------------------------------------ 1 file changed, 4 insertions(+), 38 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index d934774e9733b..ece00b84e3a7a 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -3432,29 +3432,6 @@ static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqu (unsigned int)GOOD_PACKET_LEN); } -static void virtnet_config_sizes(struct virtnet_info *vi, u32 *sizes) -{ - u32 i, rx_size, tx_size; - - if (vi->speed == SPEED_UNKNOWN || vi->speed < SPEED_10000) { - rx_size = 1024; - tx_size = 1024; - - } else if (vi->speed < SPEED_40000) { - rx_size = 1024 * 4; - tx_size = 1024 * 4; - - } else { - rx_size = 1024 * 8; - tx_size = 1024 * 8; - } - - for (i = 0; i < vi->max_queue_pairs; i++) { - sizes[rxq2vq(i)] = rx_size; - sizes[txq2vq(i)] = tx_size; - } -} - static int virtnet_find_vqs(struct virtnet_info *vi) { vq_callback_t **callbacks; @@ -3462,7 +3439,6 @@ static int virtnet_find_vqs(struct virtnet_info *vi) int ret = -ENOMEM; int i, total_vqs; const char **names; - u32 *sizes; bool *ctx; /* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by @@ -3490,15 +3466,10 @@ static int virtnet_find_vqs(struct virtnet_info *vi) ctx = NULL; } - sizes = kmalloc_array(total_vqs, sizeof(*sizes), GFP_KERNEL); - if (!sizes) - goto err_sizes; - /* Parameters for control virtqueue, if any */ if (vi->has_cvq) { callbacks[total_vqs - 1] = NULL; names[total_vqs - 1] = "control"; - sizes[total_vqs - 1] = 64; } /* Allocate/initialize parameters for send/receive virtqueues */ @@ -3513,10 +3484,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi) ctx[rxq2vq(i)] = true; } - virtnet_config_sizes(vi, sizes); - - ret = virtio_find_vqs_ctx_size(vi->vdev, total_vqs, vqs, callbacks, - names, sizes, ctx, NULL); + ret = virtio_find_vqs_ctx(vi->vdev, total_vqs, vqs, callbacks, + names, ctx, NULL); if (ret) goto err_find; @@ -3536,8 +3505,6 @@ static int virtnet_find_vqs(struct virtnet_info *vi) err_find: - kfree(sizes); -err_sizes: kfree(ctx); err_ctx: kfree(names); @@ -3897,9 +3864,6 @@ static int virtnet_probe(struct virtio_device *vdev) vi->curr_queue_pairs = num_online_cpus(); vi->max_queue_pairs = max_queue_pairs; - virtnet_init_settings(dev); - virtnet_update_settings(vi); - /* Allocate/initialize the rx/tx queues, and invoke find_vqs */ err = init_vqs(vi); if (err) @@ -3912,6 +3876,8 @@ static int virtnet_probe(struct virtio_device *vdev) netif_set_real_num_tx_queues(dev, vi->curr_queue_pairs); netif_set_real_num_rx_queues(dev, vi->curr_queue_pairs); + virtnet_init_settings(dev); + if (virtio_has_feature(vdev, VIRTIO_NET_F_STANDBY)) { vi->failover = net_failover_create(vi->dev); if (IS_ERR(vi->failover)) { From 484b9fa4886bd9377969aad5e9ea17efda4ecda6 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 16 Aug 2022 01:36:31 -0400 Subject: [PATCH 216/427] virtio: Revert "virtio: add helper virtio_find_vqs_ctx_size()" This reverts commit fe3dc04e31aa51f91dc7f741a5f76cc4817eb5b4: the API is now unused and in fact can't be implemented on top of a legacy device. Fixes: fe3dc04e31aa ("virtio: add helper virtio_find_vqs_ctx_size()") Cc: "Xuan Zhuo" Signed-off-by: Michael S. Tsirkin Message-Id: <20220816053602.173815-3-mst@redhat.com> --- include/linux/virtio_config.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index 6adff09f7170a..888f7e96f0c72 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -241,18 +241,6 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs, ctx, desc); } -static inline -int virtio_find_vqs_ctx_size(struct virtio_device *vdev, u32 nvqs, - struct virtqueue *vqs[], - vq_callback_t *callbacks[], - const char * const names[], - u32 sizes[], - const bool *ctx, struct irq_affinity *desc) -{ - return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, sizes, - ctx, desc); -} - /** * virtio_synchronize_cbs - synchronize with virtqueue callbacks * @vdev: the device From c62f61b58f6e41cab9c07557213b61d71e6b221c Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 16 Aug 2022 01:36:35 -0400 Subject: [PATCH 217/427] virtio-mmio: Revert "virtio_mmio: support the arg sizes of find_vqs()" This reverts commit fbed86abba6e0472d98079790e58060e4332608a. The API is now unused, let's not carry dead code around. Fixes: fbed86abba6e ("virtio_mmio: support the arg sizes of find_vqs()") Signed-off-by: Michael S. Tsirkin Message-Id: <20220816053602.173815-4-mst@redhat.com> --- drivers/virtio/virtio_mmio.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index c492a57531c61..dfcecfd7aba11 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -360,7 +360,7 @@ static void vm_synchronize_cbs(struct virtio_device *vdev) static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned int index, void (*callback)(struct virtqueue *vq), - const char *name, u32 size, bool ctx) + const char *name, bool ctx) { struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); struct virtio_mmio_vq_info *info; @@ -395,11 +395,8 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned int in goto error_new_virtqueue; } - if (!size || size > num) - size = num; - /* Create the vring */ - vq = vring_create_virtqueue(index, size, VIRTIO_MMIO_VRING_ALIGN, vdev, + vq = vring_create_virtqueue(index, num, VIRTIO_MMIO_VRING_ALIGN, vdev, true, true, ctx, vm_notify, callback, name); if (!vq) { err = -ENOMEM; @@ -503,7 +500,6 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned int nvqs, } vqs[i] = vm_setup_vq(vdev, queue_idx++, callbacks[i], names[i], - sizes ? sizes[i] : 0, ctx ? ctx[i] : false); if (IS_ERR(vqs[i])) { vm_del_vqs(vdev); From 13aa8c6c37bd54eaf16f89e2e07019796fb9e681 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 16 Aug 2022 01:36:40 -0400 Subject: [PATCH 218/427] virtio_pci: Revert "virtio_pci: support the arg sizes of find_vqs()" This reverts commit cdb44806fca2d0ad29ca644cbf1505433902ee0c: the legacy path is wrong and in fact can not support the proposed API since for a legacy device we never communicate the vq size to the hypervisor. Reported-by: Andres Freund Fixes: cdb44806fca2 ("virtio_pci: support the arg sizes of find_vqs()") Signed-off-by: Michael S. Tsirkin Message-Id: <20220816053602.173815-5-mst@redhat.com> --- drivers/virtio/virtio_pci_common.c | 18 ++++++++---------- drivers/virtio/virtio_pci_common.h | 1 - drivers/virtio/virtio_pci_legacy.c | 6 +----- drivers/virtio/virtio_pci_modern.c | 10 +++------- 4 files changed, 12 insertions(+), 23 deletions(-) diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c index 00ad476a815d7..7ad734584823b 100644 --- a/drivers/virtio/virtio_pci_common.c +++ b/drivers/virtio/virtio_pci_common.c @@ -174,7 +174,6 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned int index, void (*callback)(struct virtqueue *vq), const char *name, - u32 size, bool ctx, u16 msix_vec) { @@ -187,7 +186,7 @@ static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned int in if (!info) return ERR_PTR(-ENOMEM); - vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, size, ctx, + vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, ctx, msix_vec); if (IS_ERR(vq)) goto out_info; @@ -284,7 +283,7 @@ void vp_del_vqs(struct virtio_device *vdev) static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned int nvqs, struct virtqueue *vqs[], vq_callback_t *callbacks[], - const char * const names[], u32 sizes[], bool per_vq_vectors, + const char * const names[], bool per_vq_vectors, const bool *ctx, struct irq_affinity *desc) { @@ -327,8 +326,8 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned int nvqs, else msix_vec = VP_MSIX_VQ_VECTOR; vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i], - sizes ? sizes[i] : 0, - ctx ? ctx[i] : false, msix_vec); + ctx ? ctx[i] : false, + msix_vec); if (IS_ERR(vqs[i])) { err = PTR_ERR(vqs[i]); goto error_find; @@ -358,7 +357,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned int nvqs, static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned int nvqs, struct virtqueue *vqs[], vq_callback_t *callbacks[], - const char * const names[], u32 sizes[], const bool *ctx) + const char * const names[], const bool *ctx) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); int i, err, queue_idx = 0; @@ -380,7 +379,6 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned int nvqs, continue; } vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i], - sizes ? sizes[i] : 0, ctx ? ctx[i] : false, VIRTIO_MSI_NO_VECTOR); if (IS_ERR(vqs[i])) { @@ -404,15 +402,15 @@ int vp_find_vqs(struct virtio_device *vdev, unsigned int nvqs, int err; /* Try MSI-X with one vector per queue. */ - err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, sizes, true, ctx, desc); + err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, true, ctx, desc); if (!err) return 0; /* Fallback: MSI-X with one vector for config, one shared for queues. */ - err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, sizes, false, ctx, desc); + err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, false, ctx, desc); if (!err) return 0; /* Finally fall back to regular interrupts. */ - return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names, sizes, ctx); + return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names, ctx); } const char *vp_bus_name(struct virtio_device *vdev) diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h index c0448378b6986..a5ff838b85a5c 100644 --- a/drivers/virtio/virtio_pci_common.h +++ b/drivers/virtio/virtio_pci_common.h @@ -80,7 +80,6 @@ struct virtio_pci_device { unsigned int idx, void (*callback)(struct virtqueue *vq), const char *name, - u32 size, bool ctx, u16 msix_vec); void (*del_vq)(struct virtio_pci_vq_info *info); diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c index d75e5c4e637fc..2257f1b3d8ae1 100644 --- a/drivers/virtio/virtio_pci_legacy.c +++ b/drivers/virtio/virtio_pci_legacy.c @@ -112,7 +112,6 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, unsigned int index, void (*callback)(struct virtqueue *vq), const char *name, - u32 size, bool ctx, u16 msix_vec) { @@ -126,13 +125,10 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, if (!num || vp_legacy_get_queue_enable(&vp_dev->ldev, index)) return ERR_PTR(-ENOENT); - if (!size || size > num) - size = num; - info->msix_vector = msix_vec; /* create the vring */ - vq = vring_create_virtqueue(index, size, + vq = vring_create_virtqueue(index, num, VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev, true, false, ctx, vp_notify, callback, name); diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index f7965c5dd36b0..be51ec8492526 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c @@ -293,7 +293,6 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, unsigned int index, void (*callback)(struct virtqueue *vq), const char *name, - u32 size, bool ctx, u16 msix_vec) { @@ -311,18 +310,15 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, if (!num || vp_modern_get_queue_enable(mdev, index)) return ERR_PTR(-ENOENT); - if (!size || size > num) - size = num; - - if (size & (size - 1)) { - dev_warn(&vp_dev->pci_dev->dev, "bad queue size %u", size); + if (num & (num - 1)) { + dev_warn(&vp_dev->pci_dev->dev, "bad queue size %u", num); return ERR_PTR(-EINVAL); } info->msix_vector = msix_vec; /* create the vring */ - vq = vring_create_virtqueue(index, size, + vq = vring_create_virtqueue(index, num, SMP_CACHE_BYTES, &vp_dev->vdev, true, true, ctx, vp_notify, callback, name); From 9e82eb574c5d90a175ae830916af8b8a1ccc31e7 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 16 Aug 2022 01:36:45 -0400 Subject: [PATCH 219/427] virtio_vdpa: Revert "virtio_vdpa: support the arg sizes of find_vqs()" This reverts commit 99e8927d8a4da8eb8a8a5904dc13a3156be8e7c0: proposed API isn't supported on all transports but no effort was made to address this. It might not be hard to fix if we want to: maybe just rename size to size_hint and make sure legacy transports ignore the hint. But it's not sure what the benefit is in any case, so let's drop it. Fixes: 99e8927d8a4d ("virtio_vdpa: support the arg sizes of find_vqs()") Signed-off-by: Michael S. Tsirkin Message-Id: <20220816053602.173815-6-mst@redhat.com> --- drivers/virtio/virtio_vdpa.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c index 9bc4d110b8000..832d2c5b1b19a 100644 --- a/drivers/virtio/virtio_vdpa.c +++ b/drivers/virtio/virtio_vdpa.c @@ -131,7 +131,7 @@ static irqreturn_t virtio_vdpa_virtqueue_cb(void *private) static struct virtqueue * virtio_vdpa_setup_vq(struct virtio_device *vdev, unsigned int index, void (*callback)(struct virtqueue *vq), - const char *name, u32 size, bool ctx) + const char *name, bool ctx) { struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev); struct vdpa_device *vdpa = vd_get_vdpa(vdev); @@ -168,17 +168,14 @@ virtio_vdpa_setup_vq(struct virtio_device *vdev, unsigned int index, goto error_new_virtqueue; } - if (!size || size > max_num) - size = max_num; - if (ops->get_vq_num_min) min_num = ops->get_vq_num_min(vdpa); - may_reduce_num = (size == min_num) ? false : true; + may_reduce_num = (max_num == min_num) ? false : true; /* Create the vring */ align = ops->get_vq_align(vdpa); - vq = vring_create_virtqueue(index, size, align, vdev, + vq = vring_create_virtqueue(index, max_num, align, vdev, true, may_reduce_num, ctx, virtio_vdpa_notify, callback, name); if (!vq) { @@ -288,9 +285,9 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned int nvqs, continue; } - vqs[i] = virtio_vdpa_setup_vq(vdev, queue_idx++, callbacks[i], - names[i], sizes ? sizes[i] : 0, - ctx ? ctx[i] : false); + vqs[i] = virtio_vdpa_setup_vq(vdev, queue_idx++, + callbacks[i], names[i], ctx ? + ctx[i] : false); if (IS_ERR(vqs[i])) { err = PTR_ERR(vqs[i]); goto err_setup_vq; From 9993a4f989c7ca5e227329b2878f65d05c9fc20f Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 16 Aug 2022 01:36:58 -0400 Subject: [PATCH 220/427] virtio: Revert "virtio: find_vqs() add arg sizes" This reverts commit a10fba0377145fccefea4dc4dd5915b7ed87e546: the proposed API isn't supported on all transports but no effort was made to address this. It might not be hard to fix if we want to: maybe just rename size to size_hint and make sure legacy transports ignore the hint. But it's not sure what the benefit is in any case, so let's drop it. Fixes: a10fba037714 ("virtio: find_vqs() add arg sizes") Signed-off-by: Michael S. Tsirkin Message-Id: <20220816053602.173815-8-mst@redhat.com> --- arch/um/drivers/virtio_uml.c | 2 +- drivers/platform/mellanox/mlxbf-tmfifo.c | 1 - drivers/remoteproc/remoteproc_virtio.c | 1 - drivers/s390/virtio/virtio_ccw.c | 1 - drivers/virtio/virtio_mmio.c | 1 - drivers/virtio/virtio_pci_common.c | 2 +- drivers/virtio/virtio_pci_common.h | 2 +- drivers/virtio/virtio_pci_modern.c | 7 ++----- drivers/virtio/virtio_vdpa.c | 1 - include/linux/virtio_config.h | 14 +++++--------- 10 files changed, 10 insertions(+), 22 deletions(-) diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c index 79e38afd4b91e..e719af8bdf56d 100644 --- a/arch/um/drivers/virtio_uml.c +++ b/arch/um/drivers/virtio_uml.c @@ -1011,7 +1011,7 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev, static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs, struct virtqueue *vqs[], vq_callback_t *callbacks[], - const char * const names[], u32 sizes[], const bool *ctx, + const char * const names[], const bool *ctx, struct irq_affinity *desc) { struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev); diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c index 8be13d416f485..1ae3c56b66b09 100644 --- a/drivers/platform/mellanox/mlxbf-tmfifo.c +++ b/drivers/platform/mellanox/mlxbf-tmfifo.c @@ -928,7 +928,6 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev, struct virtqueue *vqs[], vq_callback_t *callbacks[], const char * const names[], - u32 sizes[], const bool *ctx, struct irq_affinity *desc) { diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c index 81c4f57761092..0f7706e23eb91 100644 --- a/drivers/remoteproc/remoteproc_virtio.c +++ b/drivers/remoteproc/remoteproc_virtio.c @@ -158,7 +158,6 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs, struct virtqueue *vqs[], vq_callback_t *callbacks[], const char * const names[], - u32 sizes[], const bool * ctx, struct irq_affinity *desc) { diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c index 896896e326645..a10dbe632ef9b 100644 --- a/drivers/s390/virtio/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c @@ -637,7 +637,6 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs, struct virtqueue *vqs[], vq_callback_t *callbacks[], const char * const names[], - u32 sizes[], const bool *ctx, struct irq_affinity *desc) { diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index dfcecfd7aba11..3ff746e3f24aa 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -474,7 +474,6 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned int nvqs, struct virtqueue *vqs[], vq_callback_t *callbacks[], const char * const names[], - u32 sizes[], const bool *ctx, struct irq_affinity *desc) { diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c index 7ad734584823b..ad258a9d3b9f4 100644 --- a/drivers/virtio/virtio_pci_common.c +++ b/drivers/virtio/virtio_pci_common.c @@ -396,7 +396,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned int nvqs, /* the config->find_vqs() implementation */ int vp_find_vqs(struct virtio_device *vdev, unsigned int nvqs, struct virtqueue *vqs[], vq_callback_t *callbacks[], - const char * const names[], u32 sizes[], const bool *ctx, + const char * const names[], const bool *ctx, struct irq_affinity *desc) { int err; diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h index a5ff838b85a5c..23112d84218fb 100644 --- a/drivers/virtio/virtio_pci_common.h +++ b/drivers/virtio/virtio_pci_common.h @@ -110,7 +110,7 @@ void vp_del_vqs(struct virtio_device *vdev); /* the config->find_vqs() implementation */ int vp_find_vqs(struct virtio_device *vdev, unsigned int nvqs, struct virtqueue *vqs[], vq_callback_t *callbacks[], - const char * const names[], u32 sizes[], const bool *ctx, + const char * const names[], const bool *ctx, struct irq_affinity *desc); const char *vp_bus_name(struct virtio_device *vdev); diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index be51ec8492526..c3b9f27618497 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c @@ -347,15 +347,12 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned int nvqs, struct virtqueue *vqs[], vq_callback_t *callbacks[], - const char * const names[], - u32 sizes[], - const bool *ctx, + const char * const names[], const bool *ctx, struct irq_affinity *desc) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); struct virtqueue *vq; - int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, sizes, ctx, - desc); + int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc); if (rc) return rc; diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c index 832d2c5b1b19a..9670cc79371d8 100644 --- a/drivers/virtio/virtio_vdpa.c +++ b/drivers/virtio/virtio_vdpa.c @@ -269,7 +269,6 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned int nvqs, struct virtqueue *vqs[], vq_callback_t *callbacks[], const char * const names[], - u32 sizes[], const bool *ctx, struct irq_affinity *desc) { diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index 888f7e96f0c72..36ec7be1f480c 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -55,7 +55,6 @@ struct virtio_shm_region { * include a NULL entry for vqs that do not need a callback * names: array of virtqueue names (mainly for debugging) * include a NULL entry for vqs unused by driver - * sizes: array of virtqueue sizes * Returns 0 on success or error status * @del_vqs: free virtqueues found by find_vqs(). * @synchronize_cbs: synchronize with the virtqueue callbacks (optional) @@ -104,9 +103,7 @@ struct virtio_config_ops { void (*reset)(struct virtio_device *vdev); int (*find_vqs)(struct virtio_device *, unsigned nvqs, struct virtqueue *vqs[], vq_callback_t *callbacks[], - const char * const names[], - u32 sizes[], - const bool *ctx, + const char * const names[], const bool *ctx, struct irq_affinity *desc); void (*del_vqs)(struct virtio_device *); void (*synchronize_cbs)(struct virtio_device *); @@ -215,7 +212,7 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev, const char *names[] = { n }; struct virtqueue *vq; int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL, - NULL, NULL); + NULL); if (err < 0) return ERR_PTR(err); return vq; @@ -227,8 +224,7 @@ int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs, const char * const names[], struct irq_affinity *desc) { - return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, - NULL, desc); + return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc); } static inline @@ -237,8 +233,8 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs, const char * const names[], const bool *ctx, struct irq_affinity *desc) { - return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, - ctx, desc); + return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, + desc); } /** From 5c669c4a4c6aa0489848093c93b8029f5c5c75ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Ca=C3=B1uelo?= Date: Wed, 10 Aug 2022 11:40:03 +0200 Subject: [PATCH 221/427] virtio: kerneldocs fixes and enhancements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix variable names in some kerneldocs, naming in others. Add kerneldocs for struct vring_desc and vring_interrupt. Signed-off-by: Ricardo Cañuelo Message-Id: <20220810094004.1250-2-ricardo.canuelo@collabora.com> Signed-off-by: Michael S. Tsirkin Reviewed-by: Cornelia Huck --- drivers/virtio/virtio_ring.c | 8 ++++++++ include/linux/virtio.h | 6 +++--- include/linux/virtio_config.h | 6 +++--- include/uapi/linux/virtio_ring.h | 16 +++++++++++----- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index d66c8e6d0ef31..4620e9d79dde8 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -2426,6 +2426,14 @@ static inline bool more_used(const struct vring_virtqueue *vq) return vq->packed_ring ? more_used_packed(vq) : more_used_split(vq); } +/** + * vring_interrupt - notify a virtqueue on an interrupt + * @irq: the IRQ number (ignored) + * @_vq: the struct virtqueue to notify + * + * Calls the callback function of @_vq to process the virtqueue + * notification. + */ irqreturn_t vring_interrupt(int irq, void *_vq) { struct vring_virtqueue *vq = to_vvq(_vq); diff --git a/include/linux/virtio.h b/include/linux/virtio.h index a3f73bb6733e8..dcab9c7e87843 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -11,7 +11,7 @@ #include /** - * virtqueue - a queue to register buffers for sending or receiving. + * struct virtqueue - a queue to register buffers for sending or receiving. * @list: the chain of virtqueues for this device * @callback: the function to call when buffers are consumed (can be NULL). * @name: the name of this virtqueue (mainly for debugging) @@ -97,7 +97,7 @@ int virtqueue_resize(struct virtqueue *vq, u32 num, void (*recycle)(struct virtqueue *vq, void *buf)); /** - * virtio_device - representation of a device using virtio + * struct virtio_device - representation of a device using virtio * @index: unique position on the virtio bus * @failed: saved value for VIRTIO_CONFIG_S_FAILED bit (for restore) * @config_enabled: configuration change reporting enabled @@ -156,7 +156,7 @@ size_t virtio_max_dma_size(struct virtio_device *vdev); list_for_each_entry(vq, &vdev->vqs, list) /** - * virtio_driver - operations for a virtio I/O driver + * struct virtio_driver - operations for a virtio I/O driver * @driver: underlying device driver (populate name and owner). * @id_table: the ids serviced by this driver. * @feature_table: an array of feature numbers supported by this driver. diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index 36ec7be1f480c..4b517649cfe84 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -239,7 +239,7 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs, /** * virtio_synchronize_cbs - synchronize with virtqueue callbacks - * @vdev: the device + * @dev: the virtio device */ static inline void virtio_synchronize_cbs(struct virtio_device *dev) @@ -258,7 +258,7 @@ void virtio_synchronize_cbs(struct virtio_device *dev) /** * virtio_device_ready - enable vq use in probe function - * @vdev: the device + * @dev: the virtio device * * Driver must call this to use vqs in the probe function. * @@ -306,7 +306,7 @@ const char *virtio_bus_name(struct virtio_device *vdev) /** * virtqueue_set_affinity - setting affinity for a virtqueue * @vq: the virtqueue - * @cpu: the cpu no. + * @cpu_mask: the cpu mask * * Pay attention the function are best-effort: the affinity hint may not be set * due to config support, irq type and sharing. diff --git a/include/uapi/linux/virtio_ring.h b/include/uapi/linux/virtio_ring.h index 476d3e5c0fe70..f8c20d3de8da1 100644 --- a/include/uapi/linux/virtio_ring.h +++ b/include/uapi/linux/virtio_ring.h @@ -93,15 +93,21 @@ #define VRING_USED_ALIGN_SIZE 4 #define VRING_DESC_ALIGN_SIZE 16 -/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */ +/** + * struct vring_desc - Virtio ring descriptors, + * 16 bytes long. These can chain together via @next. + * + * @addr: buffer address (guest-physical) + * @len: buffer length + * @flags: descriptor flags + * @next: index of the next descriptor in the chain, + * if the VRING_DESC_F_NEXT flag is set. We chain unused + * descriptors via this, too. + */ struct vring_desc { - /* Address (guest-physical). */ __virtio64 addr; - /* Length. */ __virtio32 len; - /* The flags as indicated above. */ __virtio16 flags; - /* We chain unused descriptors via this, too */ __virtio16 next; }; From 966120b51a245c9ff5857c5b169310c248e0ae87 Mon Sep 17 00:00:00 2001 From: ZiyangZhang Date: Mon, 15 Aug 2022 10:36:31 +0800 Subject: [PATCH 222/427] ublk_drv: check ubq_daemon_is_dying() in __ublk_rq_task_work() Replace direct check on PF_EXITING in __ublk_rq_task_work() by the existing wrapper. Also inline ubq_daemon_is_dying(). Reviewed-by: Ming Lei Signed-off-by: ZiyangZhang Link: https://lore.kernel.org/r/20220815023633.259825-2-ZiyangZhang@linux.alibaba.com Signed-off-by: Jens Axboe --- drivers/block/ublk_drv.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 5d8c7234639cc..17896172b0fee 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -555,7 +555,7 @@ static inline struct ublk_uring_cmd_pdu *ublk_get_uring_cmd_pdu( return (struct ublk_uring_cmd_pdu *)&ioucmd->pdu; } -static bool ubq_daemon_is_dying(struct ublk_queue *ubq) +static inline bool ubq_daemon_is_dying(struct ublk_queue *ubq) { return ubq->ubq_daemon->flags & PF_EXITING; } @@ -644,8 +644,7 @@ static inline void __ublk_rq_task_work(struct request *req) struct ublk_device *ub = ubq->dev; int tag = req->tag; struct ublk_io *io = &ubq->ios[tag]; - bool task_exiting = current != ubq->ubq_daemon || - (current->flags & PF_EXITING); + bool task_exiting = current != ubq->ubq_daemon || ubq_daemon_is_dying(ubq); unsigned int mapped_bytes; pr_devel("%s: complete: op %d, qid %d tag %d io_flags %x addr %llx\n", From bb24174754afc5a7d185ca5406dcfbc608cdf157 Mon Sep 17 00:00:00 2001 From: ZiyangZhang Date: Mon, 15 Aug 2022 10:36:32 +0800 Subject: [PATCH 223/427] ublk_drv: update comment for __ublk_fail_req() Since __ublk_rq_task_work always fails requests immediately during exiting, __ublk_fail_req() is only called from abort context during exiting. So lock is unnecessary. Signed-off-by: ZiyangZhang Reviewed-by: Ming Lei Link: https://lore.kernel.org/r/20220815023633.259825-3-ZiyangZhang@linux.alibaba.com Signed-off-by: Jens Axboe --- drivers/block/ublk_drv.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 17896172b0fee..685a43b7ae6e7 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -605,8 +605,9 @@ static void ublk_complete_rq(struct request *req) } /* - * __ublk_fail_req() may be called from abort context or ->ubq_daemon - * context during exiting, so lock is required. + * Since __ublk_rq_task_work always fails requests immediately during + * exiting, __ublk_fail_req() is only called from abort context during + * exiting. So lock is unnecessary. * * Also aborting may not be started yet, keep in mind that one failed * request may be issued by block layer again. From e6190dd0031d335c22586d34ef898301ed20f230 Mon Sep 17 00:00:00 2001 From: ZiyangZhang Date: Mon, 15 Aug 2022 10:36:33 +0800 Subject: [PATCH 224/427] ublk_drv: do not add a re-issued request aborted previously to ioucmd's task_work In ublk_queue_rq(), Assume current request is a re-issued request aborted previously in monitor_work because the ubq_daemon(ioucmd's task) is PF_EXITING. For this request, we cannot call io_uring_cmd_complete_in_task() anymore because at that moment io_uring context may be freed in case that no inflight ioucmd exists. Otherwise, we may cause null-deref in ctx->fallback_work. Add a check on UBLK_IO_FLAG_ABORTED to prevent the above situation. This check is safe and makes sense. Note: monitor_work sets UBLK_IO_FLAG_ABORTED and ends this request (releasing the tag). Then the request is restarted(allocating the tag) and we are here. Since releasing/allocating a tag implies smp_mb(), finding UBLK_IO_FLAG_ABORTED guarantees that here is a re-issued request aborted previously. Suggested-by: Ming Lei Signed-off-by: ZiyangZhang Reviewed-by: Ming Lei Link: https://lore.kernel.org/r/20220815023633.259825-4-ZiyangZhang@linux.alibaba.com Signed-off-by: Jens Axboe --- drivers/block/ublk_drv.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 685a43b7ae6e7..6a4a94b4cdf42 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -756,9 +756,25 @@ static blk_status_t ublk_queue_rq(struct blk_mq_hw_ctx *hctx, if (task_work_add(ubq->ubq_daemon, &data->work, notify_mode)) goto fail; } else { - struct io_uring_cmd *cmd = ubq->ios[rq->tag].cmd; + struct ublk_io *io = &ubq->ios[rq->tag]; + struct io_uring_cmd *cmd = io->cmd; struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd); + /* + * If the check pass, we know that this is a re-issued request aborted + * previously in monitor_work because the ubq_daemon(cmd's task) is + * PF_EXITING. We cannot call io_uring_cmd_complete_in_task() anymore + * because this ioucmd's io_uring context may be freed now if no inflight + * ioucmd exists. Otherwise we may cause null-deref in ctx->fallback_work. + * + * Note: monitor_work sets UBLK_IO_FLAG_ABORTED and ends this request(releasing + * the tag). Then the request is re-started(allocating the tag) and we are here. + * Since releasing/allocating a tag implies smp_mb(), finding UBLK_IO_FLAG_ABORTED + * guarantees that here is a re-issued request aborted previously. + */ + if ((io->flags & UBLK_IO_FLAG_ABORTED)) + goto fail; + pdu->req = rq; io_uring_cmd_complete_in_task(cmd, ublk_rq_task_work_cb); } From d6d142cb7f79bec6051c5ecf744b7a5309c5a0ee Mon Sep 17 00:00:00 2001 From: Sergey Gorenko Date: Fri, 5 Aug 2022 09:01:35 +0300 Subject: [PATCH 225/427] IB/iser: Fix login with authentication The iSER Initiator uses two types of receive buffers: - one big login buffer posted by iser_post_recvl(); - several small message buffers posted by iser_post_recvm(). The login buffer is used at the login phase and full feature phase in the discovery session. It may take a few requests and responses to complete the login phase. The message buffers are only used in the normal operational session at the full feature phase. After the commit referred in the fixes line, the login operation fails if the authentication is enabled. That happens because the Initiator posts a small receive buffer after the first response from Target. So, the next send operation fails because Target's second response does not fit into the small receive buffer. This commit adds additional checks to prevent posting small receive buffers until the full feature phase. Fixes: 39b169ea0d36 ("IB/iser: Fix RNR errors") Link: https://lore.kernel.org/r/20220805060135.18493-1-sergeygo@nvidia.com Signed-off-by: Sergey Gorenko Reviewed-by: Max Gurtovoy Signed-off-by: Leon Romanovsky --- drivers/infiniband/ulp/iser/iser_initiator.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c index bd5f3b5e17278..7b83f48f60c5e 100644 --- a/drivers/infiniband/ulp/iser/iser_initiator.c +++ b/drivers/infiniband/ulp/iser/iser_initiator.c @@ -537,6 +537,7 @@ void iser_login_rsp(struct ib_cq *cq, struct ib_wc *wc) struct iscsi_hdr *hdr; char *data; int length; + bool full_feature_phase; if (unlikely(wc->status != IB_WC_SUCCESS)) { iser_err_comp(wc, "login_rsp"); @@ -550,6 +551,9 @@ void iser_login_rsp(struct ib_cq *cq, struct ib_wc *wc) hdr = desc->rsp + sizeof(struct iser_ctrl); data = desc->rsp + ISER_HEADERS_LEN; length = wc->byte_len - ISER_HEADERS_LEN; + full_feature_phase = ((hdr->flags & ISCSI_FULL_FEATURE_PHASE) == + ISCSI_FULL_FEATURE_PHASE) && + (hdr->flags & ISCSI_FLAG_CMD_FINAL); iser_dbg("op 0x%x itt 0x%x dlen %d\n", hdr->opcode, hdr->itt, length); @@ -560,7 +564,8 @@ void iser_login_rsp(struct ib_cq *cq, struct ib_wc *wc) desc->rsp_dma, ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE); - if (iser_conn->iscsi_conn->session->discovery_sess) + if (!full_feature_phase || + iser_conn->iscsi_conn->session->discovery_sess) return; /* Post the first RX buffer that is skipped in iser_post_rx_bufs() */ From 4d4c4bff4f8ed79d95e0592aed6c6144d558a236 Mon Sep 17 00:00:00 2001 From: Stefan Binding Date: Mon, 15 Aug 2022 17:29:06 +0100 Subject: [PATCH 226/427] ALSA: hda: cs35l41: Clarify support for CSC3551 without _DSD Properties For devices which use HID CSC3551, correct ACPI _DSD properties are required to be able support those systems. Add error message to clarify this. Signed-off-by: Stefan Binding Link: https://lore.kernel.org/r/20220815162906.463108-1-sbinding@opensource.cirrus.com Signed-off-by: Takashi Iwai --- sound/pci/hda/cs35l41_hda.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 129bffb431c22..15e2a0009080e 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -1163,6 +1163,11 @@ static int cs35l41_no_acpi_dsd(struct cs35l41_hda *cs35l41, struct device *physd hw_cfg->gpio1.func = CS35l41_VSPK_SWITCH; hw_cfg->gpio1.valid = true; } else { + /* + * Note: CLSA010(0/1) are special cases which use a slightly different design. + * All other HIDs e.g. CSC3551 require valid ACPI _DSD properties to be supported. + */ + dev_err(cs35l41->dev, "Error: ACPI _DSD Properties are missing for HID %s.\n", hid); hw_cfg->valid = false; hw_cfg->gpio1.valid = false; hw_cfg->gpio2.valid = false; From 4b83c3caf289b80acecc539c79f10a6937cc42dd Mon Sep 17 00:00:00 2001 From: Mark Bloch Date: Mon, 8 Aug 2022 10:48:06 +0300 Subject: [PATCH 227/427] RDMA/mlx5: Use the proper number of ports The cited commit allowed the driver to operate over HCAs that have 4 physical ports. Use the number of ports of the RDMA device in the for loop instead of using the struct size. Fixes: 4cd14d44b11d ("net/mlx5: Support devices with more than 2 ports") Link: https://lore.kernel.org/r/a54a56c2ede16044a29d119209b35189c662ac72.1659944855.git.leonro@nvidia.com Signed-off-by: Mark Bloch Signed-off-by: Leon Romanovsky --- drivers/infiniband/hw/mlx5/main.c | 34 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index a174a0eee8dca..fc94a1b25485d 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -2738,26 +2738,24 @@ static int set_has_smi_cap(struct mlx5_ib_dev *dev) int err; int port; - for (port = 1; port <= ARRAY_SIZE(dev->port_caps); port++) { - dev->port_caps[port - 1].has_smi = false; - if (MLX5_CAP_GEN(dev->mdev, port_type) == - MLX5_CAP_PORT_TYPE_IB) { - if (MLX5_CAP_GEN(dev->mdev, ib_virt)) { - err = mlx5_query_hca_vport_context(dev->mdev, 0, - port, 0, - &vport_ctx); - if (err) { - mlx5_ib_err(dev, "query_hca_vport_context for port=%d failed %d\n", - port, err); - return err; - } - dev->port_caps[port - 1].has_smi = - vport_ctx.has_smi; - } else { - dev->port_caps[port - 1].has_smi = true; - } + if (MLX5_CAP_GEN(dev->mdev, port_type) != MLX5_CAP_PORT_TYPE_IB) + return 0; + + for (port = 1; port <= dev->num_ports; port++) { + if (!MLX5_CAP_GEN(dev->mdev, ib_virt)) { + dev->port_caps[port - 1].has_smi = true; + continue; } + err = mlx5_query_hca_vport_context(dev->mdev, 0, port, 0, + &vport_ctx); + if (err) { + mlx5_ib_err(dev, "query_hca_vport_context for port=%d failed %d\n", + port, err); + return err; + } + dev->port_caps[port - 1].has_smi = vport_ctx.has_smi; } + return 0; } From ef0162298abf46b881e4a4d0c604d1a066228647 Mon Sep 17 00:00:00 2001 From: Potnuri Bharat Teja Date: Wed, 10 Aug 2022 00:11:18 +0530 Subject: [PATCH 228/427] RDMA/cxgb4: fix accept failure due to increased cpl_t5_pass_accept_rpl size Commit 'c2ed5611afd7' has increased the cpl_t5_pass_accept_rpl{} structure size by 8B to avoid roundup. cpl_t5_pass_accept_rpl{} is a HW specific structure and increasing its size will lead to unwanted adapter errors. Current commit reverts the cpl_t5_pass_accept_rpl{} back to its original and allocates zeroed skb buffer there by avoiding the memset for iss field. Reorder code to minimize chip type checks. Fixes: c2ed5611afd7 ("iw_cxgb4: Use memset_startat() for cpl_t5_pass_accept_rpl") Link: https://lore.kernel.org/r/20220809184118.2029-1-rahul.lakkireddy@chelsio.com Signed-off-by: Potnuri Bharat Teja Signed-off-by: Rahul Lakkireddy Reviewed-by: Kees Cook Signed-off-by: Leon Romanovsky --- drivers/infiniband/hw/cxgb4/cm.c | 25 ++++++++------------- drivers/net/ethernet/chelsio/cxgb4/t4_msg.h | 2 +- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index c16017f6e8db2..14392c942f492 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -2468,31 +2468,24 @@ static int accept_cr(struct c4iw_ep *ep, struct sk_buff *skb, opt2 |= CCTRL_ECN_V(1); } - skb_get(skb); - rpl = cplhdr(skb); if (!is_t4(adapter_type)) { - BUILD_BUG_ON(sizeof(*rpl5) != roundup(sizeof(*rpl5), 16)); - skb_trim(skb, sizeof(*rpl5)); - rpl5 = (void *)rpl; - INIT_TP_WR(rpl5, ep->hwtid); - } else { - skb_trim(skb, sizeof(*rpl)); - INIT_TP_WR(rpl, ep->hwtid); - } - OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL, - ep->hwtid)); - - if (CHELSIO_CHIP_VERSION(adapter_type) > CHELSIO_T4) { u32 isn = (prandom_u32() & ~7UL) - 1; + + skb = get_skb(skb, roundup(sizeof(*rpl5), 16), GFP_KERNEL); + rpl5 = __skb_put_zero(skb, roundup(sizeof(*rpl5), 16)); + rpl = (void *)rpl5; + INIT_TP_WR_CPL(rpl5, CPL_PASS_ACCEPT_RPL, ep->hwtid); opt2 |= T5_OPT_2_VALID_F; opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE); opt2 |= T5_ISS_F; - rpl5 = (void *)rpl; - memset_after(rpl5, 0, iss); if (peer2peer) isn += 4; rpl5->iss = cpu_to_be32(isn); pr_debug("iss %u\n", be32_to_cpu(rpl5->iss)); + } else { + skb = get_skb(skb, sizeof(*rpl), GFP_KERNEL); + rpl = __skb_put_zero(skb, sizeof(*rpl)); + INIT_TP_WR_CPL(rpl, CPL_PASS_ACCEPT_RPL, ep->hwtid); } rpl->opt0 = cpu_to_be64(opt0); diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h index 26433a62d7f0d..fed5f93bf620a 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h @@ -497,7 +497,7 @@ struct cpl_t5_pass_accept_rpl { __be32 opt2; __be64 opt0; __be32 iss; - __be32 rsvd[3]; + __be32 rsvd; }; struct cpl_act_open_req { From 70cfdd0365acf550350d8949096c0b34a96b6b48 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 16 Aug 2022 15:21:32 +0200 Subject: [PATCH 229/427] ALSA: hda/realtek: Add quirk for Lenovo Yoga7 14IAL7 Lenovo Yoga7 14IAL7 requires the same quirk as Lenovo Yoga9 14IAP7 for fixing the bass speaker problems. Reported-by: Pascal Gross Cc: Link: https://lore.kernel.org/r/N9_CjBz--3-2@tutanota.com Link: https://lore.kernel.org/r/20220816132132.15520-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f544761eb11b7..b42496c01c437 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9492,6 +9492,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x3852, "Lenovo Yoga 7 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6), + SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI), From 1374901b850c8f2ff1ee0e62ffafbc4030572fc6 Mon Sep 17 00:00:00 2001 From: Cheng Xu Date: Wed, 10 Aug 2022 09:43:20 +0800 Subject: [PATCH 230/427] RDMA/erdma: Using the key in FMR WR instead of MR structure RDMA driver should get the MR key from FMR WR, not the MR structure passed in. Fixes: 155055771704 ("RDMA/erdma: Add verbs implementation") Link: https://lore.kernel.org/r/20220810014320.88026-2-chengyou@linux.alibaba.com Signed-off-by: Cheng Xu Signed-off-by: Leon Romanovsky --- drivers/infiniband/hw/erdma/erdma_qp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/erdma/erdma_qp.c b/drivers/infiniband/hw/erdma/erdma_qp.c index 72f08171a28a7..bc3ec22a62c57 100644 --- a/drivers/infiniband/hw/erdma/erdma_qp.c +++ b/drivers/infiniband/hw/erdma/erdma_qp.c @@ -407,7 +407,7 @@ static int erdma_push_one_sqe(struct erdma_qp *qp, u16 *pi, to_erdma_access_flags(reg_wr(send_wr)->access); regmr_sge->addr = cpu_to_le64(mr->ibmr.iova); regmr_sge->length = cpu_to_le32(mr->ibmr.length); - regmr_sge->stag = cpu_to_le32(mr->ibmr.lkey); + regmr_sge->stag = cpu_to_le32(reg_wr(send_wr)->key); attrs = FIELD_PREP(ERDMA_SQE_MR_MODE_MASK, 0) | FIELD_PREP(ERDMA_SQE_MR_ACCESS_MASK, mr->access) | FIELD_PREP(ERDMA_SQE_MR_MTT_CNT_MASK, From 6cd8351c4ede5b3335c7eb13d009c3456e90b6df Mon Sep 17 00:00:00 2001 From: Cheng Xu Date: Wed, 10 Aug 2022 09:43:19 +0800 Subject: [PATCH 231/427] RDMA/erdma: Correct the max_qp and max_cq capacities of the device QP0 in HW is used for CMDQ, and the rest is for RDMA QPs. So the actual max_qp capacity reported to core should be max_qp (reported by HW) - 1. So does max_cq. Fixes: 155055771704 ("RDMA/erdma: Add verbs implementation") Link: https://lore.kernel.org/all/20220810014320.88026-1-chengyou@linux.alibaba.com Signed-off-by: Cheng Xu Signed-off-by: Leon Romanovsky --- drivers/infiniband/hw/erdma/erdma_verbs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c index a7a3d42e20167..699bd3f59cd34 100644 --- a/drivers/infiniband/hw/erdma/erdma_verbs.c +++ b/drivers/infiniband/hw/erdma/erdma_verbs.c @@ -280,7 +280,7 @@ int erdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr, attr->vendor_id = PCI_VENDOR_ID_ALIBABA; attr->vendor_part_id = dev->pdev->device; attr->hw_ver = dev->pdev->revision; - attr->max_qp = dev->attrs.max_qp; + attr->max_qp = dev->attrs.max_qp - 1; attr->max_qp_wr = min(dev->attrs.max_send_wr, dev->attrs.max_recv_wr); attr->max_qp_rd_atom = dev->attrs.max_ord; attr->max_qp_init_rd_atom = dev->attrs.max_ird; @@ -291,7 +291,7 @@ int erdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr, attr->max_send_sge = dev->attrs.max_send_sge; attr->max_recv_sge = dev->attrs.max_recv_sge; attr->max_sge_rd = dev->attrs.max_sge_rd; - attr->max_cq = dev->attrs.max_cq; + attr->max_cq = dev->attrs.max_cq - 1; attr->max_cqe = dev->attrs.max_cqe; attr->max_mr = dev->attrs.max_mr; attr->max_pd = dev->attrs.max_pd; From b16de8b9e7d1aae169d059c3a0dd9a881a3c0d1d Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Tue, 16 Aug 2022 11:03:20 -0300 Subject: [PATCH 232/427] RDMA: Handle the return code from dma_resv_wait_timeout() properly ib_umem_dmabuf_map_pages() returns 0 on success and -ERRNO on failure. dma_resv_wait_timeout() uses a different scheme: * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or * greater than zero on success. This results in ib_umem_dmabuf_map_pages() being non-functional as a positive return will be understood to be an error by drivers. Fixes: f30bceab16d1 ("RDMA: use dma_resv_wait() instead of extracting the fence") Cc: stable@kernel.org Link: https://lore.kernel.org/r/0-v1-d8f4e1fa84c8+17-rdma_dmabuf_fix_jgg@nvidia.com Tested-by: Maor Gottlieb Signed-off-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky --- drivers/infiniband/core/umem_dmabuf.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c index fce80a4a5147c..04c04e6d24c35 100644 --- a/drivers/infiniband/core/umem_dmabuf.c +++ b/drivers/infiniband/core/umem_dmabuf.c @@ -18,6 +18,7 @@ int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf) struct scatterlist *sg; unsigned long start, end, cur = 0; unsigned int nmap = 0; + long ret; int i; dma_resv_assert_held(umem_dmabuf->attach->dmabuf->resv); @@ -67,9 +68,14 @@ int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf) * may be not up-to-date. Wait for the exporter to finish * the migration. */ - return dma_resv_wait_timeout(umem_dmabuf->attach->dmabuf->resv, + ret = dma_resv_wait_timeout(umem_dmabuf->attach->dmabuf->resv, DMA_RESV_USAGE_KERNEL, false, MAX_SCHEDULE_TIMEOUT); + if (ret < 0) + return ret; + if (ret == 0) + return -ETIMEDOUT; + return 0; } EXPORT_SYMBOL(ib_umem_dmabuf_map_pages); From 2c6482091f01ba104cf8ee549aa5c717e80d43ea Mon Sep 17 00:00:00 2001 From: Przemyslaw Patynowski Date: Wed, 27 Jul 2022 11:19:40 +0200 Subject: [PATCH 233/427] i40e: Fix tunnel checksum offload with fragmented traffic Fix checksum offload on VXLAN tunnels. In case, when mpls protocol is not used, set l4 header to transport header of skb. This fixes case, when user tries to offload checksums of VXLAN tunneled traffic. Steps for reproduction (requires link partner with tunnels): ip l s enp130s0f0 up ip a f enp130s0f0 ip a a 10.10.110.2/24 dev enp130s0f0 ip l s enp130s0f0 mtu 1600 ip link add vxlan12_sut type vxlan id 12 group 238.168.100.100 dev \ enp130s0f0 dstport 4789 ip l s vxlan12_sut up ip a a 20.10.110.2/24 dev vxlan12_sut iperf3 -c 20.10.110.1 #should connect Without this patch, TX descriptor was using wrong data, due to l4 header pointing wrong address. NIC would then drop those packets internally, due to incorrect TX descriptor data, which increased GLV_TEPC register. Fixes: b4fb2d33514a ("i40e: Add support for MPLS + TSO") Signed-off-by: Przemyslaw Patynowski Signed-off-by: Mateusz Palczewski Tested-by: Marek Szlosek Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index f6ba97a0166eb..d4226161a3efc 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -3203,11 +3203,13 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, protocol = vlan_get_protocol(skb); - if (eth_p_mpls(protocol)) + if (eth_p_mpls(protocol)) { ip.hdr = skb_inner_network_header(skb); - else + l4.hdr = skb_checksum_start(skb); + } else { ip.hdr = skb_network_header(skb); - l4.hdr = skb_checksum_start(skb); + l4.hdr = skb_transport_header(skb); + } /* set the tx_flags to indicate the IP protocol type. this is * required so that checksum header computation below is accurate. From 57c942bc3bef0970f0b21f8e0998e76a900ea80d Mon Sep 17 00:00:00 2001 From: Alan Brady Date: Tue, 2 Aug 2022 10:19:17 +0200 Subject: [PATCH 234/427] i40e: Fix to stop tx_timeout recovery if GLOBR fails When a tx_timeout fires, the PF attempts to recover by incrementally resetting. First we try a PFR, then CORER and finally a GLOBR. If the GLOBR fails, then we keep hitting the tx_timeout and incrementing the recovery level and issuing dmesgs, which is both annoying to the user and accomplishes nothing. If the GLOBR fails, then we're pretty much totally hosed, and there's not much else we can do to recover, so this makes it such that we just kill the VSI and stop hitting the tx_timeout in such a case. Fixes: 41c445ff0f48 ("i40e: main driver core") Signed-off-by: Alan Brady Signed-off-by: Mateusz Palczewski Tested-by: Gurucharan (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index b36bf9c3e1e49..9f1d5de7bf161 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -384,7 +384,9 @@ static void i40e_tx_timeout(struct net_device *netdev, unsigned int txqueue) set_bit(__I40E_GLOBAL_RESET_REQUESTED, pf->state); break; default: - netdev_err(netdev, "tx_timeout recovery unsuccessful\n"); + netdev_err(netdev, "tx_timeout recovery unsuccessful, device is in non-recoverable state.\n"); + set_bit(__I40E_DOWN_REQUESTED, pf->state); + set_bit(__I40E_VSI_DOWN_REQUESTED, vsi->state); break; } From 415d832497098030241605c52ea83d4e2cfa7879 Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Tue, 16 Aug 2022 16:03:11 +0900 Subject: [PATCH 235/427] locking/atomic: Make test_and_*_bit() ordered on failure These operations are documented as always ordered in include/asm-generic/bitops/instrumented-atomic.h, and producer-consumer type use cases where one side needs to ensure a flag is left pending after some shared data was updated rely on this ordering, even in the failure case. This is the case with the workqueue code, which currently suffers from a reproducible ordering violation on Apple M1 platforms (which are notoriously out-of-order) that ends up causing the TTY layer to fail to deliver data to userspace properly under the right conditions. This change fixes that bug. Change the documentation to restrict the "no order on failure" story to the _lock() variant (for which it makes sense), and remove the early-exit from the generic implementation, which is what causes the missing barrier semantics in that case. Without this, the remaining atomic op is fully ordered (including on ARM64 LSE, as of recent versions of the architecture spec). Suggested-by: Linus Torvalds Cc: stable@vger.kernel.org Fixes: e986a0d6cb36 ("locking/atomics, asm-generic/bitops/atomic.h: Rewrite using atomic_*() APIs") Fixes: 61e02392d3c7 ("locking/atomic/bitops: Document and clarify ordering semantics for failed test_and_{}_bit()") Signed-off-by: Hector Martin Acked-by: Will Deacon Reviewed-by: Arnd Bergmann Signed-off-by: Linus Torvalds --- Documentation/atomic_bitops.txt | 2 +- include/asm-generic/bitops/atomic.h | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Documentation/atomic_bitops.txt b/Documentation/atomic_bitops.txt index 093cdaefdb373..d8b101c97031b 100644 --- a/Documentation/atomic_bitops.txt +++ b/Documentation/atomic_bitops.txt @@ -59,7 +59,7 @@ Like with atomic_t, the rule of thumb is: - RMW operations that have a return value are fully ordered. - RMW operations that are conditional are unordered on FAILURE, - otherwise the above rules apply. In the case of test_and_{}_bit() operations, + otherwise the above rules apply. In the case of test_and_set_bit_lock(), if the bit in memory is unchanged by the operation then it is deemed to have failed. diff --git a/include/asm-generic/bitops/atomic.h b/include/asm-generic/bitops/atomic.h index 3096f086b5a32..71ab4ba9c25d1 100644 --- a/include/asm-generic/bitops/atomic.h +++ b/include/asm-generic/bitops/atomic.h @@ -39,9 +39,6 @@ arch_test_and_set_bit(unsigned int nr, volatile unsigned long *p) unsigned long mask = BIT_MASK(nr); p += BIT_WORD(nr); - if (READ_ONCE(*p) & mask) - return 1; - old = arch_atomic_long_fetch_or(mask, (atomic_long_t *)p); return !!(old & mask); } @@ -53,9 +50,6 @@ arch_test_and_clear_bit(unsigned int nr, volatile unsigned long *p) unsigned long mask = BIT_MASK(nr); p += BIT_WORD(nr); - if (!(READ_ONCE(*p) & mask)) - return 0; - old = arch_atomic_long_fetch_andnot(mask, (atomic_long_t *)p); return !!(old & mask); } From c4e34dd99f2e3fdfc63584078ce0fed20f4e7386 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 14 Aug 2022 14:16:13 -0700 Subject: [PATCH 236/427] x86: simplify load_unaligned_zeropad() implementation The exception for the "unaligned access at the end of the page, next page not mapped" never happens, but the fixup code ends up causing trouble for compilers to optimize well. clang in particular ends up seeing it being in the middle of a loop, and tries desperately to optimize the exception fixup code that is never really reached. The simple solution is to just move all the fixups into the exception handler itself, which moves it all out of the hot case code, and means that the compiler never sees it or needs to worry about it. Acked-by: Peter Zijlstra Signed-off-by: Linus Torvalds --- arch/x86/include/asm/extable_fixup_types.h | 2 + arch/x86/include/asm/word-at-a-time.h | 46 ++---------------- arch/x86/mm/extable.c | 55 ++++++++++++++++++++++ 3 files changed, 60 insertions(+), 43 deletions(-) diff --git a/arch/x86/include/asm/extable_fixup_types.h b/arch/x86/include/asm/extable_fixup_types.h index 5036226274004..991e31cfde94c 100644 --- a/arch/x86/include/asm/extable_fixup_types.h +++ b/arch/x86/include/asm/extable_fixup_types.h @@ -64,4 +64,6 @@ #define EX_TYPE_UCOPY_LEN4 (EX_TYPE_UCOPY_LEN | EX_DATA_IMM(4)) #define EX_TYPE_UCOPY_LEN8 (EX_TYPE_UCOPY_LEN | EX_DATA_IMM(8)) +#define EX_TYPE_ZEROPAD 20 /* longword load with zeropad on fault */ + #endif diff --git a/arch/x86/include/asm/word-at-a-time.h b/arch/x86/include/asm/word-at-a-time.h index 8338b0432b50e..46b4f1f7f3545 100644 --- a/arch/x86/include/asm/word-at-a-time.h +++ b/arch/x86/include/asm/word-at-a-time.h @@ -77,58 +77,18 @@ static inline unsigned long find_zero(unsigned long mask) * and the next page not being mapped, take the exception and * return zeroes in the non-existing part. */ -#ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT - static inline unsigned long load_unaligned_zeropad(const void *addr) { - unsigned long offset, data; unsigned long ret; - asm_volatile_goto( + asm volatile( "1: mov %[mem], %[ret]\n" - - _ASM_EXTABLE(1b, %l[do_exception]) - - : [ret] "=r" (ret) - : [mem] "m" (*(unsigned long *)addr) - : : do_exception); - - return ret; - -do_exception: - offset = (unsigned long)addr & (sizeof(long) - 1); - addr = (void *)((unsigned long)addr & ~(sizeof(long) - 1)); - data = *(unsigned long *)addr; - ret = data >> offset * 8; - - return ret; -} - -#else /* !CONFIG_CC_HAS_ASM_GOTO_OUTPUT */ - -static inline unsigned long load_unaligned_zeropad(const void *addr) -{ - unsigned long offset, data; - unsigned long ret, err = 0; - - asm( "1: mov %[mem], %[ret]\n" "2:\n" - - _ASM_EXTABLE_FAULT(1b, 2b) - - : [ret] "=&r" (ret), "+a" (err) + _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_ZEROPAD) + : [ret] "=r" (ret) : [mem] "m" (*(unsigned long *)addr)); - if (unlikely(err)) { - offset = (unsigned long)addr & (sizeof(long) - 1); - addr = (void *)((unsigned long)addr & ~(sizeof(long) - 1)); - data = *(unsigned long *)addr; - ret = data >> offset * 8; - } - return ret; } -#endif /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */ - #endif /* _ASM_WORD_AT_A_TIME_H */ diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index 331310c293492..60814e110a54c 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -41,6 +41,59 @@ static bool ex_handler_default(const struct exception_table_entry *e, return true; } +/* + * This is the *very* rare case where we do a "load_unaligned_zeropad()" + * and it's a page crosser into a non-existent page. + * + * This happens when we optimistically load a pathname a word-at-a-time + * and the name is less than the full word and the next page is not + * mapped. Typically that only happens for CONFIG_DEBUG_PAGEALLOC. + * + * NOTE! The faulting address is always a 'mov mem,reg' type instruction + * of size 'long', and the exception fixup must always point to right + * after the instruction. + */ +static bool ex_handler_zeropad(const struct exception_table_entry *e, + struct pt_regs *regs, + unsigned long fault_addr) +{ + struct insn insn; + const unsigned long mask = sizeof(long) - 1; + unsigned long offset, addr, next_ip, len; + unsigned long *reg; + + next_ip = ex_fixup_addr(e); + len = next_ip - regs->ip; + if (len > MAX_INSN_SIZE) + return false; + + if (insn_decode(&insn, (void *) regs->ip, len, INSN_MODE_KERN)) + return false; + if (insn.length != len) + return false; + + if (insn.opcode.bytes[0] != 0x8b) + return false; + if (insn.opnd_bytes != sizeof(long)) + return false; + + addr = (unsigned long) insn_get_addr_ref(&insn, regs); + if (addr == ~0ul) + return false; + + offset = addr & mask; + addr = addr & ~mask; + if (fault_addr != addr + sizeof(long)) + return false; + + reg = insn_get_modrm_reg_ptr(&insn, regs); + if (!reg) + return false; + + *reg = *(unsigned long *)addr >> (offset * 8); + return ex_handler_default(e, regs); +} + static bool ex_handler_fault(const struct exception_table_entry *fixup, struct pt_regs *regs, int trapnr) { @@ -217,6 +270,8 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code, return ex_handler_sgx(e, regs, trapnr); case EX_TYPE_UCOPY_LEN: return ex_handler_ucopy_len(e, regs, trapnr, reg, imm); + case EX_TYPE_ZEROPAD: + return ex_handler_zeropad(e, regs, fault_addr); } BUG(); } From 3a608cfee97e99b3fff9ffe62246a098042e725d Mon Sep 17 00:00:00 2001 From: "Fabio M. De Francesco" Date: Wed, 3 Aug 2022 20:28:56 +0200 Subject: [PATCH 237/427] exec: Replace kmap{,_atomic}() with kmap_local_page() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The use of kmap() and kmap_atomic() are being deprecated in favor of kmap_local_page(). There are two main problems with kmap(): (1) It comes with an overhead as mapping space is restricted and protected by a global lock for synchronization and (2) it also requires global TLB invalidation when the kmap’s pool wraps and it might block when the mapping space is fully utilized until a slot becomes available. With kmap_local_page() the mappings are per thread, CPU local, can take page faults, and can be called from any context (including interrupts). It is faster than kmap() in kernels with HIGHMEM enabled. Furthermore, the tasks can be preempted and, when they are scheduled to run again, the kernel virtual addresses are restored and are still valid. Since the use of kmap_local_page() in exec.c is safe, it should be preferred everywhere in exec.c. As said, since kmap_local_page() can be also called from atomic context, and since remove_arg_zero() doesn't (and shouldn't ever) rely on an implicit preempt_disable(), this function can also safely replace kmap_atomic(). Therefore, replace kmap() and kmap_atomic() with kmap_local_page() in fs/exec.c. Tested with xfstests on a QEMU/KVM x86_32 VM, 6GB RAM, booting a kernel with HIGHMEM64GB enabled. Cc: Eric W. Biederman Suggested-by: Ira Weiny Reviewed-by: Ira Weiny Signed-off-by: Fabio M. De Francesco Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20220803182856.28246-1-fmdefrancesco@gmail.com --- fs/exec.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 7e842d1bcb674..ba9eca9c826d8 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -584,11 +584,11 @@ static int copy_strings(int argc, struct user_arg_ptr argv, if (kmapped_page) { flush_dcache_page(kmapped_page); - kunmap(kmapped_page); + kunmap_local(kaddr); put_arg_page(kmapped_page); } kmapped_page = page; - kaddr = kmap(kmapped_page); + kaddr = kmap_local_page(kmapped_page); kpos = pos & PAGE_MASK; flush_arg_page(bprm, kpos, kmapped_page); } @@ -602,7 +602,7 @@ static int copy_strings(int argc, struct user_arg_ptr argv, out: if (kmapped_page) { flush_dcache_page(kmapped_page); - kunmap(kmapped_page); + kunmap_local(kaddr); put_arg_page(kmapped_page); } return ret; @@ -880,11 +880,11 @@ int transfer_args_to_stack(struct linux_binprm *bprm, for (index = MAX_ARG_PAGES - 1; index >= stop; index--) { unsigned int offset = index == stop ? bprm->p & ~PAGE_MASK : 0; - char *src = kmap(bprm->page[index]) + offset; + char *src = kmap_local_page(bprm->page[index]) + offset; sp -= PAGE_SIZE - offset; if (copy_to_user((void *) sp, src, PAGE_SIZE - offset) != 0) ret = -EFAULT; - kunmap(bprm->page[index]); + kunmap_local(src); if (ret) goto out; } @@ -1683,13 +1683,13 @@ int remove_arg_zero(struct linux_binprm *bprm) ret = -EFAULT; goto out; } - kaddr = kmap_atomic(page); + kaddr = kmap_local_page(page); for (; offset < PAGE_SIZE && kaddr[offset]; offset++, bprm->p++) ; - kunmap_atomic(kaddr); + kunmap_local(kaddr); put_arg_page(page); } while (offset == PAGE_SIZE); From 6a3981af3fd97fec57f2c5eeca213cbf5216a3c0 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 16 Aug 2022 12:14:54 -0700 Subject: [PATCH 238/427] LoadPin: Return EFAULT on copy_from_user() failures The copy_from_user() function returns the number of bytes remaining to be copied on a failure. Such failures should return -EFAULT to high levels. Reported-by: kernel test robot Reported-by: Dan Carpenter Fixes: 3f805f8cc23b ("LoadPin: Enable loading from trusted dm-verity devices") Cc: Matthias Kaehlcke Cc: James Morris Cc: "Serge E. Hallyn" Cc: linux-security-module@vger.kernel.org Signed-off-by: Kees Cook --- security/loadpin/loadpin.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c index 6ab5f2bbf41f9..44521582dcba2 100644 --- a/security/loadpin/loadpin.c +++ b/security/loadpin/loadpin.c @@ -356,13 +356,11 @@ static long dm_verity_ioctl(struct file *filp, unsigned int cmd, unsigned long a { void __user *uarg = (void __user *)arg; unsigned int fd; - int rc; switch (cmd) { case LOADPIN_IOC_SET_TRUSTED_VERITY_DIGESTS: - rc = copy_from_user(&fd, uarg, sizeof(fd)); - if (rc) - return rc; + if (copy_from_user(&fd, uarg, sizeof(fd))) + return -EFAULT; return read_trusted_verity_root_digests(fd); From 012e8d2034f1bda8863435cd589636e618d6a659 Mon Sep 17 00:00:00 2001 From: Andrew Donnellan Date: Tue, 16 Aug 2022 15:17:20 +1000 Subject: [PATCH 239/427] gcc-plugins: Undefine LATENT_ENTROPY_PLUGIN when plugin disabled for a file Commit 36d4b36b6959 ("lib/nodemask: inline next_node_in() and node_random()") refactored some code by moving node_random() from lib/nodemask.c to include/linux/nodemask.h, thus requiring nodemask.h to include random.h, which conditionally defines add_latent_entropy() depending on whether the macro LATENT_ENTROPY_PLUGIN is defined. This broke the build on powerpc, where nodemask.h is indirectly included in arch/powerpc/kernel/prom_init.c, part of the early boot machinery that is excluded from the latent entropy plugin using DISABLE_LATENT_ENTROPY_PLUGIN. It turns out that while we add a gcc flag to disable the actual plugin, we don't undefine LATENT_ENTROPY_PLUGIN. This leads to the following: CC arch/powerpc/kernel/prom_init.o In file included from ./include/linux/nodemask.h:97, from ./include/linux/mmzone.h:17, from ./include/linux/gfp.h:7, from ./include/linux/xarray.h:15, from ./include/linux/radix-tree.h:21, from ./include/linux/idr.h:15, from ./include/linux/kernfs.h:12, from ./include/linux/sysfs.h:16, from ./include/linux/kobject.h:20, from ./include/linux/pci.h:35, from arch/powerpc/kernel/prom_init.c:24: ./include/linux/random.h: In function 'add_latent_entropy': ./include/linux/random.h:25:46: error: 'latent_entropy' undeclared (first use in this function); did you mean 'add_latent_entropy'? 25 | add_device_randomness((const void *)&latent_entropy, sizeof(latent_entropy)); | ^~~~~~~~~~~~~~ | add_latent_entropy ./include/linux/random.h:25:46: note: each undeclared identifier is reported only once for each function it appears in make[2]: *** [scripts/Makefile.build:249: arch/powerpc/kernel/prom_init.o] Fehler 1 make[1]: *** [scripts/Makefile.build:465: arch/powerpc/kernel] Fehler 2 make: *** [Makefile:1855: arch/powerpc] Error 2 Change the DISABLE_LATENT_ENTROPY_PLUGIN flags to undefine LATENT_ENTROPY_PLUGIN for files where the plugin is disabled. Cc: Yury Norov Fixes: 38addce8b600 ("gcc-plugins: Add latent_entropy plugin") Link: https://bugzilla.kernel.org/show_bug.cgi?id=216367 Link: https://lore.kernel.org/linuxppc-dev/alpine.DEB.2.22.394.2208152006320.289321@ramsan.of.borg/ Reported-by: Erhard Furtner Signed-off-by: Andrew Donnellan Reviewed-by: Yury Norov Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20220816051720.44108-1-ajd@linux.ibm.com --- scripts/Makefile.gcc-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins index 692d64a70542a..e4deaf5fa571d 100644 --- a/scripts/Makefile.gcc-plugins +++ b/scripts/Makefile.gcc-plugins @@ -4,7 +4,7 @@ gcc-plugin-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) += latent_entropy_plugin.so gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) \ += -DLATENT_ENTROPY_PLUGIN ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY - DISABLE_LATENT_ENTROPY_PLUGIN += -fplugin-arg-latent_entropy_plugin-disable + DISABLE_LATENT_ENTROPY_PLUGIN += -fplugin-arg-latent_entropy_plugin-disable -ULATENT_ENTROPY_PLUGIN endif export DISABLE_LATENT_ENTROPY_PLUGIN From 1b586595df6d04c27088ef348b8202204ce26d45 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 3 Aug 2022 16:13:56 +0800 Subject: [PATCH 240/427] drm/amdgpu: disable 3DCGCG/CGLS temporarily due to stability issue Some stability issues were reported with these features. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc21.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index bbbf760f8ad2b..77d549dbe2a8c 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -546,8 +546,10 @@ static int soc21_common_early_init(void *handle) case IP_VERSION(11, 0, 0): adev->cg_flags = AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS | +#if 0 AMD_CG_SUPPORT_GFX_3D_CGCG | AMD_CG_SUPPORT_GFX_3D_CGLS | +#endif AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_REPEATER_FGCG | AMD_CG_SUPPORT_GFX_FGCG | From 0a2d922a5618377cdf8fa476351362733ef55342 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 10 Aug 2022 11:08:31 +0800 Subject: [PATCH 241/427] drm/amd/pm: add missing ->fini_microcode interface for Sienna Cichlid To avoid any potential memory leak. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index fa520d79ef67f..6db67f082d917 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -4283,6 +4283,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .dump_pptable = sienna_cichlid_dump_pptable, .init_microcode = smu_v11_0_init_microcode, .load_microcode = smu_v11_0_load_microcode, + .fini_microcode = smu_v11_0_fini_microcode, .init_smc_tables = sienna_cichlid_init_smc_tables, .fini_smc_tables = smu_v11_0_fini_smc_tables, .init_power = smu_v11_0_init_power, From 4bac1c846eff8042dd59ddecd0a43f3b9de5fd23 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 10 Aug 2022 11:11:16 +0800 Subject: [PATCH 242/427] drm/amd/pm: add missing ->fini_xxxx interfaces for some SMU13 asics Without these, potential memory leak may be induced. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 2 ++ drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index 1bbeceeb9e3cb..df4a47acd7247 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -1792,7 +1792,9 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = { .dump_pptable = smu_v13_0_0_dump_pptable, .init_microcode = smu_v13_0_init_microcode, .load_microcode = smu_v13_0_load_microcode, + .fini_microcode = smu_v13_0_fini_microcode, .init_smc_tables = smu_v13_0_0_init_smc_tables, + .fini_smc_tables = smu_v13_0_fini_smc_tables, .init_power = smu_v13_0_init_power, .fini_power = smu_v13_0_fini_power, .check_fw_status = smu_v13_0_check_fw_status, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c index 9dd56e73218be..d78375d9a1414 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c @@ -1574,7 +1574,9 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = { .dump_pptable = smu_v13_0_7_dump_pptable, .init_microcode = smu_v13_0_init_microcode, .load_microcode = smu_v13_0_load_microcode, + .fini_microcode = smu_v13_0_fini_microcode, .init_smc_tables = smu_v13_0_7_init_smc_tables, + .fini_smc_tables = smu_v13_0_fini_smc_tables, .init_power = smu_v13_0_init_power, .fini_power = smu_v13_0_fini_power, .check_fw_status = smu_v13_0_7_check_fw_status, From b4ddb27d1dc7349fc882dbb7702bd2628fe27af6 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Thu, 11 Aug 2022 09:48:00 +0800 Subject: [PATCH 243/427] drm/amd/amdgpu: add ih cg and hdp sd on smu_v13_0_7 add ih cg and hdp sd on smu_v13_0_7 Signed-off-by: Kenneth Feng Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc21.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 77d549dbe2a8c..71e184ca60045 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -577,7 +577,9 @@ static int soc21_common_early_init(void *handle) AMD_CG_SUPPORT_VCN_MGCG | AMD_CG_SUPPORT_JPEG_MGCG | AMD_CG_SUPPORT_ATHUB_MGCG | - AMD_CG_SUPPORT_ATHUB_LS; + AMD_CG_SUPPORT_ATHUB_LS | + AMD_CG_SUPPORT_IH_CG | + AMD_CG_SUPPORT_HDP_SD; adev->pg_flags = AMD_PG_SUPPORT_VCN | AMD_PG_SUPPORT_VCN_DPG | @@ -692,6 +694,7 @@ static int soc21_common_set_clockgating_state(void *handle, switch (adev->ip_versions[NBIO_HWIP][0]) { case IP_VERSION(4, 3, 0): + case IP_VERSION(4, 3, 1): adev->nbio.funcs->update_medium_grain_clock_gating(adev, state == AMD_CG_STATE_GATE); adev->nbio.funcs->update_medium_grain_light_sleep(adev, From ea8793f214ce1e4db205390c0241955f7ff6f383 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Thu, 11 Aug 2022 16:38:52 +0800 Subject: [PATCH 244/427] drm/amd/pm: add mode1 support on smu_v13_0_7 add mode1 support since it's missing on smu_v13_0_7 Signed-off-by: Kenneth Feng Reviewed-by: Yang Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c index d78375d9a1414..1016d1c216d8c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c @@ -1567,6 +1567,16 @@ static int smu_v13_0_7_set_mp1_state(struct smu_context *smu, return ret; } +static bool smu_v13_0_7_is_mode1_reset_supported(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + + /* SRIOV does not support SMU mode1 reset */ + if (amdgpu_sriov_vf(adev)) + return false; + + return true; +} static const struct pptable_funcs smu_v13_0_7_ppt_funcs = { .get_allowed_feature_mask = smu_v13_0_7_get_allowed_feature_mask, .set_default_dpm_table = smu_v13_0_7_set_default_dpm_table, @@ -1626,6 +1636,8 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = { .baco_set_state = smu_v13_0_baco_set_state, .baco_enter = smu_v13_0_baco_enter, .baco_exit = smu_v13_0_baco_exit, + .mode1_reset_is_support = smu_v13_0_7_is_mode1_reset_supported, + .mode1_reset = smu_v13_0_mode1_reset, .set_mp1_state = smu_v13_0_7_set_mp1_state, }; From c02895577b834a6148f6d9d0006a6f196511cc79 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Mon, 8 Aug 2022 17:00:38 -0400 Subject: [PATCH 245/427] drm/amdkfd: Fix mm reference in SVM eviction worker Use the mm reference from the fence. This allows removing the svm_bo->svms pointer, which was problematic because we cannot assume that the struct kfd_process containing the svms is still allocated without holding a refcount on the process. Use mmget_not_zero to ensure the mm is still valid, and drop the svm_bo reference if it isn't. Signed-off-by: Felix Kuehling Reviewed-by: Philip Yang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 17 +++++++---------- drivers/gpu/drm/amd/amdkfd/kfd_svm.h | 1 - 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index a67ba8879a567..11074cc8c333b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -541,7 +541,6 @@ svm_range_vram_node_new(struct amdgpu_device *adev, struct svm_range *prange, kfree(svm_bo); return -ESRCH; } - svm_bo->svms = prange->svms; svm_bo->eviction_fence = amdgpu_amdkfd_fence_create(dma_fence_context_alloc(1), mm, @@ -3273,7 +3272,6 @@ int svm_range_schedule_evict_svm_bo(struct amdgpu_amdkfd_fence *fence) static void svm_range_evict_svm_bo_worker(struct work_struct *work) { struct svm_range_bo *svm_bo; - struct kfd_process *p; struct mm_struct *mm; int r = 0; @@ -3281,13 +3279,12 @@ static void svm_range_evict_svm_bo_worker(struct work_struct *work) if (!svm_bo_ref_unless_zero(svm_bo)) return; /* svm_bo was freed while eviction was pending */ - /* svm_range_bo_release destroys this worker thread. So during - * the lifetime of this thread, kfd_process and mm will be valid. - */ - p = container_of(svm_bo->svms, struct kfd_process, svms); - mm = p->mm; - if (!mm) + if (mmget_not_zero(svm_bo->eviction_fence->mm)) { + mm = svm_bo->eviction_fence->mm; + } else { + svm_range_bo_unref(svm_bo); return; + } mmap_read_lock(mm); spin_lock(&svm_bo->list_lock); @@ -3305,8 +3302,7 @@ static void svm_range_evict_svm_bo_worker(struct work_struct *work) mutex_lock(&prange->migrate_mutex); do { - r = svm_migrate_vram_to_ram(prange, - svm_bo->eviction_fence->mm, + r = svm_migrate_vram_to_ram(prange, mm, KFD_MIGRATE_TRIGGER_TTM_EVICTION); } while (!r && prange->actual_loc && --retries); @@ -3324,6 +3320,7 @@ static void svm_range_evict_svm_bo_worker(struct work_struct *work) } spin_unlock(&svm_bo->list_lock); mmap_read_unlock(mm); + mmput(mm); dma_fence_signal(&svm_bo->eviction_fence->base); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h index 9156b041ef175..cfac13ad06ef0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h @@ -46,7 +46,6 @@ struct svm_range_bo { spinlock_t list_lock; struct amdgpu_amdkfd_fence *eviction_fence; struct work_struct eviction_work; - struct svm_range_list *svms; uint32_t evicting; struct work_struct release_work; }; From c8007d362c0150aef34323702e7fa996fa0cfd8d Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 9 Aug 2022 14:42:46 +0800 Subject: [PATCH 246/427] drm/amd/pm: update the smu driver interface version for SMU IP v13.0.4 The pmfw has changed the driver interface version, so keep same with the fw. Signed-off-by: Tim Huang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h index c02e5e5767282..6fe2fe92ebd75 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h @@ -28,7 +28,7 @@ #define SMU13_DRIVER_IF_VERSION_INV 0xFFFFFFFF #define SMU13_DRIVER_IF_VERSION_YELLOW_CARP 0x04 #define SMU13_DRIVER_IF_VERSION_ALDE 0x08 -#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x04 +#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x05 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0 0x2C #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_7 0x2C From 8172cebac588c3c5e238d02be30914fbbc5b1234 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 9 Aug 2022 17:46:39 +0800 Subject: [PATCH 247/427] drm/amdgpu: add MMHUB IP v3.0.1 Clock Gating support Add set/get_clockgating for MMHUB IP v3.0.1. Signed-off-by: Tim Huang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c | 42 +++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c index cac72ced94c85..e8058edc1d108 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c @@ -518,18 +518,41 @@ static u64 mmhub_v3_0_1_get_mc_fb_offset(struct amdgpu_device *adev) static void mmhub_v3_0_1_update_medium_grain_clock_gating(struct amdgpu_device *adev, bool enable) { - //TODO + uint32_t def, data; + + def = data = RREG32_SOC15(MMHUB, 0, regMM_ATC_L2_MISC_CG); + + if (enable) + data |= MM_ATC_L2_MISC_CG__ENABLE_MASK; + else + data &= ~MM_ATC_L2_MISC_CG__ENABLE_MASK; + + if (def != data) + WREG32_SOC15(MMHUB, 0, regMM_ATC_L2_MISC_CG, data); } static void mmhub_v3_0_1_update_medium_grain_light_sleep(struct amdgpu_device *adev, bool enable) { - //TODO + uint32_t def, data; + + def = data = RREG32_SOC15(MMHUB, 0, regMM_ATC_L2_MISC_CG); + + if (enable) + data |= MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK; + else + data &= ~MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK; + + if (def != data) + WREG32_SOC15(MMHUB, 0, regMM_ATC_L2_MISC_CG, data); } static int mmhub_v3_0_1_set_clockgating(struct amdgpu_device *adev, enum amd_clockgating_state state) { + if (amdgpu_sriov_vf(adev)) + return 0; + mmhub_v3_0_1_update_medium_grain_clock_gating(adev, state == AMD_CG_STATE_GATE); mmhub_v3_0_1_update_medium_grain_light_sleep(adev, @@ -539,7 +562,20 @@ static int mmhub_v3_0_1_set_clockgating(struct amdgpu_device *adev, static void mmhub_v3_0_1_get_clockgating(struct amdgpu_device *adev, u64 *flags) { - //TODO + int data; + + if (amdgpu_sriov_vf(adev)) + *flags = 0; + + data = RREG32_SOC15(MMHUB, 0, regMM_ATC_L2_MISC_CG); + + /* AMD_CG_SUPPORT_MC_MGCG */ + if (data & MM_ATC_L2_MISC_CG__ENABLE_MASK) + *flags |= AMD_CG_SUPPORT_MC_MGCG; + + /* AMD_CG_SUPPORT_MC_LS */ + if (data & MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK) + *flags |= AMD_CG_SUPPORT_MC_LS; } const struct amdgpu_mmhub_funcs mmhub_v3_0_1_funcs = { From 73c49a624a8db1ec38b138741203d9d7c76eedd7 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 9 Aug 2022 18:59:49 +0800 Subject: [PATCH 248/427] drm/amdgpu: add HDP IP v5.2.1 Clock Gating support Add set/get_clockgating for HDP IP v5.2.1. Signed-off-by: Tim Huang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/hdp_v5_2.c | 150 ++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v5_2.c b/drivers/gpu/drm/amd/amdgpu/hdp_v5_2.c index 39a696cd45b5e..29c3484ae1f16 100644 --- a/drivers/gpu/drm/amd/amdgpu/hdp_v5_2.c +++ b/drivers/gpu/drm/amd/amdgpu/hdp_v5_2.c @@ -40,6 +40,156 @@ static void hdp_v5_2_flush_hdp(struct amdgpu_device *adev, 0); } +static void hdp_v5_2_update_mem_power_gating(struct amdgpu_device *adev, + bool enable) +{ + uint32_t hdp_clk_cntl; + uint32_t hdp_mem_pwr_cntl; + + if (!(adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS | + AMD_CG_SUPPORT_HDP_DS | + AMD_CG_SUPPORT_HDP_SD))) + return; + + hdp_clk_cntl = RREG32_SOC15(HDP, 0, regHDP_CLK_CNTL); + hdp_mem_pwr_cntl = RREG32_SOC15(HDP, 0, regHDP_MEM_POWER_CTRL); + + /* Before doing clock/power mode switch, forced on MEM clock */ + hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL, + ATOMIC_MEM_CLK_SOFT_OVERRIDE, 1); + hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL, + RC_MEM_CLK_SOFT_OVERRIDE, 1); + WREG32_SOC15(HDP, 0, regHDP_CLK_CNTL, hdp_clk_cntl); + + /* disable clock and power gating before any changing */ + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL, + ATOMIC_MEM_POWER_CTRL_EN, 0); + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL, + ATOMIC_MEM_POWER_LS_EN, 0); + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL, + ATOMIC_MEM_POWER_DS_EN, 0); + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL, + ATOMIC_MEM_POWER_SD_EN, 0); + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL, + RC_MEM_POWER_CTRL_EN, 0); + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL, + RC_MEM_POWER_LS_EN, 0); + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL, + RC_MEM_POWER_DS_EN, 0); + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL, + RC_MEM_POWER_SD_EN, 0); + WREG32_SOC15(HDP, 0, regHDP_MEM_POWER_CTRL, hdp_mem_pwr_cntl); + + /* Already disabled above. The actions below are for "enabled" only */ + if (enable) { + /* only one clock gating mode (LS/DS/SD) can be enabled */ + if (adev->cg_flags & AMD_CG_SUPPORT_HDP_SD) { + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, + HDP_MEM_POWER_CTRL, + ATOMIC_MEM_POWER_SD_EN, 1); + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, + HDP_MEM_POWER_CTRL, + RC_MEM_POWER_SD_EN, 1); + } else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS) { + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, + HDP_MEM_POWER_CTRL, + ATOMIC_MEM_POWER_LS_EN, 1); + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, + HDP_MEM_POWER_CTRL, + RC_MEM_POWER_LS_EN, 1); + } else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_DS) { + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, + HDP_MEM_POWER_CTRL, + ATOMIC_MEM_POWER_DS_EN, 1); + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, + HDP_MEM_POWER_CTRL, + RC_MEM_POWER_DS_EN, 1); + } + + /* confirmed that ATOMIC/RC_MEM_POWER_CTRL_EN have to be set for SRAM LS/DS/SD */ + if (adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_HDP_DS | + AMD_CG_SUPPORT_HDP_SD)) { + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL, + ATOMIC_MEM_POWER_CTRL_EN, 1); + hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL, + RC_MEM_POWER_CTRL_EN, 1); + WREG32_SOC15(HDP, 0, regHDP_MEM_POWER_CTRL, hdp_mem_pwr_cntl); + } + } + + /* disable MEM clock override after clock/power mode changing */ + hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL, + ATOMIC_MEM_CLK_SOFT_OVERRIDE, 0); + hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL, + RC_MEM_CLK_SOFT_OVERRIDE, 0); + WREG32_SOC15(HDP, 0, regHDP_CLK_CNTL, hdp_clk_cntl); +} + +static void hdp_v5_2_update_medium_grain_clock_gating(struct amdgpu_device *adev, + bool enable) +{ + uint32_t hdp_clk_cntl; + + if (!(adev->cg_flags & AMD_CG_SUPPORT_HDP_MGCG)) + return; + + hdp_clk_cntl = RREG32_SOC15(HDP, 0, regHDP_CLK_CNTL); + + if (enable) { + hdp_clk_cntl &= + ~(uint32_t) + (HDP_CLK_CNTL__ATOMIC_MEM_CLK_SOFT_OVERRIDE_MASK | + HDP_CLK_CNTL__RC_MEM_CLK_SOFT_OVERRIDE_MASK | + HDP_CLK_CNTL__DBUS_CLK_SOFT_OVERRIDE_MASK | + HDP_CLK_CNTL__DYN_CLK_SOFT_OVERRIDE_MASK | + HDP_CLK_CNTL__XDP_REG_CLK_SOFT_OVERRIDE_MASK | + HDP_CLK_CNTL__HDP_REG_CLK_SOFT_OVERRIDE_MASK); + } else { + hdp_clk_cntl |= HDP_CLK_CNTL__ATOMIC_MEM_CLK_SOFT_OVERRIDE_MASK | + HDP_CLK_CNTL__RC_MEM_CLK_SOFT_OVERRIDE_MASK | + HDP_CLK_CNTL__DBUS_CLK_SOFT_OVERRIDE_MASK | + HDP_CLK_CNTL__DYN_CLK_SOFT_OVERRIDE_MASK | + HDP_CLK_CNTL__XDP_REG_CLK_SOFT_OVERRIDE_MASK | + HDP_CLK_CNTL__HDP_REG_CLK_SOFT_OVERRIDE_MASK; + } + + WREG32_SOC15(HDP, 0, regHDP_CLK_CNTL, hdp_clk_cntl); +} + +static void hdp_v5_2_get_clockgating_state(struct amdgpu_device *adev, + u64 *flags) +{ + uint32_t tmp; + + /* AMD_CG_SUPPORT_HDP_MGCG */ + tmp = RREG32_SOC15(HDP, 0, regHDP_CLK_CNTL); + if (!(tmp & (HDP_CLK_CNTL__ATOMIC_MEM_CLK_SOFT_OVERRIDE_MASK | + HDP_CLK_CNTL__RC_MEM_CLK_SOFT_OVERRIDE_MASK | + HDP_CLK_CNTL__DBUS_CLK_SOFT_OVERRIDE_MASK | + HDP_CLK_CNTL__DYN_CLK_SOFT_OVERRIDE_MASK | + HDP_CLK_CNTL__XDP_REG_CLK_SOFT_OVERRIDE_MASK | + HDP_CLK_CNTL__HDP_REG_CLK_SOFT_OVERRIDE_MASK))) + *flags |= AMD_CG_SUPPORT_HDP_MGCG; + + /* AMD_CG_SUPPORT_HDP_LS/DS/SD */ + tmp = RREG32_SOC15(HDP, 0, regHDP_MEM_POWER_CTRL); + if (tmp & HDP_MEM_POWER_CTRL__ATOMIC_MEM_POWER_LS_EN_MASK) + *flags |= AMD_CG_SUPPORT_HDP_LS; + else if (tmp & HDP_MEM_POWER_CTRL__ATOMIC_MEM_POWER_DS_EN_MASK) + *flags |= AMD_CG_SUPPORT_HDP_DS; + else if (tmp & HDP_MEM_POWER_CTRL__ATOMIC_MEM_POWER_SD_EN_MASK) + *flags |= AMD_CG_SUPPORT_HDP_SD; +} + +static void hdp_v5_2_update_clock_gating(struct amdgpu_device *adev, + bool enable) +{ + hdp_v5_2_update_mem_power_gating(adev, enable); + hdp_v5_2_update_medium_grain_clock_gating(adev, enable); +} + const struct amdgpu_hdp_funcs hdp_v5_2_funcs = { .flush_hdp = hdp_v5_2_flush_hdp, + .update_clock_gating = hdp_v5_2_update_clock_gating, + .get_clock_gating_state = hdp_v5_2_get_clockgating_state, }; From cede849e9e2755084798236735d045298f9d9979 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 9 Aug 2022 16:26:05 +0800 Subject: [PATCH 249/427] drm/amdgpu: add ATHUB IP v3.0.1 Clock Gating support Add ATHUB IP v3.0.1 in athub_v3_0_set_clockgating. The regATHUB_MISC_CNTL has different offset for ATHUB IP v3.0.1, so need to add IP version checking to use the right REG offset. Signed-off-by: Tim Huang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/athub_v3_0.c | 42 ++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v3_0.c b/drivers/gpu/drm/amd/amdgpu/athub_v3_0.c index 33a8a7365aef9..f0e235f98afb2 100644 --- a/drivers/gpu/drm/amd/amdgpu/athub_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/athub_v3_0.c @@ -28,13 +28,44 @@ #include "navi10_enum.h" #include "soc15_common.h" +#define regATHUB_MISC_CNTL_V3_0_1 0x00d7 +#define regATHUB_MISC_CNTL_V3_0_1_BASE_IDX 0 + + +static uint32_t athub_v3_0_get_cg_cntl(struct amdgpu_device *adev) +{ + uint32_t data; + + switch (adev->ip_versions[ATHUB_HWIP][0]) { + case IP_VERSION(3, 0, 1): + data = RREG32_SOC15(ATHUB, 0, regATHUB_MISC_CNTL_V3_0_1); + break; + default: + data = RREG32_SOC15(ATHUB, 0, regATHUB_MISC_CNTL); + break; + } + return data; +} + +static void athub_v3_0_set_cg_cntl(struct amdgpu_device *adev, uint32_t data) +{ + switch (adev->ip_versions[ATHUB_HWIP][0]) { + case IP_VERSION(3, 0, 1): + WREG32_SOC15(ATHUB, 0, regATHUB_MISC_CNTL_V3_0_1, data); + break; + default: + WREG32_SOC15(ATHUB, 0, regATHUB_MISC_CNTL, data); + break; + } +} + static void athub_v3_0_update_medium_grain_clock_gating(struct amdgpu_device *adev, bool enable) { uint32_t def, data; - def = data = RREG32_SOC15(ATHUB, 0, regATHUB_MISC_CNTL); + def = data = athub_v3_0_get_cg_cntl(adev); if (enable && (adev->cg_flags & AMD_CG_SUPPORT_ATHUB_MGCG)) data |= ATHUB_MISC_CNTL__CG_ENABLE_MASK; @@ -42,7 +73,7 @@ athub_v3_0_update_medium_grain_clock_gating(struct amdgpu_device *adev, data &= ~ATHUB_MISC_CNTL__CG_ENABLE_MASK; if (def != data) - WREG32_SOC15(ATHUB, 0, regATHUB_MISC_CNTL, data); + athub_v3_0_set_cg_cntl(adev, data); } static void @@ -51,7 +82,7 @@ athub_v3_0_update_medium_grain_light_sleep(struct amdgpu_device *adev, { uint32_t def, data; - def = data = RREG32_SOC15(ATHUB, 0, regATHUB_MISC_CNTL); + def = data = athub_v3_0_get_cg_cntl(adev); if (enable && (adev->cg_flags & AMD_CG_SUPPORT_ATHUB_LS)) data |= ATHUB_MISC_CNTL__CG_MEM_LS_ENABLE_MASK; @@ -59,7 +90,7 @@ athub_v3_0_update_medium_grain_light_sleep(struct amdgpu_device *adev, data &= ~ATHUB_MISC_CNTL__CG_MEM_LS_ENABLE_MASK; if (def != data) - WREG32_SOC15(ATHUB, 0, regATHUB_MISC_CNTL, data); + athub_v3_0_set_cg_cntl(adev, data); } int athub_v3_0_set_clockgating(struct amdgpu_device *adev, @@ -70,6 +101,7 @@ int athub_v3_0_set_clockgating(struct amdgpu_device *adev, switch (adev->ip_versions[ATHUB_HWIP][0]) { case IP_VERSION(3, 0, 0): + case IP_VERSION(3, 0, 1): case IP_VERSION(3, 0, 2): athub_v3_0_update_medium_grain_clock_gating(adev, state == AMD_CG_STATE_GATE); @@ -88,7 +120,7 @@ void athub_v3_0_get_clockgating(struct amdgpu_device *adev, u64 *flags) int data; /* AMD_CG_SUPPORT_ATHUB_MGCG */ - data = RREG32_SOC15(ATHUB, 0, regATHUB_MISC_CNTL); + data = athub_v3_0_get_cg_cntl(adev); if (data & ATHUB_MISC_CNTL__CG_ENABLE_MASK) *flags |= AMD_CG_SUPPORT_ATHUB_MGCG; From adcd15dc47dadfb176a14fa74af5b0cb0f659f2d Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Fri, 29 Jul 2022 15:13:03 +0800 Subject: [PATCH 250/427] drm/amdgpu: enable MMHUB IP v3.0.1 Clock Gating Enable AMD_CG_SUPPORT_MC_MGCG and AMD_CG_SUPPORT_MC_LS support. Signed-off-by: Tim Huang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc21.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 71e184ca60045..543cf40adf8e0 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -596,6 +596,8 @@ static int soc21_common_early_init(void *handle) AMD_CG_SUPPORT_GFX_FGCG | AMD_CG_SUPPORT_REPEATER_FGCG | AMD_CG_SUPPORT_GFX_PERF_CLK | + AMD_CG_SUPPORT_MC_MGCG | + AMD_CG_SUPPORT_MC_LS | AMD_CG_SUPPORT_VCN_MGCG | AMD_CG_SUPPORT_JPEG_MGCG; adev->pg_flags = From 7e4a77de08f655e159e6355bdfbea73be71fab88 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Fri, 29 Jul 2022 15:18:10 +0800 Subject: [PATCH 251/427] drm/amdgpu: enable HDP IP v5.2.1 Clock Gating Enable AMD_CG_SUPPORT_HDP_MGCG and AMD_CG_SUPPORT_HDP_LS support. Signed-off-by: Tim Huang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc21.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 543cf40adf8e0..d9e5bae82e836 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -598,6 +598,8 @@ static int soc21_common_early_init(void *handle) AMD_CG_SUPPORT_GFX_PERF_CLK | AMD_CG_SUPPORT_MC_MGCG | AMD_CG_SUPPORT_MC_LS | + AMD_CG_SUPPORT_HDP_MGCG | + AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_VCN_MGCG | AMD_CG_SUPPORT_JPEG_MGCG; adev->pg_flags = @@ -704,6 +706,10 @@ static int soc21_common_set_clockgating_state(void *handle, adev->hdp.funcs->update_clock_gating(adev, state == AMD_CG_STATE_GATE); break; + case IP_VERSION(7, 7, 0): + adev->hdp.funcs->update_clock_gating(adev, + state == AMD_CG_STATE_GATE); + break; default: break; } From 8e78c7c4fe29f7ab8f87634c5f4dedc66107e66b Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Fri, 29 Jul 2022 15:21:08 +0800 Subject: [PATCH 252/427] drm/amdgpu: enable ATHUB IP v3.0.1 Clock Gating Enable AMD_CG_SUPPORT_ATHUB_MGCG and AMD_CG_SUPPORT_ATHUB_LS support. Signed-off-by: Tim Huang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc21.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index d9e5bae82e836..6c3440e7ed3f0 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -600,6 +600,8 @@ static int soc21_common_early_init(void *handle) AMD_CG_SUPPORT_MC_LS | AMD_CG_SUPPORT_HDP_MGCG | AMD_CG_SUPPORT_HDP_LS | + AMD_CG_SUPPORT_ATHUB_MGCG | + AMD_CG_SUPPORT_ATHUB_LS | AMD_CG_SUPPORT_VCN_MGCG | AMD_CG_SUPPORT_JPEG_MGCG; adev->pg_flags = From e48e6a131d34de54ce6852149e4c97c2208f45cc Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Wed, 10 Aug 2022 22:09:36 +0800 Subject: [PATCH 253/427] drm/amdkfd: reserve 2 queues for sdma 6.0.1 in bitmap There is only one engine in sdma 6.0.1, the total number of reserved queues should be 2, reflect this number in bitmap as well. Signed-off-by: Yifan Zhang Reviewed-by: Tim Huang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index f5853835f03a2..357298e69495f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -102,13 +102,18 @@ static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd) switch (sdma_version) { case IP_VERSION(6, 0, 0): - case IP_VERSION(6, 0, 1): case IP_VERSION(6, 0, 2): /* Reserve 1 for paging and 1 for gfx */ kfd->device_info.num_reserved_sdma_queues_per_engine = 2; /* BIT(0)=engine-0 queue-0; BIT(1)=engine-1 queue-0; BIT(2)=engine-0 queue-1; ... */ kfd->device_info.reserved_sdma_queues_bitmap = 0xFULL; break; + case IP_VERSION(6, 0, 1): + /* Reserve 1 for paging and 1 for gfx */ + kfd->device_info.num_reserved_sdma_queues_per_engine = 2; + /* BIT(0)=engine-0 queue-0; BIT(1)=engine-0 queue-1; ... */ + kfd->device_info.reserved_sdma_queues_bitmap = 0x3ULL; + break; default: break; } From 7d50b92d588d1e7bdcf38f523200b7b113b46c14 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 12 Aug 2022 09:20:58 +0300 Subject: [PATCH 254/427] drm/amdkfd: potential crash in kfd_create_indirect_link_prop() This code has two bugs. If kfd_topology_device_by_proximity_domain() failed on the first iteration through the loop then "cpu_link" is uninitialized and should not be dereferenced. The second bug is that we cannot dereference a list iterator when it points to the list head. In other words, if we exit the list_for_each_entry() loop exits without hitting a break then "cpu_link" is not a valid pointer and should not be dereferenced. Fix both of these problems by setting "cpu_link" to NULL when it is invalid and non-NULL when it is valid. That makes it easier to test for valid vs invalid. Fixes: 0f28cca87e9a ("drm/amdkfd: Extend KFD device topology to surface peer-to-peer links") Signed-off-by: Dan Carpenter Signed-off-by: Felix Kuehling Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index 25990bec600d0..3f0a4a415907d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -1392,8 +1392,8 @@ static int kfd_build_p2p_node_entry(struct kfd_topology_device *dev, static int kfd_create_indirect_link_prop(struct kfd_topology_device *kdev, int gpu_node) { + struct kfd_iolink_properties *gpu_link, *tmp_link, *cpu_link; struct kfd_iolink_properties *props = NULL, *props2 = NULL; - struct kfd_iolink_properties *gpu_link, *cpu_link; struct kfd_topology_device *cpu_dev; int ret = 0; int i, num_cpu; @@ -1416,16 +1416,19 @@ static int kfd_create_indirect_link_prop(struct kfd_topology_device *kdev, int g continue; /* find CPU <--> CPU links */ + cpu_link = NULL; cpu_dev = kfd_topology_device_by_proximity_domain(i); if (cpu_dev) { - list_for_each_entry(cpu_link, + list_for_each_entry(tmp_link, &cpu_dev->io_link_props, list) { - if (cpu_link->node_to == gpu_link->node_to) + if (tmp_link->node_to == gpu_link->node_to) { + cpu_link = tmp_link; break; + } } } - if (cpu_link->node_to != gpu_link->node_to) + if (!cpu_link) return -ENOMEM; /* CPU <--> CPU <--> GPU, GPU node*/ From fa0bbd3be91dd46f4e56e5cf1fb6e8c2837c649c Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Fri, 29 Jul 2022 15:22:44 +0800 Subject: [PATCH 255/427] drm/amdgpu: enable IH Clock Gating for OSS IP v6.0.1 Enable AMD_CG_SUPPORT_IH_CG support. Signed-off-by: Tim Huang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc21.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 6c3440e7ed3f0..1ff7fc7bb3400 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -602,6 +602,7 @@ static int soc21_common_early_init(void *handle) AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_ATHUB_MGCG | AMD_CG_SUPPORT_ATHUB_LS | + AMD_CG_SUPPORT_IH_CG | AMD_CG_SUPPORT_VCN_MGCG | AMD_CG_SUPPORT_JPEG_MGCG; adev->pg_flags = From 5a0918b4cb90a90fc8d8bfd9b0f81efe6651951f Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Fri, 12 Aug 2022 11:37:37 +0800 Subject: [PATCH 256/427] drm/amd/pm: Enable GFXOFF feature for SMU IP v13.0.4 The driver needs to set EnableGfxImu message parameter to tell the PMFW to set the flag that enables the GFXOFF feature. Signed-off-by: Tim Huang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index fc5772352cfb0..18ee3b5e64c50 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -2345,8 +2345,8 @@ int smu_v13_0_set_gfx_power_up_by_imu(struct smu_context *smu) index = smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG, SMU_MSG_EnableGfxImu); - - return smu_cmn_send_msg_without_waiting(smu, index, 0); + /* Param 1 to tell PMFW to enable GFXOFF feature */ + return smu_cmn_send_msg_without_waiting(smu, index, 1); } int smu_v13_0_od_edit_dpm_table(struct smu_context *smu, From e0df49b3045180fdd23dc27193344a767cf68fe1 Mon Sep 17 00:00:00 2001 From: Ethan Wellenreiter Date: Fri, 29 Jul 2022 13:45:51 -0400 Subject: [PATCH 257/427] drm/amd/display: reverted limiting vscsdp_for_colorimetry and ARGB16161616 pixel format addition [WHY] Limiting vscsdp_for_colorimetry for YCbCr420/BT2020 resulted in red/green point failures in HDR10 DTN tests. The re-implementation of ARGB16161616 was to fix this however it did not actually fix this issue but a side effect of the issue. [HOW] Change ARGB16161616 pixel format to 26. Reviewed-by: Martin Leung Acked-by: Brian Chang Signed-off-by: Ethan Wellenreiter Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c | 3 --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c | 3 --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c | 2 -- 5 files changed, 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index d4a6504dfe000..db7ca4b0cdb9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -361,8 +361,6 @@ void dpp1_cnv_setup ( select = INPUT_CSC_SELECT_ICSC; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: - pixel_format = 22; - break; case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: pixel_format = 26; /* ARGB16161616_UNORM */ break; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c index b54c124003237..564e061ccb589 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c @@ -278,9 +278,6 @@ void hubp1_program_pixel_format( SURFACE_PIXEL_FORMAT, 10); break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: - REG_UPDATE(DCSURF_SURFACE_CONFIG, - SURFACE_PIXEL_FORMAT, 22); - break; case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: /*we use crossbar already*/ REG_UPDATE(DCSURF_SURFACE_CONFIG, SURFACE_PIXEL_FORMAT, 26); /* ARGB16161616_UNORM */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.c index ea1f14af0db75..eaa7032f0f1a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.c @@ -166,8 +166,6 @@ static void dpp2_cnv_setup ( select = DCN2_ICSC_SELECT_ICSC_A; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: - pixel_format = 22; - break; case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: pixel_format = 26; /* ARGB16161616_UNORM */ break; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c index 936af65381ef7..9570c2118ccc7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c @@ -463,9 +463,6 @@ void hubp2_program_pixel_format( SURFACE_PIXEL_FORMAT, 10); break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: - REG_UPDATE(DCSURF_SURFACE_CONFIG, - SURFACE_PIXEL_FORMAT, 22); - break; case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: /*we use crossbar already*/ REG_UPDATE(DCSURF_SURFACE_CONFIG, SURFACE_PIXEL_FORMAT, 26); /* ARGB16161616_UNORM */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c index 77b00f86c2165..4a668d6563dfd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c @@ -244,8 +244,6 @@ void dpp3_cnv_setup ( select = INPUT_CSC_SELECT_ICSC; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: - pixel_format = 22; - break; case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: pixel_format = 26; /* ARGB16161616_UNORM */ break; From 84435d1d912140958213beda37c708ec3072b5e1 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Mon, 1 Aug 2022 20:17:54 -0400 Subject: [PATCH 258/427] drm/amd/display: 3.2.198 This version brings along following fixes: -Fix edp panel missing event -Set ARGB16161616 pixel format to 26 -Fix dcn32 interger issue -Clear optc underflow bit after ODM clock off -Fix issue with stereo3D -Fix DML2 lightup issue -Correct DTBCLK for dcn314 -Revert for a regression -Fix clocks and bugs in DML2 -Enable SubVP by defalut on DCN32 & DCN321 -Corret boundary condition for engin ID on DCN303 -Fix FRL encoder override registry key -Fix VPG for dcn314 HPO -Fix Linux compile-time warning -Add new prefetch modes in DML for DCN32 Acked-by: Brian Chang Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 2de45aaad7f75..efa827b45e047 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.197" +#define DC_VER "3.2.198" #define MAX_SURFACES 3 #define MAX_PLANES 6 From 04fb918bf421b299feaee1006e82921d7d381f18 Mon Sep 17 00:00:00 2001 From: Ilya Bakoulin Date: Tue, 26 Jul 2022 16:19:38 -0400 Subject: [PATCH 259/427] drm/amd/display: Fix pixel clock programming [Why] Some pixel clock values could cause HDMI TMDS SSCPs to be misaligned between different HDMI lanes when using YCbCr420 10-bit pixel format. BIOS functions for transmitter/encoder control take pixel clock in kHz increments, whereas the function for setting the pixel clock is in 100Hz increments. Setting pixel clock to a value that is not on a kHz boundary will cause the issue. [How] Round pixel clock down to nearest kHz in 10/12-bpc cases. Reviewed-by: Aric Cyr Acked-by: Brian Chang Signed-off-by: Ilya Bakoulin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 213de8cabfadb..165392380842a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -543,9 +543,11 @@ static void dce112_get_pix_clk_dividers_helper ( switch (pix_clk_params->color_depth) { case COLOR_DEPTH_101010: actual_pixel_clock_100hz = (actual_pixel_clock_100hz * 5) >> 2; + actual_pixel_clock_100hz -= actual_pixel_clock_100hz % 10; break; case COLOR_DEPTH_121212: actual_pixel_clock_100hz = (actual_pixel_clock_100hz * 6) >> 2; + actual_pixel_clock_100hz -= actual_pixel_clock_100hz % 10; break; case COLOR_DEPTH_161616: actual_pixel_clock_100hz = actual_pixel_clock_100hz * 2; From 5c1943820156e9a120faba320a72578578a69ab8 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Tue, 2 Aug 2022 15:13:37 +0800 Subject: [PATCH 260/427] drm/amd/display: Add reserved dc_log_type. Reviewed-by: Anthony Koo Acked-by: Brian Chang Signed-off-by: Ian Chen Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/include/logger_types.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index f093b49c5e6e6..3bf08a60c45c6 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -119,13 +119,15 @@ enum dc_log_type { LOG_HDMI_RETIMER_REDRIVER, LOG_DSC, LOG_SMU_MSG, + LOG_DC2RESERVED4, + LOG_DC2RESERVED5, LOG_DWB, LOG_GAMMA_DEBUG, LOG_MAX_HW_POINTS, LOG_ALL_TF_CHANNELS, LOG_SAMPLE_1DLUT, LOG_DP2, - LOG_SECTION_TOTAL_COUNT + LOG_DC2RESERVED12, }; #define DC_MIN_LOG_MASK ((1 << LOG_ERROR) | \ From c7dafdfa90f708b6e4630abf824ba388a3947400 Mon Sep 17 00:00:00 2001 From: Josip Pavic Date: Fri, 29 Jul 2022 11:08:09 -0400 Subject: [PATCH 261/427] drm/amd/display: do not compare integers of different widths [Why & How] Increase width of some variables to avoid comparing integers of different widths. Reviewed-by: Alvin Lee Acked-by: Brian Chang Signed-off-by: Josip Pavic Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c index 4aecbf2304463..ebd3945c71f1b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c @@ -331,7 +331,8 @@ static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *c bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable) { union dmub_rb_cmd cmd; - uint8_t ways, i, j; + uint8_t ways, i; + int j; bool stereo_in_use = false; struct dc_plane_state *plane = NULL; From 373008bfc9cdb0f050258947fa5a095f0657e1bc Mon Sep 17 00:00:00 2001 From: Dusica Milinkovic Date: Wed, 10 Aug 2022 09:43:15 +0200 Subject: [PATCH 262/427] drm/amdgpu: Increase tlb flush timeout for sriov [Why] During multi-vf executing benchmark (Luxmark) observed kiq error timeout. It happenes because all of VFs do the tlb invalidation at the same time. Although each VF has the invalidate register set, from hardware side the invalidate requests are queue to execute. [How] In case of 12 VF increase timeout on 12*100ms Signed-off-by: Dusica Milinkovic Acked-by: Shaoyun Liu Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 3 ++- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index e146810c700ba..d597e2656c475 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -317,7 +317,7 @@ enum amdgpu_kiq_irq { AMDGPU_CP_KIQ_IRQ_DRIVER0 = 0, AMDGPU_CP_KIQ_IRQ_LAST }; - +#define SRIOV_USEC_TIMEOUT 1200000 /* wait 12 * 100ms for SRIOV */ #define MAX_KIQ_REG_WAIT 5000 /* in usecs, 5ms */ #define MAX_KIQ_REG_BAILOUT_INTERVAL 5 /* in msecs, 5ms */ #define MAX_KIQ_REG_TRY 1000 diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 9ae8cdaa033ee..f513e2c2e964f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -419,6 +419,7 @@ static int gmc_v10_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint32_t seq; uint16_t queried_pasid; bool ret; + u32 usec_timeout = amdgpu_sriov_vf(adev) ? SRIOV_USEC_TIMEOUT : adev->usec_timeout; struct amdgpu_ring *ring = &adev->gfx.kiq.ring; struct amdgpu_kiq *kiq = &adev->gfx.kiq; @@ -437,7 +438,7 @@ static int gmc_v10_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, amdgpu_ring_commit(ring); spin_unlock(&adev->gfx.kiq.ring_lock); - r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout); + r = amdgpu_fence_wait_polling(ring, seq, usec_timeout); if (r < 1) { dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r); return -ETIME; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index ab89d91975ab0..4603653916f5a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -896,6 +896,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint32_t seq; uint16_t queried_pasid; bool ret; + u32 usec_timeout = amdgpu_sriov_vf(adev) ? SRIOV_USEC_TIMEOUT : adev->usec_timeout; struct amdgpu_ring *ring = &adev->gfx.kiq.ring; struct amdgpu_kiq *kiq = &adev->gfx.kiq; @@ -935,7 +936,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, amdgpu_ring_commit(ring); spin_unlock(&adev->gfx.kiq.ring_lock); - r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout); + r = amdgpu_fence_wait_polling(ring, seq, usec_timeout); if (r < 1) { dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r); up_read(&adev->reset_domain->sem); From d83a348b172dd7f9f10f049b3fd7e44cf4d2ed8a Mon Sep 17 00:00:00 2001 From: Daniel Miess Date: Tue, 2 Aug 2022 16:53:47 -0400 Subject: [PATCH 263/427] drm/amd/display: Add debug parameter to retain default clock table [Why] Need a way to retain default clock table to aid the investigation into why 8k@30 display not lighting up on dcn314 [How] Use flag to prevent execution of bw_params helper function and function for updating bw_bounding_box Reviewed-by: Nicholas Kazlauskas Reviewed-by: Jun Lei Acked-by: Brian Chang Signed-off-by: Daniel Miess Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c index 7af19823a29db..c74f2d5bbbc56 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c @@ -719,7 +719,7 @@ void dcn314_clk_mgr_construct( if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) { dcn314_get_dpm_table_from_smu(&clk_mgr->base, &smu_dpm_clks); - if (ctx->dc_bios && ctx->dc_bios->integrated_info) { + if (ctx->dc_bios && ctx->dc_bios->integrated_info && ctx->dc->config.use_default_clock_table == false) { dcn314_clk_mgr_helper_populate_bw_params( &clk_mgr->base, ctx->dc_bios->integrated_info, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index efa827b45e047..5908b60db3139 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -353,6 +353,7 @@ struct dc_config { bool use_pipe_ctx_sync_logic; bool ignore_dpref_ss; bool enable_mipi_converter_optimization; + bool use_default_clock_table; }; enum visual_confirm { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c index c80307a6af1bf..34a5d0f87b5f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c @@ -189,7 +189,7 @@ void dcn314_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p dc_assert_fp_enabled(); // Default clock levels are used for diags, which may lead to overclocking. - if (!IS_DIAG_DC(dc->ctx->dce_environment)) { + if (!IS_DIAG_DC(dc->ctx->dce_environment) && dc->config.use_default_clock_table == false) { dcn3_14_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator; dcn3_14_ip.max_num_dpp = dc->res_pool->pipe_count; From e98459c06e3d45c2229b097f7b8cdd412357fa2f Mon Sep 17 00:00:00 2001 From: Tom Chung Date: Wed, 3 Aug 2022 15:15:17 +0800 Subject: [PATCH 264/427] drm/amd/display: Fix plug/unplug external monitor will hang while playback MPO video [Why] Pipes for MPO primary and overlay will be power down and power up during plug/unplug external monitor while MPO video playback. But the pipes were the same after plug/unplug and should not need to be power down and power up or it will make page flip interrupt disabled and cause hang issue. [How] Add pipe split change condition that not only check the top pipe pointer but also check the index of top pipe if both top pipes are available. Reviewed-by: Sun peng Li Acked-by: Brian Chang Signed-off-by: Tom Chung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 663be10b292be..aeecca68dea73 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1074,8 +1074,15 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) struct dc_stream_state *old_stream = dc->current_state->res_ctx.pipe_ctx[i].stream; bool should_disable = true; - bool pipe_split_change = - context->res_ctx.pipe_ctx[i].top_pipe != dc->current_state->res_ctx.pipe_ctx[i].top_pipe; + bool pipe_split_change = false; + + if ((context->res_ctx.pipe_ctx[i].top_pipe) && + (dc->current_state->res_ctx.pipe_ctx[i].top_pipe)) + pipe_split_change = context->res_ctx.pipe_ctx[i].top_pipe->pipe_idx != + dc->current_state->res_ctx.pipe_ctx[i].top_pipe->pipe_idx; + else + pipe_split_change = context->res_ctx.pipe_ctx[i].top_pipe != + dc->current_state->res_ctx.pipe_ctx[i].top_pipe; for (j = 0; j < context->stream_count; j++) { if (old_stream == context->streams[j]) { From dd49c07f3ab67e8d7ae7b8231b88a746c668b4e8 Mon Sep 17 00:00:00 2001 From: Chaitanya Dhere Date: Wed, 27 Jul 2022 15:48:30 -0400 Subject: [PATCH 265/427] drm/amd/display: Modify header inclusion pattern [Why] Recent backport from opensource broke the Nightly tool build that tests DC and DML for bugs and regressions. This was because the backport had a header inclusion that was not consistent with the AMD style of including headers was allowed to be merged back in DML code that caused tool compilation failures. [How] Modify the way in which the header file in included so that it is consistent with AMD style of including headers. This then automatically fixes the tool compilation process and also helps maintain the code quality and consistency. Reviewed-by: Alvin Lee Reviewed-by: Jun Lei Acked-by: Brian Chang Signed-off-by: Chaitanya Dhere Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c | 2 +- .../gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c index 3fab19134480d..d63b4209b14c0 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c @@ -26,7 +26,7 @@ #include "dc.h" #include "dc_link.h" #include "../display_mode_lib.h" -#include "dml/dcn30/display_mode_vba_30.h" +#include "../dcn30/display_mode_vba_30.h" #include "display_mode_vba_31.h" #include "../dml_inline_defs.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c index 66b82e4f05c6e..35d10b4d018bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c @@ -27,7 +27,7 @@ #include "../display_mode_vba.h" #include "../dml_inline_defs.h" #include "display_rq_dlg_calc_31.h" -#include "dml/dcn30/display_mode_vba_30.h" +#include "../dcn30/display_mode_vba_30.h" static bool is_dual_plane(enum source_format_class source_format) { From 19f7b8334484d6b610c8eb527c3f56cb42bc8bf1 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Fri, 5 Aug 2022 12:02:10 -0400 Subject: [PATCH 266/427] drm/amd/display: Update clock table policy for DCN314 [Why & How] Depending on how the clock table is constructed from PMFW we can run into issues where we don't think we have enough bandwidth available due to FCLK too low - eg. when the FCLK table contains invalid entries or a single entry. We should always pick up the maximum clocks for each state as a final state in this case to prevent validation from failing if the table is malformed. We should also contain sensible defaults in the case where values are invalid. Redfine the clock table structures by adding a 314 prefix to make debugging these issues easier by avoiding symbol name clashes. Overall this policy more closely aligns to how we did things for 315, but because of how the voltage rail is setup we should favor keeping DCFCLK low rather than DISPCLK or DPPCLK - so use the max for those in every entry. Reviewed-by: Daniel Miess Acked-by: Brian Chang Signed-off-by: Nicholas Kazlauskas Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../dc/clk_mgr/dcn314/dcn314_clk_mgr.c | 186 ++++++++++++------ .../display/dc/clk_mgr/dcn314/dcn314_smu.h | 33 +++- 2 files changed, 154 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c index c74f2d5bbbc56..beb025cd3dc29 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c @@ -415,7 +415,7 @@ static struct wm_table lpddr5_wm_table = { } }; -static DpmClocks_t dummy_clocks; +static DpmClocks314_t dummy_clocks; static struct dcn314_watermarks dummy_wms = { 0 }; @@ -500,7 +500,7 @@ static void dcn314_notify_wm_ranges(struct clk_mgr *clk_mgr_base) static void dcn314_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, struct dcn314_smu_dpm_clks *smu_dpm_clks) { - DpmClocks_t *table = smu_dpm_clks->dpm_clks; + DpmClocks314_t *table = smu_dpm_clks->dpm_clks; if (!clk_mgr->smu_ver) return; @@ -517,6 +517,26 @@ static void dcn314_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, dcn314_smu_transfer_dpm_table_smu_2_dram(clk_mgr); } +static inline bool is_valid_clock_value(uint32_t clock_value) +{ + return clock_value > 1 && clock_value < 100000; +} + +static unsigned int convert_wck_ratio(uint8_t wck_ratio) +{ + switch (wck_ratio) { + case WCK_RATIO_1_2: + return 2; + + case WCK_RATIO_1_4: + return 4; + + default: + break; + } + return 1; +} + static uint32_t find_max_clk_value(const uint32_t clocks[], uint32_t num_clocks) { uint32_t max = 0; @@ -530,89 +550,127 @@ static uint32_t find_max_clk_value(const uint32_t clocks[], uint32_t num_clocks) return max; } -static unsigned int find_clk_for_voltage( - const DpmClocks_t *clock_table, - const uint32_t clocks[], - unsigned int voltage) -{ - int i; - int max_voltage = 0; - int clock = 0; - - for (i = 0; i < NUM_SOC_VOLTAGE_LEVELS; i++) { - if (clock_table->SocVoltage[i] == voltage) { - return clocks[i]; - } else if (clock_table->SocVoltage[i] >= max_voltage && - clock_table->SocVoltage[i] < voltage) { - max_voltage = clock_table->SocVoltage[i]; - clock = clocks[i]; - } - } - - ASSERT(clock); - return clock; -} - static void dcn314_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk_mgr, struct integrated_info *bios_info, - const DpmClocks_t *clock_table) + const DpmClocks314_t *clock_table) { - int i, j; struct clk_bw_params *bw_params = clk_mgr->base.bw_params; - uint32_t max_dispclk = 0, max_dppclk = 0; - - j = -1; - - ASSERT(NUM_DF_PSTATE_LEVELS <= MAX_NUM_DPM_LVL); - - /* Find lowest DPM, FCLK is filled in reverse order*/ + struct clk_limit_table_entry def_max = bw_params->clk_table.entries[bw_params->clk_table.num_entries - 1]; + uint32_t max_pstate = 0, max_fclk = 0, min_pstate = 0, max_dispclk = 0, max_dppclk = 0; + int i; - for (i = NUM_DF_PSTATE_LEVELS - 1; i >= 0; i--) { - if (clock_table->DfPstateTable[i].FClk != 0) { - j = i; - break; + /* Find highest valid fclk pstate */ + for (i = 0; i < clock_table->NumDfPstatesEnabled; i++) { + if (is_valid_clock_value(clock_table->DfPstateTable[i].FClk) && + clock_table->DfPstateTable[i].FClk > max_fclk) { + max_fclk = clock_table->DfPstateTable[i].FClk; + max_pstate = i; } } - if (j == -1) { - /* clock table is all 0s, just use our own hardcode */ - ASSERT(0); - return; - } - - bw_params->clk_table.num_entries = j + 1; + /* We expect the table to contain at least one valid fclk entry. */ + ASSERT(is_valid_clock_value(max_fclk)); - /* dispclk and dppclk can be max at any voltage, same number of levels for both */ + /* Dispclk and dppclk can be max at any voltage, same number of levels for both */ if (clock_table->NumDispClkLevelsEnabled <= NUM_DISPCLK_DPM_LEVELS && clock_table->NumDispClkLevelsEnabled <= NUM_DPPCLK_DPM_LEVELS) { max_dispclk = find_max_clk_value(clock_table->DispClocks, clock_table->NumDispClkLevelsEnabled); max_dppclk = find_max_clk_value(clock_table->DppClocks, clock_table->NumDispClkLevelsEnabled); } else { + /* Invalid number of entries in the table from PMFW. */ ASSERT(0); } - for (i = 0; i < bw_params->clk_table.num_entries; i++, j--) { - bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[j].FClk; - bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[j].MemClk; - bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[j].Voltage; - switch (clock_table->DfPstateTable[j].WckRatio) { - case WCK_RATIO_1_2: - bw_params->clk_table.entries[i].wck_ratio = 2; - break; - case WCK_RATIO_1_4: - bw_params->clk_table.entries[i].wck_ratio = 4; - break; - default: - bw_params->clk_table.entries[i].wck_ratio = 1; + /* Base the clock table on dcfclk, need at least one entry regardless of pmfw table */ + for (i = 0; i < clock_table->NumDcfClkLevelsEnabled; i++) { + uint32_t min_fclk = clock_table->DfPstateTable[0].FClk; + int j; + + for (j = 1; j < clock_table->NumDfPstatesEnabled; j++) { + if (is_valid_clock_value(clock_table->DfPstateTable[j].FClk) && + clock_table->DfPstateTable[j].FClk < min_fclk && + clock_table->DfPstateTable[j].Voltage <= clock_table->SocVoltage[i]) { + min_fclk = clock_table->DfPstateTable[j].FClk; + min_pstate = j; + } } - bw_params->clk_table.entries[i].dcfclk_mhz = find_clk_for_voltage(clock_table, clock_table->DcfClocks, clock_table->DfPstateTable[j].Voltage); - bw_params->clk_table.entries[i].socclk_mhz = find_clk_for_voltage(clock_table, clock_table->SocClocks, clock_table->DfPstateTable[j].Voltage); + + /* First search defaults for the clocks we don't read using closest lower or equal default dcfclk */ + for (j = bw_params->clk_table.num_entries - 1; j > 0; j--) + if (bw_params->clk_table.entries[j].dcfclk_mhz <= clock_table->DcfClocks[i]) + break; + + bw_params->clk_table.entries[i].phyclk_mhz = bw_params->clk_table.entries[j].phyclk_mhz; + bw_params->clk_table.entries[i].phyclk_d18_mhz = bw_params->clk_table.entries[j].phyclk_d18_mhz; + bw_params->clk_table.entries[i].dtbclk_mhz = bw_params->clk_table.entries[j].dtbclk_mhz; + + /* Now update clocks we do read */ + bw_params->clk_table.entries[i].fclk_mhz = min_fclk; + bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[min_pstate].MemClk; + bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[min_pstate].Voltage; + bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[i]; + bw_params->clk_table.entries[i].socclk_mhz = clock_table->SocClocks[i]; + bw_params->clk_table.entries[i].dispclk_mhz = max_dispclk; + bw_params->clk_table.entries[i].dppclk_mhz = max_dppclk; + bw_params->clk_table.entries[i].wck_ratio = convert_wck_ratio( + clock_table->DfPstateTable[min_pstate].WckRatio); + }; + + /* Make sure to include at least one entry at highest pstate */ + if (max_pstate != min_pstate || i == 0) { + if (i > MAX_NUM_DPM_LVL - 1) + i = MAX_NUM_DPM_LVL - 1; + + bw_params->clk_table.entries[i].fclk_mhz = max_fclk; + bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[max_pstate].MemClk; + bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[max_pstate].Voltage; + bw_params->clk_table.entries[i].dcfclk_mhz = find_max_clk_value(clock_table->DcfClocks, NUM_DCFCLK_DPM_LEVELS); + bw_params->clk_table.entries[i].socclk_mhz = find_max_clk_value(clock_table->SocClocks, NUM_SOCCLK_DPM_LEVELS); bw_params->clk_table.entries[i].dispclk_mhz = max_dispclk; bw_params->clk_table.entries[i].dppclk_mhz = max_dppclk; + bw_params->clk_table.entries[i].wck_ratio = convert_wck_ratio( + clock_table->DfPstateTable[max_pstate].WckRatio); + i++; } + bw_params->clk_table.num_entries = i--; + + /* Make sure all highest clocks are included*/ + bw_params->clk_table.entries[i].socclk_mhz = find_max_clk_value(clock_table->SocClocks, NUM_SOCCLK_DPM_LEVELS); + bw_params->clk_table.entries[i].dispclk_mhz = find_max_clk_value(clock_table->DispClocks, NUM_DISPCLK_DPM_LEVELS); + bw_params->clk_table.entries[i].dppclk_mhz = find_max_clk_value(clock_table->DppClocks, NUM_DPPCLK_DPM_LEVELS); + ASSERT(clock_table->DcfClocks[i] == find_max_clk_value(clock_table->DcfClocks, NUM_DCFCLK_DPM_LEVELS)); + bw_params->clk_table.entries[i].phyclk_mhz = def_max.phyclk_mhz; + bw_params->clk_table.entries[i].phyclk_d18_mhz = def_max.phyclk_d18_mhz; + bw_params->clk_table.entries[i].dtbclk_mhz = def_max.dtbclk_mhz; + /* + * Set any 0 clocks to max default setting. Not an issue for + * power since we aren't doing switching in such case anyway + */ + for (i = 0; i < bw_params->clk_table.num_entries; i++) { + if (!bw_params->clk_table.entries[i].fclk_mhz) { + bw_params->clk_table.entries[i].fclk_mhz = def_max.fclk_mhz; + bw_params->clk_table.entries[i].memclk_mhz = def_max.memclk_mhz; + bw_params->clk_table.entries[i].voltage = def_max.voltage; + } + if (!bw_params->clk_table.entries[i].dcfclk_mhz) + bw_params->clk_table.entries[i].dcfclk_mhz = def_max.dcfclk_mhz; + if (!bw_params->clk_table.entries[i].socclk_mhz) + bw_params->clk_table.entries[i].socclk_mhz = def_max.socclk_mhz; + if (!bw_params->clk_table.entries[i].dispclk_mhz) + bw_params->clk_table.entries[i].dispclk_mhz = def_max.dispclk_mhz; + if (!bw_params->clk_table.entries[i].dppclk_mhz) + bw_params->clk_table.entries[i].dppclk_mhz = def_max.dppclk_mhz; + if (!bw_params->clk_table.entries[i].phyclk_mhz) + bw_params->clk_table.entries[i].phyclk_mhz = def_max.phyclk_mhz; + if (!bw_params->clk_table.entries[i].phyclk_d18_mhz) + bw_params->clk_table.entries[i].phyclk_d18_mhz = def_max.phyclk_d18_mhz; + if (!bw_params->clk_table.entries[i].dtbclk_mhz) + bw_params->clk_table.entries[i].dtbclk_mhz = def_max.dtbclk_mhz; + } + ASSERT(bw_params->clk_table.entries[i-1].dcfclk_mhz); bw_params->vram_type = bios_info->memory_type; - bw_params->num_channels = bios_info->ma_channel_number; + bw_params->num_channels = bios_info->ma_channel_number ? bios_info->ma_channel_number : 4; for (i = 0; i < WM_SET_COUNT; i++) { bw_params->wm_table.entries[i].wm_inst = i; @@ -671,10 +729,10 @@ void dcn314_clk_mgr_construct( } ASSERT(clk_mgr->smu_wm_set.wm_set); - smu_dpm_clks.dpm_clks = (DpmClocks_t *)dm_helpers_allocate_gpu_mem( + smu_dpm_clks.dpm_clks = (DpmClocks314_t *)dm_helpers_allocate_gpu_mem( clk_mgr->base.base.ctx, DC_MEM_ALLOC_TYPE_FRAME_BUFFER, - sizeof(DpmClocks_t), + sizeof(DpmClocks314_t), &smu_dpm_clks.mc_address.quad_part); if (smu_dpm_clks.dpm_clks == NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_smu.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_smu.h index a7958dc965810..047d19ea919c7 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_smu.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_smu.h @@ -36,6 +36,37 @@ typedef enum { WCK_RATIO_MAX } WCK_RATIO_e; +typedef struct { + uint32_t FClk; + uint32_t MemClk; + uint32_t Voltage; + uint8_t WckRatio; + uint8_t Spare[3]; +} DfPstateTable314_t; + +//Freq in MHz +//Voltage in milli volts with 2 fractional bits +typedef struct { + uint32_t DcfClocks[NUM_DCFCLK_DPM_LEVELS]; + uint32_t DispClocks[NUM_DISPCLK_DPM_LEVELS]; + uint32_t DppClocks[NUM_DPPCLK_DPM_LEVELS]; + uint32_t SocClocks[NUM_SOCCLK_DPM_LEVELS]; + uint32_t VClocks[NUM_VCN_DPM_LEVELS]; + uint32_t DClocks[NUM_VCN_DPM_LEVELS]; + uint32_t SocVoltage[NUM_SOC_VOLTAGE_LEVELS]; + DfPstateTable314_t DfPstateTable[NUM_DF_PSTATE_LEVELS]; + + uint8_t NumDcfClkLevelsEnabled; + uint8_t NumDispClkLevelsEnabled; //Applies to both Dispclk and Dppclk + uint8_t NumSocClkLevelsEnabled; + uint8_t VcnClkLevelsEnabled; //Applies to both Vclk and Dclk + uint8_t NumDfPstatesEnabled; + uint8_t spare[3]; + + uint32_t MinGfxClk; + uint32_t MaxGfxClk; +} DpmClocks314_t; + struct dcn314_watermarks { // Watermarks WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES]; @@ -43,7 +74,7 @@ struct dcn314_watermarks { }; struct dcn314_smu_dpm_clks { - DpmClocks_t *dpm_clks; + DpmClocks314_t *dpm_clks; union large_integer mc_address; }; From 31ec699ac5d8d17c4f696888708bb6b2567dfcd4 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Fri, 5 Aug 2022 16:18:31 -0400 Subject: [PATCH 267/427] drm/amd/display: Don't set DSC for phantom pipes [Description] Don't set DSC bit for phantom pipes, not required since phantom pipe don't have any actual output Reviewed-by: Jun Lei Acked-by: Brian Chang Signed-off-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 3316c4a649011..8118cfc5b4056 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -493,6 +493,7 @@ void dcn32_set_phantom_stream_timing(struct dc *dc, phantom_stream->timing.v_front_porch + phantom_stream->timing.v_sync_width + phantom_bp; + phantom_stream->timing.flags.DSC = 0; // Don't need DSC for phantom timing } /** From c65c71ae85095f94aae32d86aa78811318bf6a90 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Sat, 6 Aug 2022 12:00:26 -0400 Subject: [PATCH 268/427] drm/amd/display: Use pitch when calculating size to cache in MALL [Description] Use pitch when calculating size to cache in MALL Reviewed-by: Samson Tam Acked-by: Brian Chang Signed-off-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c index b3f8503cea9c5..955f52e6064df 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c @@ -63,7 +63,7 @@ uint32_t dcn32_helper_calculate_num_ways_for_subvp(struct dc *dc, struct dc_stat if (pipe->stream && pipe->plane_state && !pipe->top_pipe && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { bytes_per_pixel = pipe->plane_state->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4; - mall_region_pixels = pipe->stream->timing.h_addressable * pipe->stream->timing.v_addressable; + mall_region_pixels = pipe->plane_state->plane_size.surface_pitch * pipe->stream->timing.v_addressable; // For bytes required in MALL, calculate based on number of MBlks required num_mblks = (mall_region_pixels * bytes_per_pixel + From 5544a7b5a07480192eb5fd3536462faed2c21528 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 5 Aug 2022 12:59:47 -0400 Subject: [PATCH 269/427] drm/amd/display: avoid doing vm_init multiple time [why] this is to ensure that driver will not reprogram hvm_prefetch_req again if it is done. Reviewed-by: Martin Leung Acked-by: Brian Chang Signed-off-by: Charlene Liu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c index c5e200d09038f..5752271f22dfe 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c @@ -67,9 +67,15 @@ static uint32_t convert_and_clamp( void dcn21_dchvm_init(struct hubbub *hubbub) { struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); - uint32_t riommu_active; + uint32_t riommu_active, prefetch_done; int i; + REG_GET(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, &prefetch_done); + + if (prefetch_done) { + hubbub->riommu_active = true; + return; + } //Init DCHVM block REG_UPDATE(DCHVM_CTRL0, HOSTVM_INIT_REQ, 1); From ca01eba4e5b6b50144a62d7704763c41b68a0de9 Mon Sep 17 00:00:00 2001 From: Samson Tam Date: Mon, 25 Jul 2022 14:04:26 -0400 Subject: [PATCH 270/427] drm/amd/display: add chip revision to DCN32 [Why & How] Add GC_11_0_3_A0 as a chip revision to the DCN32 family Reviewed-by: Rodrigo Siqueira Acked-by: Brian Chang Signed-off-by: Samson Tam Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/include/dal_asic_id.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index e054f3494087f..9f3558c0ef110 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -247,10 +247,12 @@ enum { #define AMDGPU_FAMILY_GC_11_0_1 148 #define GC_11_0_0_A0 0x1 #define GC_11_0_2_A0 0x10 +#define GC_11_0_3_A0 0x20 #define GC_11_UNKNOWN 0xFF #define ASICREV_IS_GC_11_0_0(eChipRev) (eChipRev < GC_11_0_2_A0) -#define ASICREV_IS_GC_11_0_2(eChipRev) (eChipRev >= GC_11_0_2_A0 && eChipRev < GC_11_UNKNOWN) +#define ASICREV_IS_GC_11_0_2(eChipRev) (eChipRev >= GC_11_0_2_A0 && eChipRev < GC_11_0_3_A0) +#define ASICREV_IS_GC_11_0_3(eChipRev) (eChipRev >= GC_11_0_3_A0 && eChipRev < GC_11_UNKNOWN) /* * ASIC chip ID From 1af9add1f1512b10d9ce44ec7137612bc81ff069 Mon Sep 17 00:00:00 2001 From: Harish Kasiviswanathan Date: Fri, 5 Aug 2022 18:04:08 -0400 Subject: [PATCH 271/427] drm/amdgpu: Add decode_iv_ts helper for ih_v6 block Was missing. Add it. Signed-off-by: Harish Kasiviswanathan Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/ih_v6_0.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c b/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c index 92dc60a9d2094..085e613f3646d 100644 --- a/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c @@ -727,6 +727,7 @@ static const struct amd_ip_funcs ih_v6_0_ip_funcs = { static const struct amdgpu_ih_funcs ih_v6_0_funcs = { .get_wptr = ih_v6_0_get_wptr, .decode_iv = amdgpu_ih_decode_iv_helper, + .decode_iv_ts = amdgpu_ih_decode_iv_ts_helper, .set_rptr = ih_v6_0_set_rptr }; From bf7f7efbe051a59e9d0710cd26ea05f7ebc411a2 Mon Sep 17 00:00:00 2001 From: Andrey Strachuk Date: Tue, 19 Jul 2022 13:39:54 +0300 Subject: [PATCH 272/427] drm/amdgpu: remove useless condition in amdgpu_job_stop_all_jobs_on_sched() Local variable 'rq' is initialized by an address of field of drm_sched_job, so it does not make sense to compare 'rq' with NULL. Found by Linux Verification Center (linuxtesting.org) with SVACE. Reviewed-by: Andrey Grodzovsky Signed-off-by: Andrey Strachuk Fixes: 7c6e68c777f1 ("drm/amdgpu: Avoid HW GPU reset for RAS.") Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 5071b96be9824..b1099ee79c50b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -272,10 +272,6 @@ void amdgpu_job_stop_all_jobs_on_sched(struct drm_gpu_scheduler *sched) /* Signal all jobs not yet scheduled */ for (i = DRM_SCHED_PRIORITY_COUNT - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) { struct drm_sched_rq *rq = &sched->sched_rq[i]; - - if (!rq) - continue; - spin_lock(&rq->lock); list_for_each_entry(s_entity, &rq->entities, list) { while ((s_job = to_drm_sched_job(spsc_queue_pop(&s_entity->job_queue)))) { From 385bf5a856c196d5997ce4111a23df7e1b679c17 Mon Sep 17 00:00:00 2001 From: Khalid Masum Date: Tue, 16 Aug 2022 00:34:25 +0600 Subject: [PATCH 273/427] drm/amdgpu/vcn: Return void from the stop_dbg_mode There is no point in returning an int here. It only returns 0 which the caller never uses. Therefore return void and remove the unnecessary assignment. Addresses-Coverity: 1504988 ("Unused value") Fixes: 8da1170a16e4 ("drm/amdgpu: add VCN4 ip block support") Reviewed-by: Ruijing Dong Suggested-by: Ruijing Dong Suggested-by: Greg Kroah-Hartman Signed-off-by: Khalid Masum Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index ca14c3ef742ec..fb2d74f304481 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -1115,7 +1115,7 @@ static int vcn_v4_0_start(struct amdgpu_device *adev) * * Stop VCN block with dpg mode */ -static int vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) +static void vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) { uint32_t tmp; @@ -1133,7 +1133,6 @@ static int vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) /* disable dynamic power gating mode */ WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, regUVD_POWER_STATUS), 0, ~UVD_POWER_STATUS__UVD_PG_MODE_MASK); - return 0; } /** @@ -1154,7 +1153,7 @@ static int vcn_v4_0_stop(struct amdgpu_device *adev) fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF; if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { - r = vcn_v4_0_stop_dpg_mode(adev, i); + vcn_v4_0_stop_dpg_mode(adev, i); continue; } From fbe43dcd1aad7dbcee1cffdbe6c3e1d62c85f76a Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 4 Aug 2022 14:42:47 -0400 Subject: [PATCH 274/427] drm/amd/display: Include scaling factor for SubVP command [Description] For SubVP scaling cases, we must include the scaling info as part of the cmd. This is required when converting OTG line to HUBP line for the MALL_START_LINE programming. Reviewed-by: Jun Lei Acked-by: Brian Chang Signed-off-by: Alvin Lee Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/basics/conversion.c | 21 +++++++++++++++++++ .../drm/amd/display/dc/basics/conversion.h | 3 +++ drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 11 ++++++++++ .../amd/display/dc/dcn321/dcn321_resource.c | 2 +- 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.c b/drivers/gpu/drm/amd/display/dc/basics/conversion.c index 6767fab55c260..352e9afb85c6d 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.c +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.c @@ -100,3 +100,24 @@ void convert_float_matrix( matrix[i] = (uint16_t)reg_value; } } + +static uint32_t find_gcd(uint32_t a, uint32_t b) +{ + uint32_t remainder = 0; + while (b != 0) { + remainder = a % b; + a = b; + b = remainder; + } + return a; +} + +void reduce_fraction(uint32_t num, uint32_t den, + uint32_t *out_num, uint32_t *out_den) +{ + uint32_t gcd = 0; + + gcd = find_gcd(num, den); + *out_num = num / gcd; + *out_den = den / gcd; +} diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.h b/drivers/gpu/drm/amd/display/dc/basics/conversion.h index ade785c4fdc7d..81da4e6f7a1ac 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.h +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.h @@ -38,6 +38,9 @@ void convert_float_matrix( struct fixed31_32 *flt, uint32_t buffer_size); +void reduce_fraction(uint32_t num, uint32_t den, + uint32_t *out_num, uint32_t *out_den); + static inline unsigned int log_2(unsigned int num) { return ilog2(num); diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index c8059c28ac494..09b304507badb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -29,6 +29,7 @@ #include "dm_helpers.h" #include "dc_hw_types.h" #include "core_types.h" +#include "../basics/conversion.h" #define CTX dc_dmub_srv->ctx #define DC_LOGGER CTX->logger @@ -600,6 +601,7 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc, &cmd->fw_assisted_mclk_switch_v2.config_data.pipe_data[cmd_pipe_index]; struct dc_crtc_timing *main_timing = &subvp_pipe->stream->timing; struct dc_crtc_timing *phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing; + uint32_t out_num, out_den; pipe_data->mode = SUBVP; pipe_data->pipe_config.subvp_data.pix_clk_100hz = subvp_pipe->stream->timing.pix_clk_100hz; @@ -613,6 +615,15 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc, pipe_data->pipe_config.subvp_data.main_pipe_index = subvp_pipe->pipe_idx; pipe_data->pipe_config.subvp_data.is_drr = subvp_pipe->stream->ignore_msa_timing_param; + /* Calculate the scaling factor from the src and dst height. + * e.g. If 3840x2160 being downscaled to 1920x1080, the scaling factor is 1/2. + * Reduce the fraction 1080/2160 = 1/2 for the "scaling factor" + */ + reduce_fraction(subvp_pipe->stream->src.height, subvp_pipe->stream->dst.height, &out_num, &out_den); + // TODO: Uncomment below lines once DMCUB include headers are promoted + //pipe_data->pipe_config.subvp_data.scale_factor_numerator = out_num; + //pipe_data->pipe_config.subvp_data.scale_factor_denominator = out_den; + // Prefetch lines is equal to VACTIVE + BP + VSYNC pipe_data->pipe_config.subvp_data.prefetch_lines = phantom_timing->v_total - phantom_timing->v_front_porch; diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c index e9db5f8b6fdcc..c8b7d6ff38f4f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c @@ -1664,7 +1664,7 @@ static bool dcn321_resource_construct( dc->caps.subvp_prefetch_end_to_mall_start_us = 15; dc->caps.subvp_swath_height_margin_lines = 16; dc->caps.subvp_pstate_allow_width_us = 20; - + dc->caps.subvp_vertical_int_margin_us = 30; dc->caps.max_slave_planes = 1; dc->caps.max_slave_yuv_planes = 1; dc->caps.max_slave_rgb_planes = 1; From e42dfa66d59240afbdd8d4b47b87486db39504aa Mon Sep 17 00:00:00 2001 From: Shane Xiao Date: Mon, 15 Aug 2022 16:32:15 +0800 Subject: [PATCH 275/427] drm/amdgpu: Add secure display TA load for Renoir Add secure display TA load for Renoir Signed-off-by: Shane Xiao Reviewed-by: Aaron Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/psp_v12_0.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c index a2588200ea580..0b2ac418e4ac4 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c @@ -101,6 +101,16 @@ static int psp_v12_0_init_microcode(struct psp_context *psp) adev->psp.dtm_context.context.bin_desc.start_addr = (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr + le32_to_cpu(ta_hdr->dtm.offset_bytes); + + if (adev->apu_flags & AMD_APU_IS_RENOIR) { + adev->psp.securedisplay_context.context.bin_desc.fw_version = + le32_to_cpu(ta_hdr->securedisplay.fw_version); + adev->psp.securedisplay_context.context.bin_desc.size_bytes = + le32_to_cpu(ta_hdr->securedisplay.size_bytes); + adev->psp.securedisplay_context.context.bin_desc.start_addr = + (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr + + le32_to_cpu(ta_hdr->securedisplay.offset_bytes); + } } return 0; From de8341ee3ce7316883e836a2c4e9bf01ab651e0f Mon Sep 17 00:00:00 2001 From: Mukul Joshi Date: Fri, 12 Aug 2022 15:23:51 -0400 Subject: [PATCH 276/427] drm/amdgpu: Fix interrupt handling on ih_soft ring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are no backing hardware registers for ih_soft ring. As a result, don't try to access hardware registers for read and write pointers when processing interrupts on the IH soft ring. Signed-off-by: Mukul Joshi Acked-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/navi10_ih.c | 7 ++++++- drivers/gpu/drm/amd/amdgpu/vega10_ih.c | 7 ++++++- drivers/gpu/drm/amd/amdgpu/vega20_ih.c | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c index 4b5396d3e60f6..eec13cb5bf758 100644 --- a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c @@ -409,9 +409,11 @@ static u32 navi10_ih_get_wptr(struct amdgpu_device *adev, u32 wptr, tmp; struct amdgpu_ih_regs *ih_regs; - if (ih == &adev->irq.ih) { + if (ih == &adev->irq.ih || ih == &adev->irq.ih_soft) { /* Only ring0 supports writeback. On other rings fall back * to register-based code with overflow checking below. + * ih_soft ring doesn't have any backing hardware registers, + * update wptr and return. */ wptr = le32_to_cpu(*ih->wptr_cpu); @@ -483,6 +485,9 @@ static void navi10_ih_set_rptr(struct amdgpu_device *adev, { struct amdgpu_ih_regs *ih_regs; + if (ih == &adev->irq.ih_soft) + return; + if (ih->use_doorbell) { /* XXX check if swapping is necessary on BE */ *ih->rptr_cpu = ih->rptr; diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c index cdd599a081258..03b7066471f9a 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c @@ -334,9 +334,11 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev, u32 wptr, tmp; struct amdgpu_ih_regs *ih_regs; - if (ih == &adev->irq.ih) { + if (ih == &adev->irq.ih || ih == &adev->irq.ih_soft) { /* Only ring0 supports writeback. On other rings fall back * to register-based code with overflow checking below. + * ih_soft ring doesn't have any backing hardware registers, + * update wptr and return. */ wptr = le32_to_cpu(*ih->wptr_cpu); @@ -409,6 +411,9 @@ static void vega10_ih_set_rptr(struct amdgpu_device *adev, { struct amdgpu_ih_regs *ih_regs; + if (ih == &adev->irq.ih_soft) + return; + if (ih->use_doorbell) { /* XXX check if swapping is necessary on BE */ *ih->rptr_cpu = ih->rptr; diff --git a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c index 3b4eb8285943c..2022ffbb8dba5 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c @@ -385,9 +385,11 @@ static u32 vega20_ih_get_wptr(struct amdgpu_device *adev, u32 wptr, tmp; struct amdgpu_ih_regs *ih_regs; - if (ih == &adev->irq.ih) { + if (ih == &adev->irq.ih || ih == &adev->irq.ih_soft) { /* Only ring0 supports writeback. On other rings fall back * to register-based code with overflow checking below. + * ih_soft ring doesn't have any backing hardware registers, + * update wptr and return. */ wptr = le32_to_cpu(*ih->wptr_cpu); @@ -461,6 +463,9 @@ static void vega20_ih_set_rptr(struct amdgpu_device *adev, { struct amdgpu_ih_regs *ih_regs; + if (ih == &adev->irq.ih_soft) + return; + if (ih->use_doorbell) { /* XXX check if swapping is necessary on BE */ *ih->rptr_cpu = ih->rptr; From bbca24d0a3c11193bafb9e174f89f52a379006e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= Date: Mon, 15 Aug 2022 08:39:31 -0300 Subject: [PATCH 277/427] drm/amdgpu: Fix use-after-free on amdgpu_bo_list mutex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If amdgpu_cs_vm_handling returns r != 0, then it will unlock the bo_list_mutex inside the function amdgpu_cs_vm_handling and again on amdgpu_cs_parser_fini. This problem results in the following use-after-free problem: [ 220.280990] ------------[ cut here ]------------ [ 220.281000] refcount_t: underflow; use-after-free. [ 220.281019] WARNING: CPU: 1 PID: 3746 at lib/refcount.c:28 refcount_warn_saturate+0xba/0x110 [ 220.281029] ------------[ cut here ]------------ [ 220.281415] CPU: 1 PID: 3746 Comm: chrome:cs0 Tainted: G W L ------- --- 5.20.0-0.rc0.20220812git7ebfc85e2cd7.10.fc38.x86_64 #1 [ 220.281421] Hardware name: System manufacturer System Product Name/ROG STRIX X570-I GAMING, BIOS 4403 04/27/2022 [ 220.281426] RIP: 0010:refcount_warn_saturate+0xba/0x110 [ 220.281431] Code: 01 01 e8 79 4a 6f 00 0f 0b e9 42 47 a5 00 80 3d de 7e be 01 00 75 85 48 c7 c7 f8 98 8e 98 c6 05 ce 7e be 01 01 e8 56 4a 6f 00 <0f> 0b e9 1f 47 a5 00 80 3d b9 7e be 01 00 0f 85 5e ff ff ff 48 c7 [ 220.281437] RSP: 0018:ffffb4b0d18d7a80 EFLAGS: 00010282 [ 220.281443] RAX: 0000000000000026 RBX: 0000000000000003 RCX: 0000000000000000 [ 220.281448] RDX: 0000000000000001 RSI: ffffffff988d06dc RDI: 00000000ffffffff [ 220.281452] RBP: 00000000ffffffff R08: 0000000000000000 R09: ffffb4b0d18d7930 [ 220.281457] R10: 0000000000000003 R11: ffffa0672e2fffe8 R12: ffffa058ca360400 [ 220.281461] R13: ffffa05846c50a18 R14: 00000000fffffe00 R15: 0000000000000003 [ 220.281465] FS: 00007f82683e06c0(0000) GS:ffffa066e2e00000(0000) knlGS:0000000000000000 [ 220.281470] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 220.281475] CR2: 00003590005cc000 CR3: 00000001fca46000 CR4: 0000000000350ee0 [ 220.281480] Call Trace: [ 220.281485] [ 220.281490] amdgpu_cs_ioctl+0x4e2/0x2070 [amdgpu] [ 220.281806] ? amdgpu_cs_find_mapping+0xe0/0xe0 [amdgpu] [ 220.282028] drm_ioctl_kernel+0xa4/0x150 [ 220.282043] drm_ioctl+0x21f/0x420 [ 220.282053] ? amdgpu_cs_find_mapping+0xe0/0xe0 [amdgpu] [ 220.282275] ? lock_release+0x14f/0x460 [ 220.282282] ? _raw_spin_unlock_irqrestore+0x30/0x60 [ 220.282290] ? _raw_spin_unlock_irqrestore+0x30/0x60 [ 220.282297] ? lockdep_hardirqs_on+0x7d/0x100 [ 220.282305] ? _raw_spin_unlock_irqrestore+0x40/0x60 [ 220.282317] amdgpu_drm_ioctl+0x4a/0x80 [amdgpu] [ 220.282534] __x64_sys_ioctl+0x90/0xd0 [ 220.282545] do_syscall_64+0x5b/0x80 [ 220.282551] ? futex_wake+0x6c/0x150 [ 220.282568] ? lock_is_held_type+0xe8/0x140 [ 220.282580] ? do_syscall_64+0x67/0x80 [ 220.282585] ? lockdep_hardirqs_on+0x7d/0x100 [ 220.282592] ? do_syscall_64+0x67/0x80 [ 220.282597] ? do_syscall_64+0x67/0x80 [ 220.282602] ? lockdep_hardirqs_on+0x7d/0x100 [ 220.282609] entry_SYSCALL_64_after_hwframe+0x63/0xcd [ 220.282616] RIP: 0033:0x7f8282a4f8bf [ 220.282639] Code: 00 48 89 44 24 18 31 c0 48 8d 44 24 60 c7 04 24 10 00 00 00 48 89 44 24 08 48 8d 44 24 20 48 89 44 24 10 b8 10 00 00 00 0f 05 <89> c2 3d 00 f0 ff ff 77 18 48 8b 44 24 18 64 48 2b 04 25 28 00 00 [ 220.282644] RSP: 002b:00007f82683df410 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 [ 220.282651] RAX: ffffffffffffffda RBX: 00007f82683df588 RCX: 00007f8282a4f8bf [ 220.282655] RDX: 00007f82683df4d0 RSI: 00000000c0186444 RDI: 0000000000000018 [ 220.282659] RBP: 00007f82683df4d0 R08: 00007f82683df5e0 R09: 00007f82683df4b0 [ 220.282663] R10: 00001d04000a0600 R11: 0000000000000246 R12: 00000000c0186444 [ 220.282667] R13: 0000000000000018 R14: 00007f82683df588 R15: 0000000000000003 [ 220.282689] [ 220.282693] irq event stamp: 6232311 [ 220.282697] hardirqs last enabled at (6232319): [] __up_console_sem+0x5e/0x70 [ 220.282704] hardirqs last disabled at (6232326): [] __up_console_sem+0x43/0x70 [ 220.282709] softirqs last enabled at (6232072): [] __irq_exit_rcu+0xf9/0x170 [ 220.282716] softirqs last disabled at (6232061): [] __irq_exit_rcu+0xf9/0x170 [ 220.282722] ---[ end trace 0000000000000000 ]--- Therefore, remove the mutex_unlock from the amdgpu_cs_vm_handling function, so that amdgpu_cs_submit and amdgpu_cs_parser_fini can handle the unlock. Fixes: 90af0ca047f3 ("drm/amdgpu: Protect the amdgpu_bo_list list with a mutex v2") Reported-by: Mikhail Gavrilov Reviewed-by: Christian König Reviewed-by: Melissa Wen Signed-off-by: Maíra Canal Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index d8f1335bc68f4..b7bae833c804b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -837,16 +837,12 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) continue; r = amdgpu_vm_bo_update(adev, bo_va, false); - if (r) { - mutex_unlock(&p->bo_list->bo_list_mutex); + if (r) return r; - } r = amdgpu_sync_fence(&p->job->sync, bo_va->last_pt_update); - if (r) { - mutex_unlock(&p->bo_list->bo_list_mutex); + if (r) return r; - } } r = amdgpu_vm_handle_moved(adev, vm); From 085292c3d78015412b752ee1ca4c7725fd2bf2fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Tue, 16 Aug 2022 10:44:10 +0200 Subject: [PATCH 278/427] Revert "drm/amd/amdgpu: add pipe1 hardware support" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 4c7631800e6bf0eced08dd7b4f793fcd972f597d. Triggered GFX hangs with GNOME Wayland on Navi 21. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2117 Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index fafbad3cf08d8..a2a4dc1844c0a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -4846,7 +4846,7 @@ static int gfx_v10_0_sw_init(void *handle) case IP_VERSION(10, 3, 3): case IP_VERSION(10, 3, 7): adev->gfx.me.num_me = 1; - adev->gfx.me.num_pipe_per_me = 2; + adev->gfx.me.num_pipe_per_me = 1; adev->gfx.me.num_queue_per_pipe = 1; adev->gfx.mec.num_mec = 2; adev->gfx.mec.num_pipe_per_mec = 4; From eb6354e116305afbfde196be5120bfa8669fdc6a Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 16 Aug 2022 18:30:58 +0200 Subject: [PATCH 279/427] riscv: Ensure isa-ext static keys are writable riscv_isa_ext_keys[] is an array of static keys used in the unified ISA extension framework. The keys added to this array may be used anywhere, including in modules. Ensure the keys remain writable by placing them in the data section. The need to change riscv_isa_ext_keys[]'s section was found when the kvm module started failing to load. Commit 8eb060e10185 ("arch/riscv: add Zihintpause support") adds a static branch check for a newly added isa-ext key to cpu_relax(), which kvm uses. Fixes: c360cbec3511 ("riscv: introduce unified static key mechanism for ISA extensions") Signed-off-by: Andrew Jones Cc: stable@vger.kernel.org Reported-by: Ron Economos Reported-by: Anup Patel Reported-by: Conor Dooley Tested-by: Atish Patra Link: https://lore.kernel.org/r/20220816163058.3004536-1-ajones@ventanamicro.com Signed-off-by: Palmer Dabbelt --- arch/riscv/kernel/cpufeature.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index 553d755483ed6..3b5583db9d80e 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -28,7 +28,7 @@ unsigned long elf_hwcap __read_mostly; /* Host ISA bitmap */ static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly; -__ro_after_init DEFINE_STATIC_KEY_ARRAY_FALSE(riscv_isa_ext_keys, RISCV_ISA_EXT_KEY_MAX); +DEFINE_STATIC_KEY_ARRAY_FALSE(riscv_isa_ext_keys, RISCV_ISA_EXT_KEY_MAX); EXPORT_SYMBOL(riscv_isa_ext_keys); /** From de64b6b6fb6f369840d171b7c5a9baf31b8b2630 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Mon, 15 Aug 2022 11:08:48 +0800 Subject: [PATCH 280/427] net: sched: fix misuse of qcpu->backlog in gnet_stats_add_queue_cpu In the gnet_stats_add_queue_cpu function, the qstats->qlen statistics are incorrectly set to qcpu->backlog. Fixes: 448e163f8b9b ("gen_stats: Add gnet_stats_add_queue()") Signed-off-by: Zhengchao Shao Link: https://lore.kernel.org/r/20220815030848.276746-1-shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski --- net/core/gen_stats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c index a10335b4ba2d0..c8d137ef5980e 100644 --- a/net/core/gen_stats.c +++ b/net/core/gen_stats.c @@ -345,7 +345,7 @@ static void gnet_stats_add_queue_cpu(struct gnet_stats_queue *qstats, for_each_possible_cpu(i) { const struct gnet_stats_queue *qcpu = per_cpu_ptr(q, i); - qstats->qlen += qcpu->backlog; + qstats->qlen += qcpu->qlen; qstats->backlog += qcpu->backlog; qstats->drops += qcpu->drops; qstats->requeues += qcpu->requeues; From aa5762c34213aba7a72dc58e70601370805fa794 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 15 Aug 2022 12:39:20 +0200 Subject: [PATCH 281/427] netfilter: conntrack: NF_CONNTRACK_PROCFS should no longer default to y NF_CONNTRACK_PROCFS was marked obsolete in commit 54b07dca68557b09 ("netfilter: provide config option to disable ancient procfs parts") in v3.3. Signed-off-by: Geert Uytterhoeven Signed-off-by: Florian Westphal --- net/netfilter/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 22f15ebf6045b..4b8d04640ff32 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -144,7 +144,6 @@ config NF_CONNTRACK_ZONES config NF_CONNTRACK_PROCFS bool "Supply CT list in procfs (OBSOLETE)" - default y depends on PROC_FS help This option enables for the list of known conntrack entries From b71b7bfeac38c7a21c423ddafb29aa6258949df8 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 16 Aug 2022 14:15:21 +0200 Subject: [PATCH 282/427] testing: selftests: nft_flowtable.sh: use random netns names "ns1" is a too generic name, use a random suffix to avoid errors when such a netns exists. Also allows to run multiple instances of the script in parallel. Signed-off-by: Florian Westphal --- .../selftests/netfilter/nft_flowtable.sh | 246 +++++++++--------- 1 file changed, 128 insertions(+), 118 deletions(-) diff --git a/tools/testing/selftests/netfilter/nft_flowtable.sh b/tools/testing/selftests/netfilter/nft_flowtable.sh index d4ffebb989f88..c336e6c148d1f 100755 --- a/tools/testing/selftests/netfilter/nft_flowtable.sh +++ b/tools/testing/selftests/netfilter/nft_flowtable.sh @@ -14,6 +14,11 @@ # nft_flowtable.sh -o8000 -l1500 -r2000 # +sfx=$(mktemp -u "XXXXXXXX") +ns1="ns1-$sfx" +ns2="ns2-$sfx" +nsr1="nsr1-$sfx" +nsr2="nsr2-$sfx" # Kselftest framework requirement - SKIP code is 4. ksft_skip=4 @@ -36,18 +41,17 @@ checktool (){ checktool "nft --version" "run test without nft tool" checktool "ip -Version" "run test without ip tool" checktool "which nc" "run test without nc (netcat)" -checktool "ip netns add nsr1" "create net namespace" +checktool "ip netns add $nsr1" "create net namespace $nsr1" -ip netns add ns1 -ip netns add ns2 - -ip netns add nsr2 +ip netns add $ns1 +ip netns add $ns2 +ip netns add $nsr2 cleanup() { - for i in 1 2; do - ip netns del ns$i - ip netns del nsr$i - done + ip netns del $ns1 + ip netns del $ns2 + ip netns del $nsr1 + ip netns del $nsr2 rm -f "$ns1in" "$ns1out" rm -f "$ns2in" "$ns2out" @@ -59,22 +63,21 @@ trap cleanup EXIT sysctl -q net.netfilter.nf_log_all_netns=1 -ip link add veth0 netns nsr1 type veth peer name eth0 netns ns1 -ip link add veth1 netns nsr1 type veth peer name veth0 netns nsr2 +ip link add veth0 netns $nsr1 type veth peer name eth0 netns $ns1 +ip link add veth1 netns $nsr1 type veth peer name veth0 netns $nsr2 -ip link add veth1 netns nsr2 type veth peer name eth0 netns ns2 +ip link add veth1 netns $nsr2 type veth peer name eth0 netns $ns2 for dev in lo veth0 veth1; do - for i in 1 2; do - ip -net nsr$i link set $dev up - done + ip -net $nsr1 link set $dev up + ip -net $nsr2 link set $dev up done -ip -net nsr1 addr add 10.0.1.1/24 dev veth0 -ip -net nsr1 addr add dead:1::1/64 dev veth0 +ip -net $nsr1 addr add 10.0.1.1/24 dev veth0 +ip -net $nsr1 addr add dead:1::1/64 dev veth0 -ip -net nsr2 addr add 10.0.2.1/24 dev veth1 -ip -net nsr2 addr add dead:2::1/64 dev veth1 +ip -net $nsr2 addr add 10.0.2.1/24 dev veth1 +ip -net $nsr2 addr add dead:2::1/64 dev veth1 # set different MTUs so we need to push packets coming from ns1 (large MTU) # to ns2 (smaller MTU) to stack either to perform fragmentation (ip_no_pmtu_disc=1), @@ -106,49 +109,56 @@ do esac done -if ! ip -net nsr1 link set veth0 mtu $omtu; then +if ! ip -net $nsr1 link set veth0 mtu $omtu; then exit 1 fi -ip -net ns1 link set eth0 mtu $omtu +ip -net $ns1 link set eth0 mtu $omtu -if ! ip -net nsr2 link set veth1 mtu $rmtu; then +if ! ip -net $nsr2 link set veth1 mtu $rmtu; then exit 1 fi -ip -net ns2 link set eth0 mtu $rmtu +ip -net $ns2 link set eth0 mtu $rmtu # transfer-net between nsr1 and nsr2. # these addresses are not used for connections. -ip -net nsr1 addr add 192.168.10.1/24 dev veth1 -ip -net nsr1 addr add fee1:2::1/64 dev veth1 - -ip -net nsr2 addr add 192.168.10.2/24 dev veth0 -ip -net nsr2 addr add fee1:2::2/64 dev veth0 - -for i in 1 2; do - ip netns exec nsr$i sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null - ip netns exec nsr$i sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null - - ip -net ns$i link set lo up - ip -net ns$i link set eth0 up - ip -net ns$i addr add 10.0.$i.99/24 dev eth0 - ip -net ns$i route add default via 10.0.$i.1 - ip -net ns$i addr add dead:$i::99/64 dev eth0 - ip -net ns$i route add default via dead:$i::1 - if ! ip netns exec ns$i sysctl net.ipv4.tcp_no_metrics_save=1 > /dev/null; then +ip -net $nsr1 addr add 192.168.10.1/24 dev veth1 +ip -net $nsr1 addr add fee1:2::1/64 dev veth1 + +ip -net $nsr2 addr add 192.168.10.2/24 dev veth0 +ip -net $nsr2 addr add fee1:2::2/64 dev veth0 + +for i in 0 1; do + ip netns exec $nsr1 sysctl net.ipv4.conf.veth$i.forwarding=1 > /dev/null + ip netns exec $nsr2 sysctl net.ipv4.conf.veth$i.forwarding=1 > /dev/null +done + +for ns in $ns1 $ns2;do + ip -net $ns link set lo up + ip -net $ns link set eth0 up + + if ! ip netns exec $ns sysctl net.ipv4.tcp_no_metrics_save=1 > /dev/null; then echo "ERROR: Check Originator/Responder values (problem during address addition)" exit 1 fi - # don't set ip DF bit for first two tests - ip netns exec ns$i sysctl net.ipv4.ip_no_pmtu_disc=1 > /dev/null + ip netns exec $ns sysctl net.ipv4.ip_no_pmtu_disc=1 > /dev/null done -ip -net nsr1 route add default via 192.168.10.2 -ip -net nsr2 route add default via 192.168.10.1 +ip -net $ns1 addr add 10.0.1.99/24 dev eth0 +ip -net $ns2 addr add 10.0.2.99/24 dev eth0 +ip -net $ns1 route add default via 10.0.1.1 +ip -net $ns2 route add default via 10.0.2.1 +ip -net $ns1 addr add dead:1::99/64 dev eth0 +ip -net $ns2 addr add dead:2::99/64 dev eth0 +ip -net $ns1 route add default via dead:1::1 +ip -net $ns2 route add default via dead:2::1 + +ip -net $nsr1 route add default via 192.168.10.2 +ip -net $nsr2 route add default via 192.168.10.1 -ip netns exec nsr1 nft -f - < /dev/null; then - echo "ERROR: ns1 cannot reach ns2" 1>&2 +if ! ip netns exec $ns1 ping -c 1 -q 10.0.2.99 > /dev/null; then + echo "ERROR: $ns1 cannot reach ns2" 1>&2 exit 1 fi -if ! ip netns exec ns2 ping -c 1 -q 10.0.1.99 > /dev/null; then - echo "ERROR: ns2 cannot reach ns1" 1>&2 +if ! ip netns exec $ns2 ping -c 1 -q 10.0.1.99 > /dev/null; then + echo "ERROR: $ns2 cannot reach $ns1" 1>&2 exit 1 fi if [ $ret -eq 0 ];then - echo "PASS: netns routing/connectivity: ns1 can reach ns2" + echo "PASS: netns routing/connectivity: $ns1 can reach $ns2" fi ns1in=$(mktemp) @@ -312,24 +322,24 @@ make_file "$ns2in" # First test: # No PMTU discovery, nsr1 is expected to fragment packets from ns1 to ns2 as needed. -if test_tcp_forwarding ns1 ns2; then +if test_tcp_forwarding $ns1 $ns2; then echo "PASS: flow offloaded for ns1/ns2" else echo "FAIL: flow offload for ns1/ns2:" 1>&2 - ip netns exec nsr1 nft list ruleset + ip netns exec $nsr1 nft list ruleset ret=1 fi # delete default route, i.e. ns2 won't be able to reach ns1 and # will depend on ns1 being masqueraded in nsr1. # expect ns1 has nsr1 address. -ip -net ns2 route del default via 10.0.2.1 -ip -net ns2 route del default via dead:2::1 -ip -net ns2 route add 192.168.10.1 via 10.0.2.1 +ip -net $ns2 route del default via 10.0.2.1 +ip -net $ns2 route del default via dead:2::1 +ip -net $ns2 route add 192.168.10.1 via 10.0.2.1 # Second test: # Same, but with NAT enabled. -ip netns exec nsr1 nft -f - <&2 - ip netns exec nsr1 nft list ruleset + ip netns exec $nsr1 nft list ruleset ret=1 fi # Third test: # Same as second test, but with PMTU discovery enabled. -handle=$(ip netns exec nsr1 nft -a list table inet filter | grep something-to-grep-for | cut -d \# -f 2) +handle=$(ip netns exec $nsr1 nft -a list table inet filter | grep something-to-grep-for | cut -d \# -f 2) -if ! ip netns exec nsr1 nft delete rule inet filter forward $handle; then +if ! ip netns exec $nsr1 nft delete rule inet filter forward $handle; then echo "FAIL: Could not delete large-packet accept rule" exit 1 fi -ip netns exec ns1 sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null -ip netns exec ns2 sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null +ip netns exec $ns1 sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null +ip netns exec $ns2 sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null -if test_tcp_forwarding_nat ns1 ns2; then +if test_tcp_forwarding_nat $ns1 $ns2; then echo "PASS: flow offloaded for ns1/ns2 with NAT and pmtu discovery" else echo "FAIL: flow offload for ns1/ns2 with NAT and pmtu discovery" 1>&2 - ip netns exec nsr1 nft list ruleset + ip netns exec $nsr1 nft list ruleset fi # Another test: # Add bridge interface br0 to Router1, with NAT enabled. -ip -net nsr1 link add name br0 type bridge -ip -net nsr1 addr flush dev veth0 -ip -net nsr1 link set up dev veth0 -ip -net nsr1 link set veth0 master br0 -ip -net nsr1 addr add 10.0.1.1/24 dev br0 -ip -net nsr1 addr add dead:1::1/64 dev br0 -ip -net nsr1 link set up dev br0 +ip -net $nsr1 link add name br0 type bridge +ip -net $nsr1 addr flush dev veth0 +ip -net $nsr1 link set up dev veth0 +ip -net $nsr1 link set veth0 master br0 +ip -net $nsr1 addr add 10.0.1.1/24 dev br0 +ip -net $nsr1 addr add dead:1::1/64 dev br0 +ip -net $nsr1 link set up dev br0 -ip netns exec nsr1 sysctl net.ipv4.conf.br0.forwarding=1 > /dev/null +ip netns exec $nsr1 sysctl net.ipv4.conf.br0.forwarding=1 > /dev/null # br0 with NAT enabled. -ip netns exec nsr1 nft -f - <&2 - ip netns exec nsr1 nft list ruleset + ip netns exec $nsr1 nft list ruleset ret=1 fi # Another test: # Add bridge interface br0 to Router1, with NAT and VLAN. -ip -net nsr1 link set veth0 nomaster -ip -net nsr1 link set down dev veth0 -ip -net nsr1 link add link veth0 name veth0.10 type vlan id 10 -ip -net nsr1 link set up dev veth0 -ip -net nsr1 link set up dev veth0.10 -ip -net nsr1 link set veth0.10 master br0 - -ip -net ns1 addr flush dev eth0 -ip -net ns1 link add link eth0 name eth0.10 type vlan id 10 -ip -net ns1 link set eth0 up -ip -net ns1 link set eth0.10 up -ip -net ns1 addr add 10.0.1.99/24 dev eth0.10 -ip -net ns1 route add default via 10.0.1.1 -ip -net ns1 addr add dead:1::99/64 dev eth0.10 - -if test_tcp_forwarding_nat ns1 ns2; then +ip -net $nsr1 link set veth0 nomaster +ip -net $nsr1 link set down dev veth0 +ip -net $nsr1 link add link veth0 name veth0.10 type vlan id 10 +ip -net $nsr1 link set up dev veth0 +ip -net $nsr1 link set up dev veth0.10 +ip -net $nsr1 link set veth0.10 master br0 + +ip -net $ns1 addr flush dev eth0 +ip -net $ns1 link add link eth0 name eth0.10 type vlan id 10 +ip -net $ns1 link set eth0 up +ip -net $ns1 link set eth0.10 up +ip -net $ns1 addr add 10.0.1.99/24 dev eth0.10 +ip -net $ns1 route add default via 10.0.1.1 +ip -net $ns1 addr add dead:1::99/64 dev eth0.10 + +if test_tcp_forwarding_nat $ns1 $ns2; then echo "PASS: flow offloaded for ns1/ns2 with bridge NAT and VLAN" else echo "FAIL: flow offload for ns1/ns2 with bridge NAT and VLAN" 1>&2 - ip netns exec nsr1 nft list ruleset + ip netns exec $nsr1 nft list ruleset ret=1 fi # restore test topology (remove bridge and VLAN) -ip -net nsr1 link set veth0 nomaster -ip -net nsr1 link set veth0 down -ip -net nsr1 link set veth0.10 down -ip -net nsr1 link delete veth0.10 type vlan -ip -net nsr1 link delete br0 type bridge -ip -net ns1 addr flush dev eth0.10 -ip -net ns1 link set eth0.10 down -ip -net ns1 link set eth0 down -ip -net ns1 link delete eth0.10 type vlan +ip -net $nsr1 link set veth0 nomaster +ip -net $nsr1 link set veth0 down +ip -net $nsr1 link set veth0.10 down +ip -net $nsr1 link delete veth0.10 type vlan +ip -net $nsr1 link delete br0 type bridge +ip -net $ns1 addr flush dev eth0.10 +ip -net $ns1 link set eth0.10 down +ip -net $ns1 link set eth0 down +ip -net $ns1 link delete eth0.10 type vlan # restore address in ns1 and nsr1 -ip -net ns1 link set eth0 up -ip -net ns1 addr add 10.0.1.99/24 dev eth0 -ip -net ns1 route add default via 10.0.1.1 -ip -net ns1 addr add dead:1::99/64 dev eth0 -ip -net ns1 route add default via dead:1::1 -ip -net nsr1 addr add 10.0.1.1/24 dev veth0 -ip -net nsr1 addr add dead:1::1/64 dev veth0 -ip -net nsr1 link set up dev veth0 +ip -net $ns1 link set eth0 up +ip -net $ns1 addr add 10.0.1.99/24 dev eth0 +ip -net $ns1 route add default via 10.0.1.1 +ip -net $ns1 addr add dead:1::99/64 dev eth0 +ip -net $ns1 route add default via dead:1::1 +ip -net $nsr1 addr add 10.0.1.1/24 dev veth0 +ip -net $nsr1 addr add dead:1::1/64 dev veth0 +ip -net $nsr1 link set up dev veth0 KEY_SHA="0x"$(ps -xaf | sha1sum | cut -d " " -f 1) KEY_AES="0x"$(ps -xaf | md5sum | cut -d " " -f 1) @@ -480,23 +490,23 @@ do_esp() { } -do_esp nsr1 192.168.10.1 192.168.10.2 10.0.1.0/24 10.0.2.0/24 $SPI1 $SPI2 +do_esp $nsr1 192.168.10.1 192.168.10.2 10.0.1.0/24 10.0.2.0/24 $SPI1 $SPI2 -do_esp nsr2 192.168.10.2 192.168.10.1 10.0.2.0/24 10.0.1.0/24 $SPI2 $SPI1 +do_esp $nsr2 192.168.10.2 192.168.10.1 10.0.2.0/24 10.0.1.0/24 $SPI2 $SPI1 -ip netns exec nsr1 nft delete table ip nat +ip netns exec $nsr1 nft delete table ip nat # restore default routes -ip -net ns2 route del 192.168.10.1 via 10.0.2.1 -ip -net ns2 route add default via 10.0.2.1 -ip -net ns2 route add default via dead:2::1 +ip -net $ns2 route del 192.168.10.1 via 10.0.2.1 +ip -net $ns2 route add default via 10.0.2.1 +ip -net $ns2 route add default via dead:2::1 -if test_tcp_forwarding ns1 ns2; then +if test_tcp_forwarding $ns1 $ns2; then echo "PASS: ipsec tunnel mode for ns1/ns2" else echo "FAIL: ipsec tunnel mode for ns1/ns2" - ip netns exec nsr1 nft list ruleset 1>&2 - ip netns exec nsr1 cat /proc/net/xfrm_stat 1>&2 + ip netns exec $nsr1 nft list ruleset 1>&2 + ip netns exec $nsr1 cat /proc/net/xfrm_stat 1>&2 fi exit $ret From 88392a0dd0ab263edb4ca416ebdecabd8289158a Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Wed, 27 Jul 2022 10:59:24 +0100 Subject: [PATCH 283/427] platform/x86: serial-multi-instantiate: Add CLSA0101 Laptop The device CLSA0101 has two instances of CS35L41 connected by I2C. Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20220727095924.80884-5-tanureal@opensource.cirrus.com Link: https://lore.kernel.org/r/20220816194639.13870-1-cam@neo-zeon.de Signed-off-by: Takashi Iwai --- drivers/platform/x86/serial-multi-instantiate.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/serial-multi-instantiate.c b/drivers/platform/x86/serial-multi-instantiate.c index 1e8063b7c169e..e98007197cf52 100644 --- a/drivers/platform/x86/serial-multi-instantiate.c +++ b/drivers/platform/x86/serial-multi-instantiate.c @@ -329,6 +329,7 @@ static const struct acpi_device_id smi_acpi_ids[] = { { "CSC3551", (unsigned long)&cs35l41_hda }, /* Non-conforming _HID for Cirrus Logic already released */ { "CLSA0100", (unsigned long)&cs35l41_hda }, + { "CLSA0101", (unsigned long)&cs35l41_hda }, { } }; MODULE_DEVICE_TABLE(acpi, smi_acpi_ids); From 849f16bbfb686cf75e67c536d196027fa8bfc803 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 15 Aug 2022 17:23:58 -0700 Subject: [PATCH 284/427] tls: rx: react to strparser initialization errors Even though the normal strparser's init function has a return value we got away with ignoring errors until now, as it only validates the parameters and we were passing correct parameters. tls_strp can fail to init on memory allocation errors, which syzbot duly induced and reported. Reported-by: syzbot+abd45eb849b05194b1b6@syzkaller.appspotmail.com Fixes: 84c61fe1a75b ("tls: rx: do not use the standard strparser") Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- net/tls/tls_sw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index f76119f62f1b5..fe27241cd13fc 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -2702,7 +2702,9 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx) crypto_info->version != TLS_1_3_VERSION && !!(tfm->__crt_alg->cra_flags & CRYPTO_ALG_ASYNC); - tls_strp_init(&sw_ctx_rx->strp, sk); + rc = tls_strp_init(&sw_ctx_rx->strp, sk); + if (rc) + goto free_aead; } goto out; From f3c6efc72f3b20ec23566e768979802f0a398f04 Mon Sep 17 00:00:00 2001 From: Oliver Upton Date: Tue, 16 Aug 2022 19:25:53 +0000 Subject: [PATCH 285/427] KVM: arm64: Treat PMCR_EL1.LC as RES1 on asymmetric systems KVM does not support AArch32 on asymmetric systems. To that end, enforce AArch64-only behavior on PMCR_EL1.LC when on an asymmetric system. Fixes: 2122a833316f ("arm64: Allow mismatched 32-bit EL0 support") Signed-off-by: Oliver Upton Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20220816192554.1455559-2-oliver.upton@linux.dev --- arch/arm64/include/asm/kvm_host.h | 4 ++++ arch/arm64/kvm/arm.c | 3 +-- arch/arm64/kvm/sys_regs.c | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index f38ef299f13bd..e9c9388ccc024 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -929,6 +929,10 @@ bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu); (system_supports_mte() && \ test_bit(KVM_ARCH_FLAG_MTE_ENABLED, &(kvm)->arch.flags)) +#define kvm_supports_32bit_el0() \ + (system_supports_32bit_el0() && \ + !static_branch_unlikely(&arm64_mismatched_32bit_el0)) + int kvm_trng_call(struct kvm_vcpu *vcpu); #ifdef CONFIG_KVM extern phys_addr_t hyp_mem_base; diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 8fe73ee5fa845..e508b613ce6ee 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -757,8 +757,7 @@ static bool vcpu_mode_is_bad_32bit(struct kvm_vcpu *vcpu) if (likely(!vcpu_mode_is_32bit(vcpu))) return false; - return !system_supports_32bit_el0() || - static_branch_unlikely(&arm64_mismatched_32bit_el0); + return !kvm_supports_32bit_el0(); } /** diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 333efddb1e271..3c4f5c9ac9f75 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -652,7 +652,7 @@ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) */ val = ((pmcr & ~ARMV8_PMU_PMCR_MASK) | (ARMV8_PMU_PMCR_MASK & 0xdecafbad)) & (~ARMV8_PMU_PMCR_E); - if (!system_supports_32bit_el0()) + if (!kvm_supports_32bit_el0()) val |= ARMV8_PMU_PMCR_LC; __vcpu_sys_reg(vcpu, r->reg) = val; } @@ -701,7 +701,7 @@ static bool access_pmcr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, val = __vcpu_sys_reg(vcpu, PMCR_EL0); val &= ~ARMV8_PMU_PMCR_MASK; val |= p->regval & ARMV8_PMU_PMCR_MASK; - if (!system_supports_32bit_el0()) + if (!kvm_supports_32bit_el0()) val |= ARMV8_PMU_PMCR_LC; __vcpu_sys_reg(vcpu, PMCR_EL0) = val; kvm_pmu_handle_pmcr(vcpu, val); From b10d86fb8e46cc812171728bcd326df2f34e9ed5 Mon Sep 17 00:00:00 2001 From: Oliver Upton Date: Tue, 16 Aug 2022 19:25:54 +0000 Subject: [PATCH 286/427] KVM: arm64: Reject 32bit user PSTATE on asymmetric systems KVM does not support AArch32 EL0 on asymmetric systems. To that end, prevent userspace from configuring a vCPU in such a state through setting PSTATE. It is already ABI that KVM rejects such a write on a system where AArch32 EL0 is unsupported. Though the kernel's definition of a 32bit system changed in commit 2122a833316f ("arm64: Allow mismatched 32-bit EL0 support"), KVM's did not. Fixes: 2122a833316f ("arm64: Allow mismatched 32-bit EL0 support") Signed-off-by: Oliver Upton Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20220816192554.1455559-3-oliver.upton@linux.dev --- arch/arm64/kvm/guest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 8c607199cad14..f802a3b3f8dbc 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -242,7 +242,7 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) u64 mode = (*(u64 *)valp) & PSR_AA32_MODE_MASK; switch (mode) { case PSR_AA32_MODE_USR: - if (!system_supports_32bit_el0()) + if (!kvm_supports_32bit_el0()) return -EINVAL; break; case PSR_AA32_MODE_FIQ: From 1ff954f9ab054675b9eb02dd14add8f7aa376d71 Mon Sep 17 00:00:00 2001 From: Stefan Binding Date: Tue, 16 Aug 2022 16:19:01 +0100 Subject: [PATCH 287/427] ALSA: hda/cs8409: Support new Dolphin Variants Add 4 new Dolphin Systems, same configuration as older systems. Signed-off-by: Stefan Binding Link: https://lore.kernel.org/r/20220816151901.1398007-1-sbinding@opensource.cirrus.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_cs8409-tables.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/pci/hda/patch_cs8409-tables.c b/sound/pci/hda/patch_cs8409-tables.c index e0d3a8be2e38b..b288874e401e5 100644 --- a/sound/pci/hda/patch_cs8409-tables.c +++ b/sound/pci/hda/patch_cs8409-tables.c @@ -546,6 +546,10 @@ const struct snd_pci_quirk cs8409_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0BD6, "Dolphin", CS8409_DOLPHIN), SND_PCI_QUIRK(0x1028, 0x0BD7, "Dolphin", CS8409_DOLPHIN), SND_PCI_QUIRK(0x1028, 0x0BD8, "Dolphin", CS8409_DOLPHIN), + SND_PCI_QUIRK(0x1028, 0x0C43, "Dolphin", CS8409_DOLPHIN), + SND_PCI_QUIRK(0x1028, 0x0C50, "Dolphin", CS8409_DOLPHIN), + SND_PCI_QUIRK(0x1028, 0x0C51, "Dolphin", CS8409_DOLPHIN), + SND_PCI_QUIRK(0x1028, 0x0C52, "Dolphin", CS8409_DOLPHIN), {} /* terminator */ }; From 3fd6d6e2b4e80fe45bfd1c8f01dff7d30a0f9b53 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:17 +0200 Subject: [PATCH 288/427] thermal/of: Rework the thermal device tree initialization The following changes are reworking entirely the thermal device tree initialization. The old version is kept until the different drivers using it are converted to the new API. The old approach creates the different actors independently. This approach is the source of the code duplication in the thermal OF because a thermal zone is created but a sensor is registered after. The thermal zones are created unconditionnaly with a fake sensor at init time, thus forcing to provide fake ops and store all the thermal zone related information in duplicated structures. Then the sensor is initialized and the code looks up the thermal zone name using the device tree. Then the sensor is associated to the thermal zone, and the sensor specific ops are called with a second level of indirection from the thermal zone ops. When a sensor is removed (with a module unload), the thermal zone stays there with the fake sensor. The cooling device associated with a thermal zone and a trip point is stored in a list, again duplicating information, using the node name of the device tree to match afterwards the cooling devices. The new approach is simpler, it creates a thermal zone when the sensor is registered and destroys it when the sensor is removed. All the matching between the cooling device, trip points and thermal zones are done using the device tree, as well as bindings. The ops are no longer specific but uses the generic ones provided by the thermal framework. When the old code won't have any users, it can be removed and the remaining thermal OF code will be much simpler. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-2-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/thermal_of.c | 460 ++++++++++++++++++++++++++++++++++- include/linux/thermal.h | 18 ++ 2 files changed, 468 insertions(+), 10 deletions(-) diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 802c30b72a925..82236fec7c654 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -811,16 +811,6 @@ static int thermal_of_get_trip_type(struct device_node *np, return -ENODEV; } -/** - * thermal_of_populate_trip - parse and fill one trip point data - * @np: DT node containing a trip point node - * @trip: trip point data structure to be filled up - * - * This function parses a trip point type of node represented by - * @np parameter and fills the read data into @trip data structure. - * - * Return: 0 on success, proper error code otherwise - */ static int thermal_of_populate_trip(struct device_node *np, struct thermal_trip *trip) { @@ -1065,6 +1055,456 @@ static __init void of_thermal_destroy_zones(void) of_node_put(np); } +static struct device_node *of_thermal_zone_find(struct device_node *sensor, int id) +{ + struct device_node *np, *tz; + struct of_phandle_args sensor_specs; + + np = of_find_node_by_name(NULL, "thermal-zones"); + if (!np) { + pr_err("Unable to find thermal zones description\n"); + return ERR_PTR(-EINVAL); + } + + /* + * Search for each thermal zone, a defined sensor + * corresponding to the one passed as parameter + */ + for_each_available_child_of_node(np, tz) { + + int count, i; + + count = of_count_phandle_with_args(tz, "thermal-sensors", + "#thermal-sensor-cells"); + if (count <= 0) { + pr_err("%pOFn: missing thermal sensor\n", tz); + tz = ERR_PTR(-EINVAL); + goto out; + } + + for (i = 0; i < count; i++) { + + int ret; + + ret = of_parse_phandle_with_args(tz, "thermal-sensors", + "#thermal-sensor-cells", + i, &sensor_specs); + if (ret < 0) { + pr_err("%pOFn: Failed to read thermal-sensors cells: %d\n", tz, ret); + tz = ERR_PTR(ret); + goto out; + } + + if ((sensor == sensor_specs.np) && id == (sensor_specs.args_count ? + sensor_specs.args[0] : 0)) { + pr_debug("sensor %pOFn id=%d belongs to %pOFn\n", sensor, id, tz); + goto out; + } + } + } +out: + of_node_put(np); + return tz; +} + +static int thermal_of_monitor_init(struct device_node *np, int *delay, int *pdelay) +{ + int ret; + + ret = of_property_read_u32(np, "polling-delay-passive", pdelay); + if (ret < 0) { + pr_err("%pOFn: missing polling-delay-passive property\n", np); + return ret; + } + + ret = of_property_read_u32(np, "polling-delay", delay); + if (ret < 0) { + pr_err("%pOFn: missing polling-delay property\n", np); + return ret; + } + + return 0; +} + +static struct thermal_zone_params *thermal_of_parameters_init(struct device_node *np) +{ + struct thermal_zone_params *tzp; + int coef[2]; + int ncoef = ARRAY_SIZE(coef); + int prop, ret; + + tzp = kzalloc(sizeof(*tzp), GFP_KERNEL); + if (!tzp) + return ERR_PTR(-ENOMEM); + + tzp->no_hwmon = true; + + if (!of_property_read_u32(np, "sustainable-power", &prop)) + tzp->sustainable_power = prop; + + /* + * For now, the thermal framework supports only one sensor per + * thermal zone. Thus, we are considering only the first two + * values as slope and offset. + */ + ret = of_property_read_u32_array(np, "coefficients", coef, ncoef); + if (ret) { + coef[0] = 1; + coef[1] = 0; + } + + tzp->slope = coef[0]; + tzp->offset = coef[1]; + + return tzp; +} + +static struct device_node *thermal_of_zone_get_by_name(struct thermal_zone_device *tz) +{ + struct device_node *np, *tz_np; + + np = of_find_node_by_name(NULL, "thermal-zones"); + if (!np) + return ERR_PTR(-ENODEV); + + tz_np = of_get_child_by_name(np, tz->type); + + of_node_put(np); + + if (!tz_np) + return ERR_PTR(-ENODEV); + + return tz_np; +} + +static int __thermal_of_unbind(struct device_node *map_np, int index, int trip_id, + struct thermal_zone_device *tz, struct thermal_cooling_device *cdev) +{ + struct of_phandle_args cooling_spec; + int ret; + + ret = of_parse_phandle_with_args(map_np, "cooling-device", "#cooling-cells", + index, &cooling_spec); + + of_node_put(cooling_spec.np); + + if (ret < 0) { + pr_err("Invalid cooling-device entry\n"); + return ret; + } + + if (cooling_spec.args_count < 2) { + pr_err("wrong reference to cooling device, missing limits\n"); + return -EINVAL; + } + + if (cooling_spec.np != cdev->np) + return 0; + + ret = thermal_zone_unbind_cooling_device(tz, trip_id, cdev); + if (ret) + pr_err("Failed to unbind '%s' with '%s': %d\n", tz->type, cdev->type, ret); + + return ret; +} + +static int __thermal_of_bind(struct device_node *map_np, int index, int trip_id, + struct thermal_zone_device *tz, struct thermal_cooling_device *cdev) +{ + struct of_phandle_args cooling_spec; + int ret, weight = THERMAL_WEIGHT_DEFAULT; + + of_property_read_u32(map_np, "contribution", &weight); + + ret = of_parse_phandle_with_args(map_np, "cooling-device", "#cooling-cells", + index, &cooling_spec); + + of_node_put(cooling_spec.np); + + if (ret < 0) { + pr_err("Invalid cooling-device entry\n"); + return ret; + } + + if (cooling_spec.args_count < 2) { + pr_err("wrong reference to cooling device, missing limits\n"); + return -EINVAL; + } + + if (cooling_spec.np != cdev->np) + return 0; + + ret = thermal_zone_bind_cooling_device(tz, trip_id, cdev, cooling_spec.args[1], + cooling_spec.args[0], + weight); + if (ret) + pr_err("Failed to bind '%s' with '%s': %d\n", tz->type, cdev->type, ret); + + return ret; +} + +static int thermal_of_for_each_cooling_device(struct device_node *tz_np, struct device_node *map_np, + struct thermal_zone_device *tz, struct thermal_cooling_device *cdev, + int (*action)(struct device_node *, int, int, + struct thermal_zone_device *, struct thermal_cooling_device *)) +{ + struct device_node *tr_np; + int count, i, trip_id; + + tr_np = of_parse_phandle(map_np, "trip", 0); + if (!tr_np) + return -ENODEV; + + trip_id = of_find_trip_id(tz_np, tr_np); + if (trip_id < 0) + return trip_id; + + count = of_count_phandle_with_args(map_np, "cooling-device", "#cooling-cells"); + if (count <= 0) { + pr_err("Add a cooling_device property with at least one device\n"); + return -ENOENT; + } + + /* + * At this point, we don't want to bail out when there is an + * error, we will try to bind/unbind as many as possible + * cooling devices + */ + for (i = 0; i < count; i++) + action(map_np, i, trip_id, tz, cdev); + + return 0; +} + +static int thermal_of_for_each_cooling_maps(struct thermal_zone_device *tz, + struct thermal_cooling_device *cdev, + int (*action)(struct device_node *, int, int, + struct thermal_zone_device *, struct thermal_cooling_device *)) +{ + struct device_node *tz_np, *cm_np, *child; + int ret = 0; + + tz_np = thermal_of_zone_get_by_name(tz); + if (IS_ERR(tz_np)) { + pr_err("Failed to get node tz by name\n"); + return PTR_ERR(tz_np); + } + + cm_np = of_get_child_by_name(tz_np, "cooling-maps"); + if (!cm_np) + goto out; + + for_each_child_of_node(cm_np, child) { + ret = thermal_of_for_each_cooling_device(tz_np, child, tz, cdev, action); + if (ret) + break; + } + + of_node_put(cm_np); +out: + of_node_put(tz_np); + + return ret; +} + +static int thermal_of_bind(struct thermal_zone_device *tz, + struct thermal_cooling_device *cdev) +{ + return thermal_of_for_each_cooling_maps(tz, cdev, __thermal_of_bind); +} + +static int thermal_of_unbind(struct thermal_zone_device *tz, + struct thermal_cooling_device *cdev) +{ + return thermal_of_for_each_cooling_maps(tz, cdev, __thermal_of_unbind); +} + +/** + * thermal_of_zone_unregister - Cleanup the specific allocated ressources + * + * This function disables the thermal zone and frees the different + * ressources allocated specific to the thermal OF. + * + * @tz: a pointer to the thermal zone structure + */ +void thermal_of_zone_unregister(struct thermal_zone_device *tz) +{ + thermal_zone_device_disable(tz); + thermal_zone_device_unregister(tz); + kfree(tz->trips); + kfree(tz->tzp); + kfree(tz->ops); +} +EXPORT_SYMBOL_GPL(thermal_of_zone_unregister); + +/** + * thermal_of_zone_register - Register a thermal zone with device node + * sensor + * + * The thermal_of_zone_register() parses a device tree given a device + * node sensor and identifier. It searches for the thermal zone + * associated to the couple sensor/id and retrieves all the thermal + * zone properties and registers new thermal zone with those + * properties. + * + * @sensor: A device node pointer corresponding to the sensor in the device tree + * @id: An integer as sensor identifier + * @data: A private data to be stored in the thermal zone dedicated private area + * @ops: A set of thermal sensor ops + * + * Return: a valid thermal zone structure pointer on success. + * - EINVAL: if the device tree thermal description is malformed + * - ENOMEM: if one structure can not be allocated + * - Other negative errors are returned by the underlying called functions + */ +struct thermal_zone_device *thermal_of_zone_register(struct device_node *sensor, int id, void *data, + const struct thermal_zone_device_ops *ops) +{ + struct thermal_zone_device *tz; + struct thermal_trip *trips; + struct thermal_zone_params *tzp; + struct thermal_zone_device_ops *of_ops; + struct device_node *np; + int delay, pdelay; + int ntrips, mask; + int ret; + + of_ops = kmemdup(ops, sizeof(*ops), GFP_KERNEL); + if (!of_ops) + return ERR_PTR(-ENOMEM); + + np = of_thermal_zone_find(sensor, id); + if (IS_ERR(np)) { + pr_err("Failed to find thermal zone for %pOFn id=%d\n", sensor, id); + return ERR_CAST(np); + } + + trips = thermal_of_trips_init(np, &ntrips); + if (IS_ERR(trips)) { + pr_err("Failed to find trip points for %pOFn id=%d\n", sensor, id); + return ERR_CAST(trips); + } + + ret = thermal_of_monitor_init(np, &delay, &pdelay); + if (ret) { + pr_err("Failed to initialize monitoring delays from %pOFn\n", np); + goto out_kfree_trips; + } + + tzp = thermal_of_parameters_init(np); + if (IS_ERR(tzp)) { + ret = PTR_ERR(tzp); + pr_err("Failed to initialize parameter from %pOFn: %d\n", np, ret); + goto out_kfree_trips; + } + + of_ops->get_trip_type = of_ops->get_trip_type ? : of_thermal_get_trip_type; + of_ops->get_trip_temp = of_ops->get_trip_temp ? : of_thermal_get_trip_temp; + of_ops->get_trip_hyst = of_ops->get_trip_hyst ? : of_thermal_get_trip_hyst; + of_ops->set_trip_hyst = of_ops->set_trip_hyst ? : of_thermal_set_trip_hyst; + of_ops->get_crit_temp = of_ops->get_crit_temp ? : of_thermal_get_crit_temp; + of_ops->bind = thermal_of_bind; + of_ops->unbind = thermal_of_unbind; + + mask = GENMASK_ULL((ntrips) - 1, 0); + + tz = thermal_zone_device_register_with_trips(np->name, trips, ntrips, + mask, data, of_ops, tzp, + pdelay, delay); + if (IS_ERR(tz)) { + ret = PTR_ERR(tz); + pr_err("Failed to register thermal zone %pOFn: %d\n", np, ret); + goto out_kfree_tzp; + } + + ret = thermal_zone_device_enable(tz); + if (ret) { + pr_err("Failed to enabled thermal zone '%s', id=%d: %d\n", + tz->type, tz->id, ret); + thermal_of_zone_unregister(tz); + return ERR_PTR(ret); + } + + return tz; + +out_kfree_tzp: + kfree(tzp); +out_kfree_trips: + kfree(trips); + + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(thermal_of_zone_register); + +static void devm_thermal_of_zone_release(struct device *dev, void *res) +{ + thermal_of_zone_unregister(*(struct thermal_zone_device **)res); +} + +static int devm_thermal_of_zone_match(struct device *dev, void *res, + void *data) +{ + struct thermal_zone_device **r = res; + + if (WARN_ON(!r || !*r)) + return 0; + + return *r == data; +} + +/** + * devm_thermal_of_zone_register - register a thermal tied with the sensor life cycle + * + * This function is the device version of the thermal_of_zone_register() function. + * + * @dev: a device structure pointer to sensor to be tied with the thermal zone OF life cycle + * @sensor_id: the sensor identifier + * @data: a pointer to a private data to be stored in the thermal zone 'devdata' field + * @ops: a pointer to the ops structure associated with the sensor + */ +struct thermal_zone_device *devm_thermal_of_zone_register(struct device *dev, int sensor_id, void *data, + const struct thermal_zone_device_ops *ops) +{ + struct thermal_zone_device **ptr, *tzd; + + ptr = devres_alloc(devm_thermal_of_zone_release, sizeof(*ptr), + GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + tzd = thermal_of_zone_register(dev->of_node, sensor_id, data, ops); + if (IS_ERR(tzd)) { + devres_free(ptr); + return tzd; + } + + *ptr = tzd; + devres_add(dev, ptr); + + return tzd; +} +EXPORT_SYMBOL_GPL(devm_thermal_of_zone_register); + +/** + * devm_thermal_of_zone_unregister - Resource managed version of + * thermal_of_zone_unregister(). + * @dev: Device for which which resource was allocated. + * @tz: a pointer to struct thermal_zone where the sensor is registered. + * + * This function removes the sensor callbacks and private data from the + * thermal zone device registered with devm_thermal_zone_of_sensor_register() + * API. It will also silent the zone by remove the .get_temp() and .get_trend() + * thermal zone device callbacks. + * Normally this function will not need to be called and the resource + * management code will ensure that the resource is freed. + */ +void devm_thermal_of_zone_unregister(struct device *dev, struct thermal_zone_device *tz) +{ + WARN_ON(devres_release(dev, devm_thermal_zone_of_sensor_release, + devm_thermal_of_zone_match, tz)); +} +EXPORT_SYMBOL_GPL(devm_thermal_of_zone_unregister); + /** * of_parse_thermal_zones - parse device tree thermal data * diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 1386c713885d8..e2ac9d473bd6c 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -325,6 +325,16 @@ struct thermal_zone_of_device_ops { /* Function declarations */ #ifdef CONFIG_THERMAL_OF +struct thermal_zone_device *thermal_of_zone_register(struct device_node *sensor, int id, void *data, + const struct thermal_zone_device_ops *ops); + +struct thermal_zone_device *devm_thermal_of_zone_register(struct device *dev, int id, void *data, + const struct thermal_zone_device_ops *ops); + +void thermal_of_zone_unregister(struct thermal_zone_device *tz); + +void devm_thermal_of_zone_unregister(struct device *dev, struct thermal_zone_device *tz); + int thermal_zone_of_get_sensor_id(struct device_node *tz_np, struct device_node *sensor_np, u32 *id); @@ -366,6 +376,14 @@ static inline struct thermal_zone_device *devm_thermal_zone_of_sensor_register( return ERR_PTR(-ENODEV); } +static inline void thermal_of_zone_unregister(struct thermal_zone_device *tz) +{ +} + +static inline void devm_thermal_of_zone_unregister(struct device *dev, struct thermal_zone_device *tz) +{ +} + static inline void devm_thermal_zone_of_sensor_unregister(struct device *dev, struct thermal_zone_device *tz) From 45b8850b3d3071d5ea9e19ad4a29ad5f0b5d1ec1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 9 Aug 2022 10:56:26 +0200 Subject: [PATCH 289/427] thermal/of: Fix error code in of_thermal_zone_find() Currently, if we cannot find the correct thermal zone then this error path returns NULL and it would lead to an Oops in the caller. Return ERR_PTR(-EINVAL) instead. Fixes: 3bd52ac87347 ("thermal/of: Rework the thermal device tree initialization") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/YvDzovkMCQecPDjz@kili Signed-off-by: Daniel Lezcano --- drivers/thermal/thermal_of.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 82236fec7c654..15b342fa81d6d 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -1102,6 +1102,7 @@ static struct device_node *of_thermal_zone_find(struct device_node *sensor, int } } } + tz = ERR_PTR(-EINVAL); out: of_node_put(np); return tz; From 9d6792df07367aab42009d2b24c62c11a5968ee3 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Tue, 9 Aug 2022 10:56:27 +0200 Subject: [PATCH 290/427] thermal/of: Return -ENODEV instead of -EINVAL if registration fails The previous version of the OF code was returning -ENODEV if no thermal zones description was found or if the lookup of the sensor in the thermal zones was not found. The backend drivers are expecting this return value as an information about skipping the sensor initialization and considered as normal. Fix the return value by replacing -EINVAL by -ENODEV and remove the error message as this missing is not considered as an error. Fixes: 3bd52ac87347 ("thermal/of: Rework the thermal device tree initialization") Signed-off-by: Daniel Lezcano Tested-by: Michael Walle Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220809085629.509116-2-daniel.lezcano@linaro.org --- drivers/thermal/thermal_of.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 15b342fa81d6d..072e05477855a 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -1062,8 +1062,8 @@ static struct device_node *of_thermal_zone_find(struct device_node *sensor, int np = of_find_node_by_name(NULL, "thermal-zones"); if (!np) { - pr_err("Unable to find thermal zones description\n"); - return ERR_PTR(-EINVAL); + pr_debug("No thermal zones description\n"); + return ERR_PTR(-ENODEV); } /* @@ -1102,7 +1102,7 @@ static struct device_node *of_thermal_zone_find(struct device_node *sensor, int } } } - tz = ERR_PTR(-EINVAL); + tz = ERR_PTR(-ENODEV); out: of_node_put(np); return tz; @@ -1376,7 +1376,8 @@ struct thermal_zone_device *thermal_of_zone_register(struct device_node *sensor, np = of_thermal_zone_find(sensor, id); if (IS_ERR(np)) { - pr_err("Failed to find thermal zone for %pOFn id=%d\n", sensor, id); + if (PTR_ERR(np) != -ENODEV) + pr_err("Failed to find thermal zone for %pOFn id=%d\n", sensor, id); return ERR_CAST(np); } From 8fb5b71ed37dbe469eaa930e2ddc93ec9e305f3c Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Tue, 9 Aug 2022 10:56:29 +0200 Subject: [PATCH 291/427] thermal/of: Fix free after use in thermal_of_unregister() The thermal zone is freed after being unregistered. The release method devm_thermal_zone_device_register() calls -> thermal_of_zone_device_unregister() This one calls thermal_zone_device_unregister() which frees the thermal zone. However, thermal_of_zone_device_unregister() does access this freed pointer to free different resources allocated by the thermal_of framework which is invalid. It results in a kernel panic: [ 1.915140] thermal_sys: Failed to find thermal zone for tmu id=2 [ 1.921279] qoriq_thermal 1f80000.tmu: Failed to register sensors [ 1.927395] qoriq_thermal: probe of 1f80000.tmu failed with error -22 [ 1.934189] Unable to handle kernel paging request at virtual address 01adadadadadad88 [ 1.942146] Mem abort info: [ 1.944948] ESR = 0x0000000096000004 [ 1.948708] EC = 0x25: DABT (current EL), IL = 32 bits [ 1.954042] SET = 0, FnV = 0 [ 1.957107] EA = 0, S1PTW = 0 [ 1.960253] FSC = 0x04: level 0 translation fault [ 1.965147] Data abort info: [ 1.968030] ISV = 0, ISS = 0x00000004 [ 1.971878] CM = 0, WnR = 0 [ 1.974852] [01adadadadadad88] address between user and kernel address ranges [ 1.982016] Internal error: Oops: 96000004 [#1] SMP [ 1.986907] Modules linked in: [ 1.989969] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.19.0-next-20220808-00080-g1c46f44502e0 #1697 [ 1.999135] Hardware name: Kontron KBox A-230-LS (DT) [ 2.004199] pstate: 20000005 (nzCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 2.011185] pc : kfree+0x5c/0x3c0 [ 2.014516] lr : devm_thermal_of_zone_release+0x38/0x60 [ 2.019761] sp : ffff80000a22bad0 [ 2.023081] x29: ffff80000a22bad0 x28: 0000000000000000 x27: ffff800009960464 [ 2.030245] x26: ffff800009a16960 x25: 0000000000000006 x24: ffff800009f09a40 [ 2.037407] x23: ffff800009ab9008 x22: ffff800008d0eea8 x21: 01adadadadadad80 [ 2.044569] x20: 6b6b6b6b6b6b6b6b x19: ffff00200232b800 x18: 00000000fffffffb [ 2.051731] x17: ffff800008d0eea0 x16: ffff800008d07d44 x15: ffff800008d0d154 [ 2.056647] usb 1-1: new high-speed USB device number 2 using xhci-hcd [ 2.058893] x14: ffff800008d0cddc x13: ffff8000088d1c2c x12: ffff8000088d5034 [ 2.072597] x11: ffff8000088d46d4 x10: 0000000000000000 x9 : ffff800008d0eea8 [ 2.079759] x8 : ffff002000b1a158 x7 : bbbbbbbbbbbbbbbb x6 : ffff80000a0f53b8 [ 2.086921] x5 : ffff80000a22b960 x4 : 0000000000000000 x3 : 0000000000000000 [ 2.094082] x2 : fffffc0000000000 x1 : ffff002000838040 x0 : 01adb1adadadad80 [ 2.101244] Call trace: [ 2.103692] kfree+0x5c/0x3c0 [ 2.106666] devm_thermal_of_zone_release+0x38/0x60 [ 2.111561] release_nodes+0x64/0xd0 [ 2.115146] devres_release_all+0xbc/0x350 [ 2.119253] device_unbind_cleanup+0x20/0x70 [ 2.123536] really_probe+0x1a0/0x2e4 [ 2.127208] __driver_probe_device+0x80/0xec [ 2.131490] driver_probe_device+0x44/0x130 [ 2.135685] __driver_attach+0x104/0x1b4 [ 2.139619] bus_for_each_dev+0x7c/0xe0 [ 2.143465] driver_attach+0x30/0x40 [ 2.147048] bus_add_driver+0x160/0x210 [ 2.150894] driver_register+0x84/0x140 [ 2.154741] __platform_driver_register+0x34/0x40 [ 2.159461] qoriq_tmu_init+0x28/0x34 [ 2.163133] do_one_initcall+0x50/0x250 [ 2.166979] kernel_init_freeable+0x278/0x31c [ 2.171349] kernel_init+0x30/0x140 [ 2.174847] ret_from_fork+0x10/0x20 [ 2.178433] Code: b25657e2 d34cfc00 d37ae400 8b020015 (f94006a1) [ 2.184546] ---[ end trace 0000000000000000 ]--- Store the allocated resource pointers before the thermal zone is free and use them to release the resource after unregistering the thermal zone. Fixes: 3bd52ac87347 ("thermal/of: Rework the thermal device tree initialization") Reported-by: Michael Walle Signed-off-by: Daniel Lezcano Tested-by: Michael Walle Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220809085629.509116-4-daniel.lezcano@linaro.org --- drivers/thermal/thermal_of.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 072e05477855a..c5cbe254a4f13 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -1330,11 +1330,15 @@ static int thermal_of_unbind(struct thermal_zone_device *tz, */ void thermal_of_zone_unregister(struct thermal_zone_device *tz) { + struct thermal_trip *trips = tz->trips; + struct thermal_zone_params *tzp = tz->tzp; + struct thermal_zone_device_ops *ops = tz->ops; + thermal_zone_device_disable(tz); thermal_zone_device_unregister(tz); - kfree(tz->trips); - kfree(tz->tzp); - kfree(tz->ops); + kfree(trips); + kfree(tzp); + kfree(ops); } EXPORT_SYMBOL_GPL(thermal_of_zone_unregister); From 48ad3b104b9ec85de58c2b4e38fdad9a26446f99 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:18 +0200 Subject: [PATCH 292/427] thermal/of: Make new code and old code co-exist This transient change allows to use old and new OF together until all the drivers are converted to use the new OF API. This will go away when the old OF code will be removed. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-3-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/thermal_core.c | 6 ------ drivers/thermal/thermal_of.c | 13 +++++++++++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 50d50cec77740..69447aba7e656 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1492,10 +1492,6 @@ static int __init thermal_init(void) if (result) goto unregister_governors; - result = of_parse_thermal_zones(); - if (result) - goto unregister_class; - result = register_pm_notifier(&thermal_pm_nb); if (result) pr_warn("Thermal: Can not register suspend notifier, return %d\n", @@ -1503,8 +1499,6 @@ static int __init thermal_init(void) return 0; -unregister_class: - class_unregister(&thermal_class); unregister_governors: thermal_unregister_governors(); error: diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index c5cbe254a4f13..a17087c9295da 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -485,6 +485,15 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data, { struct device_node *np, *child, *sensor_np; struct thermal_zone_device *tzd = ERR_PTR(-ENODEV); + static int old_tz_initialized; + int ret; + + if (!old_tz_initialized) { + ret = of_parse_thermal_zones(); + if (ret) + return ERR_PTR(ret); + old_tz_initialized = 1; + } np = of_find_node_by_name(NULL, "thermal-zones"); if (!np) @@ -1004,7 +1013,7 @@ __init *thermal_of_build_thermal_zone(struct device_node *np) return ERR_PTR(ret); } -static __init void of_thermal_free_zone(struct __thermal_zone *tz) +static void of_thermal_free_zone(struct __thermal_zone *tz) { struct __thermal_bind_params *tbp; int i, j; @@ -1523,7 +1532,7 @@ EXPORT_SYMBOL_GPL(devm_thermal_of_zone_unregister); * Return: 0 on success, proper error code otherwise * */ -int __init of_parse_thermal_zones(void) +int of_parse_thermal_zones(void) { struct device_node *np, *child; struct __thermal_zone *tz; From 90b2ca02a969963bb37c30b42510fc3dfb0a3ae7 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:19 +0200 Subject: [PATCH 293/427] thermal/drivers/rockchip: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-4-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/rockchip_thermal.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index dc3a9c276a09b..819e059cde710 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -1211,9 +1211,9 @@ static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev) return IRQ_HANDLED; } -static int rockchip_thermal_set_trips(void *_sensor, int low, int high) +static int rockchip_thermal_set_trips(struct thermal_zone_device *tz, int low, int high) { - struct rockchip_thermal_sensor *sensor = _sensor; + struct rockchip_thermal_sensor *sensor = tz->devdata; struct rockchip_thermal_data *thermal = sensor->thermal; const struct rockchip_tsadc_chip *tsadc = thermal->chip; @@ -1224,9 +1224,9 @@ static int rockchip_thermal_set_trips(void *_sensor, int low, int high) sensor->id, thermal->regs, high); } -static int rockchip_thermal_get_temp(void *_sensor, int *out_temp) +static int rockchip_thermal_get_temp(struct thermal_zone_device *tz, int *out_temp) { - struct rockchip_thermal_sensor *sensor = _sensor; + struct rockchip_thermal_sensor *sensor = tz->devdata; struct rockchip_thermal_data *thermal = sensor->thermal; const struct rockchip_tsadc_chip *tsadc = sensor->thermal->chip; int retval; @@ -1239,7 +1239,7 @@ static int rockchip_thermal_get_temp(void *_sensor, int *out_temp) return retval; } -static const struct thermal_zone_of_device_ops rockchip_of_thermal_ops = { +static const struct thermal_zone_device_ops rockchip_of_thermal_ops = { .get_temp = rockchip_thermal_get_temp, .set_trips = rockchip_thermal_set_trips, }; @@ -1326,8 +1326,8 @@ rockchip_thermal_register_sensor(struct platform_device *pdev, sensor->thermal = thermal; sensor->id = id; - sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, id, - sensor, &rockchip_of_thermal_ops); + sensor->tzd = devm_thermal_of_zone_register(&pdev->dev, id, sensor, + &rockchip_of_thermal_ops); if (IS_ERR(sensor->tzd)) { error = PTR_ERR(sensor->tzd); dev_err(&pdev->dev, "failed to register sensor %d: %d\n", From c5f12023ff1d5622c7499352786233399beab7f8 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:20 +0200 Subject: [PATCH 294/427] thermal/drivers/uniphier: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-5-daniel.lezcano@linexp.org Reviewed-by: Kunihiko Hayashi Signed-off-by: Daniel Lezcano --- drivers/thermal/uniphier_thermal.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/thermal/uniphier_thermal.c b/drivers/thermal/uniphier_thermal.c index 4cae5561a2a38..4111d99ef50e3 100644 --- a/drivers/thermal/uniphier_thermal.c +++ b/drivers/thermal/uniphier_thermal.c @@ -187,9 +187,9 @@ static void uniphier_tm_disable_sensor(struct uniphier_tm_dev *tdev) usleep_range(1000, 2000); /* The spec note says at least 1ms */ } -static int uniphier_tm_get_temp(void *data, int *out_temp) +static int uniphier_tm_get_temp(struct thermal_zone_device *tz, int *out_temp) { - struct uniphier_tm_dev *tdev = data; + struct uniphier_tm_dev *tdev = tz->devdata; struct regmap *map = tdev->regmap; int ret; u32 temp; @@ -204,7 +204,7 @@ static int uniphier_tm_get_temp(void *data, int *out_temp) return 0; } -static const struct thermal_zone_of_device_ops uniphier_of_thermal_ops = { +static const struct thermal_zone_device_ops uniphier_of_thermal_ops = { .get_temp = uniphier_tm_get_temp, }; @@ -289,8 +289,8 @@ static int uniphier_tm_probe(struct platform_device *pdev) platform_set_drvdata(pdev, tdev); - tdev->tz_dev = devm_thermal_zone_of_sensor_register(dev, 0, tdev, - &uniphier_of_thermal_ops); + tdev->tz_dev = devm_thermal_of_zone_register(dev, 0, tdev, + &uniphier_of_thermal_ops); if (IS_ERR(tdev->tz_dev)) { dev_err(dev, "failed to register sensor device\n"); return PTR_ERR(tdev->tz_dev); From 2ff66cba5beb9302f5787fd34617c5f64ad98309 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:21 +0200 Subject: [PATCH 295/427] thermal/drivers/generic-adc: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-6-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/thermal-generic-adc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/thermal/thermal-generic-adc.c b/drivers/thermal/thermal-generic-adc.c index 73665c3ccfe0b..323e273e32982 100644 --- a/drivers/thermal/thermal-generic-adc.c +++ b/drivers/thermal/thermal-generic-adc.c @@ -52,9 +52,9 @@ static int gadc_thermal_adc_to_temp(struct gadc_thermal_info *gti, int val) return temp; } -static int gadc_thermal_get_temp(void *data, int *temp) +static int gadc_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { - struct gadc_thermal_info *gti = data; + struct gadc_thermal_info *gti = tz->devdata; int val; int ret; @@ -68,7 +68,7 @@ static int gadc_thermal_get_temp(void *data, int *temp) return 0; } -static const struct thermal_zone_of_device_ops gadc_thermal_ops = { +static const struct thermal_zone_device_ops gadc_thermal_ops = { .get_temp = gadc_thermal_get_temp, }; @@ -143,8 +143,8 @@ static int gadc_thermal_probe(struct platform_device *pdev) gti->dev = &pdev->dev; platform_set_drvdata(pdev, gti); - gti->tz_dev = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, gti, - &gadc_thermal_ops); + gti->tz_dev = devm_thermal_of_zone_register(&pdev->dev, 0, gti, + &gadc_thermal_ops); if (IS_ERR(gti->tz_dev)) { ret = PTR_ERR(gti->tz_dev); if (ret != -EPROBE_DEFER) From 44b5554d98d422a4411341d9aed5352c2ce34fc1 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:22 +0200 Subject: [PATCH 296/427] thermal/drivers/mmio: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Reviewed-by: Talel Shenhar Link: https://lore.kernel.org/r/20220804224349.1926752-7-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/thermal_mmio.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/thermal/thermal_mmio.c b/drivers/thermal/thermal_mmio.c index 360b0dfdc3b07..1bf1a16533da1 100644 --- a/drivers/thermal/thermal_mmio.c +++ b/drivers/thermal/thermal_mmio.c @@ -20,11 +20,10 @@ static u32 thermal_mmio_readb(void __iomem *mmio_base) return readb(mmio_base); } -static int thermal_mmio_get_temperature(void *private, int *temp) +static int thermal_mmio_get_temperature(struct thermal_zone_device *tz, int *temp) { int t; - struct thermal_mmio *sensor = - (struct thermal_mmio *)private; + struct thermal_mmio *sensor = tz->devdata; t = sensor->read_mmio(sensor->mmio_base) & sensor->mask; t *= sensor->factor; @@ -34,7 +33,7 @@ static int thermal_mmio_get_temperature(void *private, int *temp) return 0; } -static const struct thermal_zone_of_device_ops thermal_mmio_ops = { +static const struct thermal_zone_device_ops thermal_mmio_ops = { .get_temp = thermal_mmio_get_temperature, }; @@ -68,10 +67,10 @@ static int thermal_mmio_probe(struct platform_device *pdev) } } - thermal_zone = devm_thermal_zone_of_sensor_register(&pdev->dev, - 0, - sensor, - &thermal_mmio_ops); + thermal_zone = devm_thermal_of_zone_register(&pdev->dev, + 0, + sensor, + &thermal_mmio_ops); if (IS_ERR(thermal_zone)) { dev_err(&pdev->dev, "failed to register sensor (%ld)\n", @@ -79,7 +78,7 @@ static int thermal_mmio_probe(struct platform_device *pdev) return PTR_ERR(thermal_zone); } - thermal_mmio_get_temperature(sensor, &temperature); + thermal_mmio_get_temperature(thermal_zone, &temperature); dev_info(&pdev->dev, "thermal mmio sensor %s registered, current temperature: %d\n", pdev->name, temperature); From 6fc2e1a5f98feb9cf0698b69c90701e0b9de2bf5 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:23 +0200 Subject: [PATCH 297/427] thermal/drivers/tegra: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-8-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/tegra/soctherm.c | 21 ++++++++++----------- drivers/thermal/tegra/tegra-bpmp-thermal.c | 19 ++++++++++++------- drivers/thermal/tegra/tegra30-tsensor.c | 12 ++++++------ 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c index 825eab5266196..1efe470f31e9a 100644 --- a/drivers/thermal/tegra/soctherm.c +++ b/drivers/thermal/tegra/soctherm.c @@ -421,9 +421,9 @@ static int translate_temp(u16 val) return t; } -static int tegra_thermctl_get_temp(void *data, int *out_temp) +static int tegra_thermctl_get_temp(struct thermal_zone_device *tz, int *out_temp) { - struct tegra_thermctl_zone *zone = data; + struct tegra_thermctl_zone *zone = tz->devdata; u32 val; val = readl(zone->reg); @@ -582,10 +582,9 @@ static int tsensor_group_thermtrip_get(struct tegra_soctherm *ts, int id) return temp; } -static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp) +static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip, int temp) { - struct tegra_thermctl_zone *zone = data; - struct thermal_zone_device *tz = zone->tz; + struct tegra_thermctl_zone *zone = tz->devdata; struct tegra_soctherm *ts = zone->ts; const struct tegra_tsensor_group *sg = zone->sg; struct device *dev = zone->dev; @@ -657,9 +656,9 @@ static void thermal_irq_disable(struct tegra_thermctl_zone *zn) mutex_unlock(&zn->ts->thermctl_lock); } -static int tegra_thermctl_set_trips(void *data, int lo, int hi) +static int tegra_thermctl_set_trips(struct thermal_zone_device *tz, int lo, int hi) { - struct tegra_thermctl_zone *zone = data; + struct tegra_thermctl_zone *zone = tz->devdata; u32 r; thermal_irq_disable(zone); @@ -682,7 +681,7 @@ static int tegra_thermctl_set_trips(void *data, int lo, int hi) return 0; } -static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = { +static const struct thermal_zone_device_ops tegra_of_thermal_ops = { .get_temp = tegra_thermctl_get_temp, .set_trip_temp = tegra_thermctl_set_trip_temp, .set_trips = tegra_thermctl_set_trips, @@ -2194,9 +2193,9 @@ static int tegra_soctherm_probe(struct platform_device *pdev) zone->sg = soc->ttgs[i]; zone->ts = tegra; - z = devm_thermal_zone_of_sensor_register(&pdev->dev, - soc->ttgs[i]->id, zone, - &tegra_of_thermal_ops); + z = devm_thermal_of_zone_register(&pdev->dev, + soc->ttgs[i]->id, zone, + &tegra_of_thermal_ops); if (IS_ERR(z)) { err = PTR_ERR(z); dev_err(&pdev->dev, "failed to register sensor: %d\n", diff --git a/drivers/thermal/tegra/tegra-bpmp-thermal.c b/drivers/thermal/tegra/tegra-bpmp-thermal.c index 5affc3d196be8..eb84f0b9dc7c2 100644 --- a/drivers/thermal/tegra/tegra-bpmp-thermal.c +++ b/drivers/thermal/tegra/tegra-bpmp-thermal.c @@ -30,9 +30,9 @@ struct tegra_bpmp_thermal { struct tegra_bpmp_thermal_zone **zones; }; -static int tegra_bpmp_thermal_get_temp(void *data, int *out_temp) +static int __tegra_bpmp_thermal_get_temp(struct tegra_bpmp_thermal_zone *zone, + int *out_temp) { - struct tegra_bpmp_thermal_zone *zone = data; struct mrq_thermal_host_to_bpmp_request req; union mrq_thermal_bpmp_to_host_response reply; struct tegra_bpmp_message msg; @@ -60,9 +60,14 @@ static int tegra_bpmp_thermal_get_temp(void *data, int *out_temp) return 0; } -static int tegra_bpmp_thermal_set_trips(void *data, int low, int high) +static int tegra_bpmp_thermal_get_temp(struct thermal_zone_device *tz, int *out_temp) { - struct tegra_bpmp_thermal_zone *zone = data; + return __tegra_bpmp_thermal_get_temp(tz->devdata, out_temp); +} + +static int tegra_bpmp_thermal_set_trips(struct thermal_zone_device *tz, int low, int high) +{ + struct tegra_bpmp_thermal_zone *zone = tz->devdata; struct mrq_thermal_host_to_bpmp_request req; struct tegra_bpmp_message msg; int err; @@ -157,7 +162,7 @@ static int tegra_bpmp_thermal_get_num_zones(struct tegra_bpmp *bpmp, return 0; } -static const struct thermal_zone_of_device_ops tegra_bpmp_of_thermal_ops = { +static const struct thermal_zone_device_ops tegra_bpmp_of_thermal_ops = { .get_temp = tegra_bpmp_thermal_get_temp, .set_trips = tegra_bpmp_thermal_set_trips, }; @@ -200,13 +205,13 @@ static int tegra_bpmp_thermal_probe(struct platform_device *pdev) zone->idx = i; zone->tegra = tegra; - err = tegra_bpmp_thermal_get_temp(zone, &temp); + err = __tegra_bpmp_thermal_get_temp(zone, &temp); if (err < 0) { devm_kfree(&pdev->dev, zone); continue; } - tzd = devm_thermal_zone_of_sensor_register( + tzd = devm_thermal_of_zone_register( &pdev->dev, i, zone, &tegra_bpmp_of_thermal_ops); if (IS_ERR(tzd)) { if (PTR_ERR(tzd) == -EPROBE_DEFER) diff --git a/drivers/thermal/tegra/tegra30-tsensor.c b/drivers/thermal/tegra/tegra30-tsensor.c index 05886684f4295..c34501287e96c 100644 --- a/drivers/thermal/tegra/tegra30-tsensor.c +++ b/drivers/thermal/tegra/tegra30-tsensor.c @@ -159,9 +159,9 @@ static void devm_tegra_tsensor_hw_disable(void *data) tegra_tsensor_hw_disable(ts); } -static int tegra_tsensor_get_temp(void *data, int *temp) +static int tegra_tsensor_get_temp(struct thermal_zone_device *tz, int *temp) { - const struct tegra_tsensor_channel *tsc = data; + const struct tegra_tsensor_channel *tsc = tz->devdata; const struct tegra_tsensor *ts = tsc->ts; int err, c1, c2, c3, c4, counter; u32 val; @@ -217,9 +217,9 @@ static int tegra_tsensor_temp_to_counter(const struct tegra_tsensor *ts, int tem return DIV_ROUND_CLOSEST(c2 * 1000000 - ts->calib.b, ts->calib.a); } -static int tegra_tsensor_set_trips(void *data, int low, int high) +static int tegra_tsensor_set_trips(struct thermal_zone_device *tz, int low, int high) { - const struct tegra_tsensor_channel *tsc = data; + const struct tegra_tsensor_channel *tsc = tz->devdata; const struct tegra_tsensor *ts = tsc->ts; u32 val; @@ -240,7 +240,7 @@ static int tegra_tsensor_set_trips(void *data, int low, int high) return 0; } -static const struct thermal_zone_of_device_ops ops = { +static const struct thermal_zone_device_ops ops = { .get_temp = tegra_tsensor_get_temp, .set_trips = tegra_tsensor_set_trips, }; @@ -516,7 +516,7 @@ static int tegra_tsensor_register_channel(struct tegra_tsensor *ts, tsc->id = id; tsc->regs = ts->regs + 0x40 * (hw_id + 1); - tsc->tzd = devm_thermal_zone_of_sensor_register(ts->dev, id, tsc, &ops); + tsc->tzd = devm_thermal_of_zone_register(ts->dev, id, tsc, &ops); if (IS_ERR(tsc->tzd)) { if (PTR_ERR(tsc->tzd) != -ENODEV) return dev_err_probe(ts->dev, PTR_ERR(tsc->tzd), From 2e2150c7946764f289bafd716cbd6721283dc9ce Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:24 +0200 Subject: [PATCH 298/427] thermal/drivers/sun8i: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-9-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/sun8i_thermal.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c index 212c87e63a667..e64d06d1328ce 100644 --- a/drivers/thermal/sun8i_thermal.c +++ b/drivers/thermal/sun8i_thermal.c @@ -108,9 +108,9 @@ static int sun50i_h5_calc_temp(struct ths_device *tmdev, return -1590 * reg / 10 + 276000; } -static int sun8i_ths_get_temp(void *data, int *temp) +static int sun8i_ths_get_temp(struct thermal_zone_device *tz, int *temp) { - struct tsensor *s = data; + struct tsensor *s = tz->devdata; struct ths_device *tmdev = s->tmdev; int val = 0; @@ -135,7 +135,7 @@ static int sun8i_ths_get_temp(void *data, int *temp) return 0; } -static const struct thermal_zone_of_device_ops ths_ops = { +static const struct thermal_zone_device_ops ths_ops = { .get_temp = sun8i_ths_get_temp, }; @@ -468,10 +468,10 @@ static int sun8i_ths_register(struct ths_device *tmdev) tmdev->sensor[i].tmdev = tmdev; tmdev->sensor[i].id = i; tmdev->sensor[i].tzd = - devm_thermal_zone_of_sensor_register(tmdev->dev, - i, - &tmdev->sensor[i], - &ths_ops); + devm_thermal_of_zone_register(tmdev->dev, + i, + &tmdev->sensor[i], + &ths_ops); if (IS_ERR(tmdev->sensor[i].tzd)) return PTR_ERR(tmdev->sensor[i].tzd); From 7f689a2ef4f6422b200682f80be225c1f61218f7 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:25 +0200 Subject: [PATCH 299/427] thermal/drivers/sprd: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-10-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/sprd_thermal.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/thermal/sprd_thermal.c b/drivers/thermal/sprd_thermal.c index fff80fc180028..ac884514f116a 100644 --- a/drivers/thermal/sprd_thermal.c +++ b/drivers/thermal/sprd_thermal.c @@ -204,9 +204,9 @@ static int sprd_thm_temp_to_rawdata(int temp, struct sprd_thermal_sensor *sen) return clamp(val, val, (u32)(SPRD_THM_RAW_DATA_HIGH - 1)); } -static int sprd_thm_read_temp(void *devdata, int *temp) +static int sprd_thm_read_temp(struct thermal_zone_device *tz, int *temp) { - struct sprd_thermal_sensor *sen = devdata; + struct sprd_thermal_sensor *sen = tz->devdata; u32 data; data = readl(sen->data->base + SPRD_THM_TEMP(sen->id)) & @@ -217,7 +217,7 @@ static int sprd_thm_read_temp(void *devdata, int *temp) return 0; } -static const struct thermal_zone_of_device_ops sprd_thm_ops = { +static const struct thermal_zone_device_ops sprd_thm_ops = { .get_temp = sprd_thm_read_temp, }; @@ -408,10 +408,10 @@ static int sprd_thm_probe(struct platform_device *pdev) sprd_thm_sensor_init(thm, sen); - sen->tzd = devm_thermal_zone_of_sensor_register(sen->dev, - sen->id, - sen, - &sprd_thm_ops); + sen->tzd = devm_thermal_of_zone_register(sen->dev, + sen->id, + sen, + &sprd_thm_ops); if (IS_ERR(sen->tzd)) { dev_err(&pdev->dev, "register thermal zone failed %d\n", sen->id); @@ -523,8 +523,8 @@ static int sprd_thm_remove(struct platform_device *pdev) for (i = 0; i < thm->nr_sensors; i++) { sprd_thm_toggle_sensor(thm->sensor[i], false); - devm_thermal_zone_of_sensor_unregister(&pdev->dev, - thm->sensor[i]->tzd); + devm_thermal_of_zone_unregister(&pdev->dev, + thm->sensor[i]->tzd); } clk_disable_unprepare(thm->clk); From 944441d878b0aebd87ec404fe86c322186da458d Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:26 +0200 Subject: [PATCH 300/427] thermal/drivers/broadcom: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Tested-by: Florian Fainelli Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20220804224349.1926752-11-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/broadcom/bcm2711_thermal.c | 14 +++--- drivers/thermal/broadcom/bcm2835_thermal.c | 14 +++--- drivers/thermal/broadcom/brcmstb_thermal.c | 20 ++++----- drivers/thermal/broadcom/ns-thermal.c | 50 +++++++++------------- drivers/thermal/broadcom/sr-thermal.c | 16 +++---- 5 files changed, 53 insertions(+), 61 deletions(-) diff --git a/drivers/thermal/broadcom/bcm2711_thermal.c b/drivers/thermal/broadcom/bcm2711_thermal.c index e9bef5c3414b6..1f8651d15160c 100644 --- a/drivers/thermal/broadcom/bcm2711_thermal.c +++ b/drivers/thermal/broadcom/bcm2711_thermal.c @@ -31,11 +31,11 @@ struct bcm2711_thermal_priv { struct thermal_zone_device *thermal; }; -static int bcm2711_get_temp(void *data, int *temp) +static int bcm2711_get_temp(struct thermal_zone_device *tz, int *temp) { - struct bcm2711_thermal_priv *priv = data; - int slope = thermal_zone_get_slope(priv->thermal); - int offset = thermal_zone_get_offset(priv->thermal); + struct bcm2711_thermal_priv *priv = tz->devdata; + int slope = thermal_zone_get_slope(tz); + int offset = thermal_zone_get_offset(tz); u32 val; int ret; @@ -54,7 +54,7 @@ static int bcm2711_get_temp(void *data, int *temp) return 0; } -static const struct thermal_zone_of_device_ops bcm2711_thermal_of_ops = { +static const struct thermal_zone_device_ops bcm2711_thermal_of_ops = { .get_temp = bcm2711_get_temp, }; @@ -88,8 +88,8 @@ static int bcm2711_thermal_probe(struct platform_device *pdev) } priv->regmap = regmap; - thermal = devm_thermal_zone_of_sensor_register(dev, 0, priv, - &bcm2711_thermal_of_ops); + thermal = devm_thermal_of_zone_register(dev, 0, priv, + &bcm2711_thermal_of_ops); if (IS_ERR(thermal)) { ret = PTR_ERR(thermal); dev_err(dev, "could not register sensor: %d\n", ret); diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c index c8e4344d5a3d8..2c67841a11151 100644 --- a/drivers/thermal/broadcom/bcm2835_thermal.c +++ b/drivers/thermal/broadcom/bcm2835_thermal.c @@ -88,9 +88,9 @@ static int bcm2835_thermal_temp2adc(int temp, int offset, int slope) return temp; } -static int bcm2835_thermal_get_temp(void *d, int *temp) +static int bcm2835_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { - struct bcm2835_thermal_data *data = d; + struct bcm2835_thermal_data *data = tz->devdata; u32 val = readl(data->regs + BCM2835_TS_TSENSSTAT); if (!(val & BCM2835_TS_TSENSSTAT_VALID)) @@ -135,7 +135,7 @@ static void bcm2835_thermal_debugfs(struct platform_device *pdev) debugfs_create_regset32("regset", 0444, data->debugfsdir, regset); } -static const struct thermal_zone_of_device_ops bcm2835_thermal_ops = { +static const struct thermal_zone_device_ops bcm2835_thermal_ops = { .get_temp = bcm2835_thermal_get_temp, }; @@ -206,8 +206,8 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) data->clk, rate); /* register of thermal sensor and get info from DT */ - tz = thermal_zone_of_sensor_register(&pdev->dev, 0, data, - &bcm2835_thermal_ops); + tz = devm_thermal_of_zone_register(&pdev->dev, 0, data, + &bcm2835_thermal_ops); if (IS_ERR(tz)) { err = PTR_ERR(tz); dev_err(&pdev->dev, @@ -277,7 +277,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) return 0; err_tz: - thermal_zone_of_sensor_unregister(&pdev->dev, tz); + thermal_of_zone_unregister(tz); err_clk: clk_disable_unprepare(data->clk); @@ -290,7 +290,7 @@ static int bcm2835_thermal_remove(struct platform_device *pdev) struct thermal_zone_device *tz = data->tz; debugfs_remove_recursive(data->debugfsdir); - thermal_zone_of_sensor_unregister(&pdev->dev, tz); + thermal_of_zone_unregister(tz); clk_disable_unprepare(data->clk); return 0; diff --git a/drivers/thermal/broadcom/brcmstb_thermal.c b/drivers/thermal/broadcom/brcmstb_thermal.c index 0cedb8b4f00a4..c79c6cfdd74d5 100644 --- a/drivers/thermal/broadcom/brcmstb_thermal.c +++ b/drivers/thermal/broadcom/brcmstb_thermal.c @@ -105,7 +105,7 @@ static struct avs_tmon_trip avs_tmon_trips[] = { struct brcmstb_thermal_params { unsigned int offset; unsigned int mult; - const struct thermal_zone_of_device_ops *of_ops; + const struct thermal_zone_device_ops *of_ops; }; struct brcmstb_thermal_priv { @@ -150,9 +150,9 @@ static inline u32 avs_tmon_temp_to_code(struct brcmstb_thermal_priv *priv, return (u32)((offset - temp) / mult); } -static int brcmstb_get_temp(void *data, int *temp) +static int brcmstb_get_temp(struct thermal_zone_device *tz, int *temp) { - struct brcmstb_thermal_priv *priv = data; + struct brcmstb_thermal_priv *priv = tz->devdata; u32 val; long t; @@ -260,9 +260,9 @@ static irqreturn_t brcmstb_tmon_irq_thread(int irq, void *data) return IRQ_HANDLED; } -static int brcmstb_set_trips(void *data, int low, int high) +static int brcmstb_set_trips(struct thermal_zone_device *tz, int low, int high) { - struct brcmstb_thermal_priv *priv = data; + struct brcmstb_thermal_priv *priv = tz->devdata; dev_dbg(priv->dev, "set trips %d <--> %d\n", low, high); @@ -288,7 +288,7 @@ static int brcmstb_set_trips(void *data, int low, int high) return 0; } -static const struct thermal_zone_of_device_ops brcmstb_16nm_of_ops = { +static const struct thermal_zone_device_ops brcmstb_16nm_of_ops = { .get_temp = brcmstb_get_temp, }; @@ -298,7 +298,7 @@ static const struct brcmstb_thermal_params brcmstb_16nm_params = { .of_ops = &brcmstb_16nm_of_ops, }; -static const struct thermal_zone_of_device_ops brcmstb_28nm_of_ops = { +static const struct thermal_zone_device_ops brcmstb_28nm_of_ops = { .get_temp = brcmstb_get_temp, .set_trips = brcmstb_set_trips, }; @@ -318,7 +318,7 @@ MODULE_DEVICE_TABLE(of, brcmstb_thermal_id_table); static int brcmstb_thermal_probe(struct platform_device *pdev) { - const struct thermal_zone_of_device_ops *of_ops; + const struct thermal_zone_device_ops *of_ops; struct thermal_zone_device *thermal; struct brcmstb_thermal_priv *priv; struct resource *res; @@ -341,8 +341,8 @@ static int brcmstb_thermal_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); of_ops = priv->temp_params->of_ops; - thermal = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, priv, - of_ops); + thermal = devm_thermal_of_zone_register(&pdev->dev, 0, priv, + of_ops); if (IS_ERR(thermal)) { ret = PTR_ERR(thermal); dev_err(&pdev->dev, "could not register sensor: %d\n", ret); diff --git a/drivers/thermal/broadcom/ns-thermal.c b/drivers/thermal/broadcom/ns-thermal.c index c9468ba9d449b..07a8a3f49bd0f 100644 --- a/drivers/thermal/broadcom/ns-thermal.c +++ b/drivers/thermal/broadcom/ns-thermal.c @@ -14,19 +14,14 @@ #define PVTMON_CONTROL0_SEL_TEST_MODE 0x0000000e #define PVTMON_STATUS 0x08 -struct ns_thermal { - struct thermal_zone_device *tz; - void __iomem *pvtmon; -}; - -static int ns_thermal_get_temp(void *data, int *temp) +static int ns_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { - struct ns_thermal *ns_thermal = data; - int offset = thermal_zone_get_offset(ns_thermal->tz); - int slope = thermal_zone_get_slope(ns_thermal->tz); + void __iomem *pvtmon = tz->devdata; + int offset = thermal_zone_get_offset(tz); + int slope = thermal_zone_get_slope(tz); u32 val; - val = readl(ns_thermal->pvtmon + PVTMON_CONTROL0); + val = readl(pvtmon + PVTMON_CONTROL0); if ((val & PVTMON_CONTROL0_SEL_MASK) != PVTMON_CONTROL0_SEL_TEMP_MONITOR) { /* Clear current mode selection */ val &= ~PVTMON_CONTROL0_SEL_MASK; @@ -34,50 +29,47 @@ static int ns_thermal_get_temp(void *data, int *temp) /* Set temp monitor mode (it's the default actually) */ val |= PVTMON_CONTROL0_SEL_TEMP_MONITOR; - writel(val, ns_thermal->pvtmon + PVTMON_CONTROL0); + writel(val, pvtmon + PVTMON_CONTROL0); } - val = readl(ns_thermal->pvtmon + PVTMON_STATUS); + val = readl(pvtmon + PVTMON_STATUS); *temp = slope * val + offset; return 0; } -static const struct thermal_zone_of_device_ops ns_thermal_ops = { +static const struct thermal_zone_device_ops ns_thermal_ops = { .get_temp = ns_thermal_get_temp, }; static int ns_thermal_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct ns_thermal *ns_thermal; - - ns_thermal = devm_kzalloc(dev, sizeof(*ns_thermal), GFP_KERNEL); - if (!ns_thermal) - return -ENOMEM; + struct thermal_zone_device *tz; + void __iomem *pvtmon; - ns_thermal->pvtmon = of_iomap(dev_of_node(dev), 0); - if (WARN_ON(!ns_thermal->pvtmon)) + pvtmon = of_iomap(dev_of_node(dev), 0); + if (WARN_ON(!pvtmon)) return -ENOENT; - ns_thermal->tz = devm_thermal_zone_of_sensor_register(dev, 0, - ns_thermal, - &ns_thermal_ops); - if (IS_ERR(ns_thermal->tz)) { - iounmap(ns_thermal->pvtmon); - return PTR_ERR(ns_thermal->tz); + tz = devm_thermal_of_zone_register(dev, 0, + pvtmon, + &ns_thermal_ops); + if (IS_ERR(tz)) { + iounmap(pvtmon); + return PTR_ERR(tz); } - platform_set_drvdata(pdev, ns_thermal); + platform_set_drvdata(pdev, pvtmon); return 0; } static int ns_thermal_remove(struct platform_device *pdev) { - struct ns_thermal *ns_thermal = platform_get_drvdata(pdev); + void __iomem *pvtmon = platform_get_drvdata(pdev); - iounmap(ns_thermal->pvtmon); + iounmap(pvtmon); return 0; } diff --git a/drivers/thermal/broadcom/sr-thermal.c b/drivers/thermal/broadcom/sr-thermal.c index 85ab9edd580cc..2b93502543ff4 100644 --- a/drivers/thermal/broadcom/sr-thermal.c +++ b/drivers/thermal/broadcom/sr-thermal.c @@ -19,7 +19,6 @@ #define SR_TMON_MAX_LIST 6 struct sr_tmon { - struct thermal_zone_device *tz; unsigned int crit_temp; unsigned int tmon_id; struct sr_thermal *priv; @@ -31,9 +30,9 @@ struct sr_thermal { struct sr_tmon tmon[SR_TMON_MAX_LIST]; }; -static int sr_get_temp(void *data, int *temp) +static int sr_get_temp(struct thermal_zone_device *tz, int *temp) { - struct sr_tmon *tmon = data; + struct sr_tmon *tmon = tz->devdata; struct sr_thermal *sr_thermal = tmon->priv; *temp = readl(sr_thermal->regs + SR_TMON_TEMP_BASE(tmon->tmon_id)); @@ -41,13 +40,14 @@ static int sr_get_temp(void *data, int *temp) return 0; } -static const struct thermal_zone_of_device_ops sr_tz_ops = { +static const struct thermal_zone_device_ops sr_tz_ops = { .get_temp = sr_get_temp, }; static int sr_thermal_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct thermal_zone_device *tz; struct sr_thermal *sr_thermal; struct sr_tmon *tmon; struct resource *res; @@ -84,10 +84,10 @@ static int sr_thermal_probe(struct platform_device *pdev) writel(0, sr_thermal->regs + SR_TMON_TEMP_BASE(i)); tmon->tmon_id = i; tmon->priv = sr_thermal; - tmon->tz = devm_thermal_zone_of_sensor_register(dev, i, tmon, - &sr_tz_ops); - if (IS_ERR(tmon->tz)) - return PTR_ERR(tmon->tz); + tz = devm_thermal_of_zone_register(dev, i, tmon, + &sr_tz_ops); + if (IS_ERR(tz)) + return PTR_ERR(tz); dev_dbg(dev, "thermal sensor %d registered\n", i); } From ca1b9a9eb3fdbb9aa39d0c174391af694ae77671 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:27 +0200 Subject: [PATCH 301/427] thermal/drivers/qcom: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220804224349.1926752-12-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/qcom/qcom-spmi-adc-tm5.c | 19 +++++++++---------- drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 12 ++++++------ drivers/thermal/qcom/tsens.c | 16 ++++++++-------- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c index 073943cbcc2be..add6f40e5e2af 100644 --- a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c +++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c @@ -357,9 +357,9 @@ static irqreturn_t adc_tm5_gen2_isr(int irq, void *data) return IRQ_HANDLED; } -static int adc_tm5_get_temp(void *data, int *temp) +static int adc_tm5_get_temp(struct thermal_zone_device *tz, int *temp) { - struct adc_tm5_channel *channel = data; + struct adc_tm5_channel *channel = tz->devdata; int ret; if (!channel || !channel->iio) @@ -639,9 +639,9 @@ static int adc_tm5_gen2_configure(struct adc_tm5_channel *channel, int low, int return ret; } -static int adc_tm5_set_trips(void *data, int low, int high) +static int adc_tm5_set_trips(struct thermal_zone_device *tz, int low, int high) { - struct adc_tm5_channel *channel = data; + struct adc_tm5_channel *channel = tz->devdata; struct adc_tm5_chip *chip; int ret; @@ -660,7 +660,7 @@ static int adc_tm5_set_trips(void *data, int low, int high) return ret; } -static struct thermal_zone_of_device_ops adc_tm5_thermal_ops = { +static const struct thermal_zone_device_ops adc_tm5_thermal_ops = { .get_temp = adc_tm5_get_temp, .set_trips = adc_tm5_set_trips, }; @@ -672,11 +672,10 @@ static int adc_tm5_register_tzd(struct adc_tm5_chip *adc_tm) for (i = 0; i < adc_tm->nchannels; i++) { adc_tm->channels[i].chip = adc_tm; - - tzd = devm_thermal_zone_of_sensor_register(adc_tm->dev, - adc_tm->channels[i].channel, - &adc_tm->channels[i], - &adc_tm5_thermal_ops); + tzd = devm_thermal_of_zone_register(adc_tm->dev, + adc_tm->channels[i].channel, + &adc_tm->channels[i], + &adc_tm5_thermal_ops); if (IS_ERR(tzd)) { if (PTR_ERR(tzd) == -ENODEV) { dev_warn(adc_tm->dev, "thermal sensor on channel %d is not used\n", diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c index 770f82cc9bca8..be785ab37e53d 100644 --- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c +++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c @@ -186,9 +186,9 @@ static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip) return 0; } -static int qpnp_tm_get_temp(void *data, int *temp) +static int qpnp_tm_get_temp(struct thermal_zone_device *tz, int *temp) { - struct qpnp_tm_chip *chip = data; + struct qpnp_tm_chip *chip = tz->devdata; int ret, mili_celsius; if (!temp) @@ -263,9 +263,9 @@ static int qpnp_tm_update_critical_trip_temp(struct qpnp_tm_chip *chip, return qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, reg); } -static int qpnp_tm_set_trip_temp(void *data, int trip, int temp) +static int qpnp_tm_set_trip_temp(struct thermal_zone_device *tz, int trip, int temp) { - struct qpnp_tm_chip *chip = data; + struct qpnp_tm_chip *chip = tz->devdata; const struct thermal_trip *trip_points; int ret; @@ -283,7 +283,7 @@ static int qpnp_tm_set_trip_temp(void *data, int trip, int temp) return ret; } -static const struct thermal_zone_of_device_ops qpnp_tm_sensor_ops = { +static const struct thermal_zone_device_ops qpnp_tm_sensor_ops = { .get_temp = qpnp_tm_get_temp, .set_trip_temp = qpnp_tm_set_trip_temp, }; @@ -446,7 +446,7 @@ static int qpnp_tm_probe(struct platform_device *pdev) * read the trip points. get_temp() returns the default temperature * before the hardware initialization is completed. */ - chip->tz_dev = devm_thermal_zone_of_sensor_register( + chip->tz_dev = devm_thermal_of_zone_register( &pdev->dev, 0, chip, &qpnp_tm_sensor_ops); if (IS_ERR(chip->tz_dev)) { dev_err(&pdev->dev, "failed to register sensor\n"); diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index e49f58e835137..b1b10005fb286 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -532,9 +532,9 @@ static irqreturn_t tsens_irq_thread(int irq, void *data) return IRQ_HANDLED; } -static int tsens_set_trips(void *_sensor, int low, int high) +static int tsens_set_trips(struct thermal_zone_device *tz, int low, int high) { - struct tsens_sensor *s = _sensor; + struct tsens_sensor *s = tz->devdata; struct tsens_priv *priv = s->priv; struct device *dev = priv->dev; struct tsens_irq_data d; @@ -925,9 +925,9 @@ int __init init_common(struct tsens_priv *priv) return ret; } -static int tsens_get_temp(void *data, int *temp) +static int tsens_get_temp(struct thermal_zone_device *tz, int *temp) { - struct tsens_sensor *s = data; + struct tsens_sensor *s = tz->devdata; struct tsens_priv *priv = s->priv; return priv->ops->get_temp(s, temp); @@ -991,7 +991,7 @@ static const struct of_device_id tsens_table[] = { }; MODULE_DEVICE_TABLE(of, tsens_table); -static const struct thermal_zone_of_device_ops tsens_of_ops = { +static const struct thermal_zone_device_ops tsens_of_ops = { .get_temp = tsens_get_temp, .set_trips = tsens_set_trips, }; @@ -1044,9 +1044,9 @@ static int tsens_register(struct tsens_priv *priv) for (i = 0; i < priv->num_sensors; i++) { priv->sensor[i].priv = priv; - tzd = devm_thermal_zone_of_sensor_register(priv->dev, priv->sensor[i].hw_id, - &priv->sensor[i], - &tsens_of_ops); + tzd = devm_thermal_of_zone_register(priv->dev, priv->sensor[i].hw_id, + &priv->sensor[i], + &tsens_of_ops); if (IS_ERR(tzd)) continue; priv->sensor[i].tzd = tzd; From 7e96f35408b6b196a3dc20db757878a7d26bf02d Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:28 +0200 Subject: [PATCH 302/427] thermal/drivers/st: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-13-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/st/stm_thermal.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/thermal/st/stm_thermal.c b/drivers/thermal/st/stm_thermal.c index 5fd3fb8912a6a..78feb802a87d2 100644 --- a/drivers/thermal/st/stm_thermal.c +++ b/drivers/thermal/st/stm_thermal.c @@ -302,9 +302,9 @@ static int stm_disable_irq(struct stm_thermal_sensor *sensor) return 0; } -static int stm_thermal_set_trips(void *data, int low, int high) +static int stm_thermal_set_trips(struct thermal_zone_device *tz, int low, int high) { - struct stm_thermal_sensor *sensor = data; + struct stm_thermal_sensor *sensor = tz->devdata; u32 itr1, th; int ret; @@ -350,9 +350,9 @@ static int stm_thermal_set_trips(void *data, int low, int high) } /* Callback to get temperature from HW */ -static int stm_thermal_get_temp(void *data, int *temp) +static int stm_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { - struct stm_thermal_sensor *sensor = data; + struct stm_thermal_sensor *sensor = tz->devdata; u32 periods; int freqM, ret; @@ -474,7 +474,7 @@ static int stm_thermal_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(stm_thermal_pm_ops, stm_thermal_suspend, stm_thermal_resume); -static const struct thermal_zone_of_device_ops stm_tz_ops = { +static const struct thermal_zone_device_ops stm_tz_ops = { .get_temp = stm_thermal_get_temp, .set_trips = stm_thermal_set_trips, }; @@ -539,9 +539,9 @@ static int stm_thermal_probe(struct platform_device *pdev) return ret; } - sensor->th_dev = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, - sensor, - &stm_tz_ops); + sensor->th_dev = devm_thermal_of_zone_register(&pdev->dev, 0, + sensor, + &stm_tz_ops); if (IS_ERR(sensor->th_dev)) { dev_err(&pdev->dev, "%s: thermal zone sensor registering KO\n", @@ -572,7 +572,6 @@ static int stm_thermal_probe(struct platform_device *pdev) return 0; err_tz: - thermal_zone_of_sensor_unregister(&pdev->dev, sensor->th_dev); return ret; } @@ -582,7 +581,6 @@ static int stm_thermal_remove(struct platform_device *pdev) stm_thermal_sensor_off(sensor); thermal_remove_hwmon_sysfs(sensor->th_dev); - thermal_zone_of_sensor_unregister(&pdev->dev, sensor->th_dev); return 0; } From 1240fd6512b7df593b99ea777c846f0b59173a6b Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:29 +0200 Subject: [PATCH 303/427] thermal/drivers/amlogic: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-14-daniel.lezcano@linexp.org Reviewed-by: Neil Armstrong Signed-off-by: Daniel Lezcano --- drivers/thermal/amlogic_thermal.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/thermal/amlogic_thermal.c b/drivers/thermal/amlogic_thermal.c index e61b91d14ad1e..d30cb791e63c8 100644 --- a/drivers/thermal/amlogic_thermal.c +++ b/drivers/thermal/amlogic_thermal.c @@ -179,12 +179,12 @@ static int amlogic_thermal_disable(struct amlogic_thermal *data) return 0; } -static int amlogic_thermal_get_temp(void *data, int *temp) +static int amlogic_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { unsigned int tval; - struct amlogic_thermal *pdata = data; + struct amlogic_thermal *pdata = tz->devdata; - if (!data) + if (!pdata) return -EINVAL; regmap_read(pdata->regmap, TSENSOR_STAT0, &tval); @@ -195,7 +195,7 @@ static int amlogic_thermal_get_temp(void *data, int *temp) return 0; } -static const struct thermal_zone_of_device_ops amlogic_thermal_ops = { +static const struct thermal_zone_device_ops amlogic_thermal_ops = { .get_temp = amlogic_thermal_get_temp, }; @@ -276,10 +276,10 @@ static int amlogic_thermal_probe(struct platform_device *pdev) return PTR_ERR(pdata->sec_ao_map); } - pdata->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, - 0, - pdata, - &amlogic_thermal_ops); + pdata->tzd = devm_thermal_of_zone_register(&pdev->dev, + 0, + pdata, + &amlogic_thermal_ops); if (IS_ERR(pdata->tzd)) { ret = PTR_ERR(pdata->tzd); dev_err(dev, "Failed to register tsensor: %d\n", ret); From e4a1150e3e8d708e989c9f7056320fbff4a2d0c4 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:30 +0200 Subject: [PATCH 304/427] thermal/drivers/armada: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-15-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/armada_thermal.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index c2ebfb5be4b3d..52d63b3997fe1 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -420,9 +420,9 @@ static struct thermal_zone_device_ops legacy_ops = { .get_temp = armada_get_temp_legacy, }; -static int armada_get_temp(void *_sensor, int *temp) +static int armada_get_temp(struct thermal_zone_device *tz, int *temp) { - struct armada_thermal_sensor *sensor = _sensor; + struct armada_thermal_sensor *sensor = tz->devdata; struct armada_thermal_priv *priv = sensor->priv; int ret; @@ -450,7 +450,7 @@ static int armada_get_temp(void *_sensor, int *temp) return ret; } -static const struct thermal_zone_of_device_ops of_ops = { +static const struct thermal_zone_device_ops of_ops = { .get_temp = armada_get_temp, }; @@ -928,9 +928,9 @@ static int armada_thermal_probe(struct platform_device *pdev) /* Register the sensor */ sensor->priv = priv; sensor->id = sensor_id; - tz = devm_thermal_zone_of_sensor_register(&pdev->dev, - sensor->id, sensor, - &of_ops); + tz = devm_thermal_of_zone_register(&pdev->dev, + sensor->id, sensor, + &of_ops); if (IS_ERR(tz)) { dev_info(&pdev->dev, "Thermal sensor %d unavailable\n", sensor_id); From 2320be6032e1c1b17a3fcac98813947d1d28c32f Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:31 +0200 Subject: [PATCH 305/427] thermal/drivers/db8500: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-16-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/db8500_thermal.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c index 121cf853e545e..cb10e280681fc 100644 --- a/drivers/thermal/db8500_thermal.c +++ b/drivers/thermal/db8500_thermal.c @@ -58,9 +58,9 @@ struct db8500_thermal_zone { }; /* Callback to get current temperature */ -static int db8500_thermal_get_temp(void *data, int *temp) +static int db8500_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { - struct db8500_thermal_zone *th = data; + struct db8500_thermal_zone *th = tz->devdata; /* * TODO: There is no PRCMU interface to get temperature data currently, @@ -72,7 +72,7 @@ static int db8500_thermal_get_temp(void *data, int *temp) return 0; } -static struct thermal_zone_of_device_ops thdev_ops = { +static const struct thermal_zone_device_ops thdev_ops = { .get_temp = db8500_thermal_get_temp, }; @@ -182,7 +182,7 @@ static int db8500_thermal_probe(struct platform_device *pdev) } /* register of thermal sensor and get info from DT */ - th->tz = devm_thermal_zone_of_sensor_register(dev, 0, th, &thdev_ops); + th->tz = devm_thermal_of_zone_register(dev, 0, th, &thdev_ops); if (IS_ERR(th->tz)) { dev_err(dev, "register thermal zone sensor failed\n"); return PTR_ERR(th->tz); From 32fb9a8a9d0db3edee50f9c2fcc74fcc26812b86 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:32 +0200 Subject: [PATCH 306/427] thermal/drivers/imx: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-17-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/imx8mm_thermal.c | 14 +++++++------- drivers/thermal/imx_sc_thermal.c | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/thermal/imx8mm_thermal.c b/drivers/thermal/imx8mm_thermal.c index af666bd9e8d4d..e2c2673025a7a 100644 --- a/drivers/thermal/imx8mm_thermal.c +++ b/drivers/thermal/imx8mm_thermal.c @@ -96,15 +96,15 @@ static int imx8mp_tmu_get_temp(void *data, int *temp) return 0; } -static int tmu_get_temp(void *data, int *temp) +static int tmu_get_temp(struct thermal_zone_device *tz, int *temp) { - struct tmu_sensor *sensor = data; + struct tmu_sensor *sensor = tz->devdata; struct imx8mm_tmu *tmu = sensor->priv; - return tmu->socdata->get_temp(data, temp); + return tmu->socdata->get_temp(sensor, temp); } -static struct thermal_zone_of_device_ops tmu_tz_ops = { +static const struct thermal_zone_device_ops tmu_tz_ops = { .get_temp = tmu_get_temp, }; @@ -165,9 +165,9 @@ static int imx8mm_tmu_probe(struct platform_device *pdev) for (i = 0; i < data->num_sensors; i++) { tmu->sensors[i].priv = tmu; tmu->sensors[i].tzd = - devm_thermal_zone_of_sensor_register(&pdev->dev, i, - &tmu->sensors[i], - &tmu_tz_ops); + devm_thermal_of_zone_register(&pdev->dev, i, + &tmu->sensors[i], + &tmu_tz_ops); if (IS_ERR(tmu->sensors[i].tzd)) { ret = PTR_ERR(tmu->sensors[i].tzd); dev_err(&pdev->dev, diff --git a/drivers/thermal/imx_sc_thermal.c b/drivers/thermal/imx_sc_thermal.c index 331a241eb0ef3..10bfa6507eb4a 100644 --- a/drivers/thermal/imx_sc_thermal.c +++ b/drivers/thermal/imx_sc_thermal.c @@ -43,11 +43,11 @@ struct imx_sc_msg_misc_get_temp { } data; } __packed __aligned(4); -static int imx_sc_thermal_get_temp(void *data, int *temp) +static int imx_sc_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { struct imx_sc_msg_misc_get_temp msg; struct imx_sc_rpc_msg *hdr = &msg.hdr; - struct imx_sc_sensor *sensor = data; + struct imx_sc_sensor *sensor = tz->devdata; int ret; msg.data.req.resource_id = sensor->resource_id; @@ -70,7 +70,7 @@ static int imx_sc_thermal_get_temp(void *data, int *temp) return 0; } -static const struct thermal_zone_of_device_ops imx_sc_thermal_ops = { +static const struct thermal_zone_device_ops imx_sc_thermal_ops = { .get_temp = imx_sc_thermal_get_temp, }; @@ -109,10 +109,10 @@ static int imx_sc_thermal_probe(struct platform_device *pdev) break; } - sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, - sensor->resource_id, - sensor, - &imx_sc_thermal_ops); + sensor->tzd = devm_thermal_of_zone_register(&pdev->dev, + sensor->resource_id, + sensor, + &imx_sc_thermal_ops); if (IS_ERR(sensor->tzd)) { dev_err(&pdev->dev, "failed to register thermal zone\n"); ret = PTR_ERR(sensor->tzd); From 2ebd4f2f2ecfde86ce490f02b28b3282d93aa405 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:33 +0200 Subject: [PATCH 307/427] thermal/drivers/rcar: Switch to new of API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Tested-by: Niklas Söderlund Link: https://lore.kernel.org/r/20220804224349.1926752-18-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/rcar_gen3_thermal.c | 16 ++++++++-------- drivers/thermal/rcar_thermal.c | 13 +++---------- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index cda7c52f2319b..4c1c6f89aa2fb 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -164,9 +164,9 @@ static int rcar_gen3_thermal_round(int temp) return result * RCAR3_THERMAL_GRAN; } -static int rcar_gen3_thermal_get_temp(void *devdata, int *temp) +static int rcar_gen3_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { - struct rcar_gen3_thermal_tsc *tsc = devdata; + struct rcar_gen3_thermal_tsc *tsc = tz->devdata; int mcelsius, val; int reg; @@ -203,9 +203,9 @@ static int rcar_gen3_thermal_mcelsius_to_temp(struct rcar_gen3_thermal_tsc *tsc, return INT_FIXPT(val); } -static int rcar_gen3_thermal_set_trips(void *devdata, int low, int high) +static int rcar_gen3_thermal_set_trips(struct thermal_zone_device *tz, int low, int high) { - struct rcar_gen3_thermal_tsc *tsc = devdata; + struct rcar_gen3_thermal_tsc *tsc = tz->devdata; u32 irqmsk = 0; if (low != -INT_MAX) { @@ -225,7 +225,7 @@ static int rcar_gen3_thermal_set_trips(void *devdata, int low, int high) return 0; } -static struct thermal_zone_of_device_ops rcar_gen3_tz_of_ops = { +static struct thermal_zone_device_ops rcar_gen3_tz_of_ops = { .get_temp = rcar_gen3_thermal_get_temp, .set_trips = rcar_gen3_thermal_set_trips, }; @@ -508,8 +508,8 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) for (i = 0; i < priv->num_tscs; i++) { struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; - zone = devm_thermal_zone_of_sensor_register(dev, i, tsc, - &rcar_gen3_tz_of_ops); + zone = devm_thermal_of_zone_register(dev, i, tsc, + &rcar_gen3_tz_of_ops); if (IS_ERR(zone)) { dev_err(dev, "Sensor %u: Can't register thermal zone\n", i); ret = PTR_ERR(zone); @@ -560,7 +560,7 @@ static int __maybe_unused rcar_gen3_thermal_resume(struct device *dev) priv->thermal_init(tsc); if (zone->ops->set_trips) - rcar_gen3_thermal_set_trips(tsc, zone->prev_low_trip, + rcar_gen3_thermal_set_trips(zone, zone->prev_low_trip, zone->prev_high_trip); } diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 1d729ed4d6856..4df42d70d867d 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -271,13 +271,6 @@ static int rcar_thermal_get_current_temp(struct rcar_thermal_priv *priv, return 0; } -static int rcar_thermal_of_get_temp(void *data, int *temp) -{ - struct rcar_thermal_priv *priv = data; - - return rcar_thermal_get_current_temp(priv, temp); -} - static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp) { struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone); @@ -323,8 +316,8 @@ static int rcar_thermal_get_trip_temp(struct thermal_zone_device *zone, return 0; } -static const struct thermal_zone_of_device_ops rcar_thermal_zone_of_ops = { - .get_temp = rcar_thermal_of_get_temp, +static struct thermal_zone_device_ops rcar_thermal_zone_of_ops = { + .get_temp = rcar_thermal_get_temp, }; static struct thermal_zone_device_ops rcar_thermal_zone_ops = { @@ -534,7 +527,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) goto error_unregister; if (chip->use_of_thermal) { - priv->zone = devm_thermal_zone_of_sensor_register( + priv->zone = devm_thermal_of_zone_register( dev, i, priv, &rcar_thermal_zone_of_ops); } else { From 396cbbc6b711ef8d329303dc179a7a1c395f1f12 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:34 +0200 Subject: [PATCH 308/427] thermal/drivers/rzg2l: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-19-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/rzg2l_thermal.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/thermal/rzg2l_thermal.c b/drivers/thermal/rzg2l_thermal.c index 51ae80eda6af4..2e0649f385060 100644 --- a/drivers/thermal/rzg2l_thermal.c +++ b/drivers/thermal/rzg2l_thermal.c @@ -73,9 +73,9 @@ static inline void rzg2l_thermal_write(struct rzg2l_thermal_priv *priv, u32 reg, iowrite32(data, priv->base + reg); } -static int rzg2l_thermal_get_temp(void *devdata, int *temp) +static int rzg2l_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { - struct rzg2l_thermal_priv *priv = devdata; + struct rzg2l_thermal_priv *priv = tz->devdata; u32 result = 0, dsensor, ts_code_ave; int val, i; @@ -114,7 +114,7 @@ static int rzg2l_thermal_get_temp(void *devdata, int *temp) return 0; } -static const struct thermal_zone_of_device_ops rzg2l_tz_of_ops = { +static const struct thermal_zone_device_ops rzg2l_tz_of_ops = { .get_temp = rzg2l_thermal_get_temp, }; @@ -207,8 +207,8 @@ static int rzg2l_thermal_probe(struct platform_device *pdev) goto err; } - zone = devm_thermal_zone_of_sensor_register(dev, 0, priv, - &rzg2l_tz_of_ops); + zone = devm_thermal_of_zone_register(dev, 0, priv, + &rzg2l_tz_of_ops); if (IS_ERR(zone)) { dev_err(dev, "Can't register thermal zone"); ret = PTR_ERR(zone); From 3e7494b41c41959cd68a3f652e286c1fb7c626fc Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:35 +0200 Subject: [PATCH 309/427] thermal/drivers/qoriq: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-20-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/qoriq_thermal.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c index 73049f9bea252..d111e218f362e 100644 --- a/drivers/thermal/qoriq_thermal.c +++ b/drivers/thermal/qoriq_thermal.c @@ -82,9 +82,9 @@ static struct qoriq_tmu_data *qoriq_sensor_to_data(struct qoriq_sensor *s) return container_of(s, struct qoriq_tmu_data, sensor[s->id]); } -static int tmu_get_temp(void *p, int *temp) +static int tmu_get_temp(struct thermal_zone_device *tz, int *temp) { - struct qoriq_sensor *qsensor = p; + struct qoriq_sensor *qsensor = tz->devdata; struct qoriq_tmu_data *qdata = qoriq_sensor_to_data(qsensor); u32 val; /* @@ -122,7 +122,7 @@ static int tmu_get_temp(void *p, int *temp) return 0; } -static const struct thermal_zone_of_device_ops tmu_tz_ops = { +static const struct thermal_zone_device_ops tmu_tz_ops = { .get_temp = tmu_get_temp, }; @@ -146,9 +146,9 @@ static int qoriq_tmu_register_tmu_zone(struct device *dev, sensor->id = id; - tzd = devm_thermal_zone_of_sensor_register(dev, id, - sensor, - &tmu_tz_ops); + tzd = devm_thermal_of_zone_register(dev, id, + sensor, + &tmu_tz_ops); ret = PTR_ERR_OR_ZERO(tzd); if (ret) { if (ret == -ENODEV) From ab7e865db9a54abd775327f87f32f4d0e6e24109 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:36 +0200 Subject: [PATCH 310/427] thermal/drivers/mtk: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20220804224349.1926752-21-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/mtk_thermal.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c index ede94eaddddae..8440692e3890d 100644 --- a/drivers/thermal/mtk_thermal.c +++ b/drivers/thermal/mtk_thermal.c @@ -679,9 +679,9 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank) return max; } -static int mtk_read_temp(void *data, int *temperature) +static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature) { - struct mtk_thermal *mt = data; + struct mtk_thermal *mt = tz->devdata; int i; int tempmax = INT_MIN; @@ -700,7 +700,7 @@ static int mtk_read_temp(void *data, int *temperature) return 0; } -static const struct thermal_zone_of_device_ops mtk_thermal_ops = { +static const struct thermal_zone_device_ops mtk_thermal_ops = { .get_temp = mtk_read_temp, }; @@ -1082,8 +1082,8 @@ static int mtk_thermal_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mt); - tzdev = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, mt, - &mtk_thermal_ops); + tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt, + &mtk_thermal_ops); if (IS_ERR(tzdev)) { ret = PTR_ERR(tzdev); goto err_disable_clk_peri_therm; From b86105ed9f3bfead2aaf3daefa99b694ba5da443 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:37 +0200 Subject: [PATCH 311/427] thermal/drivers/banggap: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-22-daniel.lezcano@linexp.org Reviewed-by: Bryan Brattlof Signed-off-by: Daniel Lezcano --- drivers/thermal/k3_bandgap.c | 12 ++++++------ drivers/thermal/k3_j72xx_bandgap.c | 12 +++++------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/thermal/k3_bandgap.c b/drivers/thermal/k3_bandgap.c index 5d0b3ffc6f46c..22c9bcb899c37 100644 --- a/drivers/thermal/k3_bandgap.c +++ b/drivers/thermal/k3_bandgap.c @@ -139,9 +139,9 @@ static int k3_bgp_read_temp(struct k3_thermal_data *devdata, return 0; } -static int k3_thermal_get_temp(void *devdata, int *temp) +static int k3_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { - struct k3_thermal_data *data = devdata; + struct k3_thermal_data *data = tz->devdata; int ret = 0; ret = k3_bgp_read_temp(data, temp); @@ -151,7 +151,7 @@ static int k3_thermal_get_temp(void *devdata, int *temp) return ret; } -static const struct thermal_zone_of_device_ops k3_of_thermal_ops = { +static const struct thermal_zone_device_ops k3_of_thermal_ops = { .get_temp = k3_thermal_get_temp, }; @@ -213,9 +213,9 @@ static int k3_bandgap_probe(struct platform_device *pdev) writel(val, data[id].bgp->base + data[id].ctrl_offset); data[id].tzd = - devm_thermal_zone_of_sensor_register(dev, id, - &data[id], - &k3_of_thermal_ops); + devm_thermal_of_zone_register(dev, id, + &data[id], + &k3_of_thermal_ops); if (IS_ERR(data[id].tzd)) { dev_err(dev, "thermal zone device is NULL\n"); ret = PTR_ERR(data[id].tzd); diff --git a/drivers/thermal/k3_j72xx_bandgap.c b/drivers/thermal/k3_j72xx_bandgap.c index 115a44eb4fbfb..16b6bcf1bf4fa 100644 --- a/drivers/thermal/k3_j72xx_bandgap.c +++ b/drivers/thermal/k3_j72xx_bandgap.c @@ -247,9 +247,9 @@ static inline int k3_bgp_read_temp(struct k3_thermal_data *devdata, } /* Get temperature callback function for thermal zone */ -static int k3_thermal_get_temp(void *devdata, int *temp) +static int k3_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { - struct k3_thermal_data *data = devdata; + struct k3_thermal_data *data = tz->devdata; int ret = 0; ret = k3_bgp_read_temp(data, temp); @@ -259,7 +259,7 @@ static int k3_thermal_get_temp(void *devdata, int *temp) return ret; } -static const struct thermal_zone_of_device_ops k3_of_thermal_ops = { +static const struct thermal_zone_device_ops k3_of_thermal_ops = { .get_temp = k3_thermal_get_temp, }; @@ -474,10 +474,8 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev) writel(val, data[id].bgp->cfg2_base + data[id].ctrl_offset); bgp->ts_data[id] = &data[id]; - ti_thermal = - devm_thermal_zone_of_sensor_register(bgp->dev, id, - &data[id], - &k3_of_thermal_ops); + ti_thermal = devm_thermal_of_zone_register(bgp->dev, id, &data[id], + &k3_of_thermal_ops); if (IS_ERR(ti_thermal)) { dev_err(bgp->dev, "thermal zone device is NULL\n"); ret = PTR_ERR(ti_thermal); From ae11d6a87c3e742418baa591be1e719a95788059 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:38 +0200 Subject: [PATCH 312/427] thermal/drivers/maxim: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-23-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/max77620_thermal.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/max77620_thermal.c b/drivers/thermal/max77620_thermal.c index 82d06c7411eb3..6451a55eb5823 100644 --- a/drivers/thermal/max77620_thermal.c +++ b/drivers/thermal/max77620_thermal.c @@ -44,9 +44,9 @@ struct max77620_therm_info { * Return 0 on success otherwise error number to show reason of failure. */ -static int max77620_thermal_read_temp(void *data, int *temp) +static int max77620_thermal_read_temp(struct thermal_zone_device *tz, int *temp) { - struct max77620_therm_info *mtherm = data; + struct max77620_therm_info *mtherm = tz->devdata; unsigned int val; int ret; @@ -66,7 +66,7 @@ static int max77620_thermal_read_temp(void *data, int *temp) return 0; } -static const struct thermal_zone_of_device_ops max77620_thermal_ops = { +static const struct thermal_zone_device_ops max77620_thermal_ops = { .get_temp = max77620_thermal_read_temp, }; @@ -114,7 +114,7 @@ static int max77620_thermal_probe(struct platform_device *pdev) */ device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent); - mtherm->tz_device = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, + mtherm->tz_device = devm_thermal_of_zone_register(&pdev->dev, 0, mtherm, &max77620_thermal_ops); if (IS_ERR(mtherm->tz_device)) { ret = PTR_ERR(mtherm->tz_device); From 5ee7811e9afa4f6a1e6bf9231d096c9e483444a2 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:39 +0200 Subject: [PATCH 313/427] thermal/drivers/hisilicon: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-24-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/hisi_thermal.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 19a242c69ce63..d6974db7aaf76 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -434,9 +434,9 @@ static int hi3660_thermal_probe(struct hisi_thermal_data *data) return 0; } -static int hisi_thermal_get_temp(void *__data, int *temp) +static int hisi_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { - struct hisi_thermal_sensor *sensor = __data; + struct hisi_thermal_sensor *sensor = tz->devdata; struct hisi_thermal_data *data = sensor->data; *temp = data->ops->get_temp(sensor); @@ -447,7 +447,7 @@ static int hisi_thermal_get_temp(void *__data, int *temp) return 0; } -static const struct thermal_zone_of_device_ops hisi_of_thermal_ops = { +static const struct thermal_zone_device_ops hisi_of_thermal_ops = { .get_temp = hisi_thermal_get_temp, }; @@ -459,7 +459,7 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) data->ops->irq_handler(sensor); - hisi_thermal_get_temp(sensor, &temp); + temp = data->ops->get_temp(sensor); if (temp >= sensor->thres_temp) { dev_crit(&data->pdev->dev, @@ -484,9 +484,9 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, int ret, i; const struct thermal_trip *trip; - sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, - sensor->id, sensor, - &hisi_of_thermal_ops); + sensor->tzd = devm_thermal_of_zone_register(&pdev->dev, + sensor->id, sensor, + &hisi_of_thermal_ops); if (IS_ERR(sensor->tzd)) { ret = PTR_ERR(sensor->tzd); sensor->tzd = NULL; From 2cf3c72a3ffba080b8188a07c19514cd43df6097 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:40 +0200 Subject: [PATCH 314/427] thermal/drivers/ti-soc: Switch to new of API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-25-daniel.lezcano@linexp.org Acked-by: Keerthy Signed-off-by: Daniel Lezcano --- .../thermal/ti-soc-thermal/ti-thermal-common.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c index 703039d8b937f..8a9055bd376ec 100644 --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c @@ -65,10 +65,10 @@ static inline int ti_thermal_hotspot_temperature(int t, int s, int c) /* thermal zone ops */ /* Get temperature callback function for thermal zone */ -static inline int __ti_thermal_get_temp(void *devdata, int *temp) +static inline int __ti_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { struct thermal_zone_device *pcb_tz = NULL; - struct ti_thermal_data *data = devdata; + struct ti_thermal_data *data = tz->devdata; struct ti_bandgap *bgp; const struct ti_temp_sensor *s; int ret, tmp, slope, constant; @@ -85,8 +85,8 @@ static inline int __ti_thermal_get_temp(void *devdata, int *temp) return ret; /* Default constants */ - slope = thermal_zone_get_slope(data->ti_thermal); - constant = thermal_zone_get_offset(data->ti_thermal); + slope = thermal_zone_get_slope(tz); + constant = thermal_zone_get_offset(tz); pcb_tz = data->pcb_tz; /* In case pcb zone is available, use the extrapolation rule with it */ @@ -107,9 +107,9 @@ static inline int __ti_thermal_get_temp(void *devdata, int *temp) return ret; } -static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend) +static int __ti_thermal_get_trend(struct thermal_zone_device *tz, int trip, enum thermal_trend *trend) { - struct ti_thermal_data *data = p; + struct ti_thermal_data *data = tz->devdata; struct ti_bandgap *bgp; int id, tr, ret = 0; @@ -130,7 +130,7 @@ static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend) return 0; } -static const struct thermal_zone_of_device_ops ti_of_thermal_ops = { +static const struct thermal_zone_device_ops ti_of_thermal_ops = { .get_temp = __ti_thermal_get_temp, .get_trend = __ti_thermal_get_trend, }; @@ -170,7 +170,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, return -EINVAL; /* in case this is specified by DT */ - data->ti_thermal = devm_thermal_zone_of_sensor_register(bgp->dev, id, + data->ti_thermal = devm_thermal_of_zone_register(bgp->dev, id, data, &ti_of_thermal_ops); if (IS_ERR(data->ti_thermal)) { dev_err(bgp->dev, "thermal zone device is NULL\n"); From f1d8b5042ecf9e99294109bb5a1566f6a2039c89 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:41 +0200 Subject: [PATCH 315/427] ata/drivers/ahci_imx: Switch to new of thermal API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. sata_ahci_read_temperature() is used by sata_ahci_show_temp() also. So in order to change the function prototype for the get_temp ops which does not take a void* but a thermal_zone_device* structure, this function wraps the call. Signed-off-by: Daniel Lezcano Acked-by: Damien Le Moal Link: https://lore.kernel.org/r/20220804224349.1926752-26-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/ata/ahci_imx.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 79aa9f2853129..b734e069034d2 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -327,7 +327,7 @@ static int read_adc_sum(void *dev, u16 rtune_ctl_reg, void __iomem * mmio) } /* SATA AHCI temperature monitor */ -static int sata_ahci_read_temperature(void *dev, int *temp) +static int __sata_ahci_read_temperature(void *dev, int *temp) { u16 mpll_test_reg, rtune_ctl_reg, dac_ctl_reg, read_sum; u32 str1, str2, str3, str4; @@ -416,6 +416,11 @@ static int sata_ahci_read_temperature(void *dev, int *temp) return 0; } +static int sata_ahci_read_temperature(struct thermal_zone_device *tz, int *temp) +{ + return __sata_ahci_read_temperature(tz->devdata, temp); +} + static ssize_t sata_ahci_show_temp(struct device *dev, struct device_attribute *da, char *buf) @@ -423,14 +428,14 @@ static ssize_t sata_ahci_show_temp(struct device *dev, unsigned int temp = 0; int err; - err = sata_ahci_read_temperature(dev, &temp); + err = __sata_ahci_read_temperature(dev, &temp); if (err < 0) return err; return sprintf(buf, "%u\n", temp); } -static const struct thermal_zone_of_device_ops fsl_sata_ahci_of_thermal_ops = { +static const struct thermal_zone_device_ops fsl_sata_ahci_of_thermal_ops = { .get_temp = sata_ahci_read_temperature, }; @@ -1131,8 +1136,8 @@ static int imx_ahci_probe(struct platform_device *pdev) ret = PTR_ERR(hwmon_dev); goto disable_clk; } - devm_thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev, - &fsl_sata_ahci_of_thermal_ops); + devm_thermal_of_zone_register(hwmon_dev, 0, hwmon_dev, + &fsl_sata_ahci_of_thermal_ops); dev_info(dev, "%s: sensor 'sata_ahci'\n", dev_name(hwmon_dev)); } From 613ed3f67609291c9b757d62f1f6734e40cb60d8 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:42 +0200 Subject: [PATCH 316/427] hwmon: pm_bus: core: Switch to new of thermal API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-27-daniel.lezcano@linexp.org Acked-by: Guenter Roeck Signed-off-by: Daniel Lezcano --- drivers/hwmon/pmbus/pmbus_core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index f10bac8860fce..5541d26e86239 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -1270,9 +1270,9 @@ struct pmbus_thermal_data { struct pmbus_sensor *sensor; }; -static int pmbus_thermal_get_temp(void *data, int *temp) +static int pmbus_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { - struct pmbus_thermal_data *tdata = data; + struct pmbus_thermal_data *tdata = tz->devdata; struct pmbus_sensor *sensor = tdata->sensor; struct pmbus_data *pmbus_data = tdata->pmbus_data; struct i2c_client *client = to_i2c_client(pmbus_data->dev); @@ -1296,7 +1296,7 @@ static int pmbus_thermal_get_temp(void *data, int *temp) return ret; } -static const struct thermal_zone_of_device_ops pmbus_thermal_ops = { +static const struct thermal_zone_device_ops pmbus_thermal_ops = { .get_temp = pmbus_thermal_get_temp, }; @@ -1314,8 +1314,8 @@ static int pmbus_thermal_add_sensor(struct pmbus_data *pmbus_data, tdata->sensor = sensor; tdata->pmbus_data = pmbus_data; - tzd = devm_thermal_zone_of_sensor_register(dev, index, tdata, - &pmbus_thermal_ops); + tzd = devm_thermal_of_zone_register(dev, index, tdata, + &pmbus_thermal_ops); /* * If CONFIG_THERMAL_OF is disabled, this returns -ENODEV, * so ignore that error but forward any other error. From e5181331359d9311b3cc7e09d9d1cb2ffe87f602 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:43 +0200 Subject: [PATCH 317/427] hwmon/drivers/core: Switch to new of thermal API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Acked-by: Guenter Roeck Link: https://lore.kernel.org/r/20220804224349.1926752-28-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/hwmon/hwmon.c | 14 +++++++------- drivers/hwmon/scpi-hwmon.c | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index 2e2cd79d89ebc..4218750d5a66b 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -151,9 +151,9 @@ static DEFINE_IDA(hwmon_ida); * between hwmon and thermal_sys modules. */ #ifdef CONFIG_THERMAL_OF -static int hwmon_thermal_get_temp(void *data, int *temp) +static int hwmon_thermal_get_temp(struct thermal_zone_device *tz, int *temp) { - struct hwmon_thermal_data *tdata = data; + struct hwmon_thermal_data *tdata = tz->devdata; struct hwmon_device *hwdev = to_hwmon_device(tdata->dev); int ret; long t; @@ -168,9 +168,9 @@ static int hwmon_thermal_get_temp(void *data, int *temp) return 0; } -static int hwmon_thermal_set_trips(void *data, int low, int high) +static int hwmon_thermal_set_trips(struct thermal_zone_device *tz, int low, int high) { - struct hwmon_thermal_data *tdata = data; + struct hwmon_thermal_data *tdata = tz->devdata; struct hwmon_device *hwdev = to_hwmon_device(tdata->dev); const struct hwmon_chip_info *chip = hwdev->chip; const struct hwmon_channel_info **info = chip->info; @@ -203,7 +203,7 @@ static int hwmon_thermal_set_trips(void *data, int low, int high) return 0; } -static const struct thermal_zone_of_device_ops hwmon_thermal_ops = { +static const struct thermal_zone_device_ops hwmon_thermal_ops = { .get_temp = hwmon_thermal_get_temp, .set_trips = hwmon_thermal_set_trips, }; @@ -227,8 +227,8 @@ static int hwmon_thermal_add_sensor(struct device *dev, int index) tdata->dev = dev; tdata->index = index; - tzd = devm_thermal_zone_of_sensor_register(dev, index, tdata, - &hwmon_thermal_ops); + tzd = devm_thermal_of_zone_register(dev, index, tdata, + &hwmon_thermal_ops); if (IS_ERR(tzd)) { if (PTR_ERR(tzd) != -ENODEV) return PTR_ERR(tzd); diff --git a/drivers/hwmon/scpi-hwmon.c b/drivers/hwmon/scpi-hwmon.c index 5187c6dd5a4f0..4d75385f7d5ec 100644 --- a/drivers/hwmon/scpi-hwmon.c +++ b/drivers/hwmon/scpi-hwmon.c @@ -62,9 +62,9 @@ static void scpi_scale_reading(u64 *value, struct sensor_data *sensor) } } -static int scpi_read_temp(void *dev, int *temp) +static int scpi_read_temp(struct thermal_zone_device *tz, int *temp) { - struct scpi_thermal_zone *zone = dev; + struct scpi_thermal_zone *zone = tz->devdata; struct scpi_sensors *scpi_sensors = zone->scpi_sensors; struct scpi_ops *scpi_ops = scpi_sensors->scpi_ops; struct sensor_data *sensor = &scpi_sensors->data[zone->sensor_id]; @@ -121,7 +121,7 @@ scpi_show_label(struct device *dev, struct device_attribute *attr, char *buf) return sprintf(buf, "%s\n", sensor->info.name); } -static const struct thermal_zone_of_device_ops scpi_sensor_ops = { +static const struct thermal_zone_device_ops scpi_sensor_ops = { .get_temp = scpi_read_temp, }; @@ -275,10 +275,10 @@ static int scpi_hwmon_probe(struct platform_device *pdev) zone->sensor_id = i; zone->scpi_sensors = scpi_sensors; - z = devm_thermal_zone_of_sensor_register(dev, - sensor->info.sensor_id, - zone, - &scpi_sensor_ops); + z = devm_thermal_of_zone_register(dev, + sensor->info.sensor_id, + zone, + &scpi_sensor_ops); /* * The call to thermal_zone_of_sensor_register returns * an error for sensors that are not associated with From de15b8403fa9872cb626a52651b257089b34f5d2 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:44 +0200 Subject: [PATCH 318/427] iio/drivers/sun4i_gpadc: Switch to new of thermal API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Acked-by: Jonathan Cameron Acked-by: Jernej Skrabec Link: https://lore.kernel.org/r/20220804224349.1926752-29-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/iio/adc/sun4i-gpadc-iio.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index 2d393a4dfff6a..a6ade70dedf89 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -412,9 +412,9 @@ static int sun4i_gpadc_runtime_resume(struct device *dev) return 0; } -static int sun4i_gpadc_get_temp(void *data, int *temp) +static int sun4i_gpadc_get_temp(struct thermal_zone_device *tz, int *temp) { - struct sun4i_gpadc_iio *info = data; + struct sun4i_gpadc_iio *info = tz->devdata; int val, scale, offset; if (sun4i_gpadc_temp_read(info->indio_dev, &val)) @@ -428,7 +428,7 @@ static int sun4i_gpadc_get_temp(void *data, int *temp) return 0; } -static const struct thermal_zone_of_device_ops sun4i_ts_tz_ops = { +static const struct thermal_zone_device_ops sun4i_ts_tz_ops = { .get_temp = &sun4i_gpadc_get_temp, }; @@ -637,9 +637,9 @@ static int sun4i_gpadc_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); if (IS_ENABLED(CONFIG_THERMAL_OF)) { - info->tzd = thermal_zone_of_sensor_register(info->sensor_device, - 0, info, - &sun4i_ts_tz_ops); + info->tzd = devm_thermal_of_zone_register(info->sensor_device, + 0, info, + &sun4i_ts_tz_ops); /* * Do not fail driver probing when failing to register in * thermal because no thermal DT node is found. @@ -681,8 +681,6 @@ static int sun4i_gpadc_remove(struct platform_device *pdev) if (!IS_ENABLED(CONFIG_THERMAL_OF)) return 0; - thermal_zone_of_sensor_unregister(info->sensor_device, info->tzd); - if (!info->no_irq) iio_map_array_unregister(indio_dev); From ad662b1d606515a048cef06c025dfb150cebaa8d Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:45 +0200 Subject: [PATCH 319/427] Input: sun4i-ts - switch to new of thermal API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Acked-by: Dmitry Torokhov Acked-by: Jernej Skrabec Link: https://lore.kernel.org/r/20220804224349.1926752-30-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/input/touchscreen/sun4i-ts.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c index 742a7e96c1b57..73eb8f80be6ef 100644 --- a/drivers/input/touchscreen/sun4i-ts.c +++ b/drivers/input/touchscreen/sun4i-ts.c @@ -192,12 +192,12 @@ static int sun4i_get_temp(const struct sun4i_ts_data *ts, int *temp) return 0; } -static int sun4i_get_tz_temp(void *data, int *temp) +static int sun4i_get_tz_temp(struct thermal_zone_device *tz, int *temp) { - return sun4i_get_temp(data, temp); + return sun4i_get_temp(tz->devdata, temp); } -static const struct thermal_zone_of_device_ops sun4i_ts_tz_ops = { +static const struct thermal_zone_device_ops sun4i_ts_tz_ops = { .get_temp = sun4i_get_tz_temp, }; @@ -356,8 +356,8 @@ static int sun4i_ts_probe(struct platform_device *pdev) if (IS_ERR(hwmon)) return PTR_ERR(hwmon); - thermal = devm_thermal_zone_of_sensor_register(ts->dev, 0, ts, - &sun4i_ts_tz_ops); + thermal = devm_thermal_of_zone_register(ts->dev, 0, ts, + &sun4i_ts_tz_ops); if (IS_ERR(thermal)) return PTR_ERR(thermal); From 826855ff5746d0f98877eaa4a438abc4e7b58fd5 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:46 +0200 Subject: [PATCH 320/427] regulator/drivers/max8976: Switch to new of thermal API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Acked-by: Mark Brown Link: https://lore.kernel.org/r/20220804224349.1926752-31-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/regulator/max8973-regulator.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c index fdcb0f508984c..596cc36aaff6b 100644 --- a/drivers/regulator/max8973-regulator.c +++ b/drivers/regulator/max8973-regulator.c @@ -434,9 +434,9 @@ static int max8973_init_dcdc(struct max8973_chip *max, return ret; } -static int max8973_thermal_read_temp(void *data, int *temp) +static int max8973_thermal_read_temp(struct thermal_zone_device *tz, int *temp) { - struct max8973_chip *mchip = data; + struct max8973_chip *mchip = tz->devdata; unsigned int val; int ret; @@ -465,7 +465,7 @@ static irqreturn_t max8973_thermal_irq(int irq, void *data) return IRQ_HANDLED; } -static const struct thermal_zone_of_device_ops max77621_tz_ops = { +static const struct thermal_zone_device_ops max77621_tz_ops = { .get_temp = max8973_thermal_read_temp, }; @@ -479,8 +479,8 @@ static int max8973_thermal_init(struct max8973_chip *mchip) if (mchip->id != MAX77621) return 0; - tzd = devm_thermal_zone_of_sensor_register(mchip->dev, 0, mchip, - &max77621_tz_ops); + tzd = devm_thermal_of_zone_register(mchip->dev, 0, mchip, + &max77621_tz_ops); if (IS_ERR(tzd)) { ret = PTR_ERR(tzd); dev_err(mchip->dev, "Failed to register thermal sensor: %d\n", From 7ea98f70c73ea37d379a76a69fa71653382a1724 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:47 +0200 Subject: [PATCH 321/427] thermal/drivers/samsung: Switch to new of thermal API The thermal OF code has a new API allowing to migrate the OF initialization to a simpler approach. The ops are no longer device tree specific and are the generic ones provided by the core code. Convert the ops to the thermal_zone_device_ops format and use the new API to register the thermal zone with these generic ops. Signed-off-by: Daniel Lezcano Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220804224349.1926752-32-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/samsung/exynos_tmu.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index f4ab4c5b4b626..51874d0a284cb 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -650,9 +650,9 @@ static void exynos7_tmu_control(struct platform_device *pdev, bool on) writel(con, data->base + EXYNOS_TMU_REG_CONTROL); } -static int exynos_get_temp(void *p, int *temp) +static int exynos_get_temp(struct thermal_zone_device *tz, int *temp) { - struct exynos_tmu_data *data = p; + struct exynos_tmu_data *data = tz->devdata; int value, ret = 0; if (!data || !data->tmu_read) @@ -728,9 +728,9 @@ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data, writel(val, data->base + emul_con); } -static int exynos_tmu_set_emulation(void *drv_data, int temp) +static int exynos_tmu_set_emulation(struct thermal_zone_device *tz, int temp) { - struct exynos_tmu_data *data = drv_data; + struct exynos_tmu_data *data = tz->devdata; int ret = -EINVAL; if (data->soc == SOC_ARCH_EXYNOS4210) @@ -750,7 +750,7 @@ static int exynos_tmu_set_emulation(void *drv_data, int temp) } #else #define exynos4412_tmu_set_emulation NULL -static int exynos_tmu_set_emulation(void *drv_data, int temp) +static int exynos_tmu_set_emulation(struct thermal_zone_device *tz, int temp) { return -EINVAL; } #endif /* CONFIG_THERMAL_EMULATION */ @@ -997,7 +997,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) return 0; } -static const struct thermal_zone_of_device_ops exynos_sensor_ops = { +static const struct thermal_zone_device_ops exynos_sensor_ops = { .get_temp = exynos_get_temp, .set_emul_temp = exynos_tmu_set_emulation, }; @@ -1091,8 +1091,8 @@ static int exynos_tmu_probe(struct platform_device *pdev) * data->tzd must be registered before calling exynos_tmu_initialize(), * requesting irq and calling exynos_tmu_control(). */ - data->tzd = thermal_zone_of_sensor_register(&pdev->dev, 0, data, - &exynos_sensor_ops); + data->tzd = devm_thermal_of_zone_register(&pdev->dev, 0, data, + &exynos_sensor_ops); if (IS_ERR(data->tzd)) { ret = PTR_ERR(data->tzd); if (ret != -EPROBE_DEFER) @@ -1104,21 +1104,19 @@ static int exynos_tmu_probe(struct platform_device *pdev) ret = exynos_tmu_initialize(pdev); if (ret) { dev_err(&pdev->dev, "Failed to initialize TMU\n"); - goto err_thermal; + goto err_sclk; } ret = devm_request_irq(&pdev->dev, data->irq, exynos_tmu_irq, IRQF_TRIGGER_RISING | IRQF_SHARED, dev_name(&pdev->dev), data); if (ret) { dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq); - goto err_thermal; + goto err_sclk; } exynos_tmu_control(pdev, true); return 0; -err_thermal: - thermal_zone_of_sensor_unregister(&pdev->dev, data->tzd); err_sclk: clk_disable_unprepare(data->sclk); err_clk: @@ -1136,9 +1134,7 @@ static int exynos_tmu_probe(struct platform_device *pdev) static int exynos_tmu_remove(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); - struct thermal_zone_device *tzd = data->tzd; - thermal_zone_of_sensor_unregister(&pdev->dev, tzd); exynos_tmu_control(pdev, false); clk_disable_unprepare(data->sclk); From 9326167058e8a5b93179f19fc0368f5324a1f628 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:48 +0200 Subject: [PATCH 322/427] thermal/core: Move set_trip_temp ops to the sysfs code Given the trip points can be set in the thermal zone structure, there is no need of a specific OF function to do that. Move the code in the place where it is generic, in the sysfs set_trip_temp storing function. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-33-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/thermal_of.c | 23 ----------------------- drivers/thermal/thermal_sysfs.c | 5 ++++- 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index a17087c9295da..1dd6b71bdbddb 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -288,28 +288,6 @@ static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip, return 0; } -static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip, - int temp) -{ - struct __thermal_zone *data = tz->devdata; - - if (trip >= tz->num_trips || trip < 0) - return -EDOM; - - if (data->ops && data->ops->set_trip_temp) { - int ret; - - ret = data->ops->set_trip_temp(data->sensor_data, trip, temp); - if (ret) - return ret; - } - - /* thermal framework should take care of data->mask & (1 << trip) */ - tz->trips[trip].temperature = temp; - - return 0; -} - static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip, int *hyst) { @@ -350,7 +328,6 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz, static struct thermal_zone_device_ops of_thermal_ops = { .get_trip_type = of_thermal_get_trip_type, .get_trip_temp = of_thermal_get_trip_temp, - .set_trip_temp = of_thermal_set_trip_temp, .get_trip_hyst = of_thermal_get_trip_hyst, .set_trip_hyst = of_thermal_set_trip_hyst, .get_crit_temp = of_thermal_get_crit_temp, diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c index 3a8d6e747c255..0f8201060c38a 100644 --- a/drivers/thermal/thermal_sysfs.c +++ b/drivers/thermal/thermal_sysfs.c @@ -115,7 +115,7 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr, int temperature, hyst = 0; enum thermal_trip_type type; - if (!tz->ops->set_trip_temp) + if (!tz->ops->set_trip_temp && !tz->trips) return -EPERM; if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1) @@ -128,6 +128,9 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr, if (ret) return ret; + if (tz->trips) + tz->trips[trip].temperature = temperature; + if (tz->ops->get_trip_hyst) { ret = tz->ops->get_trip_hyst(tz, trip, &hyst); if (ret) From f59ac19b7f44cab23df84810e2da5f57bdd3a7e7 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 00:43:49 +0200 Subject: [PATCH 323/427] thermal/of: Remove old OF code All the drivers are converted to the new OF API, remove the old OF code. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220804224349.1926752-34-daniel.lezcano@linexp.org Signed-off-by: Daniel Lezcano --- drivers/thermal/thermal_core.h | 2 - drivers/thermal/thermal_of.c | 810 +-------------------------------- include/linux/thermal.h | 77 +--- 3 files changed, 16 insertions(+), 873 deletions(-) diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index c991bb290512c..2241d2dce017f 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -135,13 +135,11 @@ thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev, /* device tree support */ #ifdef CONFIG_THERMAL_OF -int of_parse_thermal_zones(void); int of_thermal_get_ntrips(struct thermal_zone_device *); bool of_thermal_is_trip_valid(struct thermal_zone_device *, int); const struct thermal_trip * of_thermal_get_trip_points(struct thermal_zone_device *); #else -static inline int of_parse_thermal_zones(void) { return 0; } static inline int of_thermal_get_ntrips(struct thermal_zone_device *tz) { return 0; diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 1dd6b71bdbddb..fd2fb84bf2461 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -19,93 +19,6 @@ #include "thermal_core.h" -/*** Private data structures to represent thermal device tree data ***/ - -/** - * struct __thermal_cooling_bind_param - a cooling device for a trip point - * @cooling_device: a pointer to identify the referred cooling device - * @min: minimum cooling state used at this trip point - * @max: maximum cooling state used at this trip point - */ - -struct __thermal_cooling_bind_param { - struct device_node *cooling_device; - unsigned long min; - unsigned long max; -}; - -/** - * struct __thermal_bind_params - a match between trip and cooling device - * @tcbp: a pointer to an array of cooling devices - * @count: number of elements in array - * @trip_id: the trip point index - * @usage: the percentage (from 0 to 100) of cooling contribution - */ - -struct __thermal_bind_params { - struct __thermal_cooling_bind_param *tcbp; - unsigned int count; - unsigned int trip_id; - unsigned int usage; -}; - -/** - * struct __thermal_zone - internal representation of a thermal zone - * @passive_delay: polling interval while passive cooling is activated - * @polling_delay: zone polling interval - * @slope: slope of the temperature adjustment curve - * @offset: offset of the temperature adjustment curve - * @ntrips: number of trip points - * @trips: an array of trip points (0..ntrips - 1) - * @num_tbps: number of thermal bind params - * @tbps: an array of thermal bind params (0..num_tbps - 1) - * @sensor_data: sensor private data used while reading temperature and trend - * @ops: set of callbacks to handle the thermal zone based on DT - */ - -struct __thermal_zone { - int passive_delay; - int polling_delay; - int slope; - int offset; - - /* trip data */ - int ntrips; - struct thermal_trip *trips; - - /* cooling binding data */ - int num_tbps; - struct __thermal_bind_params *tbps; - - /* sensor interface */ - void *sensor_data; - const struct thermal_zone_of_device_ops *ops; -}; - -/*** DT thermal zone device callbacks ***/ - -static int of_thermal_get_temp(struct thermal_zone_device *tz, - int *temp) -{ - struct __thermal_zone *data = tz->devdata; - - if (!data->ops || !data->ops->get_temp) - return -EINVAL; - - return data->ops->get_temp(data->sensor_data, temp); -} - -static int of_thermal_set_trips(struct thermal_zone_device *tz, - int low, int high) -{ - struct __thermal_zone *data = tz->devdata; - - if (!data->ops || !data->ops->set_trips) - return -EINVAL; - - return data->ops->set_trips(data->sensor_data, low, high); -} - /** * of_thermal_get_ntrips - function to export number of available trip * points. @@ -158,114 +71,6 @@ of_thermal_get_trip_points(struct thermal_zone_device *tz) } EXPORT_SYMBOL_GPL(of_thermal_get_trip_points); -/** - * of_thermal_set_emul_temp - function to set emulated temperature - * - * @tz: pointer to a thermal zone - * @temp: temperature to set - * - * This function gives the ability to set emulated value of temperature, - * which is handy for debugging - * - * Return: zero on success, error code otherwise - */ -static int of_thermal_set_emul_temp(struct thermal_zone_device *tz, - int temp) -{ - struct __thermal_zone *data = tz->devdata; - - if (!data->ops || !data->ops->set_emul_temp) - return -EINVAL; - - return data->ops->set_emul_temp(data->sensor_data, temp); -} - -static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip, - enum thermal_trend *trend) -{ - struct __thermal_zone *data = tz->devdata; - - if (!data->ops || !data->ops->get_trend) - return -EINVAL; - - return data->ops->get_trend(data->sensor_data, trip, trend); -} - -static int of_thermal_change_mode(struct thermal_zone_device *tz, - enum thermal_device_mode mode) -{ - struct __thermal_zone *data = tz->devdata; - - return data->ops->change_mode(data->sensor_data, mode); -} - -static int of_thermal_bind(struct thermal_zone_device *thermal, - struct thermal_cooling_device *cdev) -{ - struct __thermal_zone *data = thermal->devdata; - struct __thermal_bind_params *tbp; - struct __thermal_cooling_bind_param *tcbp; - int i, j; - - if (!data || IS_ERR(data)) - return -ENODEV; - - /* find where to bind */ - for (i = 0; i < data->num_tbps; i++) { - tbp = data->tbps + i; - - for (j = 0; j < tbp->count; j++) { - tcbp = tbp->tcbp + j; - - if (tcbp->cooling_device == cdev->np) { - int ret; - - ret = thermal_zone_bind_cooling_device(thermal, - tbp->trip_id, cdev, - tcbp->max, - tcbp->min, - tbp->usage); - if (ret) - return ret; - } - } - } - - return 0; -} - -static int of_thermal_unbind(struct thermal_zone_device *thermal, - struct thermal_cooling_device *cdev) -{ - struct __thermal_zone *data = thermal->devdata; - struct __thermal_bind_params *tbp; - struct __thermal_cooling_bind_param *tcbp; - int i, j; - - if (!data || IS_ERR(data)) - return -ENODEV; - - /* find where to unbind */ - for (i = 0; i < data->num_tbps; i++) { - tbp = data->tbps + i; - - for (j = 0; j < tbp->count; j++) { - tcbp = tbp->tcbp + j; - - if (tcbp->cooling_device == cdev->np) { - int ret; - - ret = thermal_zone_unbind_cooling_device(thermal, - tbp->trip_id, cdev); - if (ret) - return ret; - } - } - } - - return 0; -} - static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip, enum thermal_trip_type *type) { @@ -325,61 +130,6 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz, return -EINVAL; } -static struct thermal_zone_device_ops of_thermal_ops = { - .get_trip_type = of_thermal_get_trip_type, - .get_trip_temp = of_thermal_get_trip_temp, - .get_trip_hyst = of_thermal_get_trip_hyst, - .set_trip_hyst = of_thermal_set_trip_hyst, - .get_crit_temp = of_thermal_get_crit_temp, - - .bind = of_thermal_bind, - .unbind = of_thermal_unbind, -}; - -/*** sensor API ***/ - -static struct thermal_zone_device * -thermal_zone_of_add_sensor(struct device_node *zone, - struct device_node *sensor, void *data, - const struct thermal_zone_of_device_ops *ops) -{ - struct thermal_zone_device *tzd; - struct __thermal_zone *tz; - - tzd = thermal_zone_get_zone_by_name(zone->name); - if (IS_ERR(tzd)) - return ERR_PTR(-EPROBE_DEFER); - - tz = tzd->devdata; - - if (!ops) - return ERR_PTR(-EINVAL); - - mutex_lock(&tzd->lock); - tz->ops = ops; - tz->sensor_data = data; - - tzd->ops->get_temp = of_thermal_get_temp; - tzd->ops->get_trend = of_thermal_get_trend; - - /* - * The thermal zone core will calculate the window if they have set the - * optional set_trips pointer. - */ - if (ops->set_trips) - tzd->ops->set_trips = of_thermal_set_trips; - - if (ops->set_emul_temp) - tzd->ops->set_emul_temp = of_thermal_set_emul_temp; - - if (ops->change_mode) - tzd->ops->change_mode = of_thermal_change_mode; - - mutex_unlock(&tzd->lock); - - return tzd; -} - /** * thermal_zone_of_get_sensor_id - get sensor ID from a DT thermal zone * @tz_np: a valid thermal zone device node. @@ -424,216 +174,6 @@ int thermal_zone_of_get_sensor_id(struct device_node *tz_np, } EXPORT_SYMBOL_GPL(thermal_zone_of_get_sensor_id); -/** - * thermal_zone_of_sensor_register - registers a sensor to a DT thermal zone - * @dev: a valid struct device pointer of a sensor device. Must contain - * a valid .of_node, for the sensor node. - * @sensor_id: a sensor identifier, in case the sensor IP has more - * than one sensors - * @data: a private pointer (owned by the caller) that will be passed - * back, when a temperature reading is needed. - * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp. - * - * This function will search the list of thermal zones described in device - * tree and look for the zone that refer to the sensor device pointed by - * @dev->of_node as temperature providers. For the zone pointing to the - * sensor node, the sensor will be added to the DT thermal zone device. - * - * The thermal zone temperature is provided by the @get_temp function - * pointer. When called, it will have the private pointer @data back. - * - * The thermal zone temperature trend is provided by the @get_trend function - * pointer. When called, it will have the private pointer @data back. - * - * TODO: - * 01 - This function must enqueue the new sensor instead of using - * it as the only source of temperature values. - * - * 02 - There must be a way to match the sensor with all thermal zones - * that refer to it. - * - * Return: On success returns a valid struct thermal_zone_device, - * otherwise, it returns a corresponding ERR_PTR(). Caller must - * check the return value with help of IS_ERR() helper. - */ -struct thermal_zone_device * -thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data, - const struct thermal_zone_of_device_ops *ops) -{ - struct device_node *np, *child, *sensor_np; - struct thermal_zone_device *tzd = ERR_PTR(-ENODEV); - static int old_tz_initialized; - int ret; - - if (!old_tz_initialized) { - ret = of_parse_thermal_zones(); - if (ret) - return ERR_PTR(ret); - old_tz_initialized = 1; - } - - np = of_find_node_by_name(NULL, "thermal-zones"); - if (!np) - return ERR_PTR(-ENODEV); - - if (!dev || !dev->of_node) { - of_node_put(np); - return ERR_PTR(-ENODEV); - } - - sensor_np = of_node_get(dev->of_node); - - for_each_available_child_of_node(np, child) { - int ret, id; - - /* For now, thermal framework supports only 1 sensor per zone */ - ret = thermal_zone_of_get_sensor_id(child, sensor_np, &id); - if (ret) - continue; - - if (id == sensor_id) { - tzd = thermal_zone_of_add_sensor(child, sensor_np, - data, ops); - if (!IS_ERR(tzd)) - thermal_zone_device_enable(tzd); - - of_node_put(child); - goto exit; - } - } -exit: - of_node_put(sensor_np); - of_node_put(np); - - return tzd; -} -EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_register); - -/** - * thermal_zone_of_sensor_unregister - unregisters a sensor from a DT thermal zone - * @dev: a valid struct device pointer of a sensor device. Must contain - * a valid .of_node, for the sensor node. - * @tzd: a pointer to struct thermal_zone_device where the sensor is registered. - * - * This function removes the sensor callbacks and private data from the - * thermal zone device registered with thermal_zone_of_sensor_register() - * API. It will also silent the zone by remove the .get_temp() and .get_trend() - * thermal zone device callbacks. - * - * TODO: When the support to several sensors per zone is added, this - * function must search the sensor list based on @dev parameter. - * - */ -void thermal_zone_of_sensor_unregister(struct device *dev, - struct thermal_zone_device *tzd) -{ - struct __thermal_zone *tz; - - if (!dev || !tzd || !tzd->devdata) - return; - - tz = tzd->devdata; - - /* no __thermal_zone, nothing to be done */ - if (!tz) - return; - - /* stop temperature polling */ - thermal_zone_device_disable(tzd); - - mutex_lock(&tzd->lock); - tzd->ops->get_temp = NULL; - tzd->ops->get_trend = NULL; - tzd->ops->set_emul_temp = NULL; - tzd->ops->change_mode = NULL; - - tz->ops = NULL; - tz->sensor_data = NULL; - mutex_unlock(&tzd->lock); -} -EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister); - -static void devm_thermal_zone_of_sensor_release(struct device *dev, void *res) -{ - thermal_zone_of_sensor_unregister(dev, - *(struct thermal_zone_device **)res); -} - -static int devm_thermal_zone_of_sensor_match(struct device *dev, void *res, - void *data) -{ - struct thermal_zone_device **r = res; - - if (WARN_ON(!r || !*r)) - return 0; - - return *r == data; -} - -/** - * devm_thermal_zone_of_sensor_register - Resource managed version of - * thermal_zone_of_sensor_register() - * @dev: a valid struct device pointer of a sensor device. Must contain - * a valid .of_node, for the sensor node. - * @sensor_id: a sensor identifier, in case the sensor IP has more - * than one sensors - * @data: a private pointer (owned by the caller) that will be passed - * back, when a temperature reading is needed. - * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp. - * - * Refer thermal_zone_of_sensor_register() for more details. - * - * Return: On success returns a valid struct thermal_zone_device, - * otherwise, it returns a corresponding ERR_PTR(). Caller must - * check the return value with help of IS_ERR() helper. - * Registered thermal_zone_device device will automatically be - * released when device is unbounded. - */ -struct thermal_zone_device *devm_thermal_zone_of_sensor_register( - struct device *dev, int sensor_id, - void *data, const struct thermal_zone_of_device_ops *ops) -{ - struct thermal_zone_device **ptr, *tzd; - - ptr = devres_alloc(devm_thermal_zone_of_sensor_release, sizeof(*ptr), - GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); - - tzd = thermal_zone_of_sensor_register(dev, sensor_id, data, ops); - if (IS_ERR(tzd)) { - devres_free(ptr); - return tzd; - } - - *ptr = tzd; - devres_add(dev, ptr); - - return tzd; -} -EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_register); - -/** - * devm_thermal_zone_of_sensor_unregister - Resource managed version of - * thermal_zone_of_sensor_unregister(). - * @dev: Device for which which resource was allocated. - * @tzd: a pointer to struct thermal_zone_device where the sensor is registered. - * - * This function removes the sensor callbacks and private data from the - * thermal zone device registered with devm_thermal_zone_of_sensor_register() - * API. It will also silent the zone by remove the .get_temp() and .get_trend() - * thermal zone device callbacks. - * Normally this function will not need to be called and the resource - * management code will ensure that the resource is freed. - */ -void devm_thermal_zone_of_sensor_unregister(struct device *dev, - struct thermal_zone_device *tzd) -{ - WARN_ON(devres_release(dev, devm_thermal_zone_of_sensor_release, - devm_thermal_zone_of_sensor_match, tzd)); -} -EXPORT_SYMBOL_GPL(devm_thermal_zone_of_sensor_unregister); - /*** functions parsing device tree nodes ***/ static int of_find_trip_id(struct device_node *np, struct device_node *trip) @@ -665,98 +205,6 @@ static int of_find_trip_id(struct device_node *np, struct device_node *trip) return i; } -/** - * thermal_of_populate_bind_params - parse and fill cooling map data - * @np: DT node containing a cooling-map node - * @__tbp: data structure to be filled with cooling map info - * @trips: array of thermal zone trip points - * @ntrips: number of trip points inside trips. - * - * This function parses a cooling-map type of node represented by - * @np parameter and fills the read data into @__tbp data structure. - * It needs the already parsed array of trip points of the thermal zone - * in consideration. - * - * Return: 0 on success, proper error code otherwise - */ -static int thermal_of_populate_bind_params(struct device_node *tz_np, - struct device_node *np, - struct __thermal_bind_params *__tbp) -{ - struct of_phandle_args cooling_spec; - struct __thermal_cooling_bind_param *__tcbp; - struct device_node *trip; - int ret, i, count; - int trip_id; - u32 prop; - - /* Default weight. Usage is optional */ - __tbp->usage = THERMAL_WEIGHT_DEFAULT; - ret = of_property_read_u32(np, "contribution", &prop); - if (ret == 0) - __tbp->usage = prop; - - trip = of_parse_phandle(np, "trip", 0); - if (!trip) { - pr_err("missing trip property\n"); - return -ENODEV; - } - - trip_id = of_find_trip_id(tz_np, trip); - if (trip_id < 0) { - ret = trip_id; - goto end; - } - - __tbp->trip_id = trip_id; - - count = of_count_phandle_with_args(np, "cooling-device", - "#cooling-cells"); - if (count <= 0) { - pr_err("Add a cooling_device property with at least one device\n"); - ret = -ENOENT; - goto end; - } - - __tcbp = kcalloc(count, sizeof(*__tcbp), GFP_KERNEL); - if (!__tcbp) { - ret = -ENOMEM; - goto end; - } - - for (i = 0; i < count; i++) { - ret = of_parse_phandle_with_args(np, "cooling-device", - "#cooling-cells", i, &cooling_spec); - if (ret < 0) { - pr_err("Invalid cooling-device entry\n"); - goto free_tcbp; - } - - __tcbp[i].cooling_device = cooling_spec.np; - - if (cooling_spec.args_count >= 2) { /* at least min and max */ - __tcbp[i].min = cooling_spec.args[0]; - __tcbp[i].max = cooling_spec.args[1]; - } else { - pr_err("wrong reference to cooling device, missing limits\n"); - } - } - - __tbp->tcbp = __tcbp; - __tbp->count = count; - - goto end; - -free_tcbp: - for (i = i - 1; i >= 0; i--) - of_node_put(__tcbp[i].cooling_device); - kfree(__tcbp); -end: - of_node_put(trip); - - return ret; -} - /* * It maps 'enum thermal_trip_type' found in include/linux/thermal.h * into the device tree binding of 'trip', property type. @@ -873,174 +321,6 @@ static struct thermal_trip *thermal_of_trips_init(struct device_node *np, int *n return ERR_PTR(ret); } -/** - * thermal_of_build_thermal_zone - parse and fill one thermal zone data - * @np: DT node containing a thermal zone node - * - * This function parses a thermal zone type of node represented by - * @np parameter and fills the read data into a __thermal_zone data structure - * and return this pointer. - * - * TODO: Missing properties to parse: thermal-sensor-names - * - * Return: On success returns a valid struct __thermal_zone, - * otherwise, it returns a corresponding ERR_PTR(). Caller must - * check the return value with help of IS_ERR() helper. - */ -static struct __thermal_zone -__init *thermal_of_build_thermal_zone(struct device_node *np) -{ - struct device_node *child = NULL, *gchild; - struct __thermal_zone *tz; - int ret, i; - u32 prop, coef[2]; - - if (!np) { - pr_err("no thermal zone np\n"); - return ERR_PTR(-EINVAL); - } - - tz = kzalloc(sizeof(*tz), GFP_KERNEL); - if (!tz) - return ERR_PTR(-ENOMEM); - - ret = of_property_read_u32(np, "polling-delay-passive", &prop); - if (ret < 0) { - pr_err("%pOFn: missing polling-delay-passive property\n", np); - goto free_tz; - } - tz->passive_delay = prop; - - ret = of_property_read_u32(np, "polling-delay", &prop); - if (ret < 0) { - pr_err("%pOFn: missing polling-delay property\n", np); - goto free_tz; - } - tz->polling_delay = prop; - - /* - * REVIST: for now, the thermal framework supports only - * one sensor per thermal zone. Thus, we are considering - * only the first two values as slope and offset. - */ - ret = of_property_read_u32_array(np, "coefficients", coef, 2); - if (ret == 0) { - tz->slope = coef[0]; - tz->offset = coef[1]; - } else { - tz->slope = 1; - tz->offset = 0; - } - - tz->trips = thermal_of_trips_init(np, &tz->ntrips); - if (IS_ERR(tz->trips)) { - ret = PTR_ERR(tz->trips); - goto finish; - } - - /* cooling-maps */ - child = of_get_child_by_name(np, "cooling-maps"); - - /* cooling-maps not provided */ - if (!child) - goto finish; - - tz->num_tbps = of_get_child_count(child); - if (tz->num_tbps == 0) - goto finish; - - tz->tbps = kcalloc(tz->num_tbps, sizeof(*tz->tbps), GFP_KERNEL); - if (!tz->tbps) { - ret = -ENOMEM; - goto free_trips; - } - - i = 0; - for_each_child_of_node(child, gchild) { - ret = thermal_of_populate_bind_params(np, gchild, &tz->tbps[i++]); - if (ret) { - of_node_put(gchild); - goto free_tbps; - } - } - -finish: - of_node_put(child); - - return tz; - -free_tbps: - for (i = i - 1; i >= 0; i--) { - struct __thermal_bind_params *tbp = tz->tbps + i; - int j; - - for (j = 0; j < tbp->count; j++) - of_node_put(tbp->tcbp[j].cooling_device); - - kfree(tbp->tcbp); - } - - kfree(tz->tbps); -free_trips: - kfree(tz->trips); -free_tz: - kfree(tz); - of_node_put(child); - - return ERR_PTR(ret); -} - -static void of_thermal_free_zone(struct __thermal_zone *tz) -{ - struct __thermal_bind_params *tbp; - int i, j; - - for (i = 0; i < tz->num_tbps; i++) { - tbp = tz->tbps + i; - - for (j = 0; j < tbp->count; j++) - of_node_put(tbp->tcbp[j].cooling_device); - - kfree(tbp->tcbp); - } - - kfree(tz->tbps); - kfree(tz->trips); - kfree(tz); -} - -/** - * of_thermal_destroy_zones - remove all zones parsed and allocated resources - * - * Finds all zones parsed and added to the thermal framework and remove them - * from the system, together with their resources. - * - */ -static __init void of_thermal_destroy_zones(void) -{ - struct device_node *np, *child; - - np = of_find_node_by_name(NULL, "thermal-zones"); - if (!np) { - pr_debug("unable to find thermal zones\n"); - return; - } - - for_each_available_child_of_node(np, child) { - struct thermal_zone_device *zone; - - zone = thermal_zone_get_zone_by_name(child->name); - if (IS_ERR(zone)) - continue; - - thermal_zone_device_unregister(zone); - kfree(zone->tzp); - kfree(zone->ops); - of_thermal_free_zone(zone->devdata); - } - of_node_put(np); -} - static struct device_node *of_thermal_zone_find(struct device_node *sensor, int id) { struct device_node *np, *tz; @@ -1492,95 +772,7 @@ EXPORT_SYMBOL_GPL(devm_thermal_of_zone_register); */ void devm_thermal_of_zone_unregister(struct device *dev, struct thermal_zone_device *tz) { - WARN_ON(devres_release(dev, devm_thermal_zone_of_sensor_release, + WARN_ON(devres_release(dev, devm_thermal_of_zone_release, devm_thermal_of_zone_match, tz)); } EXPORT_SYMBOL_GPL(devm_thermal_of_zone_unregister); - -/** - * of_parse_thermal_zones - parse device tree thermal data - * - * Initialization function that can be called by machine initialization - * code to parse thermal data and populate the thermal framework - * with hardware thermal zones info. This function only parses thermal zones. - * Cooling devices and sensor devices nodes are supposed to be parsed - * by their respective drivers. - * - * Return: 0 on success, proper error code otherwise - * - */ -int of_parse_thermal_zones(void) -{ - struct device_node *np, *child; - struct __thermal_zone *tz; - struct thermal_zone_device_ops *ops; - - np = of_find_node_by_name(NULL, "thermal-zones"); - if (!np) { - pr_debug("unable to find thermal zones\n"); - return 0; /* Run successfully on systems without thermal DT */ - } - - for_each_available_child_of_node(np, child) { - struct thermal_zone_device *zone; - struct thermal_zone_params *tzp; - int i, mask = 0; - u32 prop; - - tz = thermal_of_build_thermal_zone(child); - if (IS_ERR(tz)) { - pr_err("failed to build thermal zone %pOFn: %ld\n", - child, - PTR_ERR(tz)); - continue; - } - - ops = kmemdup(&of_thermal_ops, sizeof(*ops), GFP_KERNEL); - if (!ops) - goto exit_free; - - tzp = kzalloc(sizeof(*tzp), GFP_KERNEL); - if (!tzp) { - kfree(ops); - goto exit_free; - } - - /* No hwmon because there might be hwmon drivers registering */ - tzp->no_hwmon = true; - - if (!of_property_read_u32(child, "sustainable-power", &prop)) - tzp->sustainable_power = prop; - - for (i = 0; i < tz->ntrips; i++) - mask |= 1 << i; - - /* these two are left for temperature drivers to use */ - tzp->slope = tz->slope; - tzp->offset = tz->offset; - - zone = thermal_zone_device_register_with_trips(child->name, tz->trips, tz->ntrips, - mask, tz, ops, tzp, tz->passive_delay, - tz->polling_delay); - if (IS_ERR(zone)) { - pr_err("Failed to build %pOFn zone %ld\n", child, - PTR_ERR(zone)); - kfree(tzp); - kfree(ops); - of_thermal_free_zone(tz); - /* attempting to build remaining zones still */ - } - } - of_node_put(np); - - return 0; - -exit_free: - of_node_put(child); - of_node_put(np); - of_thermal_free_zone(tz); - - /* no memory available, so free what we have built */ - of_thermal_destroy_zones(); - - return -ENOMEM; -} diff --git a/include/linux/thermal.h b/include/linux/thermal.h index e2ac9d473bd6c..86c24ddd5985d 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -296,33 +296,6 @@ struct thermal_zone_params { int offset; }; -/** - * struct thermal_zone_of_device_ops - callbacks for handling DT based zones - * - * Mandatory: - * @get_temp: a pointer to a function that reads the sensor temperature. - * - * Optional: - * @get_trend: a pointer to a function that reads the sensor temperature trend. - * @set_trips: a pointer to a function that sets a temperature window. When - * this window is left the driver must inform the thermal core via - * thermal_zone_device_update. - * @set_emul_temp: a pointer to a function that sets sensor emulated - * temperature. - * @set_trip_temp: a pointer to a function that sets the trip temperature on - * hardware. - * @change_mode: a pointer to a function that notifies the thermal zone - * mode change. - */ -struct thermal_zone_of_device_ops { - int (*get_temp)(void *, int *); - int (*get_trend)(void *, int, enum thermal_trend *); - int (*set_trips)(void *, int, int); - int (*set_emul_temp)(void *, int); - int (*set_trip_temp)(void *, int, int); - int (*change_mode) (void *, enum thermal_device_mode); -}; - /* Function declarations */ #ifdef CONFIG_THERMAL_OF struct thermal_zone_device *thermal_of_zone_register(struct device_node *sensor, int id, void *data, @@ -335,61 +308,41 @@ void thermal_of_zone_unregister(struct thermal_zone_device *tz); void devm_thermal_of_zone_unregister(struct device *dev, struct thermal_zone_device *tz); +void thermal_of_zone_unregister(struct thermal_zone_device *tz); + int thermal_zone_of_get_sensor_id(struct device_node *tz_np, struct device_node *sensor_np, u32 *id); -struct thermal_zone_device * -thermal_zone_of_sensor_register(struct device *dev, int id, void *data, - const struct thermal_zone_of_device_ops *ops); -void thermal_zone_of_sensor_unregister(struct device *dev, - struct thermal_zone_device *tz); -struct thermal_zone_device *devm_thermal_zone_of_sensor_register( - struct device *dev, int id, void *data, - const struct thermal_zone_of_device_ops *ops); -void devm_thermal_zone_of_sensor_unregister(struct device *dev, - struct thermal_zone_device *tz); #else - -static inline int thermal_zone_of_get_sensor_id(struct device_node *tz_np, - struct device_node *sensor_np, - u32 *id) -{ - return -ENOENT; -} -static inline struct thermal_zone_device * -thermal_zone_of_sensor_register(struct device *dev, int id, void *data, - const struct thermal_zone_of_device_ops *ops) -{ - return ERR_PTR(-ENODEV); -} - static inline -void thermal_zone_of_sensor_unregister(struct device *dev, - struct thermal_zone_device *tz) +struct thermal_zone_device *thermal_of_zone_register(struct device_node *sensor, int id, void *data, + const struct thermal_zone_device_ops *ops) { + return ERR_PTR(-ENOTSUPP); } -static inline struct thermal_zone_device *devm_thermal_zone_of_sensor_register( - struct device *dev, int id, void *data, - const struct thermal_zone_of_device_ops *ops) +static inline +struct thermal_zone_device *devm_thermal_of_zone_register(struct device *dev, int id, void *data, + const struct thermal_zone_device_ops *ops) { - return ERR_PTR(-ENODEV); + return ERR_PTR(-ENOTSUPP); } static inline void thermal_of_zone_unregister(struct thermal_zone_device *tz) { } -static inline void devm_thermal_of_zone_unregister(struct device *dev, struct thermal_zone_device *tz) +static inline void devm_thermal_of_zone_unregister(struct device *dev, + struct thermal_zone_device *tz) { } -static inline -void devm_thermal_zone_of_sensor_unregister(struct device *dev, - struct thermal_zone_device *tz) +static inline int thermal_zone_of_get_sensor_id(struct device_node *tz_np, + struct device_node *sensor_np, + u32 *id) { + return -ENOENT; } - #endif #ifdef CONFIG_THERMAL From e920209847c396ca243259160b7d10d0dae17b35 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Tue, 9 Aug 2022 11:43:46 +0800 Subject: [PATCH 324/427] thermal/drivers/qcom/spmi-adc-tm5: Remove unnecessary print function dev_err() The print function dev_err() is redundant because platform_get_irq() already prints an error. ./drivers/thermal/qcom/qcom-spmi-adc-tm5.c:1029:2-9: line 1029 is redundant because platform_get_irq() already prints an error. Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=1846 Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Reviewed-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220809034346.128607-1-jiapeng.chong@linux.alibaba.com Signed-off-by: Daniel Lezcano --- drivers/thermal/qcom/qcom-spmi-adc-tm5.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c index add6f40e5e2af..af68adf720cc4 100644 --- a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c +++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c @@ -1025,10 +1025,8 @@ static int adc_tm5_probe(struct platform_device *pdev) adc_tm->base = reg; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "get_irq failed: %d\n", irq); + if (irq < 0) return irq; - } ret = adc_tm5_get_dt_data(adc_tm, node); if (ret) { From 9662756a9a1c34b3ee606dcddfda6a457f89b07f Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 17:38:30 +0200 Subject: [PATCH 325/427] thermal/core: Rearm the monitoring only one time The current code calls monitor_thermal_zone() inside the handle_thermal_trip() function. But this one is called in a loop for each trip point which means the monitoring is rearmed several times for nothing (assuming there could be several passive and active trip points). Move the monitor_thermal_zone() function out of the handle_thermal_trip() function and after the thermal trip loop, so the timer will be disabled or rearmed one time. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220805153834.2510142-1-daniel.lezcano@linaro.org --- drivers/thermal/thermal_core.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 69447aba7e656..ea41ea66702a5 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -383,11 +383,6 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) handle_critical_trips(tz, trip, trip_temp, type); else handle_non_critical_trips(tz, trip); - /* - * Alright, we handled this trip successfully. - * So, start monitoring again. - */ - monitor_thermal_zone(tz); } static void update_temperature(struct thermal_zone_device *tz) @@ -503,6 +498,8 @@ void thermal_zone_device_update(struct thermal_zone_device *tz, for (count = 0; count < tz->num_trips; count++) handle_thermal_trip(tz, count); + + monitor_thermal_zone(tz); } EXPORT_SYMBOL_GPL(thermal_zone_device_update); From 15a73839e3ced8d418e6c34548f5e2789f9da619 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 17:38:31 +0200 Subject: [PATCH 326/427] thermal/core: Rework the monitoring a bit The should_stop_polling() function wraps the function thermal_zone_device_is_enabled(). The monitor_thermal_zone() function checks if the thermal zone is enabled via the should_stop_polling() function. However, the instant after checking the thermal zone is enabled, this one can be disabled, so even if that reduces the race window, it does not prevent that and the monitoring can be set again with the thermal zone disabled. For this reason, the function should_stop_polling() is replaced by a direct check of the thermal zone mode with the mutex locks held, that prevents the situation described above. As the semantic is clear with the thermal_zone_is_enabled() function, we can remove the should_stop_polling() function and replace the check with the former function. While at it, reorder the checks to improve the readability of the monitor_thermal_zone() function. In the future, the thermal_zone_device_disable() and the thermal_zone_device_enable() functions should unset / set the polling timer directly instead of relying on the next thermal_zone_device_update() call to do that. That will make a synchronous thermal zone mode change but the locking scheme should be double checked for that which out of the scope of this change. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220805153834.2510142-2-daniel.lezcano@linaro.org --- drivers/thermal/thermal_core.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index ea41ea66702a5..5408e92a11685 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -295,25 +295,16 @@ static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, cancel_delayed_work(&tz->poll_queue); } -static inline bool should_stop_polling(struct thermal_zone_device *tz) -{ - return !thermal_zone_device_is_enabled(tz); -} - static void monitor_thermal_zone(struct thermal_zone_device *tz) { - bool stop; - - stop = should_stop_polling(tz); - mutex_lock(&tz->lock); - if (!stop && tz->passive) + if (tz->mode != THERMAL_DEVICE_ENABLED) + thermal_zone_device_set_polling(tz, 0); + else if (tz->passive) thermal_zone_device_set_polling(tz, tz->passive_delay_jiffies); - else if (!stop && tz->polling_delay_jiffies) + else if (tz->polling_delay_jiffies) thermal_zone_device_set_polling(tz, tz->polling_delay_jiffies); - else - thermal_zone_device_set_polling(tz, 0); mutex_unlock(&tz->lock); } @@ -480,7 +471,7 @@ void thermal_zone_device_update(struct thermal_zone_device *tz, { int count; - if (should_stop_polling(tz)) + if (!thermal_zone_device_is_enabled(tz)) return; if (atomic_read(&in_suspend)) From 63561fe36b094729d3d4d274bafaa030b39e89f6 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 17:38:32 +0200 Subject: [PATCH 327/427] thermal/governors: Group the thermal zone lock inside the throttle function The thermal zone lock is taken in the different places in the throttling path. At the first glance it does not hurt to move them at the beginning and the end of the 'throttle' function. That will allow a consolidation of the lock in the next following changes. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220805153834.2510142-3-daniel.lezcano@linaro.org --- drivers/thermal/gov_bang_bang.c | 8 ++----- drivers/thermal/gov_fair_share.c | 1 + drivers/thermal/gov_power_allocator.c | 34 ++++++++++++--------------- drivers/thermal/gov_step_wise.c | 8 ++----- 4 files changed, 20 insertions(+), 31 deletions(-) diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c index 991a1c54296de..f0bff2e0475b1 100644 --- a/drivers/thermal/gov_bang_bang.c +++ b/drivers/thermal/gov_bang_bang.c @@ -31,8 +31,6 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) trip, trip_temp, tz->temperature, trip_hyst); - mutex_lock(&tz->lock); - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { if (instance->trip != trip) continue; @@ -65,8 +63,6 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) instance->cdev->updated = false; /* cdev needs update */ mutex_unlock(&instance->cdev->lock); } - - mutex_unlock(&tz->lock); } /** @@ -100,10 +96,10 @@ static int bang_bang_control(struct thermal_zone_device *tz, int trip) { struct thermal_instance *instance; - thermal_zone_trip_update(tz, trip); - mutex_lock(&tz->lock); + thermal_zone_trip_update(tz, trip); + list_for_each_entry(instance, &tz->thermal_instances, tz_node) thermal_cdev_update(instance->cdev); diff --git a/drivers/thermal/gov_fair_share.c b/drivers/thermal/gov_fair_share.c index 6a2abcfc648f7..5d5ddd648cd26 100644 --- a/drivers/thermal/gov_fair_share.c +++ b/drivers/thermal/gov_fair_share.c @@ -113,6 +113,7 @@ static int fair_share_throttle(struct thermal_zone_device *tz, int trip) } mutex_unlock(&tz->lock); + return 0; } diff --git a/drivers/thermal/gov_power_allocator.c b/drivers/thermal/gov_power_allocator.c index 1d50524709672..d3aca236e2746 100644 --- a/drivers/thermal/gov_power_allocator.c +++ b/drivers/thermal/gov_power_allocator.c @@ -392,8 +392,6 @@ static int allocate_power(struct thermal_zone_device *tz, int i, num_actors, total_weight, ret = 0; int trip_max_desired_temperature = params->trip_max_desired_temperature; - mutex_lock(&tz->lock); - num_actors = 0; total_weight = 0; list_for_each_entry(instance, &tz->thermal_instances, tz_node) { @@ -404,10 +402,8 @@ static int allocate_power(struct thermal_zone_device *tz, } } - if (!num_actors) { - ret = -ENODEV; - goto unlock; - } + if (!num_actors) + return -ENODEV; /* * We need to allocate five arrays of the same size: @@ -421,10 +417,8 @@ static int allocate_power(struct thermal_zone_device *tz, BUILD_BUG_ON(sizeof(*req_power) != sizeof(*extra_actor_power)); BUILD_BUG_ON(sizeof(*req_power) != sizeof(*weighted_req_power)); req_power = kcalloc(num_actors * 5, sizeof(*req_power), GFP_KERNEL); - if (!req_power) { - ret = -ENOMEM; - goto unlock; - } + if (!req_power) + return -ENOMEM; max_power = &req_power[num_actors]; granted_power = &req_power[2 * num_actors]; @@ -496,8 +490,6 @@ static int allocate_power(struct thermal_zone_device *tz, control_temp - tz->temperature); kfree(req_power); -unlock: - mutex_unlock(&tz->lock); return ret; } @@ -576,7 +568,6 @@ static void allow_maximum_power(struct thermal_zone_device *tz, bool update) struct power_allocator_params *params = tz->governor_data; u32 req_power; - mutex_lock(&tz->lock); list_for_each_entry(instance, &tz->thermal_instances, tz_node) { struct thermal_cooling_device *cdev = instance->cdev; @@ -598,7 +589,6 @@ static void allow_maximum_power(struct thermal_zone_device *tz, bool update) mutex_unlock(&instance->cdev->lock); } - mutex_unlock(&tz->lock); } /** @@ -707,17 +697,19 @@ static void power_allocator_unbind(struct thermal_zone_device *tz) static int power_allocator_throttle(struct thermal_zone_device *tz, int trip) { - int ret; + int ret = 0; int switch_on_temp, control_temp; struct power_allocator_params *params = tz->governor_data; bool update; + mutex_lock(&tz->lock); + /* * We get called for every trip point but we only need to do * our calculations once */ if (trip != params->trip_max_desired_temperature) - return 0; + goto out; ret = tz->ops->get_trip_temp(tz, params->trip_switch_on, &switch_on_temp); @@ -726,7 +718,7 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip) tz->passive = 0; reset_pid_controller(params); allow_maximum_power(tz, update); - return 0; + goto out; } tz->passive = 1; @@ -737,10 +729,14 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip) dev_warn(&tz->device, "Failed to get the maximum desired temperature: %d\n", ret); - return ret; + goto out; } - return allocate_power(tz, control_temp); + ret = allocate_power(tz, control_temp); + + mutex_unlock(&tz->lock); +out: + return ret; } static struct thermal_governor thermal_gov_power_allocator = { diff --git a/drivers/thermal/gov_step_wise.c b/drivers/thermal/gov_step_wise.c index 9729b46d0258a..597a0ebec7a4f 100644 --- a/drivers/thermal/gov_step_wise.c +++ b/drivers/thermal/gov_step_wise.c @@ -117,8 +117,6 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n", trip, trip_type, trip_temp, trend, throttle); - mutex_lock(&tz->lock); - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { if (instance->trip != trip) continue; @@ -145,8 +143,6 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) instance->cdev->updated = false; /* cdev needs update */ mutex_unlock(&instance->cdev->lock); } - - mutex_unlock(&tz->lock); } /** @@ -164,10 +160,10 @@ static int step_wise_throttle(struct thermal_zone_device *tz, int trip) { struct thermal_instance *instance; - thermal_zone_trip_update(tz, trip); - mutex_lock(&tz->lock); + thermal_zone_trip_update(tz, trip); + list_for_each_entry(instance, &tz->thermal_instances, tz_node) thermal_cdev_update(instance->cdev); From 670a5e356cb6dfc61b87b599eba483af6a3a99ad Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 17:38:33 +0200 Subject: [PATCH 328/427] thermal/core: Move the thermal zone lock out of the governors All the governors throttling ops are taking/releasing the lock at the beginning and the end of the function. We can move the mutex to the throttling call site instead. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220805153834.2510142-4-daniel.lezcano@linaro.org --- drivers/thermal/gov_bang_bang.c | 4 +--- drivers/thermal/gov_fair_share.c | 4 +--- drivers/thermal/gov_power_allocator.c | 16 ++++++---------- drivers/thermal/gov_step_wise.c | 4 +--- drivers/thermal/thermal_core.c | 2 ++ 5 files changed, 11 insertions(+), 19 deletions(-) diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c index f0bff2e0475b1..a08bbe33be967 100644 --- a/drivers/thermal/gov_bang_bang.c +++ b/drivers/thermal/gov_bang_bang.c @@ -96,15 +96,13 @@ static int bang_bang_control(struct thermal_zone_device *tz, int trip) { struct thermal_instance *instance; - mutex_lock(&tz->lock); + lockdep_assert_held(&tz->lock); thermal_zone_trip_update(tz, trip); list_for_each_entry(instance, &tz->thermal_instances, tz_node) thermal_cdev_update(instance->cdev); - mutex_unlock(&tz->lock); - return 0; } diff --git a/drivers/thermal/gov_fair_share.c b/drivers/thermal/gov_fair_share.c index 5d5ddd648cd26..a4ee4661e9cc4 100644 --- a/drivers/thermal/gov_fair_share.c +++ b/drivers/thermal/gov_fair_share.c @@ -82,7 +82,7 @@ static int fair_share_throttle(struct thermal_zone_device *tz, int trip) int total_instance = 0; int cur_trip_level = get_trip_level(tz); - mutex_lock(&tz->lock); + lockdep_assert_held(&tz->lock); list_for_each_entry(instance, &tz->thermal_instances, tz_node) { if (instance->trip != trip) @@ -112,8 +112,6 @@ static int fair_share_throttle(struct thermal_zone_device *tz, int trip) mutex_unlock(&cdev->lock); } - mutex_unlock(&tz->lock); - return 0; } diff --git a/drivers/thermal/gov_power_allocator.c b/drivers/thermal/gov_power_allocator.c index d3aca236e2746..2d1aeaba38a88 100644 --- a/drivers/thermal/gov_power_allocator.c +++ b/drivers/thermal/gov_power_allocator.c @@ -697,19 +697,19 @@ static void power_allocator_unbind(struct thermal_zone_device *tz) static int power_allocator_throttle(struct thermal_zone_device *tz, int trip) { - int ret = 0; + int ret; int switch_on_temp, control_temp; struct power_allocator_params *params = tz->governor_data; bool update; - mutex_lock(&tz->lock); + lockdep_assert_held(&tz->lock); /* * We get called for every trip point but we only need to do * our calculations once */ if (trip != params->trip_max_desired_temperature) - goto out; + return 0; ret = tz->ops->get_trip_temp(tz, params->trip_switch_on, &switch_on_temp); @@ -718,7 +718,7 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip) tz->passive = 0; reset_pid_controller(params); allow_maximum_power(tz, update); - goto out; + return 0; } tz->passive = 1; @@ -729,14 +729,10 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip) dev_warn(&tz->device, "Failed to get the maximum desired temperature: %d\n", ret); - goto out; + return ret; } - ret = allocate_power(tz, control_temp); - - mutex_unlock(&tz->lock); -out: - return ret; + return allocate_power(tz, control_temp); } static struct thermal_governor thermal_gov_power_allocator = { diff --git a/drivers/thermal/gov_step_wise.c b/drivers/thermal/gov_step_wise.c index 597a0ebec7a4f..cdd3354bc27fe 100644 --- a/drivers/thermal/gov_step_wise.c +++ b/drivers/thermal/gov_step_wise.c @@ -160,15 +160,13 @@ static int step_wise_throttle(struct thermal_zone_device *tz, int trip) { struct thermal_instance *instance; - mutex_lock(&tz->lock); + lockdep_assert_held(&tz->lock); thermal_zone_trip_update(tz, trip); list_for_each_entry(instance, &tz->thermal_instances, tz_node) thermal_cdev_update(instance->cdev); - mutex_unlock(&tz->lock); - return 0; } diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 5408e92a11685..fcac28d28739f 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -311,8 +311,10 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz) static void handle_non_critical_trips(struct thermal_zone_device *tz, int trip) { + mutex_lock(&tz->lock); tz->governor ? tz->governor->throttle(tz, trip) : def_governor->throttle(tz, trip); + mutex_unlock(&tz->lock); } void thermal_zone_device_critical(struct thermal_zone_device *tz) From a930da9bf583b2add01fb0e086913664dadaffd0 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 5 Aug 2022 17:38:34 +0200 Subject: [PATCH 329/427] thermal/core: Move the mutex inside the thermal_zone_device_update() function All the different calls inside the thermal_zone_device_update() function take the mutex. The previous changes move the mutex out of the different functions, like the throttling ops. Now that the mutexes are all at the same level in the call stack for the thermal_zone_device_update() function, they can be moved inside this one. That has the benefit of: 1. Simplify the code by not having a plethora of places where the lock is taken 2. Probably closes more race windows because releasing the lock from one line to another can give the opportunity to the thermal zone to change its state in the meantime. For example, the thermal zone can be enabled right after checking it is disabled. Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20220805153834.2510142-5-daniel.lezcano@linaro.org --- drivers/thermal/thermal_core.c | 32 +++++--------- drivers/thermal/thermal_core.h | 2 + drivers/thermal/thermal_helpers.c | 73 ++++++++++++++++++------------- drivers/thermal/thermal_sysfs.c | 6 ++- 4 files changed, 61 insertions(+), 52 deletions(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index fcac28d28739f..481217092cddd 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -297,24 +297,18 @@ static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, static void monitor_thermal_zone(struct thermal_zone_device *tz) { - mutex_lock(&tz->lock); - if (tz->mode != THERMAL_DEVICE_ENABLED) thermal_zone_device_set_polling(tz, 0); else if (tz->passive) thermal_zone_device_set_polling(tz, tz->passive_delay_jiffies); else if (tz->polling_delay_jiffies) thermal_zone_device_set_polling(tz, tz->polling_delay_jiffies); - - mutex_unlock(&tz->lock); } static void handle_non_critical_trips(struct thermal_zone_device *tz, int trip) { - mutex_lock(&tz->lock); tz->governor ? tz->governor->throttle(tz, trip) : def_governor->throttle(tz, trip); - mutex_unlock(&tz->lock); } void thermal_zone_device_critical(struct thermal_zone_device *tz) @@ -382,7 +376,7 @@ static void update_temperature(struct thermal_zone_device *tz) { int temp, ret; - ret = thermal_zone_get_temp(tz, &temp); + ret = __thermal_zone_get_temp(tz, &temp); if (ret) { if (ret != -EAGAIN) dev_warn(&tz->device, @@ -391,10 +385,8 @@ static void update_temperature(struct thermal_zone_device *tz) return; } - mutex_lock(&tz->lock); tz->last_temperature = tz->temperature; tz->temperature = temp; - mutex_unlock(&tz->lock); trace_thermal_temperature(tz); @@ -457,15 +449,9 @@ EXPORT_SYMBOL_GPL(thermal_zone_device_disable); int thermal_zone_device_is_enabled(struct thermal_zone_device *tz) { - enum thermal_device_mode mode; - - mutex_lock(&tz->lock); - - mode = tz->mode; + lockdep_assert_held(&tz->lock); - mutex_unlock(&tz->lock); - - return mode == THERMAL_DEVICE_ENABLED; + return tz->mode == THERMAL_DEVICE_ENABLED; } void thermal_zone_device_update(struct thermal_zone_device *tz, @@ -473,9 +459,6 @@ void thermal_zone_device_update(struct thermal_zone_device *tz, { int count; - if (!thermal_zone_device_is_enabled(tz)) - return; - if (atomic_read(&in_suspend)) return; @@ -483,9 +466,14 @@ void thermal_zone_device_update(struct thermal_zone_device *tz, "'get_temp' ops set\n", __func__)) return; + mutex_lock(&tz->lock); + + if (!thermal_zone_device_is_enabled(tz)) + goto out; + update_temperature(tz); - thermal_zone_set_trips(tz); + __thermal_zone_set_trips(tz); tz->notify_event = event; @@ -493,6 +481,8 @@ void thermal_zone_device_update(struct thermal_zone_device *tz, handle_thermal_trip(tz, count); monitor_thermal_zone(tz); +out: + mutex_unlock(&tz->lock); } EXPORT_SYMBOL_GPL(thermal_zone_device_update); diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index 2241d2dce017f..1571917bd3c89 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -112,6 +112,8 @@ int thermal_build_list_of_policies(char *buf); /* Helpers */ void thermal_zone_set_trips(struct thermal_zone_device *tz); +void __thermal_zone_set_trips(struct thermal_zone_device *tz); +int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp); /* sysfs I/F */ int thermal_zone_create_device_groups(struct thermal_zone_device *, int); diff --git a/drivers/thermal/thermal_helpers.c b/drivers/thermal/thermal_helpers.c index 690890f054a39..c65cdce8f856e 100644 --- a/drivers/thermal/thermal_helpers.c +++ b/drivers/thermal/thermal_helpers.c @@ -64,27 +64,17 @@ get_thermal_instance(struct thermal_zone_device *tz, } EXPORT_SYMBOL(get_thermal_instance); -/** - * thermal_zone_get_temp() - returns the temperature of a thermal zone - * @tz: a valid pointer to a struct thermal_zone_device - * @temp: a valid pointer to where to store the resulting temperature. - * - * When a valid thermal zone reference is passed, it will fetch its - * temperature and fill @temp. - * - * Return: On success returns 0, an error code otherwise - */ -int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp) +int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp) { int ret = -EINVAL; int count; int crit_temp = INT_MAX; enum thermal_trip_type type; - if (!tz || IS_ERR(tz) || !tz->ops->get_temp) - goto exit; + lockdep_assert_held(&tz->lock); - mutex_lock(&tz->lock); + if (!tz || IS_ERR(tz) || !tz->ops->get_temp) + return -EINVAL; ret = tz->ops->get_temp(tz, temp); @@ -107,35 +97,42 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp) *temp = tz->emul_temperature; } - mutex_unlock(&tz->lock); -exit: return ret; } -EXPORT_SYMBOL_GPL(thermal_zone_get_temp); /** - * thermal_zone_set_trips - Computes the next trip points for the driver - * @tz: a pointer to a thermal zone device structure + * thermal_zone_get_temp() - returns the temperature of a thermal zone + * @tz: a valid pointer to a struct thermal_zone_device + * @temp: a valid pointer to where to store the resulting temperature. * - * The function computes the next temperature boundaries by browsing - * the trip points. The result is the closer low and high trip points - * to the current temperature. These values are passed to the backend - * driver to let it set its own notification mechanism (usually an - * interrupt). + * When a valid thermal zone reference is passed, it will fetch its + * temperature and fill @temp. * - * It does not return a value + * Return: On success returns 0, an error code otherwise */ -void thermal_zone_set_trips(struct thermal_zone_device *tz) +int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp) +{ + int ret; + + mutex_lock(&tz->lock); + ret = __thermal_zone_get_temp(tz, temp); + mutex_unlock(&tz->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(thermal_zone_get_temp); + +void __thermal_zone_set_trips(struct thermal_zone_device *tz) { int low = -INT_MAX; int high = INT_MAX; int trip_temp, hysteresis; int i, ret; - mutex_lock(&tz->lock); + lockdep_assert_held(&tz->lock); if (!tz->ops->set_trips || !tz->ops->get_trip_hyst) - goto exit; + return; for (i = 0; i < tz->num_trips; i++) { int trip_low; @@ -154,7 +151,7 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz) /* No need to change trip points */ if (tz->prev_low_trip == low && tz->prev_high_trip == high) - goto exit; + return; tz->prev_low_trip = low; tz->prev_high_trip = high; @@ -169,8 +166,24 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz) ret = tz->ops->set_trips(tz, low, high); if (ret) dev_err(&tz->device, "Failed to set trips: %d\n", ret); +} -exit: +/** + * thermal_zone_set_trips - Computes the next trip points for the driver + * @tz: a pointer to a thermal zone device structure + * + * The function computes the next temperature boundaries by browsing + * the trip points. The result is the closer low and high trip points + * to the current temperature. These values are passed to the backend + * driver to let it set its own notification mechanism (usually an + * interrupt). + * + * It does not return a value + */ +void thermal_zone_set_trips(struct thermal_zone_device *tz) +{ + mutex_lock(&tz->lock); + __thermal_zone_set_trips(tz); mutex_unlock(&tz->lock); } diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c index 0f8201060c38a..78c5841bdfae3 100644 --- a/drivers/thermal/thermal_sysfs.c +++ b/drivers/thermal/thermal_sysfs.c @@ -49,7 +49,11 @@ static ssize_t mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct thermal_zone_device *tz = to_thermal_zone(dev); - int enabled = thermal_zone_device_is_enabled(tz); + int enabled; + + mutex_lock(&tz->lock); + enabled = thermal_zone_device_is_enabled(tz); + mutex_unlock(&tz->lock); return sprintf(buf, "%s\n", enabled ? "enabled" : "disabled"); } From 2f9d142c93c293b2526d63e4e75716945edf0cd2 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 12 Aug 2022 15:07:43 +0200 Subject: [PATCH 330/427] thermal/core: Fix lockdep_assert() warning The function thermal_zone_device_is_enabled() must be called with the thermal zone lock held. In the resume path, it is called without. As the thermal_zone_device_is_enabled() is also checked in thermal_zone_device_update(), do the check in resume() function is pointless, except for saving an extra initialization which does not hurt if it is done in all the cases. Fixes: ca48ad71717dd ("thermal/core: Move the mutex inside the thermal_zone_device_update() function") Signed-off-by: Daniel Lezcano Reported-by: Marek Szyprowski Tested-by: Marek Szyprowski --- drivers/thermal/thermal_core.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 481217092cddd..99c0c19fa5a6c 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1438,9 +1438,6 @@ static int thermal_pm_notify(struct notifier_block *nb, case PM_POST_SUSPEND: atomic_set(&in_suspend, 0); list_for_each_entry(tz, &thermal_tz_list, node) { - if (!thermal_zone_device_is_enabled(tz)) - continue; - thermal_zone_device_init(tz); thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); From c8550b9077d271b9b4fbe5a9a260eb021f371c4f Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 16 Aug 2022 14:15:22 +0200 Subject: [PATCH 331/427] testing: selftests: nft_flowtable.sh: rework test to detect offload failure This test fails on current kernel releases because the flotwable path now calls dst_check from packet path and will then remove the offload. Test script has two purposes: 1. check that file (random content) can be sent to other netns (and vv) 2. check that the flow is offloaded (rather than handled by classic forwarding path). Since dst_check is in place, 2) fails because the nftables ruleset in router namespace 1 intentionally blocks traffic under the assumption that packets are not passed via classic path at all. Rework this: Instead of blocking traffic, create two named counters, one for original and one for reverse direction. The first three test cases are handled by classic forwarding path (path mtu discovery is disabled and packets exceed MTU). But all other tests enable PMTUD, so the originator and responder are expected to lower packet size and flowtable is expected to do the packet forwarding. For those tests, check that the packet counters (which are only incremented for packets that are passed up to classic forward path) are significantly lower than the file size transferred. I've tested that the counter-checks fail as expected when the 'flow add' statement is removed from the ruleset. Signed-off-by: Florian Westphal --- .../selftests/netfilter/nft_flowtable.sh | 141 +++++++++++------- 1 file changed, 84 insertions(+), 57 deletions(-) diff --git a/tools/testing/selftests/netfilter/nft_flowtable.sh b/tools/testing/selftests/netfilter/nft_flowtable.sh index c336e6c148d1f..7060bae04ec87 100755 --- a/tools/testing/selftests/netfilter/nft_flowtable.sh +++ b/tools/testing/selftests/netfilter/nft_flowtable.sh @@ -24,8 +24,7 @@ nsr2="nsr2-$sfx" ksft_skip=4 ret=0 -ns1in="" -ns2in="" +nsin="" ns1out="" ns2out="" @@ -53,8 +52,7 @@ cleanup() { ip netns del $nsr1 ip netns del $nsr2 - rm -f "$ns1in" "$ns1out" - rm -f "$ns2in" "$ns2out" + rm -f "$nsin" "$ns1out" "$ns2out" [ $log_netns -eq 0 ] && sysctl -q net.netfilter.nf_log_all_netns=$log_netns } @@ -165,36 +163,20 @@ table inet filter { devices = { veth0, veth1 } } + counter routed_orig { } + counter routed_repl { } + chain forward { type filter hook forward priority 0; policy drop; # flow offloaded? Tag ct with mark 1, so we can detect when it fails. - meta oif "veth1" tcp dport 12345 flow offload @f1 counter - - # use packet size to trigger 'should be offloaded by now'. - # otherwise, if 'flow offload' expression never offloads, the - # test will pass. - tcp dport 12345 meta length gt 200 ct mark set 1 counter - - # this turns off flow offloading internally, so expect packets again - tcp flags fin,rst ct mark set 0 accept - - # this allows large packets from responder, we need this as long - # as PMTUd is off. - # This rule is deleted for the last test, when we expect PMTUd - # to kick in and ensure all packets meet mtu requirements. - meta length gt $lmtu accept comment something-to-grep-for + meta oif "veth1" tcp dport 12345 ct mark set 1 flow add @f1 counter name routed_orig accept - # next line blocks connection w.o. working offload. - # we only do this for reverse dir, because we expect packets to - # enter slow path due to MTU mismatch of veth0 and veth1. - tcp sport 12345 ct mark 1 counter log prefix "mark failure " drop + # count packets supposedly offloaded as per direction. + ct mark 1 counter name ct direction map { original : routed_orig, reply : routed_repl } accept ct state established,related accept - # for packets that we can't offload yet, i.e. SYN (any ct that is not confirmed) - meta length lt 200 oif "veth1" tcp dport 12345 counter accept - meta nfproto ipv4 meta l4proto icmp accept meta nfproto ipv6 meta l4proto icmpv6 accept } @@ -221,16 +203,16 @@ if [ $ret -eq 0 ];then echo "PASS: netns routing/connectivity: $ns1 can reach $ns2" fi -ns1in=$(mktemp) +nsin=$(mktemp) ns1out=$(mktemp) -ns2in=$(mktemp) ns2out=$(mktemp) make_file() { name=$1 - SIZE=$((RANDOM % (1024 * 8))) + SIZE=$((RANDOM % (1024 * 128))) + SIZE=$((SIZE + (1024 * 8))) TSIZE=$((SIZE * 1024)) dd if=/dev/urandom of="$name" bs=1024 count=$SIZE 2> /dev/null @@ -241,6 +223,38 @@ make_file() dd if=/dev/urandom conf=notrunc of="$name" bs=1 count=$SIZE 2> /dev/null } +check_counters() +{ + local what=$1 + local ok=1 + + local orig=$(ip netns exec $nsr1 nft reset counter inet filter routed_orig | grep packets) + local repl=$(ip netns exec $nsr1 nft reset counter inet filter routed_repl | grep packets) + + local orig_cnt=${orig#*bytes} + local repl_cnt=${repl#*bytes} + + local fs=$(du -sb $nsin) + local max_orig=${fs%%/*} + local max_repl=$((max_orig/4)) + + if [ $orig_cnt -gt $max_orig ];then + echo "FAIL: $what: original counter $orig_cnt exceeds expected value $max_orig" 1>&2 + ret=1 + ok=0 + fi + + if [ $repl_cnt -gt $max_repl ];then + echo "FAIL: $what: reply counter $repl_cnt exceeds expected value $max_repl" 1>&2 + ret=1 + ok=0 + fi + + if [ $ok -eq 1 ]; then + echo "PASS: $what" + fi +} + check_transfer() { in=$1 @@ -265,11 +279,11 @@ test_tcp_forwarding_ip() local dstport=$4 local lret=0 - ip netns exec $nsb nc -w 5 -l -p 12345 < "$ns2in" > "$ns2out" & + ip netns exec $nsb nc -w 5 -l -p 12345 < "$nsin" > "$ns2out" & lpid=$! sleep 1 - ip netns exec $nsa nc -w 4 "$dstip" "$dstport" < "$ns1in" > "$ns1out" & + ip netns exec $nsa nc -w 4 "$dstip" "$dstport" < "$nsin" > "$ns1out" & cpid=$! sleep 3 @@ -284,11 +298,11 @@ test_tcp_forwarding_ip() wait - if ! check_transfer "$ns1in" "$ns2out" "ns1 -> ns2"; then + if ! check_transfer "$nsin" "$ns2out" "ns1 -> ns2"; then lret=1 fi - if ! check_transfer "$ns2in" "$ns1out" "ns1 <- ns2"; then + if ! check_transfer "$nsin" "$ns1out" "ns1 <- ns2"; then lret=1 fi @@ -305,23 +319,40 @@ test_tcp_forwarding() test_tcp_forwarding_nat() { local lret + local pmtu test_tcp_forwarding_ip "$1" "$2" 10.0.2.99 12345 lret=$? + pmtu=$3 + what=$4 + if [ $lret -eq 0 ] ; then + if [ $pmtu -eq 1 ] ;then + check_counters "flow offload for ns1/ns2 with masquerade and pmtu discovery $what" + else + echo "PASS: flow offload for ns1/ns2 with masquerade $what" + fi + test_tcp_forwarding_ip "$1" "$2" 10.6.6.6 1666 lret=$? + if [ $pmtu -eq 1 ] ;then + check_counters "flow offload for ns1/ns2 with dnat and pmtu discovery $what" + elif [ $lret -eq 0 ] ; then + echo "PASS: flow offload for ns1/ns2 with dnat $what" + fi fi return $lret } -make_file "$ns1in" -make_file "$ns2in" +make_file "$nsin" # First test: # No PMTU discovery, nsr1 is expected to fragment packets from ns1 to ns2 as needed. +# Due to MTU mismatch in both directions, all packets (except small packets like pure +# acks) have to be handled by normal forwarding path. Therefore, packet counters +# are not checked. if test_tcp_forwarding $ns1 $ns2; then echo "PASS: flow offloaded for ns1/ns2" else @@ -338,7 +369,8 @@ ip -net $ns2 route del default via dead:2::1 ip -net $ns2 route add 192.168.10.1 via 10.0.2.1 # Second test: -# Same, but with NAT enabled. +# Same, but with NAT enabled. Same as in first test: we expect normal forward path +# to handle most packets. ip netns exec $nsr1 nft -f - <&2 ip netns exec $nsr1 nft list ruleset ret=1 fi # Third test: -# Same as second test, but with PMTU discovery enabled. -handle=$(ip netns exec $nsr1 nft -a list table inet filter | grep something-to-grep-for | cut -d \# -f 2) - -if ! ip netns exec $nsr1 nft delete rule inet filter forward $handle; then - echo "FAIL: Could not delete large-packet accept rule" - exit 1 -fi - +# Same as second test, but with PMTU discovery enabled. This +# means that we expect the fastpath to handle packets as soon +# as the endpoints adjust the packet size. ip netns exec $ns1 sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null ip netns exec $ns2 sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null -if test_tcp_forwarding_nat $ns1 $ns2; then - echo "PASS: flow offloaded for ns1/ns2 with NAT and pmtu discovery" -else +# reset counters. +# With pmtu in-place we'll also check that nft counters +# are lower than file size and packets were forwarded via flowtable layer. +# For earlier tests (large mtus), packets cannot be handled via flowtable +# (except pure acks and other small packets). +ip netns exec $nsr1 nft reset counters table inet filter >/dev/null + +if ! test_tcp_forwarding_nat $ns1 $ns2 1 ""; then echo "FAIL: flow offload for ns1/ns2 with NAT and pmtu discovery" 1>&2 ip netns exec $nsr1 nft list ruleset fi @@ -408,14 +438,13 @@ table ip nat { } EOF -if test_tcp_forwarding_nat $ns1 $ns2; then - echo "PASS: flow offloaded for ns1/ns2 with bridge NAT" -else +if ! test_tcp_forwarding_nat $ns1 $ns2 1 "on bridge"; then echo "FAIL: flow offload for ns1/ns2 with bridge NAT" 1>&2 ip netns exec $nsr1 nft list ruleset ret=1 fi + # Another test: # Add bridge interface br0 to Router1, with NAT and VLAN. ip -net $nsr1 link set veth0 nomaster @@ -433,9 +462,7 @@ ip -net $ns1 addr add 10.0.1.99/24 dev eth0.10 ip -net $ns1 route add default via 10.0.1.1 ip -net $ns1 addr add dead:1::99/64 dev eth0.10 -if test_tcp_forwarding_nat $ns1 $ns2; then - echo "PASS: flow offloaded for ns1/ns2 with bridge NAT and VLAN" -else +if ! test_tcp_forwarding_nat $ns1 $ns2 1 "bridge and VLAN"; then echo "FAIL: flow offload for ns1/ns2 with bridge NAT and VLAN" 1>&2 ip netns exec $nsr1 nft list ruleset ret=1 @@ -502,7 +529,7 @@ ip -net $ns2 route add default via 10.0.2.1 ip -net $ns2 route add default via dead:2::1 if test_tcp_forwarding $ns1 $ns2; then - echo "PASS: ipsec tunnel mode for ns1/ns2" + check_counters "ipsec tunnel mode for ns1/ns2" else echo "FAIL: ipsec tunnel mode for ns1/ns2" ip netns exec $nsr1 nft list ruleset 1>&2 From 9be080edcca330be4af06b19916c35227891e8bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Wed, 17 Aug 2022 14:49:24 +0200 Subject: [PATCH 332/427] ALSA: info: Fix llseek return value when using callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using callback there was a flow of ret = -EINVAL if (callback) { offset = callback(); goto out; } ... offset = some other value in case of no callback; ret = offset; out: return ret; which causes the snd_info_entry_llseek() to return -EINVAL when there is callback handler. Fix this by setting "ret" directly to callback return value before jumping to "out". Fixes: 73029e0ff18d ("ALSA: info - Implement common llseek for binary mode") Signed-off-by: Amadeusz Sławiński Cc: Link: https://lore.kernel.org/r/20220817124924.3974577-1-amadeuszx.slawinski@linux.intel.com Signed-off-by: Takashi Iwai --- sound/core/info.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/core/info.c b/sound/core/info.c index b8058b3411783..0b2f04dcb5897 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -111,9 +111,9 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig) entry = data->entry; mutex_lock(&entry->access); if (entry->c.ops->llseek) { - offset = entry->c.ops->llseek(entry, - data->file_private_data, - file, offset, orig); + ret = entry->c.ops->llseek(entry, + data->file_private_data, + file, offset, orig); goto out; } From 85f02d6c856b9f3a0acf5219de6e32f58b9778eb Mon Sep 17 00:00:00 2001 From: Zixuan Fu Date: Thu, 21 Jul 2022 15:48:29 +0800 Subject: [PATCH 333/427] btrfs: unset reloc control if transaction commit fails in prepare_to_relocate() In btrfs_relocate_block_group(), the rc is allocated. Then btrfs_relocate_block_group() calls relocate_block_group() prepare_to_relocate() set_reloc_control() that assigns rc to the variable fs_info->reloc_ctl. When prepare_to_relocate() returns, it calls btrfs_commit_transaction() btrfs_start_dirty_block_groups() btrfs_alloc_path() kmem_cache_zalloc() which may fail for example (or other errors could happen). When the failure occurs, btrfs_relocate_block_group() detects the error and frees rc and doesn't set fs_info->reloc_ctl to NULL. After that, in btrfs_init_reloc_root(), rc is retrieved from fs_info->reloc_ctl and then used, which may cause a use-after-free bug. This possible bug can be triggered by calling btrfs_ioctl_balance() before calling btrfs_ioctl_defrag(). To fix this possible bug, in prepare_to_relocate(), check if btrfs_commit_transaction() fails. If the failure occurs, unset_reloc_control() is called to set fs_info->reloc_ctl to NULL. The error log in our fault-injection testing is shown as follows: [ 58.751070] BUG: KASAN: use-after-free in btrfs_init_reloc_root+0x7ca/0x920 [btrfs] ... [ 58.753577] Call Trace: ... [ 58.755800] kasan_report+0x45/0x60 [ 58.756066] btrfs_init_reloc_root+0x7ca/0x920 [btrfs] [ 58.757304] record_root_in_trans+0x792/0xa10 [btrfs] [ 58.757748] btrfs_record_root_in_trans+0x463/0x4f0 [btrfs] [ 58.758231] start_transaction+0x896/0x2950 [btrfs] [ 58.758661] btrfs_defrag_root+0x250/0xc00 [btrfs] [ 58.759083] btrfs_ioctl_defrag+0x467/0xa00 [btrfs] [ 58.759513] btrfs_ioctl+0x3c95/0x114e0 [btrfs] ... [ 58.768510] Allocated by task 23683: [ 58.768777] ____kasan_kmalloc+0xb5/0xf0 [ 58.769069] __kmalloc+0x227/0x3d0 [ 58.769325] alloc_reloc_control+0x10a/0x3d0 [btrfs] [ 58.769755] btrfs_relocate_block_group+0x7aa/0x1e20 [btrfs] [ 58.770228] btrfs_relocate_chunk+0xf1/0x760 [btrfs] [ 58.770655] __btrfs_balance+0x1326/0x1f10 [btrfs] [ 58.771071] btrfs_balance+0x3150/0x3d30 [btrfs] [ 58.771472] btrfs_ioctl_balance+0xd84/0x1410 [btrfs] [ 58.771902] btrfs_ioctl+0x4caa/0x114e0 [btrfs] ... [ 58.773337] Freed by task 23683: ... [ 58.774815] kfree+0xda/0x2b0 [ 58.775038] free_reloc_control+0x1d6/0x220 [btrfs] [ 58.775465] btrfs_relocate_block_group+0x115c/0x1e20 [btrfs] [ 58.775944] btrfs_relocate_chunk+0xf1/0x760 [btrfs] [ 58.776369] __btrfs_balance+0x1326/0x1f10 [btrfs] [ 58.776784] btrfs_balance+0x3150/0x3d30 [btrfs] [ 58.777185] btrfs_ioctl_balance+0xd84/0x1410 [btrfs] [ 58.777621] btrfs_ioctl+0x4caa/0x114e0 [btrfs] ... Reported-by: TOTE Robot CC: stable@vger.kernel.org # 5.15+ Reviewed-by: Sweet Tea Dorminy Reviewed-by: Nikolay Borisov Signed-off-by: Zixuan Fu Signed-off-by: David Sterba --- fs/btrfs/relocation.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index a6dc827e75af0..33411baf5c7a3 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -3573,7 +3573,12 @@ int prepare_to_relocate(struct reloc_control *rc) */ return PTR_ERR(trans); } - return btrfs_commit_transaction(trans); + + ret = btrfs_commit_transaction(trans); + if (ret) + unset_reloc_control(rc); + + return ret; } static noinline_for_stack int relocate_block_group(struct reloc_control *rc) From 0a27a0474d146eb79e09ec88bf0d4229f4cfc1b8 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 26 Jul 2022 16:24:03 -0400 Subject: [PATCH 334/427] btrfs: move lockdep class helpers to locking.c These definitions exist in disk-io.c, which is not related to the locking. Move this over to locking.h/c where it makes more sense. Reviewed-by: Johannes Thumshirn Signed-off-by: Josef Bacik Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/disk-io.c | 82 ---------------------------------------------- fs/btrfs/disk-io.h | 10 ------ fs/btrfs/locking.c | 80 ++++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/locking.h | 9 +++++ 4 files changed, 89 insertions(+), 92 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3fac429cf8a40..b0345aa16c017 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -86,88 +86,6 @@ struct async_submit_bio { blk_status_t status; }; -/* - * Lockdep class keys for extent_buffer->lock's in this root. For a given - * eb, the lockdep key is determined by the btrfs_root it belongs to and - * the level the eb occupies in the tree. - * - * Different roots are used for different purposes and may nest inside each - * other and they require separate keysets. As lockdep keys should be - * static, assign keysets according to the purpose of the root as indicated - * by btrfs_root->root_key.objectid. This ensures that all special purpose - * roots have separate keysets. - * - * Lock-nesting across peer nodes is always done with the immediate parent - * node locked thus preventing deadlock. As lockdep doesn't know this, use - * subclass to avoid triggering lockdep warning in such cases. - * - * The key is set by the readpage_end_io_hook after the buffer has passed - * csum validation but before the pages are unlocked. It is also set by - * btrfs_init_new_buffer on freshly allocated blocks. - * - * We also add a check to make sure the highest level of the tree is the - * same as our lockdep setup here. If BTRFS_MAX_LEVEL changes, this code - * needs update as well. - */ -#ifdef CONFIG_DEBUG_LOCK_ALLOC -# if BTRFS_MAX_LEVEL != 8 -# error -# endif - -#define DEFINE_LEVEL(stem, level) \ - .names[level] = "btrfs-" stem "-0" #level, - -#define DEFINE_NAME(stem) \ - DEFINE_LEVEL(stem, 0) \ - DEFINE_LEVEL(stem, 1) \ - DEFINE_LEVEL(stem, 2) \ - DEFINE_LEVEL(stem, 3) \ - DEFINE_LEVEL(stem, 4) \ - DEFINE_LEVEL(stem, 5) \ - DEFINE_LEVEL(stem, 6) \ - DEFINE_LEVEL(stem, 7) - -static struct btrfs_lockdep_keyset { - u64 id; /* root objectid */ - /* Longest entry: btrfs-free-space-00 */ - char names[BTRFS_MAX_LEVEL][20]; - struct lock_class_key keys[BTRFS_MAX_LEVEL]; -} btrfs_lockdep_keysets[] = { - { .id = BTRFS_ROOT_TREE_OBJECTID, DEFINE_NAME("root") }, - { .id = BTRFS_EXTENT_TREE_OBJECTID, DEFINE_NAME("extent") }, - { .id = BTRFS_CHUNK_TREE_OBJECTID, DEFINE_NAME("chunk") }, - { .id = BTRFS_DEV_TREE_OBJECTID, DEFINE_NAME("dev") }, - { .id = BTRFS_CSUM_TREE_OBJECTID, DEFINE_NAME("csum") }, - { .id = BTRFS_QUOTA_TREE_OBJECTID, DEFINE_NAME("quota") }, - { .id = BTRFS_TREE_LOG_OBJECTID, DEFINE_NAME("log") }, - { .id = BTRFS_TREE_RELOC_OBJECTID, DEFINE_NAME("treloc") }, - { .id = BTRFS_DATA_RELOC_TREE_OBJECTID, DEFINE_NAME("dreloc") }, - { .id = BTRFS_UUID_TREE_OBJECTID, DEFINE_NAME("uuid") }, - { .id = BTRFS_FREE_SPACE_TREE_OBJECTID, DEFINE_NAME("free-space") }, - { .id = 0, DEFINE_NAME("tree") }, -}; - -#undef DEFINE_LEVEL -#undef DEFINE_NAME - -void btrfs_set_buffer_lockdep_class(u64 objectid, struct extent_buffer *eb, - int level) -{ - struct btrfs_lockdep_keyset *ks; - - BUG_ON(level >= ARRAY_SIZE(ks->keys)); - - /* find the matching keyset, id 0 is the default entry */ - for (ks = btrfs_lockdep_keysets; ks->id; ks++) - if (ks->id == objectid) - break; - - lockdep_set_class_and_name(&eb->lock, - &ks->keys[level], ks->names[level]); -} - -#endif - /* * Compute the csum of a btree block and store the result to provided buffer. */ diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index 8993b428e09ce..47ad8e0a2d33f 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h @@ -137,14 +137,4 @@ int btrfs_get_num_tolerated_disk_barrier_failures(u64 flags); int btrfs_get_free_objectid(struct btrfs_root *root, u64 *objectid); int btrfs_init_root_free_objectid(struct btrfs_root *root); -#ifdef CONFIG_DEBUG_LOCK_ALLOC -void btrfs_set_buffer_lockdep_class(u64 objectid, - struct extent_buffer *eb, int level); -#else -static inline void btrfs_set_buffer_lockdep_class(u64 objectid, - struct extent_buffer *eb, int level) -{ -} -#endif - #endif diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c index 33461b4f9c8b5..5747c63929df7 100644 --- a/fs/btrfs/locking.c +++ b/fs/btrfs/locking.c @@ -13,6 +13,86 @@ #include "extent_io.h" #include "locking.h" +/* + * Lockdep class keys for extent_buffer->lock's in this root. For a given + * eb, the lockdep key is determined by the btrfs_root it belongs to and + * the level the eb occupies in the tree. + * + * Different roots are used for different purposes and may nest inside each + * other and they require separate keysets. As lockdep keys should be + * static, assign keysets according to the purpose of the root as indicated + * by btrfs_root->root_key.objectid. This ensures that all special purpose + * roots have separate keysets. + * + * Lock-nesting across peer nodes is always done with the immediate parent + * node locked thus preventing deadlock. As lockdep doesn't know this, use + * subclass to avoid triggering lockdep warning in such cases. + * + * The key is set by the readpage_end_io_hook after the buffer has passed + * csum validation but before the pages are unlocked. It is also set by + * btrfs_init_new_buffer on freshly allocated blocks. + * + * We also add a check to make sure the highest level of the tree is the + * same as our lockdep setup here. If BTRFS_MAX_LEVEL changes, this code + * needs update as well. + */ +#ifdef CONFIG_DEBUG_LOCK_ALLOC +#if BTRFS_MAX_LEVEL != 8 +#error +#endif + +#define DEFINE_LEVEL(stem, level) \ + .names[level] = "btrfs-" stem "-0" #level, + +#define DEFINE_NAME(stem) \ + DEFINE_LEVEL(stem, 0) \ + DEFINE_LEVEL(stem, 1) \ + DEFINE_LEVEL(stem, 2) \ + DEFINE_LEVEL(stem, 3) \ + DEFINE_LEVEL(stem, 4) \ + DEFINE_LEVEL(stem, 5) \ + DEFINE_LEVEL(stem, 6) \ + DEFINE_LEVEL(stem, 7) + +static struct btrfs_lockdep_keyset { + u64 id; /* root objectid */ + /* Longest entry: btrfs-free-space-00 */ + char names[BTRFS_MAX_LEVEL][20]; + struct lock_class_key keys[BTRFS_MAX_LEVEL]; +} btrfs_lockdep_keysets[] = { + { .id = BTRFS_ROOT_TREE_OBJECTID, DEFINE_NAME("root") }, + { .id = BTRFS_EXTENT_TREE_OBJECTID, DEFINE_NAME("extent") }, + { .id = BTRFS_CHUNK_TREE_OBJECTID, DEFINE_NAME("chunk") }, + { .id = BTRFS_DEV_TREE_OBJECTID, DEFINE_NAME("dev") }, + { .id = BTRFS_CSUM_TREE_OBJECTID, DEFINE_NAME("csum") }, + { .id = BTRFS_QUOTA_TREE_OBJECTID, DEFINE_NAME("quota") }, + { .id = BTRFS_TREE_LOG_OBJECTID, DEFINE_NAME("log") }, + { .id = BTRFS_TREE_RELOC_OBJECTID, DEFINE_NAME("treloc") }, + { .id = BTRFS_DATA_RELOC_TREE_OBJECTID, DEFINE_NAME("dreloc") }, + { .id = BTRFS_UUID_TREE_OBJECTID, DEFINE_NAME("uuid") }, + { .id = BTRFS_FREE_SPACE_TREE_OBJECTID, DEFINE_NAME("free-space") }, + { .id = 0, DEFINE_NAME("tree") }, +}; + +#undef DEFINE_LEVEL +#undef DEFINE_NAME + +void btrfs_set_buffer_lockdep_class(u64 objectid, struct extent_buffer *eb, int level) +{ + struct btrfs_lockdep_keyset *ks; + + BUG_ON(level >= ARRAY_SIZE(ks->keys)); + + /* Find the matching keyset, id 0 is the default entry */ + for (ks = btrfs_lockdep_keysets; ks->id; ks++) + if (ks->id == objectid) + break; + + lockdep_set_class_and_name(&eb->lock, &ks->keys[level], ks->names[level]); +} + +#endif + /* * Extent buffer locking * ===================== diff --git a/fs/btrfs/locking.h b/fs/btrfs/locking.h index bbc45534ae9a6..b21372cab8409 100644 --- a/fs/btrfs/locking.h +++ b/fs/btrfs/locking.h @@ -131,4 +131,13 @@ void btrfs_drew_write_unlock(struct btrfs_drew_lock *lock); void btrfs_drew_read_lock(struct btrfs_drew_lock *lock); void btrfs_drew_read_unlock(struct btrfs_drew_lock *lock); +#ifdef CONFIG_DEBUG_LOCK_ALLOC +void btrfs_set_buffer_lockdep_class(u64 objectid, struct extent_buffer *eb, int level); +#else +static inline void btrfs_set_buffer_lockdep_class(u64 objectid, + struct extent_buffer *eb, int level) +{ +} +#endif + #endif From b40130b23ca4a08c5785d5a3559805916bddba3c Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 26 Jul 2022 16:24:04 -0400 Subject: [PATCH 335/427] btrfs: fix lockdep splat with reloc root extent buffers We have been hitting the following lockdep splat with btrfs/187 recently WARNING: possible circular locking dependency detected 5.19.0-rc8+ #775 Not tainted ------------------------------------------------------ btrfs/752500 is trying to acquire lock: ffff97e1875a97b8 (btrfs-treloc-02#2){+.+.}-{3:3}, at: __btrfs_tree_lock+0x24/0x110 but task is already holding lock: ffff97e1875a9278 (btrfs-tree-01/1){+.+.}-{3:3}, at: __btrfs_tree_lock+0x24/0x110 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #2 (btrfs-tree-01/1){+.+.}-{3:3}: down_write_nested+0x41/0x80 __btrfs_tree_lock+0x24/0x110 btrfs_init_new_buffer+0x7d/0x2c0 btrfs_alloc_tree_block+0x120/0x3b0 __btrfs_cow_block+0x136/0x600 btrfs_cow_block+0x10b/0x230 btrfs_search_slot+0x53b/0xb70 btrfs_lookup_inode+0x2a/0xa0 __btrfs_update_delayed_inode+0x5f/0x280 btrfs_async_run_delayed_root+0x24c/0x290 btrfs_work_helper+0xf2/0x3e0 process_one_work+0x271/0x590 worker_thread+0x52/0x3b0 kthread+0xf0/0x120 ret_from_fork+0x1f/0x30 -> #1 (btrfs-tree-01){++++}-{3:3}: down_write_nested+0x41/0x80 __btrfs_tree_lock+0x24/0x110 btrfs_search_slot+0x3c3/0xb70 do_relocation+0x10c/0x6b0 relocate_tree_blocks+0x317/0x6d0 relocate_block_group+0x1f1/0x560 btrfs_relocate_block_group+0x23e/0x400 btrfs_relocate_chunk+0x4c/0x140 btrfs_balance+0x755/0xe40 btrfs_ioctl+0x1ea2/0x2c90 __x64_sys_ioctl+0x88/0xc0 do_syscall_64+0x38/0x90 entry_SYSCALL_64_after_hwframe+0x63/0xcd -> #0 (btrfs-treloc-02#2){+.+.}-{3:3}: __lock_acquire+0x1122/0x1e10 lock_acquire+0xc2/0x2d0 down_write_nested+0x41/0x80 __btrfs_tree_lock+0x24/0x110 btrfs_lock_root_node+0x31/0x50 btrfs_search_slot+0x1cb/0xb70 replace_path+0x541/0x9f0 merge_reloc_root+0x1d6/0x610 merge_reloc_roots+0xe2/0x260 relocate_block_group+0x2c8/0x560 btrfs_relocate_block_group+0x23e/0x400 btrfs_relocate_chunk+0x4c/0x140 btrfs_balance+0x755/0xe40 btrfs_ioctl+0x1ea2/0x2c90 __x64_sys_ioctl+0x88/0xc0 do_syscall_64+0x38/0x90 entry_SYSCALL_64_after_hwframe+0x63/0xcd other info that might help us debug this: Chain exists of: btrfs-treloc-02#2 --> btrfs-tree-01 --> btrfs-tree-01/1 Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(btrfs-tree-01/1); lock(btrfs-tree-01); lock(btrfs-tree-01/1); lock(btrfs-treloc-02#2); *** DEADLOCK *** 7 locks held by btrfs/752500: #0: ffff97e292fdf460 (sb_writers#12){.+.+}-{0:0}, at: btrfs_ioctl+0x208/0x2c90 #1: ffff97e284c02050 (&fs_info->reclaim_bgs_lock){+.+.}-{3:3}, at: btrfs_balance+0x55f/0xe40 #2: ffff97e284c00878 (&fs_info->cleaner_mutex){+.+.}-{3:3}, at: btrfs_relocate_block_group+0x236/0x400 #3: ffff97e292fdf650 (sb_internal#2){.+.+}-{0:0}, at: merge_reloc_root+0xef/0x610 #4: ffff97e284c02378 (btrfs_trans_num_writers){++++}-{0:0}, at: join_transaction+0x1a8/0x5a0 #5: ffff97e284c023a0 (btrfs_trans_num_extwriters){++++}-{0:0}, at: join_transaction+0x1a8/0x5a0 #6: ffff97e1875a9278 (btrfs-tree-01/1){+.+.}-{3:3}, at: __btrfs_tree_lock+0x24/0x110 stack backtrace: CPU: 1 PID: 752500 Comm: btrfs Not tainted 5.19.0-rc8+ #775 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014 Call Trace: dump_stack_lvl+0x56/0x73 check_noncircular+0xd6/0x100 ? lock_is_held_type+0xe2/0x140 __lock_acquire+0x1122/0x1e10 lock_acquire+0xc2/0x2d0 ? __btrfs_tree_lock+0x24/0x110 down_write_nested+0x41/0x80 ? __btrfs_tree_lock+0x24/0x110 __btrfs_tree_lock+0x24/0x110 btrfs_lock_root_node+0x31/0x50 btrfs_search_slot+0x1cb/0xb70 ? lock_release+0x137/0x2d0 ? _raw_spin_unlock+0x29/0x50 ? release_extent_buffer+0x128/0x180 replace_path+0x541/0x9f0 merge_reloc_root+0x1d6/0x610 merge_reloc_roots+0xe2/0x260 relocate_block_group+0x2c8/0x560 btrfs_relocate_block_group+0x23e/0x400 btrfs_relocate_chunk+0x4c/0x140 btrfs_balance+0x755/0xe40 btrfs_ioctl+0x1ea2/0x2c90 ? lock_is_held_type+0xe2/0x140 ? lock_is_held_type+0xe2/0x140 ? __x64_sys_ioctl+0x88/0xc0 __x64_sys_ioctl+0x88/0xc0 do_syscall_64+0x38/0x90 entry_SYSCALL_64_after_hwframe+0x63/0xcd This isn't necessarily new, it's just tricky to hit in practice. There are two competing things going on here. With relocation we create a snapshot of every fs tree with a reloc tree. Any extent buffers that get initialized here are initialized with the reloc root lockdep key. However since it is a snapshot, any blocks that are currently in cache that originally belonged to the fs tree will have the normal tree lockdep key set. This creates the lock dependency of reloc tree -> normal tree for the extent buffer locking during the first phase of the relocation as we walk down the reloc root to relocate blocks. However this is problematic because the final phase of the relocation is merging the reloc root into the original fs root. This involves searching down to any keys that exist in the original fs root and then swapping the relocated block and the original fs root block. We have to search down to the fs root first, and then go search the reloc root for the block we need to replace. This creates the dependency of normal tree -> reloc tree which is why lockdep complains. Additionally even if we were to fix this particular mismatch with a different nesting for the merge case, we're still slotting in a block that has a owner of the reloc root objectid into a normal tree, so that block will have its lockdep key set to the tree reloc root, and create a lockdep splat later on when we wander into that block from the fs root. Unfortunately the only solution here is to make sure we do not set the lockdep key to the reloc tree lockdep key normally, and then reset any blocks we wander into from the reloc root when we're doing the merged. This solves the problem of having mixed tree reloc keys intermixed with normal tree keys, and then allows us to make sure in the merge case we maintain the lock order of normal tree -> reloc tree We handle this by setting a bit on the reloc root when we do the search for the block we want to relocate, and any block we search into or COW at that point gets set to the reloc tree key. This works correctly because we only ever COW down to the parent node, so we aren't resetting the key for the block we're linking into the fs root. With this patch we no longer have the lockdep splat in btrfs/187. Signed-off-by: Josef Bacik Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/ctree.c | 3 +++ fs/btrfs/ctree.h | 2 ++ fs/btrfs/extent-tree.c | 18 +++++++++++++++++- fs/btrfs/extent_io.c | 11 ++++++++++- fs/btrfs/locking.c | 11 +++++++++++ fs/btrfs/locking.h | 5 +++++ fs/btrfs/relocation.c | 2 ++ 7 files changed, 50 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 6e556031a8f3a..ebfa35fe1c38b 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -2075,6 +2075,9 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root, if (!p->skip_locking) { level = btrfs_header_level(b); + + btrfs_maybe_reset_lockdep_class(root, b); + if (level <= write_lock_level) { btrfs_tree_lock(b); p->locks[level] = BTRFS_WRITE_LOCK; diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 4db85b9dc7edd..4edb4bfb21664 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1173,6 +1173,8 @@ enum { BTRFS_ROOT_ORPHAN_CLEANUP, /* This root has a drop operation that was started previously. */ BTRFS_ROOT_UNFINISHED_DROP, + /* This reloc root needs to have its buffers lockdep class reset. */ + BTRFS_ROOT_RESET_LOCKDEP_CLASS, }; static inline void btrfs_wake_unfinished_drop(struct btrfs_fs_info *fs_info) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index ea3ec1e761e84..ab944d1f94ef0 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -4867,6 +4867,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, { struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *buf; + u64 lockdep_owner = owner; buf = btrfs_find_create_tree_block(fs_info, bytenr, owner, level); if (IS_ERR(buf)) @@ -4885,12 +4886,27 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, return ERR_PTR(-EUCLEAN); } + /* + * The reloc trees are just snapshots, so we need them to appear to be + * just like any other fs tree WRT lockdep. + * + * The exception however is in replace_path() in relocation, where we + * hold the lock on the original fs root and then search for the reloc + * root. At that point we need to make sure any reloc root buffers are + * set to the BTRFS_TREE_RELOC_OBJECTID lockdep class in order to make + * lockdep happy. + */ + if (lockdep_owner == BTRFS_TREE_RELOC_OBJECTID && + !test_bit(BTRFS_ROOT_RESET_LOCKDEP_CLASS, &root->state)) + lockdep_owner = BTRFS_FS_TREE_OBJECTID; + /* * This needs to stay, because we could allocate a freed block from an * old tree into a new tree, so we need to make sure this new block is * set to the appropriate level and owner. */ - btrfs_set_buffer_lockdep_class(owner, buf, level); + btrfs_set_buffer_lockdep_class(lockdep_owner, buf, level); + __btrfs_tree_lock(buf, nest); btrfs_clean_tree_block(buf); clear_bit(EXTENT_BUFFER_STALE, &buf->bflags); diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index b290bd1b38b08..6e8e936a8a1ef 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -6140,6 +6140,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, struct extent_buffer *exists = NULL; struct page *p; struct address_space *mapping = fs_info->btree_inode->i_mapping; + u64 lockdep_owner = owner_root; int uptodate = 1; int ret; @@ -6164,7 +6165,15 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, eb = __alloc_extent_buffer(fs_info, start, len); if (!eb) return ERR_PTR(-ENOMEM); - btrfs_set_buffer_lockdep_class(owner_root, eb, level); + + /* + * The reloc trees are just snapshots, so we need them to appear to be + * just like any other fs tree WRT lockdep. + */ + if (lockdep_owner == BTRFS_TREE_RELOC_OBJECTID) + lockdep_owner = BTRFS_FS_TREE_OBJECTID; + + btrfs_set_buffer_lockdep_class(lockdep_owner, eb, level); num_pages = num_extent_pages(eb); for (i = 0; i < num_pages; i++, index++) { diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c index 5747c63929df7..9063072b399bd 100644 --- a/fs/btrfs/locking.c +++ b/fs/btrfs/locking.c @@ -91,6 +91,13 @@ void btrfs_set_buffer_lockdep_class(u64 objectid, struct extent_buffer *eb, int lockdep_set_class_and_name(&eb->lock, &ks->keys[level], ks->names[level]); } +void btrfs_maybe_reset_lockdep_class(struct btrfs_root *root, struct extent_buffer *eb) +{ + if (test_bit(BTRFS_ROOT_RESET_LOCKDEP_CLASS, &root->state)) + btrfs_set_buffer_lockdep_class(root->root_key.objectid, + eb, btrfs_header_level(eb)); +} + #endif /* @@ -244,6 +251,8 @@ struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root) while (1) { eb = btrfs_root_node(root); + + btrfs_maybe_reset_lockdep_class(root, eb); btrfs_tree_lock(eb); if (eb == root->node) break; @@ -265,6 +274,8 @@ struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root) while (1) { eb = btrfs_root_node(root); + + btrfs_maybe_reset_lockdep_class(root, eb); btrfs_tree_read_lock(eb); if (eb == root->node) break; diff --git a/fs/btrfs/locking.h b/fs/btrfs/locking.h index b21372cab8409..ab268be09bb54 100644 --- a/fs/btrfs/locking.h +++ b/fs/btrfs/locking.h @@ -133,11 +133,16 @@ void btrfs_drew_read_unlock(struct btrfs_drew_lock *lock); #ifdef CONFIG_DEBUG_LOCK_ALLOC void btrfs_set_buffer_lockdep_class(u64 objectid, struct extent_buffer *eb, int level); +void btrfs_maybe_reset_lockdep_class(struct btrfs_root *root, struct extent_buffer *eb); #else static inline void btrfs_set_buffer_lockdep_class(u64 objectid, struct extent_buffer *eb, int level) { } +static inline void btrfs_maybe_reset_lockdep_class(struct btrfs_root *root, + struct extent_buffer *eb) +{ +} #endif #endif diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 33411baf5c7a3..45c02aba2492b 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -1326,7 +1326,9 @@ int replace_path(struct btrfs_trans_handle *trans, struct reloc_control *rc, btrfs_release_path(path); path->lowest_level = level; + set_bit(BTRFS_ROOT_RESET_LOCKDEP_CLASS, &src->state); ret = btrfs_search_slot(trans, src, &key, path, 0, 1); + clear_bit(BTRFS_ROOT_RESET_LOCKDEP_CLASS, &src->state); path->lowest_level = 0; if (ret) { if (ret > 0) From 7a6b75b79902e47f46328b57733f2604774fa2d9 Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Mon, 1 Aug 2022 14:57:51 +0100 Subject: [PATCH 336/427] btrfs: fix lost error handling when looking up extended ref on log replay During log replay, when processing inode references, if we get an error when looking up for an extended reference at __add_inode_ref(), we ignore it and proceed, returning success (0) if no other error happens after the lookup. This is obviously wrong because in case an extended reference exists and it encodes some name not in the log, we need to unlink it, otherwise the filesystem state will not match the state it had after the last fsync. So just make __add_inode_ref() return an error it gets from the extended reference lookup. Fixes: f186373fef005c ("btrfs: extended inode refs") CC: stable@vger.kernel.org # 4.9+ Signed-off-by: Filipe Manana Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/tree-log.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index dcf75a8daa200..c1fdd6ef3f4aa 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -1146,7 +1146,9 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans, extref = btrfs_lookup_inode_extref(NULL, root, path, name, namelen, inode_objectid, parent_objectid, 0, 0); - if (!IS_ERR_OR_NULL(extref)) { + if (IS_ERR(extref)) { + return PTR_ERR(extref); + } else if (extref) { u32 item_size; u32 cur_offset = 0; unsigned long base; From 769030e11847c5412270c0726ff21d3a1f0a3131 Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Mon, 1 Aug 2022 14:57:52 +0100 Subject: [PATCH 337/427] btrfs: fix warning during log replay when bumping inode link count During log replay, at add_link(), we may increment the link count of another inode that has a reference that conflicts with a new reference for the inode currently being processed. During log replay, at add_link(), we may drop (unlink) a reference from some inode in the subvolume tree if that reference conflicts with a new reference found in the log for the inode we are currently processing. After the unlink, If the link count has decreased from 1 to 0, then we increment the link count to prevent the inode from being deleted if it's evicted by an iput() call, because we may have references to add to that inode later on (and we will fixup its link count later during log replay). However incrementing the link count from 0 to 1 triggers a warning: $ cat fs/inode.c (...) void inc_nlink(struct inode *inode) { if (unlikely(inode->i_nlink == 0)) { WARN_ON(!(inode->i_state & I_LINKABLE)); atomic_long_dec(&inode->i_sb->s_remove_count); } (...) The I_LINKABLE flag is only set when creating an O_TMPFILE file, so it's never set during log replay. Most of the time, the warning isn't triggered even if we dropped the last reference of the conflicting inode, and this is because: 1) The conflicting inode was previously marked for fixup, through a call to link_to_fixup_dir(), which increments the inode's link count; 2) And the last iput() on the inode has not triggered eviction of the inode, nor was eviction triggered after the iput(). So at add_link(), even if we unlink the last reference of the inode, its link count ends up being 1 and not 0. So this means that if eviction is triggered after link_to_fixup_dir() is called, at add_link() we will read the inode back from the subvolume tree and have it with a correct link count, matching the number of references it has on the subvolume tree. So if when we are at add_link() the inode has exactly one reference only, its link count is 1, and after the unlink its link count becomes 0. So fix this by using set_nlink() instead of inc_nlink(), as the former accepts a transition from 0 to 1 and it's what we use in other similar contexts (like at link_to_fixup_dir(). Also make add_inode_ref() use set_nlink() instead of inc_nlink() to bump the link count from 0 to 1. The warning is actually harmless, but it may scare users. Josef also ran into it recently. CC: stable@vger.kernel.org # 5.1+ Signed-off-by: Filipe Manana Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/tree-log.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index c1fdd6ef3f4aa..9205c4a5ca81d 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -1459,7 +1459,7 @@ static int add_link(struct btrfs_trans_handle *trans, * on the inode will not free it. We will fixup the link count later. */ if (other_inode->i_nlink == 0) - inc_nlink(other_inode); + set_nlink(other_inode, 1); add_link: ret = btrfs_add_link(trans, BTRFS_I(dir), BTRFS_I(inode), name, namelen, 0, ref_index); @@ -1602,7 +1602,7 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, * free it. We will fixup the link count later. */ if (!ret && inode->i_nlink == 0) - inc_nlink(inode); + set_nlink(inode, 1); } if (ret < 0) goto out; From 899b7f69f244e539ea5df1b4d756046337de44a5 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 3 Aug 2022 14:28:47 -0400 Subject: [PATCH 338/427] btrfs: tree-checker: check for overlapping extent items We're seeing a weird problem in production where we have overlapping extent items in the extent tree. It's unclear where these are coming from, and in debugging we realized there's no check in the tree checker for this sort of problem. Add a check to the tree-checker to make sure that the extents do not overlap each other. Reviewed-by: Qu Wenruo Signed-off-by: Josef Bacik Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/tree-checker.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c index 9e0e0ae2288cd..43f905ab0a18d 100644 --- a/fs/btrfs/tree-checker.c +++ b/fs/btrfs/tree-checker.c @@ -1233,7 +1233,8 @@ static void extent_err(const struct extent_buffer *eb, int slot, } static int check_extent_item(struct extent_buffer *leaf, - struct btrfs_key *key, int slot) + struct btrfs_key *key, int slot, + struct btrfs_key *prev_key) { struct btrfs_fs_info *fs_info = leaf->fs_info; struct btrfs_extent_item *ei; @@ -1453,6 +1454,26 @@ static int check_extent_item(struct extent_buffer *leaf, total_refs, inline_refs); return -EUCLEAN; } + + if ((prev_key->type == BTRFS_EXTENT_ITEM_KEY) || + (prev_key->type == BTRFS_METADATA_ITEM_KEY)) { + u64 prev_end = prev_key->objectid; + + if (prev_key->type == BTRFS_METADATA_ITEM_KEY) + prev_end += fs_info->nodesize; + else + prev_end += prev_key->offset; + + if (unlikely(prev_end > key->objectid)) { + extent_err(leaf, slot, + "previous extent [%llu %u %llu] overlaps current extent [%llu %u %llu]", + prev_key->objectid, prev_key->type, + prev_key->offset, key->objectid, key->type, + key->offset); + return -EUCLEAN; + } + } + return 0; } @@ -1621,7 +1642,7 @@ static int check_leaf_item(struct extent_buffer *leaf, break; case BTRFS_EXTENT_ITEM_KEY: case BTRFS_METADATA_ITEM_KEY: - ret = check_extent_item(leaf, key, slot); + ret = check_extent_item(leaf, key, slot, prev_key); break; case BTRFS_TREE_BLOCK_REF_KEY: case BTRFS_SHARED_DATA_REF_KEY: From 90d74fdbd8059bf041ac797092c9b1d461555280 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Wed, 17 Aug 2022 15:51:44 +0200 Subject: [PATCH 339/427] ALSA: hda/realtek: Add quirk for Clevo NS50PU, NS70PU Fixes headset microphone detection on Clevo NS50PU and NS70PU. Signed-off-by: Christoffer Sandberg Signed-off-by: Werner Sembach Cc: Link: https://lore.kernel.org/r/20220817135144.34103-1-wse@tuxedocomputers.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b42496c01c437..47e72cf76608e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9391,6 +9391,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1558, 0x70f4, "Clevo NH77EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x70f6, "Clevo NH77DPQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x7716, "Clevo NS50PU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x7717, "Clevo NS70PU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x7718, "Clevo L140PU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8228, "Clevo NR40BU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8520, "Clevo NH50D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), From ffa9ed86522f1c08d4face4e0a4ebf366037bf19 Mon Sep 17 00:00:00 2001 From: Grzegorz Siwik Date: Fri, 12 Aug 2022 15:25:47 +0200 Subject: [PATCH 340/427] ice: Fix double VLAN error when entering promisc mode Avoid enabling or disabling VLAN 0 when trying to set promiscuous VLAN mode if double VLAN mode is enabled. This fix is needed because the driver tries to add the VLAN 0 filter twice (once for inner and once for outer) when double VLAN mode is enabled. The filter program is rejected by the firmware when double VLAN is enabled, because the promiscuous filter only needs to be set once. This issue was missed in the initial implementation of double VLAN mode. Fixes: 5eda8afd6bcc ("ice: Add support for PF/VF promiscuous mode") Signed-off-by: Grzegorz Siwik Link: https://lore.kernel.org/all/CAK8fFZ7m-KR57M_rYX6xZN39K89O=LGooYkKsu6HKt0Bs+x6xQ@mail.gmail.com/ Tested-by: Jaroslav Pulchart Tested-by: Igor Raits Tested-by: Gurucharan (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_switch.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 262e553e3b585..0c265739cce29 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -4445,6 +4445,13 @@ ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, goto free_fltr_list; list_for_each_entry(list_itr, &vsi_list_head, list_entry) { + /* Avoid enabling or disabling VLAN zero twice when in double + * VLAN mode + */ + if (ice_is_dvm_ena(hw) && + list_itr->fltr_info.l_data.vlan.tpid == 0) + continue; + vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id; if (rm_vlan_promisc) status = ice_clear_vsi_promisc(hw, vsi_handle, From 11e551a2efa4481bd4f616ab75374a2710b480e9 Mon Sep 17 00:00:00 2001 From: Grzegorz Siwik Date: Fri, 12 Aug 2022 15:25:48 +0200 Subject: [PATCH 341/427] ice: Ignore EEXIST when setting promisc mode Ignore EEXIST error when setting promiscuous mode. This fix is needed because the driver could set promiscuous mode when it still has not cleared properly. Promiscuous mode could be set only once, so setting it second time will be rejected. Fixes: 5eda8afd6bcc ("ice: Add support for PF/VF promiscuous mode") Signed-off-by: Grzegorz Siwik Link: https://lore.kernel.org/all/CAK8fFZ7m-KR57M_rYX6xZN39K89O=LGooYkKsu6HKt0Bs+x6xQ@mail.gmail.com/ Tested-by: Jaroslav Pulchart Tested-by: Igor Raits Tested-by: Gurucharan (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_switch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 0c265739cce29..3808034f7e7e3 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -4459,7 +4459,7 @@ ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, else status = ice_set_vsi_promisc(hw, vsi_handle, promisc_mask, vlan_id); - if (status) + if (status && status != -EEXIST) break; } From abddafd4585cc825d454da3cf308ad1226f6c554 Mon Sep 17 00:00:00 2001 From: Grzegorz Siwik Date: Fri, 12 Aug 2022 15:25:49 +0200 Subject: [PATCH 342/427] ice: Fix clearing of promisc mode with bridge over bond When at least two interfaces are bonded and a bridge is enabled on the bond, an error can occur when the bridge is removed and re-added. The reason for the error is because promiscuous mode was not fully cleared from the VLAN VSI in the hardware. With this change, promiscuous mode is properly removed when the bridge disconnects from bonding. [ 1033.676359] bond1: link status definitely down for interface enp95s0f0, disabling it [ 1033.676366] bond1: making interface enp175s0f0 the new active one [ 1033.676369] device enp95s0f0 left promiscuous mode [ 1033.676522] device enp175s0f0 entered promiscuous mode [ 1033.676901] ice 0000:af:00.0 enp175s0f0: Error setting Multicast promiscuous mode on VSI 6 [ 1041.795662] ice 0000:af:00.0 enp175s0f0: Error setting Multicast promiscuous mode on VSI 6 [ 1041.944826] bond1: link status definitely down for interface enp175s0f0, disabling it [ 1041.944874] device enp175s0f0 left promiscuous mode [ 1041.944918] bond1: now running without any active interface! Fixes: c31af68a1b94 ("ice: Add outer_vlan_ops and VSI specific VLAN ops implementations") Co-developed-by: Jesse Brandeburg Signed-off-by: Jesse Brandeburg Signed-off-by: Grzegorz Siwik Link: https://lore.kernel.org/all/CAK8fFZ7m-KR57M_rYX6xZN39K89O=LGooYkKsu6HKt0Bs+x6xQ@mail.gmail.com/ Tested-by: Jaroslav Pulchart Tested-by: Igor Raits Tested-by: Gurucharan (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_lib.c | 6 +++++- drivers/net/ethernet/intel/ice/ice_main.c | 12 +++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 0d4dbca889640..733c455f65746 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -4062,7 +4062,11 @@ int ice_vsi_del_vlan_zero(struct ice_vsi *vsi) if (err && err != -EEXIST) return err; - return 0; + /* when deleting the last VLAN filter, make sure to disable the VLAN + * promisc mode so the filter isn't left by accident + */ + return ice_clear_vsi_promisc(&vsi->back->hw, vsi->idx, + ICE_MCAST_VLAN_PROMISC_BITS, 0); } /** diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index eb40526ee179f..4ecaf40cf946b 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -267,8 +267,10 @@ static int ice_set_promisc(struct ice_vsi *vsi, u8 promisc_m) status = ice_fltr_set_vsi_promisc(&vsi->back->hw, vsi->idx, promisc_m, 0); } + if (status && status != -EEXIST) + return status; - return status; + return 0; } /** @@ -3573,6 +3575,14 @@ ice_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid) while (test_and_set_bit(ICE_CFG_BUSY, vsi->state)) usleep_range(1000, 2000); + ret = ice_clear_vsi_promisc(&vsi->back->hw, vsi->idx, + ICE_MCAST_VLAN_PROMISC_BITS, vid); + if (ret) { + netdev_err(netdev, "Error clearing multicast promiscuous mode on VSI %i\n", + vsi->vsi_num); + vsi->current_netdev_flags |= IFF_ALLMULTI; + } + vlan_ops = ice_get_compat_vsi_vlan_ops(vsi); /* Make sure VLAN delete is successful before updating VLAN From 79956b83ed4281c35561c39254558092d96a9ed1 Mon Sep 17 00:00:00 2001 From: Benjamin Mikailenko Date: Fri, 12 Aug 2022 15:25:50 +0200 Subject: [PATCH 343/427] ice: Ignore error message when setting same promiscuous mode Commit 1273f89578f2 ("ice: Fix broken IFF_ALLMULTI handling") introduced new checks when setting/clearing promiscuous mode. But if the requested promiscuous mode setting already exists, an -EEXIST error message would be printed. This is incorrect because promiscuous mode is either on/off and shouldn't print an error when the requested configuration is already set. This can happen when removing a bridge with two bonded interfaces and promiscuous most isn't fully cleared from VLAN VSI in hardware. Fix this by ignoring cases where requested promiscuous mode exists. Fixes: 1273f89578f2 ("ice: Fix broken IFF_ALLMULTI handling") Signed-off-by: Benjamin Mikailenko Signed-off-by: Grzegorz Siwik Link: https://lore.kernel.org/all/CAK8fFZ7m-KR57M_rYX6xZN39K89O=LGooYkKsu6HKt0Bs+x6xQ@mail.gmail.com/ Tested-by: Gurucharan (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_fltr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_fltr.c b/drivers/net/ethernet/intel/ice/ice_fltr.c index 85a94483c2edc..40e678cfb5078 100644 --- a/drivers/net/ethernet/intel/ice/ice_fltr.c +++ b/drivers/net/ethernet/intel/ice/ice_fltr.c @@ -62,7 +62,7 @@ ice_fltr_set_vlan_vsi_promisc(struct ice_hw *hw, struct ice_vsi *vsi, int result; result = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_mask, false); - if (result) + if (result && result != -EEXIST) dev_err(ice_pf_to_dev(pf), "Error setting promisc mode on VSI %i (rc=%d)\n", vsi->vsi_num, result); @@ -86,7 +86,7 @@ ice_fltr_clear_vlan_vsi_promisc(struct ice_hw *hw, struct ice_vsi *vsi, int result; result = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_mask, true); - if (result) + if (result && result != -EEXIST) dev_err(ice_pf_to_dev(pf), "Error clearing promisc mode on VSI %i (rc=%d)\n", vsi->vsi_num, result); @@ -109,7 +109,7 @@ ice_fltr_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, int result; result = ice_clear_vsi_promisc(hw, vsi_handle, promisc_mask, vid); - if (result) + if (result && result != -EEXIST) dev_err(ice_pf_to_dev(pf), "Error clearing promisc mode on VSI %i for VID %u (rc=%d)\n", ice_get_hw_vsi_num(hw, vsi_handle), vid, result); @@ -132,7 +132,7 @@ ice_fltr_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, int result; result = ice_set_vsi_promisc(hw, vsi_handle, promisc_mask, vid); - if (result) + if (result && result != -EEXIST) dev_err(ice_pf_to_dev(pf), "Error setting promisc mode on VSI %i for VID %u (rc=%d)\n", ice_get_hw_vsi_num(hw, vsi_handle), vid, result); From 664d4646184ed986f8195df684cc4660563fb02a Mon Sep 17 00:00:00 2001 From: Sylwester Dziedziuch Date: Wed, 3 Aug 2022 10:42:46 +0200 Subject: [PATCH 344/427] ice: Fix VF not able to send tagged traffic with no VLAN filters VF was not able to send tagged traffic when it didn't have any VLAN interfaces and VLAN anti-spoofing was enabled. Fix this by allowing VFs with no VLAN filters to send tagged traffic. After VF adds a VLAN interface it will be able to send tagged traffic matching VLAN filters only. Testing hints: 1. Spawn VF 2. Send tagged packet from a VF 3. The packet should be sent out and not dropped 4. Add a VLAN interface on VF 5. Send tagged packet on that VLAN interface 6. Packet should be sent out and not dropped 7. Send tagged packet with id different than VLAN interface 8. Packet should be dropped Fixes: daf4dd16438b ("ice: Refactor spoofcheck configuration functions") Signed-off-by: Sylwester Dziedziuch Signed-off-by: Mateusz Palczewski Tested-by: Konrad Jankowski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_vf_lib.c | 11 ++-- drivers/net/ethernet/intel/ice/ice_virtchnl.c | 57 ++++++++++++++++--- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c index 76f70fe1d9989..0abeed092de1d 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c @@ -764,13 +764,16 @@ static int ice_cfg_mac_antispoof(struct ice_vsi *vsi, bool enable) static int ice_vsi_ena_spoofchk(struct ice_vsi *vsi) { struct ice_vsi_vlan_ops *vlan_ops; - int err; + int err = 0; vlan_ops = ice_get_compat_vsi_vlan_ops(vsi); - err = vlan_ops->ena_tx_filtering(vsi); - if (err) - return err; + /* Allow VF with VLAN 0 only to send all tagged traffic */ + if (vsi->type != ICE_VSI_VF || ice_vsi_has_non_zero_vlans(vsi)) { + err = vlan_ops->ena_tx_filtering(vsi); + if (err) + return err; + } return ice_cfg_mac_antispoof(vsi, true); } diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c index 094e3c97a1ea0..2b4c791b6cbad 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c @@ -2288,6 +2288,15 @@ static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v) /* Enable VLAN filtering on first non-zero VLAN */ if (!vlan_promisc && vid && !ice_is_dvm_ena(&pf->hw)) { + if (vf->spoofchk) { + status = vsi->inner_vlan_ops.ena_tx_filtering(vsi); + if (status) { + v_ret = VIRTCHNL_STATUS_ERR_PARAM; + dev_err(dev, "Enable VLAN anti-spoofing on VLAN ID: %d failed error-%d\n", + vid, status); + goto error_param; + } + } if (vsi->inner_vlan_ops.ena_rx_filtering(vsi)) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; dev_err(dev, "Enable VLAN pruning on VLAN ID: %d failed error-%d\n", @@ -2333,8 +2342,10 @@ static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v) } /* Disable VLAN filtering when only VLAN 0 is left */ - if (!ice_vsi_has_non_zero_vlans(vsi)) + if (!ice_vsi_has_non_zero_vlans(vsi)) { + vsi->inner_vlan_ops.dis_tx_filtering(vsi); vsi->inner_vlan_ops.dis_rx_filtering(vsi); + } if (vlan_promisc) ice_vf_dis_vlan_promisc(vsi, &vlan); @@ -2838,6 +2849,13 @@ ice_vc_del_vlans(struct ice_vf *vf, struct ice_vsi *vsi, if (vlan_promisc) ice_vf_dis_vlan_promisc(vsi, &vlan); + + /* Disable VLAN filtering when only VLAN 0 is left */ + if (!ice_vsi_has_non_zero_vlans(vsi) && ice_is_dvm_ena(&vsi->back->hw)) { + err = vsi->outer_vlan_ops.dis_tx_filtering(vsi); + if (err) + return err; + } } vc_vlan = &vlan_fltr->inner; @@ -2853,8 +2871,17 @@ ice_vc_del_vlans(struct ice_vf *vf, struct ice_vsi *vsi, /* no support for VLAN promiscuous on inner VLAN unless * we are in Single VLAN Mode (SVM) */ - if (!ice_is_dvm_ena(&vsi->back->hw) && vlan_promisc) - ice_vf_dis_vlan_promisc(vsi, &vlan); + if (!ice_is_dvm_ena(&vsi->back->hw)) { + if (vlan_promisc) + ice_vf_dis_vlan_promisc(vsi, &vlan); + + /* Disable VLAN filtering when only VLAN 0 is left */ + if (!ice_vsi_has_non_zero_vlans(vsi)) { + err = vsi->inner_vlan_ops.dis_tx_filtering(vsi); + if (err) + return err; + } + } } } @@ -2931,6 +2958,13 @@ ice_vc_add_vlans(struct ice_vf *vf, struct ice_vsi *vsi, if (err) return err; } + + /* Enable VLAN filtering on first non-zero VLAN */ + if (vf->spoofchk && vlan.vid && ice_is_dvm_ena(&vsi->back->hw)) { + err = vsi->outer_vlan_ops.ena_tx_filtering(vsi); + if (err) + return err; + } } vc_vlan = &vlan_fltr->inner; @@ -2946,10 +2980,19 @@ ice_vc_add_vlans(struct ice_vf *vf, struct ice_vsi *vsi, /* no support for VLAN promiscuous on inner VLAN unless * we are in Single VLAN Mode (SVM) */ - if (!ice_is_dvm_ena(&vsi->back->hw) && vlan_promisc) { - err = ice_vf_ena_vlan_promisc(vsi, &vlan); - if (err) - return err; + if (!ice_is_dvm_ena(&vsi->back->hw)) { + if (vlan_promisc) { + err = ice_vf_ena_vlan_promisc(vsi, &vlan); + if (err) + return err; + } + + /* Enable VLAN filtering on first non-zero VLAN */ + if (vf->spoofchk && vlan.vid) { + err = vsi->inner_vlan_ops.ena_tx_filtering(vsi); + if (err) + return err; + } } } } From 06f36055121769b9eb9b7d28c7499d1cc8269dc3 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Wed, 17 Aug 2022 17:30:40 +0200 Subject: [PATCH 345/427] Revert "mlxsw: core: Add the hottest thermal zone detection" This reverts commit 2dc2f760052da4925482ecdcdc5c94d4a599153c and commit 6f73862fabd93213de157d9cc6ef76084311c628. As discussed in the thread: https://lore.kernel.org/all/f3c62ebe-7d59-c537-a010-bff366c8aeba@linaro.org/ the feature provided by commits 2dc2f760052da and 6f73862fabd93 is actually already handled by the thermal framework via the cooling device state aggregation, thus all this code is pointless. The revert conflicts with the following changes: - 7f4957be0d5b8: thermal: Use mode helpers in drivers - 6a79507cfe94c: mlxsw: core: Extend thermal module with per QSFP module thermal zones These conflicts were fixed and the resulting changes are in this patch. Both reverts are in the same change as requested by Ido Schimmel: https://lore.kernel.org/all/Yvz7+RUsmVco3Xpj@shredder/ Signed-off-by: Daniel Lezcano Tested-by: Vadim Pasternak Acked-by: Jakub Kicinski Reviewed-by: Ido Schimmel Link: https://lore.kernel.org/r/20220817153040.2464245-1-daniel.lezcano@linaro.org --- .../ethernet/mellanox/mlxsw/core_thermal.c | 77 +------------------ 1 file changed, 2 insertions(+), 75 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c index 3548fe1df7c87..987fe5c9d5a36 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c @@ -21,7 +21,6 @@ #define MLXSW_THERMAL_ASIC_TEMP_HOT 105000 /* 105C */ #define MLXSW_THERMAL_HYSTERESIS_TEMP 5000 /* 5C */ #define MLXSW_THERMAL_MODULE_TEMP_SHIFT (MLXSW_THERMAL_HYSTERESIS_TEMP * 2) -#define MLXSW_THERMAL_TEMP_SCORE_MAX GENMASK(31, 0) #define MLXSW_THERMAL_MAX_STATE 10 #define MLXSW_THERMAL_MIN_STATE 2 #define MLXSW_THERMAL_MAX_DUTY 255 @@ -101,8 +100,6 @@ struct mlxsw_thermal { struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX]; u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1]; struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; - unsigned int tz_highest_score; - struct thermal_zone_device *tz_highest_dev; struct mlxsw_thermal_area line_cards[]; }; @@ -193,34 +190,6 @@ mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core, return 0; } -static void mlxsw_thermal_tz_score_update(struct mlxsw_thermal *thermal, - struct thermal_zone_device *tzdev, - struct mlxsw_thermal_trip *trips, - int temp) -{ - struct mlxsw_thermal_trip *trip = trips; - unsigned int score, delta, i, shift = 1; - - /* Calculate thermal zone score, if temperature is above the hot - * threshold score is set to MLXSW_THERMAL_TEMP_SCORE_MAX. - */ - score = MLXSW_THERMAL_TEMP_SCORE_MAX; - for (i = MLXSW_THERMAL_TEMP_TRIP_NORM; i < MLXSW_THERMAL_NUM_TRIPS; - i++, trip++) { - if (temp < trip->temp) { - delta = DIV_ROUND_CLOSEST(temp, trip->temp - temp); - score = delta * shift; - break; - } - shift *= 256; - } - - if (score > thermal->tz_highest_score) { - thermal->tz_highest_score = score; - thermal->tz_highest_dev = tzdev; - } -} - static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev, struct thermal_cooling_device *cdev) { @@ -286,9 +255,6 @@ static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev, return err; } mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL); - if (temp > 0) - mlxsw_thermal_tz_score_update(thermal, tzdev, thermal->trips, - temp); *p_temp = temp; return 0; @@ -349,21 +315,6 @@ static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev, return 0; } -static int mlxsw_thermal_trend_get(struct thermal_zone_device *tzdev, - int trip, enum thermal_trend *trend) -{ - struct mlxsw_thermal *thermal = tzdev->devdata; - - if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) - return -EINVAL; - - if (tzdev == thermal->tz_highest_dev) - return 1; - - *trend = THERMAL_TREND_STABLE; - return 0; -} - static struct thermal_zone_params mlxsw_thermal_params = { .no_hwmon = true, }; @@ -377,7 +328,6 @@ static struct thermal_zone_device_ops mlxsw_thermal_ops = { .set_trip_temp = mlxsw_thermal_set_trip_temp, .get_trip_hyst = mlxsw_thermal_get_trip_hyst, .set_trip_hyst = mlxsw_thermal_set_trip_hyst, - .get_trend = mlxsw_thermal_trend_get, }; static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev, @@ -463,7 +413,6 @@ static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev, int temp, crit_temp, emerg_temp; struct device *dev; u16 sensor_index; - int err; dev = thermal->bus_info->dev; sensor_index = MLXSW_REG_MTMP_MODULE_INDEX_MIN + tz->module; @@ -479,10 +428,8 @@ static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev, return 0; /* Update trip points. */ - err = mlxsw_thermal_module_trips_update(dev, thermal->core, tz, - crit_temp, emerg_temp); - if (!err && temp > 0) - mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp); + mlxsw_thermal_module_trips_update(dev, thermal->core, tz, + crit_temp, emerg_temp); return 0; } @@ -546,22 +493,6 @@ mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip, return 0; } -static int mlxsw_thermal_module_trend_get(struct thermal_zone_device *tzdev, - int trip, enum thermal_trend *trend) -{ - struct mlxsw_thermal_module *tz = tzdev->devdata; - struct mlxsw_thermal *thermal = tz->parent; - - if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) - return -EINVAL; - - if (tzdev == thermal->tz_highest_dev) - return 1; - - *trend = THERMAL_TREND_STABLE; - return 0; -} - static struct thermal_zone_device_ops mlxsw_thermal_module_ops = { .bind = mlxsw_thermal_module_bind, .unbind = mlxsw_thermal_module_unbind, @@ -571,7 +502,6 @@ static struct thermal_zone_device_ops mlxsw_thermal_module_ops = { .set_trip_temp = mlxsw_thermal_module_trip_temp_set, .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get, .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set, - .get_trend = mlxsw_thermal_module_trend_get, }; static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, @@ -592,8 +522,6 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, return err; mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL); - if (temp > 0) - mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp); *p_temp = temp; return 0; @@ -608,7 +536,6 @@ static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = { .set_trip_temp = mlxsw_thermal_module_trip_temp_set, .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get, .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set, - .get_trend = mlxsw_thermal_module_trend_get, }; static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev, From 36c0d935015766bf20d621c18313f17691bda5e3 Mon Sep 17 00:00:00 2001 From: Arun Ramadoss Date: Tue, 16 Aug 2022 16:25:16 +0530 Subject: [PATCH 346/427] net: dsa: microchip: ksz9477: fix fdb_dump last invalid entry In the ksz9477_fdb_dump function it reads the ALU control register and exit from the timeout loop if there is valid entry or search is complete. After exiting the loop, it reads the alu entry and report to the user space irrespective of entry is valid. It works till the valid entry. If the loop exited when search is complete, it reads the alu table. The table returns all ones and it is reported to user space. So bridge fdb show gives ff:ff:ff:ff:ff:ff as last entry for every port. To fix it, after exiting the loop the entry is reported only if it is valid one. Fixes: b987e98e50ab ("dsa: add DSA switch driver for Microchip KSZ9477") Signed-off-by: Arun Ramadoss Reviewed-by: Vladimir Oltean Link: https://lore.kernel.org/r/20220816105516.18350-1-arun.ramadoss@microchip.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/microchip/ksz9477.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index 4b14d80d27ede..e4f446db0ca18 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -613,6 +613,9 @@ int ksz9477_fdb_dump(struct ksz_device *dev, int port, goto exit; } + if (!(ksz_data & ALU_VALID)) + continue; + /* read ALU table */ ksz9477_read_table(dev, alu_table); From ae2a823643d71f40751259266f7c2e7d90909662 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 11 Aug 2022 15:29:46 -0700 Subject: [PATCH 347/427] dcache: move the DCACHE_OP_COMPARE case out of the __d_lookup_rcu loop __d_lookup_rcu() is one of the hottest functions in the kernel on certain loads, and it is complicated by filesystems that might want to have their own name compare function. We can improve code generation by moving the test of DCACHE_OP_COMPARE outside the loop, which makes the loop itself much simpler, at the cost of some code duplication. But both cases end up being simpler, and the "native" direct case-sensitive compare particularly so. Cc: Al Viro Signed-off-by: Linus Torvalds --- fs/dcache.c | 72 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index c5dc32a59c769..bb0c4d0038dbd 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -2270,6 +2270,48 @@ bool d_same_name(const struct dentry *dentry, const struct dentry *parent, } EXPORT_SYMBOL_GPL(d_same_name); +/* + * This is __d_lookup_rcu() when the parent dentry has + * DCACHE_OP_COMPARE, which makes things much nastier. + */ +static noinline struct dentry *__d_lookup_rcu_op_compare( + const struct dentry *parent, + const struct qstr *name, + unsigned *seqp) +{ + u64 hashlen = name->hash_len; + struct hlist_bl_head *b = d_hash(hashlen_hash(hashlen)); + struct hlist_bl_node *node; + struct dentry *dentry; + + hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) { + int tlen; + const char *tname; + unsigned seq; + +seqretry: + seq = raw_seqcount_begin(&dentry->d_seq); + if (dentry->d_parent != parent) + continue; + if (d_unhashed(dentry)) + continue; + if (dentry->d_name.hash != hashlen_hash(hashlen)) + continue; + tlen = dentry->d_name.len; + tname = dentry->d_name.name; + /* we want a consistent (name,len) pair */ + if (read_seqcount_retry(&dentry->d_seq, seq)) { + cpu_relax(); + goto seqretry; + } + if (parent->d_op->d_compare(dentry, tlen, tname, name) != 0) + continue; + *seqp = seq; + return dentry; + } + return NULL; +} + /** * __d_lookup_rcu - search for a dentry (racy, store-free) * @parent: parent dentry @@ -2316,6 +2358,9 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent, * Keep the two functions in sync. */ + if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) + return __d_lookup_rcu_op_compare(parent, name, seqp); + /* * The hash list is protected using RCU. * @@ -2332,7 +2377,6 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent, hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) { unsigned seq; -seqretry: /* * The dentry sequence count protects us from concurrent * renames, and thus protects parent and name fields. @@ -2355,28 +2399,10 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent, continue; if (d_unhashed(dentry)) continue; - - if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) { - int tlen; - const char *tname; - if (dentry->d_name.hash != hashlen_hash(hashlen)) - continue; - tlen = dentry->d_name.len; - tname = dentry->d_name.name; - /* we want a consistent (name,len) pair */ - if (read_seqcount_retry(&dentry->d_seq, seq)) { - cpu_relax(); - goto seqretry; - } - if (parent->d_op->d_compare(dentry, - tlen, tname, name) != 0) - continue; - } else { - if (dentry->d_name.hash_len != hashlen) - continue; - if (dentry_cmp(dentry, str, hashlen_len(hashlen)) != 0) - continue; - } + if (dentry->d_name.hash_len != hashlen) + continue; + if (dentry_cmp(dentry, str, hashlen_len(hashlen)) != 0) + continue; *seqp = seq; return dentry; } From 68ed14496b032b0c9ef21b38ee45c6c8f3a18ff1 Mon Sep 17 00:00:00 2001 From: Enzo Matsumiya Date: Wed, 17 Aug 2022 14:14:02 -0300 Subject: [PATCH 348/427] cifs: remove unused server parameter from calc_smb_size() This parameter is unused by the called function Reviewed-by: Paulo Alcantara (SUSE) Signed-off-by: Enzo Matsumiya Signed-off-by: Steve French --- fs/cifs/cifs_debug.c | 2 +- fs/cifs/cifsglob.h | 2 +- fs/cifs/cifsproto.h | 2 +- fs/cifs/misc.c | 2 +- fs/cifs/netmisc.c | 2 +- fs/cifs/readdir.c | 6 ++---- fs/cifs/smb2misc.c | 4 ++-- fs/cifs/smb2ops.c | 2 +- fs/cifs/smb2proto.h | 2 +- 9 files changed, 11 insertions(+), 13 deletions(-) diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 11fd85de72179..c05477e28cffa 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -42,7 +42,7 @@ void cifs_dump_detail(void *buf, struct TCP_Server_Info *server) smb->Command, smb->Status.CifsError, smb->Flags, smb->Flags2, smb->Mid, smb->Pid); cifs_dbg(VFS, "smb buf %p len %u\n", smb, - server->ops->calc_smb_size(smb, server)); + server->ops->calc_smb_size(smb)); #endif /* CONFIG_CIFS_DEBUG2 */ } diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index bc0ee2d4b47b2..f15d7b0c123d7 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -417,7 +417,7 @@ struct smb_version_operations { int (*close_dir)(const unsigned int, struct cifs_tcon *, struct cifs_fid *); /* calculate a size of SMB message */ - unsigned int (*calc_smb_size)(void *buf, struct TCP_Server_Info *ptcpi); + unsigned int (*calc_smb_size)(void *buf); /* check for STATUS_PENDING and process the response if yes */ bool (*is_status_pending)(char *buf, struct TCP_Server_Info *server); /* check for STATUS_NETWORK_SESSION_EXPIRED */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 87a77a684339f..3bc94bcc7177e 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -151,7 +151,7 @@ extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, struct cifsFileInfo **ret_file); -extern unsigned int smbCalcSize(void *buf, struct TCP_Server_Info *server); +extern unsigned int smbCalcSize(void *buf); extern int decode_negTokenInit(unsigned char *security_blob, int length, struct TCP_Server_Info *server); extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 34d990f06fd6a..1f2628ffe9d79 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -354,7 +354,7 @@ checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server) /* otherwise, there is enough to get to the BCC */ if (check_smb_hdr(smb)) return -EIO; - clc_len = smbCalcSize(smb, server); + clc_len = smbCalcSize(smb); if (4 + rfclen != total_read) { cifs_dbg(VFS, "Length read does not match RFC1001 length %d\n", diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 28caae7aed1bb..1b52e6ac431cb 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -909,7 +909,7 @@ map_and_check_smb_error(struct mid_q_entry *mid, bool logErr) * portion, the number of word parameters and the data portion of the message */ unsigned int -smbCalcSize(void *buf, struct TCP_Server_Info *server) +smbCalcSize(void *buf) { struct smb_hdr *ptr = buf; return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 2eece8a07c112..8e060c00c9690 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -806,8 +806,7 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos, end_of_smb = cfile->srch_inf.ntwrk_buf_start + server->ops->calc_smb_size( - cfile->srch_inf.ntwrk_buf_start, - server); + cfile->srch_inf.ntwrk_buf_start); cur_ent = cfile->srch_inf.srch_entries_start; first_entry_in_buffer = cfile->srch_inf.index_of_last_entry @@ -1161,8 +1160,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n", num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); max_len = tcon->ses->server->ops->calc_smb_size( - cifsFile->srch_inf.ntwrk_buf_start, - tcon->ses->server); + cifsFile->srch_inf.ntwrk_buf_start); end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 6a6ec6efb45a9..d73e5672aac49 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c @@ -222,7 +222,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server) } } - calc_len = smb2_calc_size(buf, server); + calc_len = smb2_calc_size(buf); /* For SMB2_IOCTL, OutputOffset and OutputLength are optional, so might * be 0, and not a real miscalculation */ @@ -410,7 +410,7 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *shdr) * portion, the number of word parameters and the data portion of the message. */ unsigned int -smb2_calc_size(void *buf, struct TCP_Server_Info *srvr) +smb2_calc_size(void *buf) { struct smb2_pdu *pdu = buf; struct smb2_hdr *shdr = &pdu->hdr; diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index f406af5968877..293fdfdf374bf 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -387,7 +387,7 @@ smb2_dump_detail(void *buf, struct TCP_Server_Info *server) shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId, shdr->Id.SyncId.ProcessId); cifs_server_dbg(VFS, "smb buf %p len %u\n", buf, - server->ops->calc_smb_size(buf, server)); + server->ops->calc_smb_size(buf)); #endif } diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 51c5bf4a338ae..08f243757b9b9 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h @@ -23,7 +23,7 @@ struct smb_rqst; extern int map_smb2_to_linux_error(char *buf, bool log_err); extern int smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *server); -extern unsigned int smb2_calc_size(void *buf, struct TCP_Server_Info *server); +extern unsigned int smb2_calc_size(void *buf); extern char *smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *shdr); extern __le16 *cifs_convert_path_to_utf16(const char *from, From fc4aaf9fb3c99bcb326d52f9d320ed5680bd1cee Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 16 Aug 2022 10:34:40 +0100 Subject: [PATCH 349/427] net: Fix suspicious RCU usage in bpf_sk_reuseport_detach() bpf_sk_reuseport_detach() calls __rcu_dereference_sk_user_data_with_flags() to obtain the value of sk->sk_user_data, but that function is only usable if the RCU read lock is held, and neither that function nor any of its callers hold it. Fix this by adding a new helper, __locked_read_sk_user_data_with_flags() that checks to see if sk->sk_callback_lock() is held and use that here instead. Alternatively, making __rcu_dereference_sk_user_data_with_flags() use rcu_dereference_checked() might suffice. Without this, the following warning can be occasionally observed: ============================= WARNING: suspicious RCU usage 6.0.0-rc1-build2+ #563 Not tainted ----------------------------- include/net/sock.h:592 suspicious rcu_dereference_check() usage! other info that might help us debug this: rcu_scheduler_active = 2, debug_locks = 1 5 locks held by locktest/29873: #0: ffff88812734b550 (&sb->s_type->i_mutex_key#9){+.+.}-{3:3}, at: __sock_release+0x77/0x121 #1: ffff88812f5621b0 (sk_lock-AF_INET){+.+.}-{0:0}, at: tcp_close+0x1c/0x70 #2: ffff88810312f5c8 (&h->lhash2[i].lock){+.+.}-{2:2}, at: inet_unhash+0x76/0x1c0 #3: ffffffff83768bb8 (reuseport_lock){+...}-{2:2}, at: reuseport_detach_sock+0x18/0xdd #4: ffff88812f562438 (clock-AF_INET){++..}-{2:2}, at: bpf_sk_reuseport_detach+0x24/0xa4 stack backtrace: CPU: 1 PID: 29873 Comm: locktest Not tainted 6.0.0-rc1-build2+ #563 Hardware name: ASUS All Series/H97-PLUS, BIOS 2306 10/09/2014 Call Trace: dump_stack_lvl+0x4c/0x5f bpf_sk_reuseport_detach+0x6d/0xa4 reuseport_detach_sock+0x75/0xdd inet_unhash+0xa5/0x1c0 tcp_set_state+0x169/0x20f ? lockdep_sock_is_held+0x3a/0x3a ? __lock_release.isra.0+0x13e/0x220 ? reacquire_held_locks+0x1bb/0x1bb ? hlock_class+0x31/0x96 ? mark_lock+0x9e/0x1af __tcp_close+0x50/0x4b6 tcp_close+0x28/0x70 inet_release+0x8e/0xa7 __sock_release+0x95/0x121 sock_close+0x14/0x17 __fput+0x20f/0x36a task_work_run+0xa3/0xcc exit_to_user_mode_prepare+0x9c/0x14d syscall_exit_to_user_mode+0x18/0x44 entry_SYSCALL_64_after_hwframe+0x63/0xcd Fixes: cf8c1e967224 ("net: refactor bpf_sk_reuseport_detach()") Signed-off-by: David Howells cc: Hawkins Jiawei Link: https://lore.kernel.org/r/166064248071.3502205.10036394558814861778.stgit@warthog.procyon.org.uk Signed-off-by: Jakub Kicinski --- include/net/sock.h | 25 +++++++++++++++++++++++++ kernel/bpf/reuseport_array.c | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/include/net/sock.h b/include/net/sock.h index 05a1bbdf58054..d08cfe190a78b 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -577,6 +577,31 @@ static inline bool sk_user_data_is_nocopy(const struct sock *sk) #define __sk_user_data(sk) ((*((void __rcu **)&(sk)->sk_user_data))) +/** + * __locked_read_sk_user_data_with_flags - return the pointer + * only if argument flags all has been set in sk_user_data. Otherwise + * return NULL + * + * @sk: socket + * @flags: flag bits + * + * The caller must be holding sk->sk_callback_lock. + */ +static inline void * +__locked_read_sk_user_data_with_flags(const struct sock *sk, + uintptr_t flags) +{ + uintptr_t sk_user_data = + (uintptr_t)rcu_dereference_check(__sk_user_data(sk), + lockdep_is_held(&sk->sk_callback_lock)); + + WARN_ON_ONCE(flags & SK_USER_DATA_PTRMASK); + + if ((sk_user_data & flags) == flags) + return (void *)(sk_user_data & SK_USER_DATA_PTRMASK); + return NULL; +} + /** * __rcu_dereference_sk_user_data_with_flags - return the pointer * only if argument flags all has been set in sk_user_data. Otherwise diff --git a/kernel/bpf/reuseport_array.c b/kernel/bpf/reuseport_array.c index 85fa9dbfa8bf8..82c61612f382a 100644 --- a/kernel/bpf/reuseport_array.c +++ b/kernel/bpf/reuseport_array.c @@ -24,7 +24,7 @@ void bpf_sk_reuseport_detach(struct sock *sk) struct sock __rcu **socks; write_lock_bh(&sk->sk_callback_lock); - socks = __rcu_dereference_sk_user_data_with_flags(sk, SK_USER_DATA_BPF); + socks = __locked_read_sk_user_data_with_flags(sk, SK_USER_DATA_BPF); if (socks) { WRITE_ONCE(sk->sk_user_data, NULL); /* From 400d0ad63b190895e29f43bc75b1260111d3fd34 Mon Sep 17 00:00:00 2001 From: Enzo Matsumiya Date: Wed, 17 Aug 2022 16:08:34 -0300 Subject: [PATCH 350/427] cifs: remove useless parameter 'is_fsctl' from SMB2_ioctl() SMB2_ioctl() is always called with is_fsctl = true, so doesn't make any sense to have it at all. Thus, always set SMB2_0_IOCTL_IS_FSCTL flag on the request. Also, as per MS-SMB2 3.3.5.15 "Receiving an SMB2 IOCTL Request", servers must fail the request if the request flags is zero anyway. Signed-off-by: Enzo Matsumiya Reviewed-by: Tom Talpey Signed-off-by: Steve French --- fs/cifs/smb2file.c | 1 - fs/cifs/smb2ops.c | 35 +++++++++++++---------------------- fs/cifs/smb2pdu.c | 20 +++++++++----------- fs/cifs/smb2proto.h | 4 ++-- 4 files changed, 24 insertions(+), 36 deletions(-) diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c index f5dcc4940b6da..9dfd2dd612c25 100644 --- a/fs/cifs/smb2file.c +++ b/fs/cifs/smb2file.c @@ -61,7 +61,6 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, nr_ioctl_req.Reserved = 0; rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid, fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY, - true /* is_fsctl */, (char *)&nr_ioctl_req, sizeof(nr_ioctl_req), CIFSMaxBufSize, NULL, NULL /* no return info */); if (rc == -EOPNOTSUPP) { diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 293fdfdf374bf..96f3b0573606e 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -681,7 +681,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon) struct cifs_ses *ses = tcon->ses; rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, - FSCTL_QUERY_NETWORK_INTERFACE_INFO, true /* is_fsctl */, + FSCTL_QUERY_NETWORK_INTERFACE_INFO, NULL /* no data input */, 0 /* no data input */, CIFSMaxBufSize, (char **)&out_buf, &ret_data_len); if (rc == -EOPNOTSUPP) { @@ -1323,9 +1323,8 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon, struct resume_key_req *res_key; rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid, - FSCTL_SRV_REQUEST_RESUME_KEY, true /* is_fsctl */, - NULL, 0 /* no input */, CIFSMaxBufSize, - (char **)&res_key, &ret_data_len); + FSCTL_SRV_REQUEST_RESUME_KEY, NULL, 0 /* no input */, + CIFSMaxBufSize, (char **)&res_key, &ret_data_len); if (rc == -EOPNOTSUPP) { pr_warn_once("Server share %s does not support copy range\n", tcon->treeName); @@ -1467,7 +1466,7 @@ smb2_ioctl_query_info(const unsigned int xid, rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE; rc = SMB2_ioctl_init(tcon, server, &rqst[1], COMPOUND_FID, COMPOUND_FID, - qi.info_type, true, buffer, qi.output_buffer_length, + qi.info_type, buffer, qi.output_buffer_length, CIFSMaxBufSize - MAX_SMB2_CREATE_RESPONSE_SIZE - MAX_SMB2_CLOSE_RESPONSE_SIZE); free_req1_func = SMB2_ioctl_free; @@ -1643,9 +1642,8 @@ smb2_copychunk_range(const unsigned int xid, retbuf = NULL; rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid, trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE, - true /* is_fsctl */, (char *)pcchunk, - sizeof(struct copychunk_ioctl), CIFSMaxBufSize, - (char **)&retbuf, &ret_data_len); + (char *)pcchunk, sizeof(struct copychunk_ioctl), + CIFSMaxBufSize, (char **)&retbuf, &ret_data_len); if (rc == 0) { if (ret_data_len != sizeof(struct copychunk_ioctl_rsp)) { @@ -1805,7 +1803,6 @@ static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon, rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, cfile->fid.volatile_fid, FSCTL_SET_SPARSE, - true /* is_fctl */, &setsparse, 1, CIFSMaxBufSize, NULL, NULL); if (rc) { tcon->broken_sparse_sup = true; @@ -1888,7 +1885,6 @@ smb2_duplicate_extents(const unsigned int xid, rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid, trgtfile->fid.volatile_fid, FSCTL_DUPLICATE_EXTENTS_TO_FILE, - true /* is_fsctl */, (char *)&dup_ext_buf, sizeof(struct duplicate_extents_to_file), CIFSMaxBufSize, NULL, @@ -1923,7 +1919,6 @@ smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon, return SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, cfile->fid.volatile_fid, FSCTL_SET_INTEGRITY_INFORMATION, - true /* is_fsctl */, (char *)&integr_info, sizeof(struct fsctl_set_integrity_information_req), CIFSMaxBufSize, NULL, @@ -1976,7 +1971,6 @@ smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon, rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, cfile->fid.volatile_fid, FSCTL_SRV_ENUMERATE_SNAPSHOTS, - true /* is_fsctl */, NULL, 0 /* no input data */, max_response_size, (char **)&retbuf, &ret_data_len); @@ -2699,7 +2693,6 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, do { rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, FSCTL_DFS_GET_REFERRALS, - true /* is_fsctl */, (char *)dfs_req, dfs_req_size, CIFSMaxBufSize, (char **)&dfs_rsp, &dfs_rsp_size); if (!is_retryable_error(rc)) @@ -2906,8 +2899,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, rc = SMB2_ioctl_init(tcon, server, &rqst[1], fid.persistent_fid, - fid.volatile_fid, FSCTL_GET_REPARSE_POINT, - true /* is_fctl */, NULL, 0, + fid.volatile_fid, FSCTL_GET_REPARSE_POINT, NULL, 0, CIFSMaxBufSize - MAX_SMB2_CREATE_RESPONSE_SIZE - MAX_SMB2_CLOSE_RESPONSE_SIZE); @@ -3087,8 +3079,7 @@ smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon, rc = SMB2_ioctl_init(tcon, server, &rqst[1], COMPOUND_FID, - COMPOUND_FID, FSCTL_GET_REPARSE_POINT, - true /* is_fctl */, NULL, 0, + COMPOUND_FID, FSCTL_GET_REPARSE_POINT, NULL, 0, CIFSMaxBufSize - MAX_SMB2_CREATE_RESPONSE_SIZE - MAX_SMB2_CLOSE_RESPONSE_SIZE); @@ -3358,7 +3349,7 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len); rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, - cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA, true, + cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA, (char *)&fsctl_buf, sizeof(struct file_zero_data_information), 0, NULL, NULL); @@ -3421,7 +3412,7 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA, - true /* is_fctl */, (char *)&fsctl_buf, + (char *)&fsctl_buf, sizeof(struct file_zero_data_information), CIFSMaxBufSize, NULL, NULL); free_xid(xid); @@ -3481,7 +3472,7 @@ static int smb3_simple_fallocate_range(unsigned int xid, in_data.length = cpu_to_le64(len); rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, cfile->fid.volatile_fid, - FSCTL_QUERY_ALLOCATED_RANGES, true, + FSCTL_QUERY_ALLOCATED_RANGES, (char *)&in_data, sizeof(in_data), 1024 * sizeof(struct file_allocated_range_buffer), (char **)&out_data, &out_data_len); @@ -3802,7 +3793,7 @@ static loff_t smb3_llseek(struct file *file, struct cifs_tcon *tcon, loff_t offs rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, cfile->fid.volatile_fid, - FSCTL_QUERY_ALLOCATED_RANGES, true, + FSCTL_QUERY_ALLOCATED_RANGES, (char *)&in_data, sizeof(in_data), sizeof(struct file_allocated_range_buffer), (char **)&out_data, &out_data_len); @@ -3862,7 +3853,7 @@ static int smb3_fiemap(struct cifs_tcon *tcon, rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, cfile->fid.volatile_fid, - FSCTL_QUERY_ALLOCATED_RANGES, true, + FSCTL_QUERY_ALLOCATED_RANGES, (char *)&in_data, sizeof(in_data), 1024 * sizeof(struct file_allocated_range_buffer), (char **)&out_data, &out_data_len); diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 9b31ea946d454..918152fb8582b 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -1173,7 +1173,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) } rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, - FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */, + FSCTL_VALIDATE_NEGOTIATE_INFO, (char *)pneg_inbuf, inbuflen, CIFSMaxBufSize, (char **)&pneg_rsp, &rsplen); if (rc == -EOPNOTSUPP) { @@ -3056,7 +3056,7 @@ int SMB2_ioctl_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, struct smb_rqst *rqst, u64 persistent_fid, u64 volatile_fid, u32 opcode, - bool is_fsctl, char *in_data, u32 indatalen, + char *in_data, u32 indatalen, __u32 max_response_size) { struct smb2_ioctl_req *req; @@ -3131,10 +3131,8 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, req->hdr.CreditCharge = cpu_to_le16(DIV_ROUND_UP(max(indatalen, max_response_size), SMB2_MAX_BUFFER_SIZE)); - if (is_fsctl) - req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL); - else - req->Flags = 0; + /* always an FSCTL (for now) */ + req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL); /* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */ if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) @@ -3161,9 +3159,9 @@ SMB2_ioctl_free(struct smb_rqst *rqst) */ int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, - u64 volatile_fid, u32 opcode, bool is_fsctl, - char *in_data, u32 indatalen, u32 max_out_data_len, - char **out_data, u32 *plen /* returned data len */) + u64 volatile_fid, u32 opcode, char *in_data, u32 indatalen, + u32 max_out_data_len, char **out_data, + u32 *plen /* returned data len */) { struct smb_rqst rqst; struct smb2_ioctl_rsp *rsp = NULL; @@ -3205,7 +3203,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, rc = SMB2_ioctl_init(tcon, server, &rqst, persistent_fid, volatile_fid, opcode, - is_fsctl, in_data, indatalen, max_out_data_len); + in_data, indatalen, max_out_data_len); if (rc) goto ioctl_exit; @@ -3297,7 +3295,7 @@ SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, cpu_to_le16(COMPRESSION_FORMAT_DEFAULT); rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid, - FSCTL_SET_COMPRESSION, true /* is_fsctl */, + FSCTL_SET_COMPRESSION, (char *)&fsctl_input /* data input */, 2 /* in data len */, CIFSMaxBufSize /* max out data */, &ret_data /* out data */, NULL); diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 08f243757b9b9..3f740f24b96a7 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h @@ -137,13 +137,13 @@ extern int SMB2_open_init(struct cifs_tcon *tcon, extern void SMB2_open_free(struct smb_rqst *rqst); extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, u32 opcode, - bool is_fsctl, char *in_data, u32 indatalen, u32 maxoutlen, + char *in_data, u32 indatalen, u32 maxoutlen, char **out_data, u32 *plen /* returned data len */); extern int SMB2_ioctl_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, struct smb_rqst *rqst, u64 persistent_fid, u64 volatile_fid, u32 opcode, - bool is_fsctl, char *in_data, u32 indatalen, + char *in_data, u32 indatalen, __u32 max_response_size); extern void SMB2_ioctl_free(struct smb_rqst *rqst); extern int SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon, From fd8e899cdb5ecaf8e8ee73854a99e10807eef1de Mon Sep 17 00:00:00 2001 From: Rustam Subkhankulov Date: Wed, 17 Aug 2022 03:38:45 +0300 Subject: [PATCH 351/427] net: dsa: sja1105: fix buffer overflow in sja1105_setup_devlink_regions() If an error occurs in dsa_devlink_region_create(), then 'priv->regions' array will be accessed by negative index '-1'. Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Rustam Subkhankulov Fixes: bf425b82059e ("net: dsa: sja1105: expose static config as devlink region") Link: https://lore.kernel.org/r/20220817003845.389644-1-subkhankulov@ispras.ru Signed-off-by: Jakub Kicinski --- drivers/net/dsa/sja1105/sja1105_devlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/dsa/sja1105/sja1105_devlink.c b/drivers/net/dsa/sja1105/sja1105_devlink.c index 0569ff066634d..10c6fea1227fa 100644 --- a/drivers/net/dsa/sja1105/sja1105_devlink.c +++ b/drivers/net/dsa/sja1105/sja1105_devlink.c @@ -93,7 +93,7 @@ static int sja1105_setup_devlink_regions(struct dsa_switch *ds) region = dsa_devlink_region_create(ds, ops, 1, size); if (IS_ERR(region)) { - while (i-- >= 0) + while (--i >= 0) dsa_devlink_region_destroy(priv->regions[i]); return PTR_ERR(region); } From 211987f3ac734000ea1548784b2a4539a974fbc8 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 16 Aug 2022 23:14:45 +0300 Subject: [PATCH 352/427] net: dsa: don't warn in dsa_port_set_state_now() when driver doesn't support it ds->ops->port_stp_state_set() is, like most DSA methods, optional, and if absent, the port is supposed to remain in the forwarding state (as standalone). Such is the case with the mv88e6060 driver, which does not offload the bridge layer. DSA warns that the STP state can't be changed to FORWARDING as part of dsa_port_enable_rt(), when in fact it should not. The error message is also not up to modern standards, so take the opportunity to make it more descriptive. Fixes: fd3645413197 ("net: dsa: change scope of STP state setter") Reported-by: Sergei Antonov Signed-off-by: Vladimir Oltean Reviewed-by: Sergei Antonov Link: https://lore.kernel.org/r/20220816201445.1809483-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- net/dsa/port.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/dsa/port.c b/net/dsa/port.c index 2dd76eb1621c7..a8895ee3cd600 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -145,11 +145,14 @@ int dsa_port_set_state(struct dsa_port *dp, u8 state, bool do_fast_age) static void dsa_port_set_state_now(struct dsa_port *dp, u8 state, bool do_fast_age) { + struct dsa_switch *ds = dp->ds; int err; err = dsa_port_set_state(dp, state, do_fast_age); - if (err) - pr_err("DSA: failed to set STP state %u (%d)\n", state, err); + if (err && err != -EOPNOTSUPP) { + dev_err(ds->dev, "port %d failed to set STP state %u: %pe\n", + dp->index, state, ERR_PTR(err)); + } } int dsa_port_set_mst_state(struct dsa_port *dp, From 40d21c4565bce064c73a03b79a157a3493c518b9 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 16 Aug 2022 16:53:45 +0300 Subject: [PATCH 353/427] net: dsa: felix: fix ethtool 256-511 and 512-1023 TX packet counters What the driver actually reports as 256-511 is in fact 512-1023, and the TX packets in the 256-511 bucket are not reported. Fix that. Fixes: 56051948773e ("net: dsa: ocelot: add driver for Felix switch family") Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/dsa/ocelot/felix_vsc9959.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index b4034b78c0ca7..5859ef3b242c0 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -602,7 +602,8 @@ static const struct ocelot_stat_layout vsc9959_stats_layout[] = { { .offset = 0x87, .name = "tx_frames_below_65_octets", }, { .offset = 0x88, .name = "tx_frames_65_to_127_octets", }, { .offset = 0x89, .name = "tx_frames_128_255_octets", }, - { .offset = 0x8B, .name = "tx_frames_256_511_octets", }, + { .offset = 0x8A, .name = "tx_frames_256_511_octets", }, + { .offset = 0x8B, .name = "tx_frames_512_1023_octets", }, { .offset = 0x8C, .name = "tx_frames_1024_1526_octets", }, { .offset = 0x8D, .name = "tx_frames_over_1526_octets", }, { .offset = 0x8E, .name = "tx_yellow_prio_0", }, From 5152de7b79ab0be150f5966481b0c8f996192531 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 16 Aug 2022 16:53:46 +0300 Subject: [PATCH 354/427] net: mscc: ocelot: fix incorrect ndo_get_stats64 packet counters Reading stats using the SYS_COUNT_* register definitions is only used by ocelot_get_stats64() from the ocelot switchdev driver, however, currently the bucket definitions are incorrect. Separately, on both RX and TX, we have the following problems: - a 256-1023 bucket which actually tracks the 256-511 packets - the 1024-1526 bucket actually tracks the 512-1023 packets - the 1527-max bucket actually tracks the 1024-1526 packets => nobody tracks the packets from the real 1527-max bucket Additionally, the RX_PAUSE, RX_CONTROL, RX_LONGS and RX_CLASSIFIED_DROPS all track the wrong thing. However this doesn't seem to have any consequence, since ocelot_get_stats64() doesn't use these. Even though this problem only manifests itself for the switchdev driver, we cannot split the fix for ocelot and for DSA, since it requires fixing the bucket definitions from enum ocelot_reg, which makes us necessarily adapt the structures from felix and seville as well. Fixes: 84705fc16552 ("net: dsa: felix: introduce support for Seville VSC9953 switch") Fixes: 56051948773e ("net: dsa: ocelot: add driver for Felix switch family") Fixes: a556c76adc05 ("net: mscc: Add initial Ocelot switch support") Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/dsa/ocelot/felix_vsc9959.c | 20 ++++++++++++-------- drivers/net/dsa/ocelot/seville_vsc9953.c | 16 +++++++++------- drivers/net/ethernet/mscc/ocelot_net.c | 6 ++++-- drivers/net/ethernet/mscc/vsc7514_regs.c | 24 +++++++++++++----------- include/soc/mscc/ocelot.h | 6 ++++-- 5 files changed, 42 insertions(+), 30 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index 5859ef3b242c0..e1ebe21cad007 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -281,19 +281,23 @@ static const u32 vsc9959_sys_regmap[] = { REG(SYS_COUNT_RX_64, 0x000024), REG(SYS_COUNT_RX_65_127, 0x000028), REG(SYS_COUNT_RX_128_255, 0x00002c), - REG(SYS_COUNT_RX_256_1023, 0x000030), - REG(SYS_COUNT_RX_1024_1526, 0x000034), - REG(SYS_COUNT_RX_1527_MAX, 0x000038), - REG(SYS_COUNT_RX_LONGS, 0x000044), + REG(SYS_COUNT_RX_256_511, 0x000030), + REG(SYS_COUNT_RX_512_1023, 0x000034), + REG(SYS_COUNT_RX_1024_1526, 0x000038), + REG(SYS_COUNT_RX_1527_MAX, 0x00003c), + REG(SYS_COUNT_RX_PAUSE, 0x000040), + REG(SYS_COUNT_RX_CONTROL, 0x000044), + REG(SYS_COUNT_RX_LONGS, 0x000048), REG(SYS_COUNT_TX_OCTETS, 0x000200), REG(SYS_COUNT_TX_COLLISION, 0x000210), REG(SYS_COUNT_TX_DROPS, 0x000214), REG(SYS_COUNT_TX_64, 0x00021c), REG(SYS_COUNT_TX_65_127, 0x000220), - REG(SYS_COUNT_TX_128_511, 0x000224), - REG(SYS_COUNT_TX_512_1023, 0x000228), - REG(SYS_COUNT_TX_1024_1526, 0x00022c), - REG(SYS_COUNT_TX_1527_MAX, 0x000230), + REG(SYS_COUNT_TX_128_255, 0x000224), + REG(SYS_COUNT_TX_256_511, 0x000228), + REG(SYS_COUNT_TX_512_1023, 0x00022c), + REG(SYS_COUNT_TX_1024_1526, 0x000230), + REG(SYS_COUNT_TX_1527_MAX, 0x000234), REG(SYS_COUNT_TX_AGING, 0x000278), REG(SYS_RESET_CFG, 0x000e00), REG(SYS_SR_ETYPE_CFG, 0x000e04), diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index ea06492113568..ebe9ddbbe2b77 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -277,19 +277,21 @@ static const u32 vsc9953_sys_regmap[] = { REG(SYS_COUNT_RX_64, 0x000024), REG(SYS_COUNT_RX_65_127, 0x000028), REG(SYS_COUNT_RX_128_255, 0x00002c), - REG(SYS_COUNT_RX_256_1023, 0x000030), - REG(SYS_COUNT_RX_1024_1526, 0x000034), - REG(SYS_COUNT_RX_1527_MAX, 0x000038), + REG(SYS_COUNT_RX_256_511, 0x000030), + REG(SYS_COUNT_RX_512_1023, 0x000034), + REG(SYS_COUNT_RX_1024_1526, 0x000038), + REG(SYS_COUNT_RX_1527_MAX, 0x00003c), REG(SYS_COUNT_RX_LONGS, 0x000048), REG(SYS_COUNT_TX_OCTETS, 0x000100), REG(SYS_COUNT_TX_COLLISION, 0x000110), REG(SYS_COUNT_TX_DROPS, 0x000114), REG(SYS_COUNT_TX_64, 0x00011c), REG(SYS_COUNT_TX_65_127, 0x000120), - REG(SYS_COUNT_TX_128_511, 0x000124), - REG(SYS_COUNT_TX_512_1023, 0x000128), - REG(SYS_COUNT_TX_1024_1526, 0x00012c), - REG(SYS_COUNT_TX_1527_MAX, 0x000130), + REG(SYS_COUNT_TX_128_255, 0x000124), + REG(SYS_COUNT_TX_256_511, 0x000128), + REG(SYS_COUNT_TX_512_1023, 0x00012c), + REG(SYS_COUNT_TX_1024_1526, 0x000130), + REG(SYS_COUNT_TX_1527_MAX, 0x000134), REG(SYS_COUNT_TX_AGING, 0x000178), REG(SYS_RESET_CFG, 0x000318), REG_RESERVED(SYS_SR_ETYPE_CFG), diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index 5e6136e80282b..9d8cea16245ef 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -739,7 +739,8 @@ static void ocelot_get_stats64(struct net_device *dev, ocelot_read(ocelot, SYS_COUNT_RX_64) + ocelot_read(ocelot, SYS_COUNT_RX_65_127) + ocelot_read(ocelot, SYS_COUNT_RX_128_255) + - ocelot_read(ocelot, SYS_COUNT_RX_256_1023) + + ocelot_read(ocelot, SYS_COUNT_RX_256_511) + + ocelot_read(ocelot, SYS_COUNT_RX_512_1023) + ocelot_read(ocelot, SYS_COUNT_RX_1024_1526) + ocelot_read(ocelot, SYS_COUNT_RX_1527_MAX); stats->multicast = ocelot_read(ocelot, SYS_COUNT_RX_MULTICAST); @@ -749,7 +750,8 @@ static void ocelot_get_stats64(struct net_device *dev, stats->tx_bytes = ocelot_read(ocelot, SYS_COUNT_TX_OCTETS); stats->tx_packets = ocelot_read(ocelot, SYS_COUNT_TX_64) + ocelot_read(ocelot, SYS_COUNT_TX_65_127) + - ocelot_read(ocelot, SYS_COUNT_TX_128_511) + + ocelot_read(ocelot, SYS_COUNT_TX_128_255) + + ocelot_read(ocelot, SYS_COUNT_TX_256_511) + ocelot_read(ocelot, SYS_COUNT_TX_512_1023) + ocelot_read(ocelot, SYS_COUNT_TX_1024_1526) + ocelot_read(ocelot, SYS_COUNT_TX_1527_MAX); diff --git a/drivers/net/ethernet/mscc/vsc7514_regs.c b/drivers/net/ethernet/mscc/vsc7514_regs.c index c2af4eb8ca5d3..38ab20b48cd43 100644 --- a/drivers/net/ethernet/mscc/vsc7514_regs.c +++ b/drivers/net/ethernet/mscc/vsc7514_regs.c @@ -180,13 +180,14 @@ const u32 vsc7514_sys_regmap[] = { REG(SYS_COUNT_RX_64, 0x000024), REG(SYS_COUNT_RX_65_127, 0x000028), REG(SYS_COUNT_RX_128_255, 0x00002c), - REG(SYS_COUNT_RX_256_1023, 0x000030), - REG(SYS_COUNT_RX_1024_1526, 0x000034), - REG(SYS_COUNT_RX_1527_MAX, 0x000038), - REG(SYS_COUNT_RX_PAUSE, 0x00003c), - REG(SYS_COUNT_RX_CONTROL, 0x000040), - REG(SYS_COUNT_RX_LONGS, 0x000044), - REG(SYS_COUNT_RX_CLASSIFIED_DROPS, 0x000048), + REG(SYS_COUNT_RX_256_511, 0x000030), + REG(SYS_COUNT_RX_512_1023, 0x000034), + REG(SYS_COUNT_RX_1024_1526, 0x000038), + REG(SYS_COUNT_RX_1527_MAX, 0x00003c), + REG(SYS_COUNT_RX_PAUSE, 0x000040), + REG(SYS_COUNT_RX_CONTROL, 0x000044), + REG(SYS_COUNT_RX_LONGS, 0x000048), + REG(SYS_COUNT_RX_CLASSIFIED_DROPS, 0x00004c), REG(SYS_COUNT_TX_OCTETS, 0x000100), REG(SYS_COUNT_TX_UNICAST, 0x000104), REG(SYS_COUNT_TX_MULTICAST, 0x000108), @@ -196,10 +197,11 @@ const u32 vsc7514_sys_regmap[] = { REG(SYS_COUNT_TX_PAUSE, 0x000118), REG(SYS_COUNT_TX_64, 0x00011c), REG(SYS_COUNT_TX_65_127, 0x000120), - REG(SYS_COUNT_TX_128_511, 0x000124), - REG(SYS_COUNT_TX_512_1023, 0x000128), - REG(SYS_COUNT_TX_1024_1526, 0x00012c), - REG(SYS_COUNT_TX_1527_MAX, 0x000130), + REG(SYS_COUNT_TX_128_255, 0x000124), + REG(SYS_COUNT_TX_256_511, 0x000128), + REG(SYS_COUNT_TX_512_1023, 0x00012c), + REG(SYS_COUNT_TX_1024_1526, 0x000130), + REG(SYS_COUNT_TX_1527_MAX, 0x000134), REG(SYS_COUNT_TX_AGING, 0x000170), REG(SYS_RESET_CFG, 0x000508), REG(SYS_CMID, 0x00050c), diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index ac151ecc7f19f..e7e5b06deb2d8 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -335,7 +335,8 @@ enum ocelot_reg { SYS_COUNT_RX_64, SYS_COUNT_RX_65_127, SYS_COUNT_RX_128_255, - SYS_COUNT_RX_256_1023, + SYS_COUNT_RX_256_511, + SYS_COUNT_RX_512_1023, SYS_COUNT_RX_1024_1526, SYS_COUNT_RX_1527_MAX, SYS_COUNT_RX_PAUSE, @@ -351,7 +352,8 @@ enum ocelot_reg { SYS_COUNT_TX_PAUSE, SYS_COUNT_TX_64, SYS_COUNT_TX_65_127, - SYS_COUNT_TX_128_511, + SYS_COUNT_TX_128_255, + SYS_COUNT_TX_256_511, SYS_COUNT_TX_512_1023, SYS_COUNT_TX_1024_1526, SYS_COUNT_TX_1527_MAX, From 173ca86618d751bd183456c9cdbb69952ba283c8 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 16 Aug 2022 16:53:47 +0300 Subject: [PATCH 355/427] net: mscc: ocelot: fix address of SYS_COUNT_TX_AGING counter This register, used as part of stats->tx_dropped in ocelot_get_stats64(), has a wrong address. At the address currently given, there is actually the c_tx_green_prio_6 counter. Fixes: a556c76adc05 ("net: mscc: Add initial Ocelot switch support") Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mscc/vsc7514_regs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mscc/vsc7514_regs.c b/drivers/net/ethernet/mscc/vsc7514_regs.c index 38ab20b48cd43..8ff935f7f150c 100644 --- a/drivers/net/ethernet/mscc/vsc7514_regs.c +++ b/drivers/net/ethernet/mscc/vsc7514_regs.c @@ -202,7 +202,7 @@ const u32 vsc7514_sys_regmap[] = { REG(SYS_COUNT_TX_512_1023, 0x00012c), REG(SYS_COUNT_TX_1024_1526, 0x000130), REG(SYS_COUNT_TX_1527_MAX, 0x000134), - REG(SYS_COUNT_TX_AGING, 0x000170), + REG(SYS_COUNT_TX_AGING, 0x000178), REG(SYS_RESET_CFG, 0x000508), REG(SYS_CMID, 0x00050c), REG(SYS_VLAN_ETYPE_CFG, 0x000510), From 22d842e3efe56402c33b5e6e303bb71ce9bf9334 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 16 Aug 2022 16:53:48 +0300 Subject: [PATCH 356/427] net: mscc: ocelot: turn stats_lock into a spinlock ocelot_get_stats64() currently runs unlocked and therefore may collide with ocelot_port_update_stats() which indirectly accesses the same counters. However, ocelot_get_stats64() runs in atomic context, and we cannot simply take the sleepable ocelot->stats_lock mutex. We need to convert it to an atomic spinlock first. Do that as a preparatory change. Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/dsa/ocelot/felix_vsc9959.c | 4 ++-- drivers/net/ethernet/mscc/ocelot.c | 11 +++++------ include/soc/mscc/ocelot.h | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index e1ebe21cad007..46fd6cd0d8f3d 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -2171,7 +2171,7 @@ static void vsc9959_psfp_sgi_table_del(struct ocelot *ocelot, static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index, struct felix_stream_filter_counters *counters) { - mutex_lock(&ocelot->stats_lock); + spin_lock(&ocelot->stats_lock); ocelot_rmw(ocelot, SYS_STAT_CFG_STAT_VIEW(index), SYS_STAT_CFG_STAT_VIEW_M, @@ -2188,7 +2188,7 @@ static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index, SYS_STAT_CFG_STAT_CLEAR_SHOT(0x10), SYS_STAT_CFG); - mutex_unlock(&ocelot->stats_lock); + spin_unlock(&ocelot->stats_lock); } static int vsc9959_psfp_filter_add(struct ocelot *ocelot, int port, diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index d4649e4ee0e7f..c67f162f8ab5e 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1906,13 +1906,13 @@ static void ocelot_check_stats_work(struct work_struct *work) stats_work); int i, err; - mutex_lock(&ocelot->stats_lock); + spin_lock(&ocelot->stats_lock); for (i = 0; i < ocelot->num_phys_ports; i++) { err = ocelot_port_update_stats(ocelot, i); if (err) break; } - mutex_unlock(&ocelot->stats_lock); + spin_unlock(&ocelot->stats_lock); if (err) dev_err(ocelot->dev, "Error %d updating ethtool stats\n", err); @@ -1925,7 +1925,7 @@ void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data) { int i, err; - mutex_lock(&ocelot->stats_lock); + spin_lock(&ocelot->stats_lock); /* check and update now */ err = ocelot_port_update_stats(ocelot, port); @@ -1934,7 +1934,7 @@ void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data) for (i = 0; i < ocelot->num_stats; i++) *data++ = ocelot->stats[port * ocelot->num_stats + i]; - mutex_unlock(&ocelot->stats_lock); + spin_unlock(&ocelot->stats_lock); if (err) dev_err(ocelot->dev, "Error %d updating ethtool stats\n", err); @@ -3363,7 +3363,7 @@ int ocelot_init(struct ocelot *ocelot) if (!ocelot->stats) return -ENOMEM; - mutex_init(&ocelot->stats_lock); + spin_lock_init(&ocelot->stats_lock); mutex_init(&ocelot->ptp_lock); mutex_init(&ocelot->mact_lock); mutex_init(&ocelot->fwd_domain_lock); @@ -3511,7 +3511,6 @@ void ocelot_deinit(struct ocelot *ocelot) cancel_delayed_work(&ocelot->stats_work); destroy_workqueue(ocelot->stats_queue); destroy_workqueue(ocelot->owq); - mutex_destroy(&ocelot->stats_lock); } EXPORT_SYMBOL(ocelot_deinit); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index e7e5b06deb2d8..72b9474391da3 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -752,7 +752,7 @@ struct ocelot { struct ocelot_psfp_list psfp; /* Workqueue to check statistics for overflow with its lock */ - struct mutex stats_lock; + spinlock_t stats_lock; u64 *stats; struct delayed_work stats_work; struct workqueue_struct *stats_queue; From 18d8e67df184081bc6ce6220a2dd965cfd3d7e6b Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 16 Aug 2022 16:53:49 +0300 Subject: [PATCH 357/427] net: mscc: ocelot: fix race between ndo_get_stats64 and ocelot_check_stats_work The 2 methods can run concurrently, and one will change the window of counters (SYS_STAT_CFG_STAT_VIEW) that the other sees. The fix is similar to what commit 7fbf6795d127 ("net: mscc: ocelot: fix mutex lock error during ethtool stats read") has done for ethtool -S. Fixes: a556c76adc05 ("net: mscc: Add initial Ocelot switch support") Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mscc/ocelot_net.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index 9d8cea16245ef..6b9d371388441 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -726,6 +726,8 @@ static void ocelot_get_stats64(struct net_device *dev, struct ocelot *ocelot = priv->port.ocelot; int port = priv->port.index; + spin_lock(&ocelot->stats_lock); + /* Configure the port to read the stats from */ ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port), SYS_STAT_CFG); @@ -758,6 +760,8 @@ static void ocelot_get_stats64(struct net_device *dev, stats->tx_dropped = ocelot_read(ocelot, SYS_COUNT_TX_DROPS) + ocelot_read(ocelot, SYS_COUNT_TX_AGING); stats->collisions = ocelot_read(ocelot, SYS_COUNT_TX_COLLISION); + + spin_unlock(&ocelot->stats_lock); } static int ocelot_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], From 9190460084ddd0e9235f55eab0fdd5456b5f2fd5 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 16 Aug 2022 16:53:50 +0300 Subject: [PATCH 358/427] net: mscc: ocelot: make struct ocelot_stat_layout array indexable The ocelot counters are 32-bit and require periodic reading, every 2 seconds, by ocelot_port_update_stats(), so that wraparounds are detected. Currently, the counters reported by ocelot_get_stats64() come from the 32-bit hardware counters directly, rather than from the 64-bit accumulated ocelot->stats, and this is a problem for their integrity. The strategy is to make ocelot_get_stats64() able to cherry-pick individual stats from ocelot->stats the way in which it currently reads them out from SYS_COUNT_* registers. But currently it can't, because ocelot->stats is an opaque u64 array that's used only to feed data into ethtool -S. To solve that problem, we need to make ocelot->stats indexable, and associate each element with an element of struct ocelot_stat_layout used by ethtool -S. This makes ocelot_stat_layout a fat (and possibly sparse) array, so we need to change the way in which we access it. We no longer need OCELOT_STAT_END as a sentinel, because we know the array's size (OCELOT_NUM_STATS). We just need to skip the array elements that were left unpopulated for the switch revision (ocelot, felix, seville). Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/dsa/ocelot/felix_vsc9959.c | 468 ++++++++++++++++----- drivers/net/dsa/ocelot/seville_vsc9953.c | 468 ++++++++++++++++----- drivers/net/ethernet/mscc/ocelot.c | 40 +- drivers/net/ethernet/mscc/ocelot_vsc7514.c | 468 ++++++++++++++++----- include/soc/mscc/ocelot.h | 105 ++++- 5 files changed, 1243 insertions(+), 306 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index 46fd6cd0d8f3d..c9f270f24b1c7 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -551,101 +551,379 @@ static const struct reg_field vsc9959_regfields[REGFIELD_MAX] = { [SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 7, 4), }; -static const struct ocelot_stat_layout vsc9959_stats_layout[] = { - { .offset = 0x00, .name = "rx_octets", }, - { .offset = 0x01, .name = "rx_unicast", }, - { .offset = 0x02, .name = "rx_multicast", }, - { .offset = 0x03, .name = "rx_broadcast", }, - { .offset = 0x04, .name = "rx_shorts", }, - { .offset = 0x05, .name = "rx_fragments", }, - { .offset = 0x06, .name = "rx_jabbers", }, - { .offset = 0x07, .name = "rx_crc_align_errs", }, - { .offset = 0x08, .name = "rx_sym_errs", }, - { .offset = 0x09, .name = "rx_frames_below_65_octets", }, - { .offset = 0x0A, .name = "rx_frames_65_to_127_octets", }, - { .offset = 0x0B, .name = "rx_frames_128_to_255_octets", }, - { .offset = 0x0C, .name = "rx_frames_256_to_511_octets", }, - { .offset = 0x0D, .name = "rx_frames_512_to_1023_octets", }, - { .offset = 0x0E, .name = "rx_frames_1024_to_1526_octets", }, - { .offset = 0x0F, .name = "rx_frames_over_1526_octets", }, - { .offset = 0x10, .name = "rx_pause", }, - { .offset = 0x11, .name = "rx_control", }, - { .offset = 0x12, .name = "rx_longs", }, - { .offset = 0x13, .name = "rx_classified_drops", }, - { .offset = 0x14, .name = "rx_red_prio_0", }, - { .offset = 0x15, .name = "rx_red_prio_1", }, - { .offset = 0x16, .name = "rx_red_prio_2", }, - { .offset = 0x17, .name = "rx_red_prio_3", }, - { .offset = 0x18, .name = "rx_red_prio_4", }, - { .offset = 0x19, .name = "rx_red_prio_5", }, - { .offset = 0x1A, .name = "rx_red_prio_6", }, - { .offset = 0x1B, .name = "rx_red_prio_7", }, - { .offset = 0x1C, .name = "rx_yellow_prio_0", }, - { .offset = 0x1D, .name = "rx_yellow_prio_1", }, - { .offset = 0x1E, .name = "rx_yellow_prio_2", }, - { .offset = 0x1F, .name = "rx_yellow_prio_3", }, - { .offset = 0x20, .name = "rx_yellow_prio_4", }, - { .offset = 0x21, .name = "rx_yellow_prio_5", }, - { .offset = 0x22, .name = "rx_yellow_prio_6", }, - { .offset = 0x23, .name = "rx_yellow_prio_7", }, - { .offset = 0x24, .name = "rx_green_prio_0", }, - { .offset = 0x25, .name = "rx_green_prio_1", }, - { .offset = 0x26, .name = "rx_green_prio_2", }, - { .offset = 0x27, .name = "rx_green_prio_3", }, - { .offset = 0x28, .name = "rx_green_prio_4", }, - { .offset = 0x29, .name = "rx_green_prio_5", }, - { .offset = 0x2A, .name = "rx_green_prio_6", }, - { .offset = 0x2B, .name = "rx_green_prio_7", }, - { .offset = 0x80, .name = "tx_octets", }, - { .offset = 0x81, .name = "tx_unicast", }, - { .offset = 0x82, .name = "tx_multicast", }, - { .offset = 0x83, .name = "tx_broadcast", }, - { .offset = 0x84, .name = "tx_collision", }, - { .offset = 0x85, .name = "tx_drops", }, - { .offset = 0x86, .name = "tx_pause", }, - { .offset = 0x87, .name = "tx_frames_below_65_octets", }, - { .offset = 0x88, .name = "tx_frames_65_to_127_octets", }, - { .offset = 0x89, .name = "tx_frames_128_255_octets", }, - { .offset = 0x8A, .name = "tx_frames_256_511_octets", }, - { .offset = 0x8B, .name = "tx_frames_512_1023_octets", }, - { .offset = 0x8C, .name = "tx_frames_1024_1526_octets", }, - { .offset = 0x8D, .name = "tx_frames_over_1526_octets", }, - { .offset = 0x8E, .name = "tx_yellow_prio_0", }, - { .offset = 0x8F, .name = "tx_yellow_prio_1", }, - { .offset = 0x90, .name = "tx_yellow_prio_2", }, - { .offset = 0x91, .name = "tx_yellow_prio_3", }, - { .offset = 0x92, .name = "tx_yellow_prio_4", }, - { .offset = 0x93, .name = "tx_yellow_prio_5", }, - { .offset = 0x94, .name = "tx_yellow_prio_6", }, - { .offset = 0x95, .name = "tx_yellow_prio_7", }, - { .offset = 0x96, .name = "tx_green_prio_0", }, - { .offset = 0x97, .name = "tx_green_prio_1", }, - { .offset = 0x98, .name = "tx_green_prio_2", }, - { .offset = 0x99, .name = "tx_green_prio_3", }, - { .offset = 0x9A, .name = "tx_green_prio_4", }, - { .offset = 0x9B, .name = "tx_green_prio_5", }, - { .offset = 0x9C, .name = "tx_green_prio_6", }, - { .offset = 0x9D, .name = "tx_green_prio_7", }, - { .offset = 0x9E, .name = "tx_aged", }, - { .offset = 0x100, .name = "drop_local", }, - { .offset = 0x101, .name = "drop_tail", }, - { .offset = 0x102, .name = "drop_yellow_prio_0", }, - { .offset = 0x103, .name = "drop_yellow_prio_1", }, - { .offset = 0x104, .name = "drop_yellow_prio_2", }, - { .offset = 0x105, .name = "drop_yellow_prio_3", }, - { .offset = 0x106, .name = "drop_yellow_prio_4", }, - { .offset = 0x107, .name = "drop_yellow_prio_5", }, - { .offset = 0x108, .name = "drop_yellow_prio_6", }, - { .offset = 0x109, .name = "drop_yellow_prio_7", }, - { .offset = 0x10A, .name = "drop_green_prio_0", }, - { .offset = 0x10B, .name = "drop_green_prio_1", }, - { .offset = 0x10C, .name = "drop_green_prio_2", }, - { .offset = 0x10D, .name = "drop_green_prio_3", }, - { .offset = 0x10E, .name = "drop_green_prio_4", }, - { .offset = 0x10F, .name = "drop_green_prio_5", }, - { .offset = 0x110, .name = "drop_green_prio_6", }, - { .offset = 0x111, .name = "drop_green_prio_7", }, - OCELOT_STAT_END +static const struct ocelot_stat_layout vsc9959_stats_layout[OCELOT_NUM_STATS] = { + [OCELOT_STAT_RX_OCTETS] = { + .name = "rx_octets", + .offset = 0x00, + }, + [OCELOT_STAT_RX_UNICAST] = { + .name = "rx_unicast", + .offset = 0x01, + }, + [OCELOT_STAT_RX_MULTICAST] = { + .name = "rx_multicast", + .offset = 0x02, + }, + [OCELOT_STAT_RX_BROADCAST] = { + .name = "rx_broadcast", + .offset = 0x03, + }, + [OCELOT_STAT_RX_SHORTS] = { + .name = "rx_shorts", + .offset = 0x04, + }, + [OCELOT_STAT_RX_FRAGMENTS] = { + .name = "rx_fragments", + .offset = 0x05, + }, + [OCELOT_STAT_RX_JABBERS] = { + .name = "rx_jabbers", + .offset = 0x06, + }, + [OCELOT_STAT_RX_CRC_ALIGN_ERRS] = { + .name = "rx_crc_align_errs", + .offset = 0x07, + }, + [OCELOT_STAT_RX_SYM_ERRS] = { + .name = "rx_sym_errs", + .offset = 0x08, + }, + [OCELOT_STAT_RX_64] = { + .name = "rx_frames_below_65_octets", + .offset = 0x09, + }, + [OCELOT_STAT_RX_65_127] = { + .name = "rx_frames_65_to_127_octets", + .offset = 0x0A, + }, + [OCELOT_STAT_RX_128_255] = { + .name = "rx_frames_128_to_255_octets", + .offset = 0x0B, + }, + [OCELOT_STAT_RX_256_511] = { + .name = "rx_frames_256_to_511_octets", + .offset = 0x0C, + }, + [OCELOT_STAT_RX_512_1023] = { + .name = "rx_frames_512_to_1023_octets", + .offset = 0x0D, + }, + [OCELOT_STAT_RX_1024_1526] = { + .name = "rx_frames_1024_to_1526_octets", + .offset = 0x0E, + }, + [OCELOT_STAT_RX_1527_MAX] = { + .name = "rx_frames_over_1526_octets", + .offset = 0x0F, + }, + [OCELOT_STAT_RX_PAUSE] = { + .name = "rx_pause", + .offset = 0x10, + }, + [OCELOT_STAT_RX_CONTROL] = { + .name = "rx_control", + .offset = 0x11, + }, + [OCELOT_STAT_RX_LONGS] = { + .name = "rx_longs", + .offset = 0x12, + }, + [OCELOT_STAT_RX_CLASSIFIED_DROPS] = { + .name = "rx_classified_drops", + .offset = 0x13, + }, + [OCELOT_STAT_RX_RED_PRIO_0] = { + .name = "rx_red_prio_0", + .offset = 0x14, + }, + [OCELOT_STAT_RX_RED_PRIO_1] = { + .name = "rx_red_prio_1", + .offset = 0x15, + }, + [OCELOT_STAT_RX_RED_PRIO_2] = { + .name = "rx_red_prio_2", + .offset = 0x16, + }, + [OCELOT_STAT_RX_RED_PRIO_3] = { + .name = "rx_red_prio_3", + .offset = 0x17, + }, + [OCELOT_STAT_RX_RED_PRIO_4] = { + .name = "rx_red_prio_4", + .offset = 0x18, + }, + [OCELOT_STAT_RX_RED_PRIO_5] = { + .name = "rx_red_prio_5", + .offset = 0x19, + }, + [OCELOT_STAT_RX_RED_PRIO_6] = { + .name = "rx_red_prio_6", + .offset = 0x1A, + }, + [OCELOT_STAT_RX_RED_PRIO_7] = { + .name = "rx_red_prio_7", + .offset = 0x1B, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_0] = { + .name = "rx_yellow_prio_0", + .offset = 0x1C, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_1] = { + .name = "rx_yellow_prio_1", + .offset = 0x1D, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_2] = { + .name = "rx_yellow_prio_2", + .offset = 0x1E, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_3] = { + .name = "rx_yellow_prio_3", + .offset = 0x1F, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_4] = { + .name = "rx_yellow_prio_4", + .offset = 0x20, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_5] = { + .name = "rx_yellow_prio_5", + .offset = 0x21, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_6] = { + .name = "rx_yellow_prio_6", + .offset = 0x22, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_7] = { + .name = "rx_yellow_prio_7", + .offset = 0x23, + }, + [OCELOT_STAT_RX_GREEN_PRIO_0] = { + .name = "rx_green_prio_0", + .offset = 0x24, + }, + [OCELOT_STAT_RX_GREEN_PRIO_1] = { + .name = "rx_green_prio_1", + .offset = 0x25, + }, + [OCELOT_STAT_RX_GREEN_PRIO_2] = { + .name = "rx_green_prio_2", + .offset = 0x26, + }, + [OCELOT_STAT_RX_GREEN_PRIO_3] = { + .name = "rx_green_prio_3", + .offset = 0x27, + }, + [OCELOT_STAT_RX_GREEN_PRIO_4] = { + .name = "rx_green_prio_4", + .offset = 0x28, + }, + [OCELOT_STAT_RX_GREEN_PRIO_5] = { + .name = "rx_green_prio_5", + .offset = 0x29, + }, + [OCELOT_STAT_RX_GREEN_PRIO_6] = { + .name = "rx_green_prio_6", + .offset = 0x2A, + }, + [OCELOT_STAT_RX_GREEN_PRIO_7] = { + .name = "rx_green_prio_7", + .offset = 0x2B, + }, + [OCELOT_STAT_TX_OCTETS] = { + .name = "tx_octets", + .offset = 0x80, + }, + [OCELOT_STAT_TX_UNICAST] = { + .name = "tx_unicast", + .offset = 0x81, + }, + [OCELOT_STAT_TX_MULTICAST] = { + .name = "tx_multicast", + .offset = 0x82, + }, + [OCELOT_STAT_TX_BROADCAST] = { + .name = "tx_broadcast", + .offset = 0x83, + }, + [OCELOT_STAT_TX_COLLISION] = { + .name = "tx_collision", + .offset = 0x84, + }, + [OCELOT_STAT_TX_DROPS] = { + .name = "tx_drops", + .offset = 0x85, + }, + [OCELOT_STAT_TX_PAUSE] = { + .name = "tx_pause", + .offset = 0x86, + }, + [OCELOT_STAT_TX_64] = { + .name = "tx_frames_below_65_octets", + .offset = 0x87, + }, + [OCELOT_STAT_TX_65_127] = { + .name = "tx_frames_65_to_127_octets", + .offset = 0x88, + }, + [OCELOT_STAT_TX_128_255] = { + .name = "tx_frames_128_255_octets", + .offset = 0x89, + }, + [OCELOT_STAT_TX_256_511] = { + .name = "tx_frames_256_511_octets", + .offset = 0x8A, + }, + [OCELOT_STAT_TX_512_1023] = { + .name = "tx_frames_512_1023_octets", + .offset = 0x8B, + }, + [OCELOT_STAT_TX_1024_1526] = { + .name = "tx_frames_1024_1526_octets", + .offset = 0x8C, + }, + [OCELOT_STAT_TX_1527_MAX] = { + .name = "tx_frames_over_1526_octets", + .offset = 0x8D, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_0] = { + .name = "tx_yellow_prio_0", + .offset = 0x8E, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_1] = { + .name = "tx_yellow_prio_1", + .offset = 0x8F, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_2] = { + .name = "tx_yellow_prio_2", + .offset = 0x90, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_3] = { + .name = "tx_yellow_prio_3", + .offset = 0x91, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_4] = { + .name = "tx_yellow_prio_4", + .offset = 0x92, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_5] = { + .name = "tx_yellow_prio_5", + .offset = 0x93, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_6] = { + .name = "tx_yellow_prio_6", + .offset = 0x94, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_7] = { + .name = "tx_yellow_prio_7", + .offset = 0x95, + }, + [OCELOT_STAT_TX_GREEN_PRIO_0] = { + .name = "tx_green_prio_0", + .offset = 0x96, + }, + [OCELOT_STAT_TX_GREEN_PRIO_1] = { + .name = "tx_green_prio_1", + .offset = 0x97, + }, + [OCELOT_STAT_TX_GREEN_PRIO_2] = { + .name = "tx_green_prio_2", + .offset = 0x98, + }, + [OCELOT_STAT_TX_GREEN_PRIO_3] = { + .name = "tx_green_prio_3", + .offset = 0x99, + }, + [OCELOT_STAT_TX_GREEN_PRIO_4] = { + .name = "tx_green_prio_4", + .offset = 0x9A, + }, + [OCELOT_STAT_TX_GREEN_PRIO_5] = { + .name = "tx_green_prio_5", + .offset = 0x9B, + }, + [OCELOT_STAT_TX_GREEN_PRIO_6] = { + .name = "tx_green_prio_6", + .offset = 0x9C, + }, + [OCELOT_STAT_TX_GREEN_PRIO_7] = { + .name = "tx_green_prio_7", + .offset = 0x9D, + }, + [OCELOT_STAT_TX_AGED] = { + .name = "tx_aged", + .offset = 0x9E, + }, + [OCELOT_STAT_DROP_LOCAL] = { + .name = "drop_local", + .offset = 0x100, + }, + [OCELOT_STAT_DROP_TAIL] = { + .name = "drop_tail", + .offset = 0x101, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_0] = { + .name = "drop_yellow_prio_0", + .offset = 0x102, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_1] = { + .name = "drop_yellow_prio_1", + .offset = 0x103, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_2] = { + .name = "drop_yellow_prio_2", + .offset = 0x104, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_3] = { + .name = "drop_yellow_prio_3", + .offset = 0x105, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_4] = { + .name = "drop_yellow_prio_4", + .offset = 0x106, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_5] = { + .name = "drop_yellow_prio_5", + .offset = 0x107, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_6] = { + .name = "drop_yellow_prio_6", + .offset = 0x108, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_7] = { + .name = "drop_yellow_prio_7", + .offset = 0x109, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_0] = { + .name = "drop_green_prio_0", + .offset = 0x10A, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_1] = { + .name = "drop_green_prio_1", + .offset = 0x10B, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_2] = { + .name = "drop_green_prio_2", + .offset = 0x10C, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_3] = { + .name = "drop_green_prio_3", + .offset = 0x10D, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_4] = { + .name = "drop_green_prio_4", + .offset = 0x10E, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_5] = { + .name = "drop_green_prio_5", + .offset = 0x10F, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_6] = { + .name = "drop_green_prio_6", + .offset = 0x110, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_7] = { + .name = "drop_green_prio_7", + .offset = 0x111, + }, }; static const struct vcap_field vsc9959_vcap_es0_keys[] = { diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index ebe9ddbbe2b77..fe5d4642d0bcb 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -545,101 +545,379 @@ static const struct reg_field vsc9953_regfields[REGFIELD_MAX] = { [SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 11, 4), }; -static const struct ocelot_stat_layout vsc9953_stats_layout[] = { - { .offset = 0x00, .name = "rx_octets", }, - { .offset = 0x01, .name = "rx_unicast", }, - { .offset = 0x02, .name = "rx_multicast", }, - { .offset = 0x03, .name = "rx_broadcast", }, - { .offset = 0x04, .name = "rx_shorts", }, - { .offset = 0x05, .name = "rx_fragments", }, - { .offset = 0x06, .name = "rx_jabbers", }, - { .offset = 0x07, .name = "rx_crc_align_errs", }, - { .offset = 0x08, .name = "rx_sym_errs", }, - { .offset = 0x09, .name = "rx_frames_below_65_octets", }, - { .offset = 0x0A, .name = "rx_frames_65_to_127_octets", }, - { .offset = 0x0B, .name = "rx_frames_128_to_255_octets", }, - { .offset = 0x0C, .name = "rx_frames_256_to_511_octets", }, - { .offset = 0x0D, .name = "rx_frames_512_to_1023_octets", }, - { .offset = 0x0E, .name = "rx_frames_1024_to_1526_octets", }, - { .offset = 0x0F, .name = "rx_frames_over_1526_octets", }, - { .offset = 0x10, .name = "rx_pause", }, - { .offset = 0x11, .name = "rx_control", }, - { .offset = 0x12, .name = "rx_longs", }, - { .offset = 0x13, .name = "rx_classified_drops", }, - { .offset = 0x14, .name = "rx_red_prio_0", }, - { .offset = 0x15, .name = "rx_red_prio_1", }, - { .offset = 0x16, .name = "rx_red_prio_2", }, - { .offset = 0x17, .name = "rx_red_prio_3", }, - { .offset = 0x18, .name = "rx_red_prio_4", }, - { .offset = 0x19, .name = "rx_red_prio_5", }, - { .offset = 0x1A, .name = "rx_red_prio_6", }, - { .offset = 0x1B, .name = "rx_red_prio_7", }, - { .offset = 0x1C, .name = "rx_yellow_prio_0", }, - { .offset = 0x1D, .name = "rx_yellow_prio_1", }, - { .offset = 0x1E, .name = "rx_yellow_prio_2", }, - { .offset = 0x1F, .name = "rx_yellow_prio_3", }, - { .offset = 0x20, .name = "rx_yellow_prio_4", }, - { .offset = 0x21, .name = "rx_yellow_prio_5", }, - { .offset = 0x22, .name = "rx_yellow_prio_6", }, - { .offset = 0x23, .name = "rx_yellow_prio_7", }, - { .offset = 0x24, .name = "rx_green_prio_0", }, - { .offset = 0x25, .name = "rx_green_prio_1", }, - { .offset = 0x26, .name = "rx_green_prio_2", }, - { .offset = 0x27, .name = "rx_green_prio_3", }, - { .offset = 0x28, .name = "rx_green_prio_4", }, - { .offset = 0x29, .name = "rx_green_prio_5", }, - { .offset = 0x2A, .name = "rx_green_prio_6", }, - { .offset = 0x2B, .name = "rx_green_prio_7", }, - { .offset = 0x40, .name = "tx_octets", }, - { .offset = 0x41, .name = "tx_unicast", }, - { .offset = 0x42, .name = "tx_multicast", }, - { .offset = 0x43, .name = "tx_broadcast", }, - { .offset = 0x44, .name = "tx_collision", }, - { .offset = 0x45, .name = "tx_drops", }, - { .offset = 0x46, .name = "tx_pause", }, - { .offset = 0x47, .name = "tx_frames_below_65_octets", }, - { .offset = 0x48, .name = "tx_frames_65_to_127_octets", }, - { .offset = 0x49, .name = "tx_frames_128_255_octets", }, - { .offset = 0x4A, .name = "tx_frames_256_511_octets", }, - { .offset = 0x4B, .name = "tx_frames_512_1023_octets", }, - { .offset = 0x4C, .name = "tx_frames_1024_1526_octets", }, - { .offset = 0x4D, .name = "tx_frames_over_1526_octets", }, - { .offset = 0x4E, .name = "tx_yellow_prio_0", }, - { .offset = 0x4F, .name = "tx_yellow_prio_1", }, - { .offset = 0x50, .name = "tx_yellow_prio_2", }, - { .offset = 0x51, .name = "tx_yellow_prio_3", }, - { .offset = 0x52, .name = "tx_yellow_prio_4", }, - { .offset = 0x53, .name = "tx_yellow_prio_5", }, - { .offset = 0x54, .name = "tx_yellow_prio_6", }, - { .offset = 0x55, .name = "tx_yellow_prio_7", }, - { .offset = 0x56, .name = "tx_green_prio_0", }, - { .offset = 0x57, .name = "tx_green_prio_1", }, - { .offset = 0x58, .name = "tx_green_prio_2", }, - { .offset = 0x59, .name = "tx_green_prio_3", }, - { .offset = 0x5A, .name = "tx_green_prio_4", }, - { .offset = 0x5B, .name = "tx_green_prio_5", }, - { .offset = 0x5C, .name = "tx_green_prio_6", }, - { .offset = 0x5D, .name = "tx_green_prio_7", }, - { .offset = 0x5E, .name = "tx_aged", }, - { .offset = 0x80, .name = "drop_local", }, - { .offset = 0x81, .name = "drop_tail", }, - { .offset = 0x82, .name = "drop_yellow_prio_0", }, - { .offset = 0x83, .name = "drop_yellow_prio_1", }, - { .offset = 0x84, .name = "drop_yellow_prio_2", }, - { .offset = 0x85, .name = "drop_yellow_prio_3", }, - { .offset = 0x86, .name = "drop_yellow_prio_4", }, - { .offset = 0x87, .name = "drop_yellow_prio_5", }, - { .offset = 0x88, .name = "drop_yellow_prio_6", }, - { .offset = 0x89, .name = "drop_yellow_prio_7", }, - { .offset = 0x8A, .name = "drop_green_prio_0", }, - { .offset = 0x8B, .name = "drop_green_prio_1", }, - { .offset = 0x8C, .name = "drop_green_prio_2", }, - { .offset = 0x8D, .name = "drop_green_prio_3", }, - { .offset = 0x8E, .name = "drop_green_prio_4", }, - { .offset = 0x8F, .name = "drop_green_prio_5", }, - { .offset = 0x90, .name = "drop_green_prio_6", }, - { .offset = 0x91, .name = "drop_green_prio_7", }, - OCELOT_STAT_END +static const struct ocelot_stat_layout vsc9953_stats_layout[OCELOT_NUM_STATS] = { + [OCELOT_STAT_RX_OCTETS] = { + .name = "rx_octets", + .offset = 0x00, + }, + [OCELOT_STAT_RX_UNICAST] = { + .name = "rx_unicast", + .offset = 0x01, + }, + [OCELOT_STAT_RX_MULTICAST] = { + .name = "rx_multicast", + .offset = 0x02, + }, + [OCELOT_STAT_RX_BROADCAST] = { + .name = "rx_broadcast", + .offset = 0x03, + }, + [OCELOT_STAT_RX_SHORTS] = { + .name = "rx_shorts", + .offset = 0x04, + }, + [OCELOT_STAT_RX_FRAGMENTS] = { + .name = "rx_fragments", + .offset = 0x05, + }, + [OCELOT_STAT_RX_JABBERS] = { + .name = "rx_jabbers", + .offset = 0x06, + }, + [OCELOT_STAT_RX_CRC_ALIGN_ERRS] = { + .name = "rx_crc_align_errs", + .offset = 0x07, + }, + [OCELOT_STAT_RX_SYM_ERRS] = { + .name = "rx_sym_errs", + .offset = 0x08, + }, + [OCELOT_STAT_RX_64] = { + .name = "rx_frames_below_65_octets", + .offset = 0x09, + }, + [OCELOT_STAT_RX_65_127] = { + .name = "rx_frames_65_to_127_octets", + .offset = 0x0A, + }, + [OCELOT_STAT_RX_128_255] = { + .name = "rx_frames_128_to_255_octets", + .offset = 0x0B, + }, + [OCELOT_STAT_RX_256_511] = { + .name = "rx_frames_256_to_511_octets", + .offset = 0x0C, + }, + [OCELOT_STAT_RX_512_1023] = { + .name = "rx_frames_512_to_1023_octets", + .offset = 0x0D, + }, + [OCELOT_STAT_RX_1024_1526] = { + .name = "rx_frames_1024_to_1526_octets", + .offset = 0x0E, + }, + [OCELOT_STAT_RX_1527_MAX] = { + .name = "rx_frames_over_1526_octets", + .offset = 0x0F, + }, + [OCELOT_STAT_RX_PAUSE] = { + .name = "rx_pause", + .offset = 0x10, + }, + [OCELOT_STAT_RX_CONTROL] = { + .name = "rx_control", + .offset = 0x11, + }, + [OCELOT_STAT_RX_LONGS] = { + .name = "rx_longs", + .offset = 0x12, + }, + [OCELOT_STAT_RX_CLASSIFIED_DROPS] = { + .name = "rx_classified_drops", + .offset = 0x13, + }, + [OCELOT_STAT_RX_RED_PRIO_0] = { + .name = "rx_red_prio_0", + .offset = 0x14, + }, + [OCELOT_STAT_RX_RED_PRIO_1] = { + .name = "rx_red_prio_1", + .offset = 0x15, + }, + [OCELOT_STAT_RX_RED_PRIO_2] = { + .name = "rx_red_prio_2", + .offset = 0x16, + }, + [OCELOT_STAT_RX_RED_PRIO_3] = { + .name = "rx_red_prio_3", + .offset = 0x17, + }, + [OCELOT_STAT_RX_RED_PRIO_4] = { + .name = "rx_red_prio_4", + .offset = 0x18, + }, + [OCELOT_STAT_RX_RED_PRIO_5] = { + .name = "rx_red_prio_5", + .offset = 0x19, + }, + [OCELOT_STAT_RX_RED_PRIO_6] = { + .name = "rx_red_prio_6", + .offset = 0x1A, + }, + [OCELOT_STAT_RX_RED_PRIO_7] = { + .name = "rx_red_prio_7", + .offset = 0x1B, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_0] = { + .name = "rx_yellow_prio_0", + .offset = 0x1C, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_1] = { + .name = "rx_yellow_prio_1", + .offset = 0x1D, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_2] = { + .name = "rx_yellow_prio_2", + .offset = 0x1E, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_3] = { + .name = "rx_yellow_prio_3", + .offset = 0x1F, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_4] = { + .name = "rx_yellow_prio_4", + .offset = 0x20, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_5] = { + .name = "rx_yellow_prio_5", + .offset = 0x21, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_6] = { + .name = "rx_yellow_prio_6", + .offset = 0x22, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_7] = { + .name = "rx_yellow_prio_7", + .offset = 0x23, + }, + [OCELOT_STAT_RX_GREEN_PRIO_0] = { + .name = "rx_green_prio_0", + .offset = 0x24, + }, + [OCELOT_STAT_RX_GREEN_PRIO_1] = { + .name = "rx_green_prio_1", + .offset = 0x25, + }, + [OCELOT_STAT_RX_GREEN_PRIO_2] = { + .name = "rx_green_prio_2", + .offset = 0x26, + }, + [OCELOT_STAT_RX_GREEN_PRIO_3] = { + .name = "rx_green_prio_3", + .offset = 0x27, + }, + [OCELOT_STAT_RX_GREEN_PRIO_4] = { + .name = "rx_green_prio_4", + .offset = 0x28, + }, + [OCELOT_STAT_RX_GREEN_PRIO_5] = { + .name = "rx_green_prio_5", + .offset = 0x29, + }, + [OCELOT_STAT_RX_GREEN_PRIO_6] = { + .name = "rx_green_prio_6", + .offset = 0x2A, + }, + [OCELOT_STAT_RX_GREEN_PRIO_7] = { + .name = "rx_green_prio_7", + .offset = 0x2B, + }, + [OCELOT_STAT_TX_OCTETS] = { + .name = "tx_octets", + .offset = 0x40, + }, + [OCELOT_STAT_TX_UNICAST] = { + .name = "tx_unicast", + .offset = 0x41, + }, + [OCELOT_STAT_TX_MULTICAST] = { + .name = "tx_multicast", + .offset = 0x42, + }, + [OCELOT_STAT_TX_BROADCAST] = { + .name = "tx_broadcast", + .offset = 0x43, + }, + [OCELOT_STAT_TX_COLLISION] = { + .name = "tx_collision", + .offset = 0x44, + }, + [OCELOT_STAT_TX_DROPS] = { + .name = "tx_drops", + .offset = 0x45, + }, + [OCELOT_STAT_TX_PAUSE] = { + .name = "tx_pause", + .offset = 0x46, + }, + [OCELOT_STAT_TX_64] = { + .name = "tx_frames_below_65_octets", + .offset = 0x47, + }, + [OCELOT_STAT_TX_65_127] = { + .name = "tx_frames_65_to_127_octets", + .offset = 0x48, + }, + [OCELOT_STAT_TX_128_255] = { + .name = "tx_frames_128_255_octets", + .offset = 0x49, + }, + [OCELOT_STAT_TX_256_511] = { + .name = "tx_frames_256_511_octets", + .offset = 0x4A, + }, + [OCELOT_STAT_TX_512_1023] = { + .name = "tx_frames_512_1023_octets", + .offset = 0x4B, + }, + [OCELOT_STAT_TX_1024_1526] = { + .name = "tx_frames_1024_1526_octets", + .offset = 0x4C, + }, + [OCELOT_STAT_TX_1527_MAX] = { + .name = "tx_frames_over_1526_octets", + .offset = 0x4D, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_0] = { + .name = "tx_yellow_prio_0", + .offset = 0x4E, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_1] = { + .name = "tx_yellow_prio_1", + .offset = 0x4F, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_2] = { + .name = "tx_yellow_prio_2", + .offset = 0x50, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_3] = { + .name = "tx_yellow_prio_3", + .offset = 0x51, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_4] = { + .name = "tx_yellow_prio_4", + .offset = 0x52, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_5] = { + .name = "tx_yellow_prio_5", + .offset = 0x53, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_6] = { + .name = "tx_yellow_prio_6", + .offset = 0x54, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_7] = { + .name = "tx_yellow_prio_7", + .offset = 0x55, + }, + [OCELOT_STAT_TX_GREEN_PRIO_0] = { + .name = "tx_green_prio_0", + .offset = 0x56, + }, + [OCELOT_STAT_TX_GREEN_PRIO_1] = { + .name = "tx_green_prio_1", + .offset = 0x57, + }, + [OCELOT_STAT_TX_GREEN_PRIO_2] = { + .name = "tx_green_prio_2", + .offset = 0x58, + }, + [OCELOT_STAT_TX_GREEN_PRIO_3] = { + .name = "tx_green_prio_3", + .offset = 0x59, + }, + [OCELOT_STAT_TX_GREEN_PRIO_4] = { + .name = "tx_green_prio_4", + .offset = 0x5A, + }, + [OCELOT_STAT_TX_GREEN_PRIO_5] = { + .name = "tx_green_prio_5", + .offset = 0x5B, + }, + [OCELOT_STAT_TX_GREEN_PRIO_6] = { + .name = "tx_green_prio_6", + .offset = 0x5C, + }, + [OCELOT_STAT_TX_GREEN_PRIO_7] = { + .name = "tx_green_prio_7", + .offset = 0x5D, + }, + [OCELOT_STAT_TX_AGED] = { + .name = "tx_aged", + .offset = 0x5E, + }, + [OCELOT_STAT_DROP_LOCAL] = { + .name = "drop_local", + .offset = 0x80, + }, + [OCELOT_STAT_DROP_TAIL] = { + .name = "drop_tail", + .offset = 0x81, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_0] = { + .name = "drop_yellow_prio_0", + .offset = 0x82, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_1] = { + .name = "drop_yellow_prio_1", + .offset = 0x83, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_2] = { + .name = "drop_yellow_prio_2", + .offset = 0x84, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_3] = { + .name = "drop_yellow_prio_3", + .offset = 0x85, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_4] = { + .name = "drop_yellow_prio_4", + .offset = 0x86, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_5] = { + .name = "drop_yellow_prio_5", + .offset = 0x87, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_6] = { + .name = "drop_yellow_prio_6", + .offset = 0x88, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_7] = { + .name = "drop_yellow_prio_7", + .offset = 0x89, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_0] = { + .name = "drop_green_prio_0", + .offset = 0x8A, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_1] = { + .name = "drop_green_prio_1", + .offset = 0x8B, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_2] = { + .name = "drop_green_prio_2", + .offset = 0x8C, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_3] = { + .name = "drop_green_prio_3", + .offset = 0x8D, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_4] = { + .name = "drop_green_prio_4", + .offset = 0x8E, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_5] = { + .name = "drop_green_prio_5", + .offset = 0x8F, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_6] = { + .name = "drop_green_prio_6", + .offset = 0x90, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_7] = { + .name = "drop_green_prio_7", + .offset = 0x91, + }, }; static const struct vcap_field vsc9953_vcap_es0_keys[] = { diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index c67f162f8ab5e..68991b021c560 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1860,16 +1860,20 @@ void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data) if (sset != ETH_SS_STATS) return; - for (i = 0; i < ocelot->num_stats; i++) + for (i = 0; i < OCELOT_NUM_STATS; i++) { + if (ocelot->stats_layout[i].name[0] == '\0') + continue; + memcpy(data + i * ETH_GSTRING_LEN, ocelot->stats_layout[i].name, ETH_GSTRING_LEN); + } } EXPORT_SYMBOL(ocelot_get_strings); /* Caller must hold &ocelot->stats_lock */ static int ocelot_port_update_stats(struct ocelot *ocelot, int port) { - unsigned int idx = port * ocelot->num_stats; + unsigned int idx = port * OCELOT_NUM_STATS; struct ocelot_stats_region *region; int err, j; @@ -1930,9 +1934,15 @@ void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data) /* check and update now */ err = ocelot_port_update_stats(ocelot, port); - /* Copy all counters */ - for (i = 0; i < ocelot->num_stats; i++) - *data++ = ocelot->stats[port * ocelot->num_stats + i]; + /* Copy all supported counters */ + for (i = 0; i < OCELOT_NUM_STATS; i++) { + int index = port * OCELOT_NUM_STATS + i; + + if (ocelot->stats_layout[i].name[0] == '\0') + continue; + + *data++ = ocelot->stats[index]; + } spin_unlock(&ocelot->stats_lock); @@ -1943,10 +1953,16 @@ EXPORT_SYMBOL(ocelot_get_ethtool_stats); int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset) { + int i, num_stats = 0; + if (sset != ETH_SS_STATS) return -EOPNOTSUPP; - return ocelot->num_stats; + for (i = 0; i < OCELOT_NUM_STATS; i++) + if (ocelot->stats_layout[i].name[0] != '\0') + num_stats++; + + return num_stats; } EXPORT_SYMBOL(ocelot_get_sset_count); @@ -1958,7 +1974,10 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot) INIT_LIST_HEAD(&ocelot->stats_regions); - for (i = 0; i < ocelot->num_stats; i++) { + for (i = 0; i < OCELOT_NUM_STATS; i++) { + if (ocelot->stats_layout[i].name[0] == '\0') + continue; + if (region && ocelot->stats_layout[i].offset == last + 1) { region->count++; } else { @@ -3340,7 +3359,6 @@ static void ocelot_detect_features(struct ocelot *ocelot) int ocelot_init(struct ocelot *ocelot) { - const struct ocelot_stat_layout *stat; char queue_name[32]; int i, ret; u32 port; @@ -3353,12 +3371,8 @@ int ocelot_init(struct ocelot *ocelot) } } - ocelot->num_stats = 0; - for_each_stat(ocelot, stat) - ocelot->num_stats++; - ocelot->stats = devm_kcalloc(ocelot->dev, - ocelot->num_phys_ports * ocelot->num_stats, + ocelot->num_phys_ports * OCELOT_NUM_STATS, sizeof(u64), GFP_KERNEL); if (!ocelot->stats) return -ENOMEM; diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 961f803aca192..9ff9105600438 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -96,101 +96,379 @@ static const struct reg_field ocelot_regfields[REGFIELD_MAX] = { [SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 12, 4), }; -static const struct ocelot_stat_layout ocelot_stats_layout[] = { - { .name = "rx_octets", .offset = 0x00, }, - { .name = "rx_unicast", .offset = 0x01, }, - { .name = "rx_multicast", .offset = 0x02, }, - { .name = "rx_broadcast", .offset = 0x03, }, - { .name = "rx_shorts", .offset = 0x04, }, - { .name = "rx_fragments", .offset = 0x05, }, - { .name = "rx_jabbers", .offset = 0x06, }, - { .name = "rx_crc_align_errs", .offset = 0x07, }, - { .name = "rx_sym_errs", .offset = 0x08, }, - { .name = "rx_frames_below_65_octets", .offset = 0x09, }, - { .name = "rx_frames_65_to_127_octets", .offset = 0x0A, }, - { .name = "rx_frames_128_to_255_octets", .offset = 0x0B, }, - { .name = "rx_frames_256_to_511_octets", .offset = 0x0C, }, - { .name = "rx_frames_512_to_1023_octets", .offset = 0x0D, }, - { .name = "rx_frames_1024_to_1526_octets", .offset = 0x0E, }, - { .name = "rx_frames_over_1526_octets", .offset = 0x0F, }, - { .name = "rx_pause", .offset = 0x10, }, - { .name = "rx_control", .offset = 0x11, }, - { .name = "rx_longs", .offset = 0x12, }, - { .name = "rx_classified_drops", .offset = 0x13, }, - { .name = "rx_red_prio_0", .offset = 0x14, }, - { .name = "rx_red_prio_1", .offset = 0x15, }, - { .name = "rx_red_prio_2", .offset = 0x16, }, - { .name = "rx_red_prio_3", .offset = 0x17, }, - { .name = "rx_red_prio_4", .offset = 0x18, }, - { .name = "rx_red_prio_5", .offset = 0x19, }, - { .name = "rx_red_prio_6", .offset = 0x1A, }, - { .name = "rx_red_prio_7", .offset = 0x1B, }, - { .name = "rx_yellow_prio_0", .offset = 0x1C, }, - { .name = "rx_yellow_prio_1", .offset = 0x1D, }, - { .name = "rx_yellow_prio_2", .offset = 0x1E, }, - { .name = "rx_yellow_prio_3", .offset = 0x1F, }, - { .name = "rx_yellow_prio_4", .offset = 0x20, }, - { .name = "rx_yellow_prio_5", .offset = 0x21, }, - { .name = "rx_yellow_prio_6", .offset = 0x22, }, - { .name = "rx_yellow_prio_7", .offset = 0x23, }, - { .name = "rx_green_prio_0", .offset = 0x24, }, - { .name = "rx_green_prio_1", .offset = 0x25, }, - { .name = "rx_green_prio_2", .offset = 0x26, }, - { .name = "rx_green_prio_3", .offset = 0x27, }, - { .name = "rx_green_prio_4", .offset = 0x28, }, - { .name = "rx_green_prio_5", .offset = 0x29, }, - { .name = "rx_green_prio_6", .offset = 0x2A, }, - { .name = "rx_green_prio_7", .offset = 0x2B, }, - { .name = "tx_octets", .offset = 0x40, }, - { .name = "tx_unicast", .offset = 0x41, }, - { .name = "tx_multicast", .offset = 0x42, }, - { .name = "tx_broadcast", .offset = 0x43, }, - { .name = "tx_collision", .offset = 0x44, }, - { .name = "tx_drops", .offset = 0x45, }, - { .name = "tx_pause", .offset = 0x46, }, - { .name = "tx_frames_below_65_octets", .offset = 0x47, }, - { .name = "tx_frames_65_to_127_octets", .offset = 0x48, }, - { .name = "tx_frames_128_255_octets", .offset = 0x49, }, - { .name = "tx_frames_256_511_octets", .offset = 0x4A, }, - { .name = "tx_frames_512_1023_octets", .offset = 0x4B, }, - { .name = "tx_frames_1024_1526_octets", .offset = 0x4C, }, - { .name = "tx_frames_over_1526_octets", .offset = 0x4D, }, - { .name = "tx_yellow_prio_0", .offset = 0x4E, }, - { .name = "tx_yellow_prio_1", .offset = 0x4F, }, - { .name = "tx_yellow_prio_2", .offset = 0x50, }, - { .name = "tx_yellow_prio_3", .offset = 0x51, }, - { .name = "tx_yellow_prio_4", .offset = 0x52, }, - { .name = "tx_yellow_prio_5", .offset = 0x53, }, - { .name = "tx_yellow_prio_6", .offset = 0x54, }, - { .name = "tx_yellow_prio_7", .offset = 0x55, }, - { .name = "tx_green_prio_0", .offset = 0x56, }, - { .name = "tx_green_prio_1", .offset = 0x57, }, - { .name = "tx_green_prio_2", .offset = 0x58, }, - { .name = "tx_green_prio_3", .offset = 0x59, }, - { .name = "tx_green_prio_4", .offset = 0x5A, }, - { .name = "tx_green_prio_5", .offset = 0x5B, }, - { .name = "tx_green_prio_6", .offset = 0x5C, }, - { .name = "tx_green_prio_7", .offset = 0x5D, }, - { .name = "tx_aged", .offset = 0x5E, }, - { .name = "drop_local", .offset = 0x80, }, - { .name = "drop_tail", .offset = 0x81, }, - { .name = "drop_yellow_prio_0", .offset = 0x82, }, - { .name = "drop_yellow_prio_1", .offset = 0x83, }, - { .name = "drop_yellow_prio_2", .offset = 0x84, }, - { .name = "drop_yellow_prio_3", .offset = 0x85, }, - { .name = "drop_yellow_prio_4", .offset = 0x86, }, - { .name = "drop_yellow_prio_5", .offset = 0x87, }, - { .name = "drop_yellow_prio_6", .offset = 0x88, }, - { .name = "drop_yellow_prio_7", .offset = 0x89, }, - { .name = "drop_green_prio_0", .offset = 0x8A, }, - { .name = "drop_green_prio_1", .offset = 0x8B, }, - { .name = "drop_green_prio_2", .offset = 0x8C, }, - { .name = "drop_green_prio_3", .offset = 0x8D, }, - { .name = "drop_green_prio_4", .offset = 0x8E, }, - { .name = "drop_green_prio_5", .offset = 0x8F, }, - { .name = "drop_green_prio_6", .offset = 0x90, }, - { .name = "drop_green_prio_7", .offset = 0x91, }, - OCELOT_STAT_END +static const struct ocelot_stat_layout ocelot_stats_layout[OCELOT_NUM_STATS] = { + [OCELOT_STAT_RX_OCTETS] = { + .name = "rx_octets", + .offset = 0x00, + }, + [OCELOT_STAT_RX_UNICAST] = { + .name = "rx_unicast", + .offset = 0x01, + }, + [OCELOT_STAT_RX_MULTICAST] = { + .name = "rx_multicast", + .offset = 0x02, + }, + [OCELOT_STAT_RX_BROADCAST] = { + .name = "rx_broadcast", + .offset = 0x03, + }, + [OCELOT_STAT_RX_SHORTS] = { + .name = "rx_shorts", + .offset = 0x04, + }, + [OCELOT_STAT_RX_FRAGMENTS] = { + .name = "rx_fragments", + .offset = 0x05, + }, + [OCELOT_STAT_RX_JABBERS] = { + .name = "rx_jabbers", + .offset = 0x06, + }, + [OCELOT_STAT_RX_CRC_ALIGN_ERRS] = { + .name = "rx_crc_align_errs", + .offset = 0x07, + }, + [OCELOT_STAT_RX_SYM_ERRS] = { + .name = "rx_sym_errs", + .offset = 0x08, + }, + [OCELOT_STAT_RX_64] = { + .name = "rx_frames_below_65_octets", + .offset = 0x09, + }, + [OCELOT_STAT_RX_65_127] = { + .name = "rx_frames_65_to_127_octets", + .offset = 0x0A, + }, + [OCELOT_STAT_RX_128_255] = { + .name = "rx_frames_128_to_255_octets", + .offset = 0x0B, + }, + [OCELOT_STAT_RX_256_511] = { + .name = "rx_frames_256_to_511_octets", + .offset = 0x0C, + }, + [OCELOT_STAT_RX_512_1023] = { + .name = "rx_frames_512_to_1023_octets", + .offset = 0x0D, + }, + [OCELOT_STAT_RX_1024_1526] = { + .name = "rx_frames_1024_to_1526_octets", + .offset = 0x0E, + }, + [OCELOT_STAT_RX_1527_MAX] = { + .name = "rx_frames_over_1526_octets", + .offset = 0x0F, + }, + [OCELOT_STAT_RX_PAUSE] = { + .name = "rx_pause", + .offset = 0x10, + }, + [OCELOT_STAT_RX_CONTROL] = { + .name = "rx_control", + .offset = 0x11, + }, + [OCELOT_STAT_RX_LONGS] = { + .name = "rx_longs", + .offset = 0x12, + }, + [OCELOT_STAT_RX_CLASSIFIED_DROPS] = { + .name = "rx_classified_drops", + .offset = 0x13, + }, + [OCELOT_STAT_RX_RED_PRIO_0] = { + .name = "rx_red_prio_0", + .offset = 0x14, + }, + [OCELOT_STAT_RX_RED_PRIO_1] = { + .name = "rx_red_prio_1", + .offset = 0x15, + }, + [OCELOT_STAT_RX_RED_PRIO_2] = { + .name = "rx_red_prio_2", + .offset = 0x16, + }, + [OCELOT_STAT_RX_RED_PRIO_3] = { + .name = "rx_red_prio_3", + .offset = 0x17, + }, + [OCELOT_STAT_RX_RED_PRIO_4] = { + .name = "rx_red_prio_4", + .offset = 0x18, + }, + [OCELOT_STAT_RX_RED_PRIO_5] = { + .name = "rx_red_prio_5", + .offset = 0x19, + }, + [OCELOT_STAT_RX_RED_PRIO_6] = { + .name = "rx_red_prio_6", + .offset = 0x1A, + }, + [OCELOT_STAT_RX_RED_PRIO_7] = { + .name = "rx_red_prio_7", + .offset = 0x1B, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_0] = { + .name = "rx_yellow_prio_0", + .offset = 0x1C, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_1] = { + .name = "rx_yellow_prio_1", + .offset = 0x1D, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_2] = { + .name = "rx_yellow_prio_2", + .offset = 0x1E, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_3] = { + .name = "rx_yellow_prio_3", + .offset = 0x1F, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_4] = { + .name = "rx_yellow_prio_4", + .offset = 0x20, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_5] = { + .name = "rx_yellow_prio_5", + .offset = 0x21, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_6] = { + .name = "rx_yellow_prio_6", + .offset = 0x22, + }, + [OCELOT_STAT_RX_YELLOW_PRIO_7] = { + .name = "rx_yellow_prio_7", + .offset = 0x23, + }, + [OCELOT_STAT_RX_GREEN_PRIO_0] = { + .name = "rx_green_prio_0", + .offset = 0x24, + }, + [OCELOT_STAT_RX_GREEN_PRIO_1] = { + .name = "rx_green_prio_1", + .offset = 0x25, + }, + [OCELOT_STAT_RX_GREEN_PRIO_2] = { + .name = "rx_green_prio_2", + .offset = 0x26, + }, + [OCELOT_STAT_RX_GREEN_PRIO_3] = { + .name = "rx_green_prio_3", + .offset = 0x27, + }, + [OCELOT_STAT_RX_GREEN_PRIO_4] = { + .name = "rx_green_prio_4", + .offset = 0x28, + }, + [OCELOT_STAT_RX_GREEN_PRIO_5] = { + .name = "rx_green_prio_5", + .offset = 0x29, + }, + [OCELOT_STAT_RX_GREEN_PRIO_6] = { + .name = "rx_green_prio_6", + .offset = 0x2A, + }, + [OCELOT_STAT_RX_GREEN_PRIO_7] = { + .name = "rx_green_prio_7", + .offset = 0x2B, + }, + [OCELOT_STAT_TX_OCTETS] = { + .name = "tx_octets", + .offset = 0x40, + }, + [OCELOT_STAT_TX_UNICAST] = { + .name = "tx_unicast", + .offset = 0x41, + }, + [OCELOT_STAT_TX_MULTICAST] = { + .name = "tx_multicast", + .offset = 0x42, + }, + [OCELOT_STAT_TX_BROADCAST] = { + .name = "tx_broadcast", + .offset = 0x43, + }, + [OCELOT_STAT_TX_COLLISION] = { + .name = "tx_collision", + .offset = 0x44, + }, + [OCELOT_STAT_TX_DROPS] = { + .name = "tx_drops", + .offset = 0x45, + }, + [OCELOT_STAT_TX_PAUSE] = { + .name = "tx_pause", + .offset = 0x46, + }, + [OCELOT_STAT_TX_64] = { + .name = "tx_frames_below_65_octets", + .offset = 0x47, + }, + [OCELOT_STAT_TX_65_127] = { + .name = "tx_frames_65_to_127_octets", + .offset = 0x48, + }, + [OCELOT_STAT_TX_128_255] = { + .name = "tx_frames_128_255_octets", + .offset = 0x49, + }, + [OCELOT_STAT_TX_256_511] = { + .name = "tx_frames_256_511_octets", + .offset = 0x4A, + }, + [OCELOT_STAT_TX_512_1023] = { + .name = "tx_frames_512_1023_octets", + .offset = 0x4B, + }, + [OCELOT_STAT_TX_1024_1526] = { + .name = "tx_frames_1024_1526_octets", + .offset = 0x4C, + }, + [OCELOT_STAT_TX_1527_MAX] = { + .name = "tx_frames_over_1526_octets", + .offset = 0x4D, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_0] = { + .name = "tx_yellow_prio_0", + .offset = 0x4E, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_1] = { + .name = "tx_yellow_prio_1", + .offset = 0x4F, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_2] = { + .name = "tx_yellow_prio_2", + .offset = 0x50, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_3] = { + .name = "tx_yellow_prio_3", + .offset = 0x51, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_4] = { + .name = "tx_yellow_prio_4", + .offset = 0x52, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_5] = { + .name = "tx_yellow_prio_5", + .offset = 0x53, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_6] = { + .name = "tx_yellow_prio_6", + .offset = 0x54, + }, + [OCELOT_STAT_TX_YELLOW_PRIO_7] = { + .name = "tx_yellow_prio_7", + .offset = 0x55, + }, + [OCELOT_STAT_TX_GREEN_PRIO_0] = { + .name = "tx_green_prio_0", + .offset = 0x56, + }, + [OCELOT_STAT_TX_GREEN_PRIO_1] = { + .name = "tx_green_prio_1", + .offset = 0x57, + }, + [OCELOT_STAT_TX_GREEN_PRIO_2] = { + .name = "tx_green_prio_2", + .offset = 0x58, + }, + [OCELOT_STAT_TX_GREEN_PRIO_3] = { + .name = "tx_green_prio_3", + .offset = 0x59, + }, + [OCELOT_STAT_TX_GREEN_PRIO_4] = { + .name = "tx_green_prio_4", + .offset = 0x5A, + }, + [OCELOT_STAT_TX_GREEN_PRIO_5] = { + .name = "tx_green_prio_5", + .offset = 0x5B, + }, + [OCELOT_STAT_TX_GREEN_PRIO_6] = { + .name = "tx_green_prio_6", + .offset = 0x5C, + }, + [OCELOT_STAT_TX_GREEN_PRIO_7] = { + .name = "tx_green_prio_7", + .offset = 0x5D, + }, + [OCELOT_STAT_TX_AGED] = { + .name = "tx_aged", + .offset = 0x5E, + }, + [OCELOT_STAT_DROP_LOCAL] = { + .name = "drop_local", + .offset = 0x80, + }, + [OCELOT_STAT_DROP_TAIL] = { + .name = "drop_tail", + .offset = 0x81, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_0] = { + .name = "drop_yellow_prio_0", + .offset = 0x82, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_1] = { + .name = "drop_yellow_prio_1", + .offset = 0x83, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_2] = { + .name = "drop_yellow_prio_2", + .offset = 0x84, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_3] = { + .name = "drop_yellow_prio_3", + .offset = 0x85, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_4] = { + .name = "drop_yellow_prio_4", + .offset = 0x86, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_5] = { + .name = "drop_yellow_prio_5", + .offset = 0x87, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_6] = { + .name = "drop_yellow_prio_6", + .offset = 0x88, + }, + [OCELOT_STAT_DROP_YELLOW_PRIO_7] = { + .name = "drop_yellow_prio_7", + .offset = 0x89, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_0] = { + .name = "drop_green_prio_0", + .offset = 0x8A, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_1] = { + .name = "drop_green_prio_1", + .offset = 0x8B, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_2] = { + .name = "drop_green_prio_2", + .offset = 0x8C, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_3] = { + .name = "drop_green_prio_3", + .offset = 0x8D, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_4] = { + .name = "drop_green_prio_4", + .offset = 0x8E, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_5] = { + .name = "drop_green_prio_5", + .offset = 0x8F, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_6] = { + .name = "drop_green_prio_6", + .offset = 0x90, + }, + [OCELOT_STAT_DROP_GREEN_PRIO_7] = { + .name = "drop_green_prio_7", + .offset = 0x91, + }, }; static void ocelot_pll5_init(struct ocelot *ocelot) diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 72b9474391da3..2428bc64cb1d6 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -105,11 +105,6 @@ #define REG_RESERVED_ADDR 0xffffffff #define REG_RESERVED(reg) REG(reg, REG_RESERVED_ADDR) -#define for_each_stat(ocelot, stat) \ - for ((stat) = (ocelot)->stats_layout; \ - ((stat)->name[0] != '\0'); \ - (stat)++) - enum ocelot_target { ANA = 1, QS, @@ -540,13 +535,108 @@ enum ocelot_ptp_pins { TOD_ACC_PIN }; +enum ocelot_stat { + OCELOT_STAT_RX_OCTETS, + OCELOT_STAT_RX_UNICAST, + OCELOT_STAT_RX_MULTICAST, + OCELOT_STAT_RX_BROADCAST, + OCELOT_STAT_RX_SHORTS, + OCELOT_STAT_RX_FRAGMENTS, + OCELOT_STAT_RX_JABBERS, + OCELOT_STAT_RX_CRC_ALIGN_ERRS, + OCELOT_STAT_RX_SYM_ERRS, + OCELOT_STAT_RX_64, + OCELOT_STAT_RX_65_127, + OCELOT_STAT_RX_128_255, + OCELOT_STAT_RX_256_511, + OCELOT_STAT_RX_512_1023, + OCELOT_STAT_RX_1024_1526, + OCELOT_STAT_RX_1527_MAX, + OCELOT_STAT_RX_PAUSE, + OCELOT_STAT_RX_CONTROL, + OCELOT_STAT_RX_LONGS, + OCELOT_STAT_RX_CLASSIFIED_DROPS, + OCELOT_STAT_RX_RED_PRIO_0, + OCELOT_STAT_RX_RED_PRIO_1, + OCELOT_STAT_RX_RED_PRIO_2, + OCELOT_STAT_RX_RED_PRIO_3, + OCELOT_STAT_RX_RED_PRIO_4, + OCELOT_STAT_RX_RED_PRIO_5, + OCELOT_STAT_RX_RED_PRIO_6, + OCELOT_STAT_RX_RED_PRIO_7, + OCELOT_STAT_RX_YELLOW_PRIO_0, + OCELOT_STAT_RX_YELLOW_PRIO_1, + OCELOT_STAT_RX_YELLOW_PRIO_2, + OCELOT_STAT_RX_YELLOW_PRIO_3, + OCELOT_STAT_RX_YELLOW_PRIO_4, + OCELOT_STAT_RX_YELLOW_PRIO_5, + OCELOT_STAT_RX_YELLOW_PRIO_6, + OCELOT_STAT_RX_YELLOW_PRIO_7, + OCELOT_STAT_RX_GREEN_PRIO_0, + OCELOT_STAT_RX_GREEN_PRIO_1, + OCELOT_STAT_RX_GREEN_PRIO_2, + OCELOT_STAT_RX_GREEN_PRIO_3, + OCELOT_STAT_RX_GREEN_PRIO_4, + OCELOT_STAT_RX_GREEN_PRIO_5, + OCELOT_STAT_RX_GREEN_PRIO_6, + OCELOT_STAT_RX_GREEN_PRIO_7, + OCELOT_STAT_TX_OCTETS, + OCELOT_STAT_TX_UNICAST, + OCELOT_STAT_TX_MULTICAST, + OCELOT_STAT_TX_BROADCAST, + OCELOT_STAT_TX_COLLISION, + OCELOT_STAT_TX_DROPS, + OCELOT_STAT_TX_PAUSE, + OCELOT_STAT_TX_64, + OCELOT_STAT_TX_65_127, + OCELOT_STAT_TX_128_255, + OCELOT_STAT_TX_256_511, + OCELOT_STAT_TX_512_1023, + OCELOT_STAT_TX_1024_1526, + OCELOT_STAT_TX_1527_MAX, + OCELOT_STAT_TX_YELLOW_PRIO_0, + OCELOT_STAT_TX_YELLOW_PRIO_1, + OCELOT_STAT_TX_YELLOW_PRIO_2, + OCELOT_STAT_TX_YELLOW_PRIO_3, + OCELOT_STAT_TX_YELLOW_PRIO_4, + OCELOT_STAT_TX_YELLOW_PRIO_5, + OCELOT_STAT_TX_YELLOW_PRIO_6, + OCELOT_STAT_TX_YELLOW_PRIO_7, + OCELOT_STAT_TX_GREEN_PRIO_0, + OCELOT_STAT_TX_GREEN_PRIO_1, + OCELOT_STAT_TX_GREEN_PRIO_2, + OCELOT_STAT_TX_GREEN_PRIO_3, + OCELOT_STAT_TX_GREEN_PRIO_4, + OCELOT_STAT_TX_GREEN_PRIO_5, + OCELOT_STAT_TX_GREEN_PRIO_6, + OCELOT_STAT_TX_GREEN_PRIO_7, + OCELOT_STAT_TX_AGED, + OCELOT_STAT_DROP_LOCAL, + OCELOT_STAT_DROP_TAIL, + OCELOT_STAT_DROP_YELLOW_PRIO_0, + OCELOT_STAT_DROP_YELLOW_PRIO_1, + OCELOT_STAT_DROP_YELLOW_PRIO_2, + OCELOT_STAT_DROP_YELLOW_PRIO_3, + OCELOT_STAT_DROP_YELLOW_PRIO_4, + OCELOT_STAT_DROP_YELLOW_PRIO_5, + OCELOT_STAT_DROP_YELLOW_PRIO_6, + OCELOT_STAT_DROP_YELLOW_PRIO_7, + OCELOT_STAT_DROP_GREEN_PRIO_0, + OCELOT_STAT_DROP_GREEN_PRIO_1, + OCELOT_STAT_DROP_GREEN_PRIO_2, + OCELOT_STAT_DROP_GREEN_PRIO_3, + OCELOT_STAT_DROP_GREEN_PRIO_4, + OCELOT_STAT_DROP_GREEN_PRIO_5, + OCELOT_STAT_DROP_GREEN_PRIO_6, + OCELOT_STAT_DROP_GREEN_PRIO_7, + OCELOT_NUM_STATS, +}; + struct ocelot_stat_layout { u32 offset; char name[ETH_GSTRING_LEN]; }; -#define OCELOT_STAT_END { .name = "" } - struct ocelot_stats_region { struct list_head node; u32 offset; @@ -709,7 +799,6 @@ struct ocelot { const u32 *const *map; const struct ocelot_stat_layout *stats_layout; struct list_head stats_regions; - unsigned int num_stats; u32 pool_size[OCELOT_SB_NUM][OCELOT_SB_POOL_NUM]; int packet_buffer_size; From d4c367650704de091d4c1f6bb379c0a5c389c73a Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 16 Aug 2022 16:53:51 +0300 Subject: [PATCH 359/427] net: mscc: ocelot: keep ocelot_stat_layout by reg address, not offset With so many counter addresses recently discovered as being wrong, it is desirable to at least have a central database of information, rather than two: one through the SYS_COUNT_* registers (used for ndo_get_stats64), and the other through the offset field of struct ocelot_stat_layout elements (used for ethtool -S). The strategy will be to keep the SYS_COUNT_* definitions as the single source of truth, but for that we need to expand our current definitions to cover all registers. Then we need to convert the ocelot region creation logic, and stats worker, to the read semantics imposed by going through SYS_COUNT_* absolute register addresses, rather than offsets of 32-bit words relative to SYS_COUNT_RX_OCTETS (which should have been SYS_CNT, by the way). Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/dsa/ocelot/felix_vsc9959.c | 253 ++++++++++++-------- drivers/net/dsa/ocelot/seville_vsc9953.c | 255 +++++++++++++-------- drivers/net/ethernet/mscc/ocelot.c | 11 +- drivers/net/ethernet/mscc/ocelot_vsc7514.c | 186 +++++++-------- drivers/net/ethernet/mscc/vsc7514_regs.c | 58 +++++ include/soc/mscc/ocelot.h | 66 +++++- 6 files changed, 540 insertions(+), 289 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index c9f270f24b1c7..1cdce8a98d1da 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -274,10 +274,14 @@ static const u32 vsc9959_rew_regmap[] = { static const u32 vsc9959_sys_regmap[] = { REG(SYS_COUNT_RX_OCTETS, 0x000000), + REG(SYS_COUNT_RX_UNICAST, 0x000004), REG(SYS_COUNT_RX_MULTICAST, 0x000008), + REG(SYS_COUNT_RX_BROADCAST, 0x00000c), REG(SYS_COUNT_RX_SHORTS, 0x000010), REG(SYS_COUNT_RX_FRAGMENTS, 0x000014), REG(SYS_COUNT_RX_JABBERS, 0x000018), + REG(SYS_COUNT_RX_CRC_ALIGN_ERRS, 0x00001c), + REG(SYS_COUNT_RX_SYM_ERRS, 0x000020), REG(SYS_COUNT_RX_64, 0x000024), REG(SYS_COUNT_RX_65_127, 0x000028), REG(SYS_COUNT_RX_128_255, 0x00002c), @@ -288,9 +292,38 @@ static const u32 vsc9959_sys_regmap[] = { REG(SYS_COUNT_RX_PAUSE, 0x000040), REG(SYS_COUNT_RX_CONTROL, 0x000044), REG(SYS_COUNT_RX_LONGS, 0x000048), + REG(SYS_COUNT_RX_CLASSIFIED_DROPS, 0x00004c), + REG(SYS_COUNT_RX_RED_PRIO_0, 0x000050), + REG(SYS_COUNT_RX_RED_PRIO_1, 0x000054), + REG(SYS_COUNT_RX_RED_PRIO_2, 0x000058), + REG(SYS_COUNT_RX_RED_PRIO_3, 0x00005c), + REG(SYS_COUNT_RX_RED_PRIO_4, 0x000060), + REG(SYS_COUNT_RX_RED_PRIO_5, 0x000064), + REG(SYS_COUNT_RX_RED_PRIO_6, 0x000068), + REG(SYS_COUNT_RX_RED_PRIO_7, 0x00006c), + REG(SYS_COUNT_RX_YELLOW_PRIO_0, 0x000070), + REG(SYS_COUNT_RX_YELLOW_PRIO_1, 0x000074), + REG(SYS_COUNT_RX_YELLOW_PRIO_2, 0x000078), + REG(SYS_COUNT_RX_YELLOW_PRIO_3, 0x00007c), + REG(SYS_COUNT_RX_YELLOW_PRIO_4, 0x000080), + REG(SYS_COUNT_RX_YELLOW_PRIO_5, 0x000084), + REG(SYS_COUNT_RX_YELLOW_PRIO_6, 0x000088), + REG(SYS_COUNT_RX_YELLOW_PRIO_7, 0x00008c), + REG(SYS_COUNT_RX_GREEN_PRIO_0, 0x000090), + REG(SYS_COUNT_RX_GREEN_PRIO_1, 0x000094), + REG(SYS_COUNT_RX_GREEN_PRIO_2, 0x000098), + REG(SYS_COUNT_RX_GREEN_PRIO_3, 0x00009c), + REG(SYS_COUNT_RX_GREEN_PRIO_4, 0x0000a0), + REG(SYS_COUNT_RX_GREEN_PRIO_5, 0x0000a4), + REG(SYS_COUNT_RX_GREEN_PRIO_6, 0x0000a8), + REG(SYS_COUNT_RX_GREEN_PRIO_7, 0x0000ac), REG(SYS_COUNT_TX_OCTETS, 0x000200), + REG(SYS_COUNT_TX_UNICAST, 0x000204), + REG(SYS_COUNT_TX_MULTICAST, 0x000208), + REG(SYS_COUNT_TX_BROADCAST, 0x00020c), REG(SYS_COUNT_TX_COLLISION, 0x000210), REG(SYS_COUNT_TX_DROPS, 0x000214), + REG(SYS_COUNT_TX_PAUSE, 0x000218), REG(SYS_COUNT_TX_64, 0x00021c), REG(SYS_COUNT_TX_65_127, 0x000220), REG(SYS_COUNT_TX_128_255, 0x000224), @@ -298,7 +331,41 @@ static const u32 vsc9959_sys_regmap[] = { REG(SYS_COUNT_TX_512_1023, 0x00022c), REG(SYS_COUNT_TX_1024_1526, 0x000230), REG(SYS_COUNT_TX_1527_MAX, 0x000234), + REG(SYS_COUNT_TX_YELLOW_PRIO_0, 0x000238), + REG(SYS_COUNT_TX_YELLOW_PRIO_1, 0x00023c), + REG(SYS_COUNT_TX_YELLOW_PRIO_2, 0x000240), + REG(SYS_COUNT_TX_YELLOW_PRIO_3, 0x000244), + REG(SYS_COUNT_TX_YELLOW_PRIO_4, 0x000248), + REG(SYS_COUNT_TX_YELLOW_PRIO_5, 0x00024c), + REG(SYS_COUNT_TX_YELLOW_PRIO_6, 0x000250), + REG(SYS_COUNT_TX_YELLOW_PRIO_7, 0x000254), + REG(SYS_COUNT_TX_GREEN_PRIO_0, 0x000258), + REG(SYS_COUNT_TX_GREEN_PRIO_1, 0x00025c), + REG(SYS_COUNT_TX_GREEN_PRIO_2, 0x000260), + REG(SYS_COUNT_TX_GREEN_PRIO_3, 0x000264), + REG(SYS_COUNT_TX_GREEN_PRIO_4, 0x000268), + REG(SYS_COUNT_TX_GREEN_PRIO_5, 0x00026c), + REG(SYS_COUNT_TX_GREEN_PRIO_6, 0x000270), + REG(SYS_COUNT_TX_GREEN_PRIO_7, 0x000274), REG(SYS_COUNT_TX_AGING, 0x000278), + REG(SYS_COUNT_DROP_LOCAL, 0x000400), + REG(SYS_COUNT_DROP_TAIL, 0x000404), + REG(SYS_COUNT_DROP_YELLOW_PRIO_0, 0x000408), + REG(SYS_COUNT_DROP_YELLOW_PRIO_1, 0x00040c), + REG(SYS_COUNT_DROP_YELLOW_PRIO_2, 0x000410), + REG(SYS_COUNT_DROP_YELLOW_PRIO_3, 0x000414), + REG(SYS_COUNT_DROP_YELLOW_PRIO_4, 0x000418), + REG(SYS_COUNT_DROP_YELLOW_PRIO_5, 0x00041c), + REG(SYS_COUNT_DROP_YELLOW_PRIO_6, 0x000420), + REG(SYS_COUNT_DROP_YELLOW_PRIO_7, 0x000424), + REG(SYS_COUNT_DROP_GREEN_PRIO_0, 0x000428), + REG(SYS_COUNT_DROP_GREEN_PRIO_1, 0x00042c), + REG(SYS_COUNT_DROP_GREEN_PRIO_2, 0x000430), + REG(SYS_COUNT_DROP_GREEN_PRIO_3, 0x000434), + REG(SYS_COUNT_DROP_GREEN_PRIO_4, 0x000438), + REG(SYS_COUNT_DROP_GREEN_PRIO_5, 0x00043c), + REG(SYS_COUNT_DROP_GREEN_PRIO_6, 0x000440), + REG(SYS_COUNT_DROP_GREEN_PRIO_7, 0x000444), REG(SYS_RESET_CFG, 0x000e00), REG(SYS_SR_ETYPE_CFG, 0x000e04), REG(SYS_VLAN_ETYPE_CFG, 0x000e08), @@ -554,375 +621,375 @@ static const struct reg_field vsc9959_regfields[REGFIELD_MAX] = { static const struct ocelot_stat_layout vsc9959_stats_layout[OCELOT_NUM_STATS] = { [OCELOT_STAT_RX_OCTETS] = { .name = "rx_octets", - .offset = 0x00, + .reg = SYS_COUNT_RX_OCTETS, }, [OCELOT_STAT_RX_UNICAST] = { .name = "rx_unicast", - .offset = 0x01, + .reg = SYS_COUNT_RX_UNICAST, }, [OCELOT_STAT_RX_MULTICAST] = { .name = "rx_multicast", - .offset = 0x02, + .reg = SYS_COUNT_RX_MULTICAST, }, [OCELOT_STAT_RX_BROADCAST] = { .name = "rx_broadcast", - .offset = 0x03, + .reg = SYS_COUNT_RX_BROADCAST, }, [OCELOT_STAT_RX_SHORTS] = { .name = "rx_shorts", - .offset = 0x04, + .reg = SYS_COUNT_RX_SHORTS, }, [OCELOT_STAT_RX_FRAGMENTS] = { .name = "rx_fragments", - .offset = 0x05, + .reg = SYS_COUNT_RX_FRAGMENTS, }, [OCELOT_STAT_RX_JABBERS] = { .name = "rx_jabbers", - .offset = 0x06, + .reg = SYS_COUNT_RX_JABBERS, }, [OCELOT_STAT_RX_CRC_ALIGN_ERRS] = { .name = "rx_crc_align_errs", - .offset = 0x07, + .reg = SYS_COUNT_RX_CRC_ALIGN_ERRS, }, [OCELOT_STAT_RX_SYM_ERRS] = { .name = "rx_sym_errs", - .offset = 0x08, + .reg = SYS_COUNT_RX_SYM_ERRS, }, [OCELOT_STAT_RX_64] = { .name = "rx_frames_below_65_octets", - .offset = 0x09, + .reg = SYS_COUNT_RX_64, }, [OCELOT_STAT_RX_65_127] = { .name = "rx_frames_65_to_127_octets", - .offset = 0x0A, + .reg = SYS_COUNT_RX_65_127, }, [OCELOT_STAT_RX_128_255] = { .name = "rx_frames_128_to_255_octets", - .offset = 0x0B, + .reg = SYS_COUNT_RX_128_255, }, [OCELOT_STAT_RX_256_511] = { .name = "rx_frames_256_to_511_octets", - .offset = 0x0C, + .reg = SYS_COUNT_RX_256_511, }, [OCELOT_STAT_RX_512_1023] = { .name = "rx_frames_512_to_1023_octets", - .offset = 0x0D, + .reg = SYS_COUNT_RX_512_1023, }, [OCELOT_STAT_RX_1024_1526] = { .name = "rx_frames_1024_to_1526_octets", - .offset = 0x0E, + .reg = SYS_COUNT_RX_1024_1526, }, [OCELOT_STAT_RX_1527_MAX] = { .name = "rx_frames_over_1526_octets", - .offset = 0x0F, + .reg = SYS_COUNT_RX_1527_MAX, }, [OCELOT_STAT_RX_PAUSE] = { .name = "rx_pause", - .offset = 0x10, + .reg = SYS_COUNT_RX_PAUSE, }, [OCELOT_STAT_RX_CONTROL] = { .name = "rx_control", - .offset = 0x11, + .reg = SYS_COUNT_RX_CONTROL, }, [OCELOT_STAT_RX_LONGS] = { .name = "rx_longs", - .offset = 0x12, + .reg = SYS_COUNT_RX_LONGS, }, [OCELOT_STAT_RX_CLASSIFIED_DROPS] = { .name = "rx_classified_drops", - .offset = 0x13, + .reg = SYS_COUNT_RX_CLASSIFIED_DROPS, }, [OCELOT_STAT_RX_RED_PRIO_0] = { .name = "rx_red_prio_0", - .offset = 0x14, + .reg = SYS_COUNT_RX_RED_PRIO_0, }, [OCELOT_STAT_RX_RED_PRIO_1] = { .name = "rx_red_prio_1", - .offset = 0x15, + .reg = SYS_COUNT_RX_RED_PRIO_1, }, [OCELOT_STAT_RX_RED_PRIO_2] = { .name = "rx_red_prio_2", - .offset = 0x16, + .reg = SYS_COUNT_RX_RED_PRIO_2, }, [OCELOT_STAT_RX_RED_PRIO_3] = { .name = "rx_red_prio_3", - .offset = 0x17, + .reg = SYS_COUNT_RX_RED_PRIO_3, }, [OCELOT_STAT_RX_RED_PRIO_4] = { .name = "rx_red_prio_4", - .offset = 0x18, + .reg = SYS_COUNT_RX_RED_PRIO_4, }, [OCELOT_STAT_RX_RED_PRIO_5] = { .name = "rx_red_prio_5", - .offset = 0x19, + .reg = SYS_COUNT_RX_RED_PRIO_5, }, [OCELOT_STAT_RX_RED_PRIO_6] = { .name = "rx_red_prio_6", - .offset = 0x1A, + .reg = SYS_COUNT_RX_RED_PRIO_6, }, [OCELOT_STAT_RX_RED_PRIO_7] = { .name = "rx_red_prio_7", - .offset = 0x1B, + .reg = SYS_COUNT_RX_RED_PRIO_7, }, [OCELOT_STAT_RX_YELLOW_PRIO_0] = { .name = "rx_yellow_prio_0", - .offset = 0x1C, + .reg = SYS_COUNT_RX_YELLOW_PRIO_0, }, [OCELOT_STAT_RX_YELLOW_PRIO_1] = { .name = "rx_yellow_prio_1", - .offset = 0x1D, + .reg = SYS_COUNT_RX_YELLOW_PRIO_1, }, [OCELOT_STAT_RX_YELLOW_PRIO_2] = { .name = "rx_yellow_prio_2", - .offset = 0x1E, + .reg = SYS_COUNT_RX_YELLOW_PRIO_2, }, [OCELOT_STAT_RX_YELLOW_PRIO_3] = { .name = "rx_yellow_prio_3", - .offset = 0x1F, + .reg = SYS_COUNT_RX_YELLOW_PRIO_3, }, [OCELOT_STAT_RX_YELLOW_PRIO_4] = { .name = "rx_yellow_prio_4", - .offset = 0x20, + .reg = SYS_COUNT_RX_YELLOW_PRIO_4, }, [OCELOT_STAT_RX_YELLOW_PRIO_5] = { .name = "rx_yellow_prio_5", - .offset = 0x21, + .reg = SYS_COUNT_RX_YELLOW_PRIO_5, }, [OCELOT_STAT_RX_YELLOW_PRIO_6] = { .name = "rx_yellow_prio_6", - .offset = 0x22, + .reg = SYS_COUNT_RX_YELLOW_PRIO_6, }, [OCELOT_STAT_RX_YELLOW_PRIO_7] = { .name = "rx_yellow_prio_7", - .offset = 0x23, + .reg = SYS_COUNT_RX_YELLOW_PRIO_7, }, [OCELOT_STAT_RX_GREEN_PRIO_0] = { .name = "rx_green_prio_0", - .offset = 0x24, + .reg = SYS_COUNT_RX_GREEN_PRIO_0, }, [OCELOT_STAT_RX_GREEN_PRIO_1] = { .name = "rx_green_prio_1", - .offset = 0x25, + .reg = SYS_COUNT_RX_GREEN_PRIO_1, }, [OCELOT_STAT_RX_GREEN_PRIO_2] = { .name = "rx_green_prio_2", - .offset = 0x26, + .reg = SYS_COUNT_RX_GREEN_PRIO_2, }, [OCELOT_STAT_RX_GREEN_PRIO_3] = { .name = "rx_green_prio_3", - .offset = 0x27, + .reg = SYS_COUNT_RX_GREEN_PRIO_3, }, [OCELOT_STAT_RX_GREEN_PRIO_4] = { .name = "rx_green_prio_4", - .offset = 0x28, + .reg = SYS_COUNT_RX_GREEN_PRIO_4, }, [OCELOT_STAT_RX_GREEN_PRIO_5] = { .name = "rx_green_prio_5", - .offset = 0x29, + .reg = SYS_COUNT_RX_GREEN_PRIO_5, }, [OCELOT_STAT_RX_GREEN_PRIO_6] = { .name = "rx_green_prio_6", - .offset = 0x2A, + .reg = SYS_COUNT_RX_GREEN_PRIO_6, }, [OCELOT_STAT_RX_GREEN_PRIO_7] = { .name = "rx_green_prio_7", - .offset = 0x2B, + .reg = SYS_COUNT_RX_GREEN_PRIO_7, }, [OCELOT_STAT_TX_OCTETS] = { .name = "tx_octets", - .offset = 0x80, + .reg = SYS_COUNT_TX_OCTETS, }, [OCELOT_STAT_TX_UNICAST] = { .name = "tx_unicast", - .offset = 0x81, + .reg = SYS_COUNT_TX_UNICAST, }, [OCELOT_STAT_TX_MULTICAST] = { .name = "tx_multicast", - .offset = 0x82, + .reg = SYS_COUNT_TX_MULTICAST, }, [OCELOT_STAT_TX_BROADCAST] = { .name = "tx_broadcast", - .offset = 0x83, + .reg = SYS_COUNT_TX_BROADCAST, }, [OCELOT_STAT_TX_COLLISION] = { .name = "tx_collision", - .offset = 0x84, + .reg = SYS_COUNT_TX_COLLISION, }, [OCELOT_STAT_TX_DROPS] = { .name = "tx_drops", - .offset = 0x85, + .reg = SYS_COUNT_TX_DROPS, }, [OCELOT_STAT_TX_PAUSE] = { .name = "tx_pause", - .offset = 0x86, + .reg = SYS_COUNT_TX_PAUSE, }, [OCELOT_STAT_TX_64] = { .name = "tx_frames_below_65_octets", - .offset = 0x87, + .reg = SYS_COUNT_TX_64, }, [OCELOT_STAT_TX_65_127] = { .name = "tx_frames_65_to_127_octets", - .offset = 0x88, + .reg = SYS_COUNT_TX_65_127, }, [OCELOT_STAT_TX_128_255] = { .name = "tx_frames_128_255_octets", - .offset = 0x89, + .reg = SYS_COUNT_TX_128_255, }, [OCELOT_STAT_TX_256_511] = { .name = "tx_frames_256_511_octets", - .offset = 0x8A, + .reg = SYS_COUNT_TX_256_511, }, [OCELOT_STAT_TX_512_1023] = { .name = "tx_frames_512_1023_octets", - .offset = 0x8B, + .reg = SYS_COUNT_TX_512_1023, }, [OCELOT_STAT_TX_1024_1526] = { .name = "tx_frames_1024_1526_octets", - .offset = 0x8C, + .reg = SYS_COUNT_TX_1024_1526, }, [OCELOT_STAT_TX_1527_MAX] = { .name = "tx_frames_over_1526_octets", - .offset = 0x8D, + .reg = SYS_COUNT_TX_1527_MAX, }, [OCELOT_STAT_TX_YELLOW_PRIO_0] = { .name = "tx_yellow_prio_0", - .offset = 0x8E, + .reg = SYS_COUNT_TX_YELLOW_PRIO_0, }, [OCELOT_STAT_TX_YELLOW_PRIO_1] = { .name = "tx_yellow_prio_1", - .offset = 0x8F, + .reg = SYS_COUNT_TX_YELLOW_PRIO_1, }, [OCELOT_STAT_TX_YELLOW_PRIO_2] = { .name = "tx_yellow_prio_2", - .offset = 0x90, + .reg = SYS_COUNT_TX_YELLOW_PRIO_2, }, [OCELOT_STAT_TX_YELLOW_PRIO_3] = { .name = "tx_yellow_prio_3", - .offset = 0x91, + .reg = SYS_COUNT_TX_YELLOW_PRIO_3, }, [OCELOT_STAT_TX_YELLOW_PRIO_4] = { .name = "tx_yellow_prio_4", - .offset = 0x92, + .reg = SYS_COUNT_TX_YELLOW_PRIO_4, }, [OCELOT_STAT_TX_YELLOW_PRIO_5] = { .name = "tx_yellow_prio_5", - .offset = 0x93, + .reg = SYS_COUNT_TX_YELLOW_PRIO_5, }, [OCELOT_STAT_TX_YELLOW_PRIO_6] = { .name = "tx_yellow_prio_6", - .offset = 0x94, + .reg = SYS_COUNT_TX_YELLOW_PRIO_6, }, [OCELOT_STAT_TX_YELLOW_PRIO_7] = { .name = "tx_yellow_prio_7", - .offset = 0x95, + .reg = SYS_COUNT_TX_YELLOW_PRIO_7, }, [OCELOT_STAT_TX_GREEN_PRIO_0] = { .name = "tx_green_prio_0", - .offset = 0x96, + .reg = SYS_COUNT_TX_GREEN_PRIO_0, }, [OCELOT_STAT_TX_GREEN_PRIO_1] = { .name = "tx_green_prio_1", - .offset = 0x97, + .reg = SYS_COUNT_TX_GREEN_PRIO_1, }, [OCELOT_STAT_TX_GREEN_PRIO_2] = { .name = "tx_green_prio_2", - .offset = 0x98, + .reg = SYS_COUNT_TX_GREEN_PRIO_2, }, [OCELOT_STAT_TX_GREEN_PRIO_3] = { .name = "tx_green_prio_3", - .offset = 0x99, + .reg = SYS_COUNT_TX_GREEN_PRIO_3, }, [OCELOT_STAT_TX_GREEN_PRIO_4] = { .name = "tx_green_prio_4", - .offset = 0x9A, + .reg = SYS_COUNT_TX_GREEN_PRIO_4, }, [OCELOT_STAT_TX_GREEN_PRIO_5] = { .name = "tx_green_prio_5", - .offset = 0x9B, + .reg = SYS_COUNT_TX_GREEN_PRIO_5, }, [OCELOT_STAT_TX_GREEN_PRIO_6] = { .name = "tx_green_prio_6", - .offset = 0x9C, + .reg = SYS_COUNT_TX_GREEN_PRIO_6, }, [OCELOT_STAT_TX_GREEN_PRIO_7] = { .name = "tx_green_prio_7", - .offset = 0x9D, + .reg = SYS_COUNT_TX_GREEN_PRIO_7, }, [OCELOT_STAT_TX_AGED] = { .name = "tx_aged", - .offset = 0x9E, + .reg = SYS_COUNT_TX_AGING, }, [OCELOT_STAT_DROP_LOCAL] = { .name = "drop_local", - .offset = 0x100, + .reg = SYS_COUNT_DROP_LOCAL, }, [OCELOT_STAT_DROP_TAIL] = { .name = "drop_tail", - .offset = 0x101, + .reg = SYS_COUNT_DROP_TAIL, }, [OCELOT_STAT_DROP_YELLOW_PRIO_0] = { .name = "drop_yellow_prio_0", - .offset = 0x102, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_0, }, [OCELOT_STAT_DROP_YELLOW_PRIO_1] = { .name = "drop_yellow_prio_1", - .offset = 0x103, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_1, }, [OCELOT_STAT_DROP_YELLOW_PRIO_2] = { .name = "drop_yellow_prio_2", - .offset = 0x104, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_2, }, [OCELOT_STAT_DROP_YELLOW_PRIO_3] = { .name = "drop_yellow_prio_3", - .offset = 0x105, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_3, }, [OCELOT_STAT_DROP_YELLOW_PRIO_4] = { .name = "drop_yellow_prio_4", - .offset = 0x106, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_4, }, [OCELOT_STAT_DROP_YELLOW_PRIO_5] = { .name = "drop_yellow_prio_5", - .offset = 0x107, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_5, }, [OCELOT_STAT_DROP_YELLOW_PRIO_6] = { .name = "drop_yellow_prio_6", - .offset = 0x108, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_6, }, [OCELOT_STAT_DROP_YELLOW_PRIO_7] = { .name = "drop_yellow_prio_7", - .offset = 0x109, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_7, }, [OCELOT_STAT_DROP_GREEN_PRIO_0] = { .name = "drop_green_prio_0", - .offset = 0x10A, + .reg = SYS_COUNT_DROP_GREEN_PRIO_0, }, [OCELOT_STAT_DROP_GREEN_PRIO_1] = { .name = "drop_green_prio_1", - .offset = 0x10B, + .reg = SYS_COUNT_DROP_GREEN_PRIO_1, }, [OCELOT_STAT_DROP_GREEN_PRIO_2] = { .name = "drop_green_prio_2", - .offset = 0x10C, + .reg = SYS_COUNT_DROP_GREEN_PRIO_2, }, [OCELOT_STAT_DROP_GREEN_PRIO_3] = { .name = "drop_green_prio_3", - .offset = 0x10D, + .reg = SYS_COUNT_DROP_GREEN_PRIO_3, }, [OCELOT_STAT_DROP_GREEN_PRIO_4] = { .name = "drop_green_prio_4", - .offset = 0x10E, + .reg = SYS_COUNT_DROP_GREEN_PRIO_4, }, [OCELOT_STAT_DROP_GREEN_PRIO_5] = { .name = "drop_green_prio_5", - .offset = 0x10F, + .reg = SYS_COUNT_DROP_GREEN_PRIO_5, }, [OCELOT_STAT_DROP_GREEN_PRIO_6] = { .name = "drop_green_prio_6", - .offset = 0x110, + .reg = SYS_COUNT_DROP_GREEN_PRIO_6, }, [OCELOT_STAT_DROP_GREEN_PRIO_7] = { .name = "drop_green_prio_7", - .offset = 0x111, + .reg = SYS_COUNT_DROP_GREEN_PRIO_7, }, }; diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index fe5d4642d0bcb..b34f4cdfe814c 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -270,10 +270,14 @@ static const u32 vsc9953_rew_regmap[] = { static const u32 vsc9953_sys_regmap[] = { REG(SYS_COUNT_RX_OCTETS, 0x000000), + REG(SYS_COUNT_RX_UNICAST, 0x000004), REG(SYS_COUNT_RX_MULTICAST, 0x000008), + REG(SYS_COUNT_RX_BROADCAST, 0x00000c), REG(SYS_COUNT_RX_SHORTS, 0x000010), REG(SYS_COUNT_RX_FRAGMENTS, 0x000014), REG(SYS_COUNT_RX_JABBERS, 0x000018), + REG(SYS_COUNT_RX_CRC_ALIGN_ERRS, 0x00001c), + REG(SYS_COUNT_RX_SYM_ERRS, 0x000020), REG(SYS_COUNT_RX_64, 0x000024), REG(SYS_COUNT_RX_65_127, 0x000028), REG(SYS_COUNT_RX_128_255, 0x00002c), @@ -281,10 +285,41 @@ static const u32 vsc9953_sys_regmap[] = { REG(SYS_COUNT_RX_512_1023, 0x000034), REG(SYS_COUNT_RX_1024_1526, 0x000038), REG(SYS_COUNT_RX_1527_MAX, 0x00003c), + REG(SYS_COUNT_RX_PAUSE, 0x000040), + REG(SYS_COUNT_RX_CONTROL, 0x000044), REG(SYS_COUNT_RX_LONGS, 0x000048), + REG(SYS_COUNT_RX_CLASSIFIED_DROPS, 0x00004c), + REG(SYS_COUNT_RX_RED_PRIO_0, 0x000050), + REG(SYS_COUNT_RX_RED_PRIO_1, 0x000054), + REG(SYS_COUNT_RX_RED_PRIO_2, 0x000058), + REG(SYS_COUNT_RX_RED_PRIO_3, 0x00005c), + REG(SYS_COUNT_RX_RED_PRIO_4, 0x000060), + REG(SYS_COUNT_RX_RED_PRIO_5, 0x000064), + REG(SYS_COUNT_RX_RED_PRIO_6, 0x000068), + REG(SYS_COUNT_RX_RED_PRIO_7, 0x00006c), + REG(SYS_COUNT_RX_YELLOW_PRIO_0, 0x000070), + REG(SYS_COUNT_RX_YELLOW_PRIO_1, 0x000074), + REG(SYS_COUNT_RX_YELLOW_PRIO_2, 0x000078), + REG(SYS_COUNT_RX_YELLOW_PRIO_3, 0x00007c), + REG(SYS_COUNT_RX_YELLOW_PRIO_4, 0x000080), + REG(SYS_COUNT_RX_YELLOW_PRIO_5, 0x000084), + REG(SYS_COUNT_RX_YELLOW_PRIO_6, 0x000088), + REG(SYS_COUNT_RX_YELLOW_PRIO_7, 0x00008c), + REG(SYS_COUNT_RX_GREEN_PRIO_0, 0x000090), + REG(SYS_COUNT_RX_GREEN_PRIO_1, 0x000094), + REG(SYS_COUNT_RX_GREEN_PRIO_2, 0x000098), + REG(SYS_COUNT_RX_GREEN_PRIO_3, 0x00009c), + REG(SYS_COUNT_RX_GREEN_PRIO_4, 0x0000a0), + REG(SYS_COUNT_RX_GREEN_PRIO_5, 0x0000a4), + REG(SYS_COUNT_RX_GREEN_PRIO_6, 0x0000a8), + REG(SYS_COUNT_RX_GREEN_PRIO_7, 0x0000ac), REG(SYS_COUNT_TX_OCTETS, 0x000100), + REG(SYS_COUNT_TX_UNICAST, 0x000104), + REG(SYS_COUNT_TX_MULTICAST, 0x000108), + REG(SYS_COUNT_TX_BROADCAST, 0x00010c), REG(SYS_COUNT_TX_COLLISION, 0x000110), REG(SYS_COUNT_TX_DROPS, 0x000114), + REG(SYS_COUNT_TX_PAUSE, 0x000118), REG(SYS_COUNT_TX_64, 0x00011c), REG(SYS_COUNT_TX_65_127, 0x000120), REG(SYS_COUNT_TX_128_255, 0x000124), @@ -292,7 +327,41 @@ static const u32 vsc9953_sys_regmap[] = { REG(SYS_COUNT_TX_512_1023, 0x00012c), REG(SYS_COUNT_TX_1024_1526, 0x000130), REG(SYS_COUNT_TX_1527_MAX, 0x000134), + REG(SYS_COUNT_TX_YELLOW_PRIO_0, 0x000138), + REG(SYS_COUNT_TX_YELLOW_PRIO_1, 0x00013c), + REG(SYS_COUNT_TX_YELLOW_PRIO_2, 0x000140), + REG(SYS_COUNT_TX_YELLOW_PRIO_3, 0x000144), + REG(SYS_COUNT_TX_YELLOW_PRIO_4, 0x000148), + REG(SYS_COUNT_TX_YELLOW_PRIO_5, 0x00014c), + REG(SYS_COUNT_TX_YELLOW_PRIO_6, 0x000150), + REG(SYS_COUNT_TX_YELLOW_PRIO_7, 0x000154), + REG(SYS_COUNT_TX_GREEN_PRIO_0, 0x000158), + REG(SYS_COUNT_TX_GREEN_PRIO_1, 0x00015c), + REG(SYS_COUNT_TX_GREEN_PRIO_2, 0x000160), + REG(SYS_COUNT_TX_GREEN_PRIO_3, 0x000164), + REG(SYS_COUNT_TX_GREEN_PRIO_4, 0x000168), + REG(SYS_COUNT_TX_GREEN_PRIO_5, 0x00016c), + REG(SYS_COUNT_TX_GREEN_PRIO_6, 0x000170), + REG(SYS_COUNT_TX_GREEN_PRIO_7, 0x000174), REG(SYS_COUNT_TX_AGING, 0x000178), + REG(SYS_COUNT_DROP_LOCAL, 0x000200), + REG(SYS_COUNT_DROP_TAIL, 0x000204), + REG(SYS_COUNT_DROP_YELLOW_PRIO_0, 0x000208), + REG(SYS_COUNT_DROP_YELLOW_PRIO_1, 0x00020c), + REG(SYS_COUNT_DROP_YELLOW_PRIO_2, 0x000210), + REG(SYS_COUNT_DROP_YELLOW_PRIO_3, 0x000214), + REG(SYS_COUNT_DROP_YELLOW_PRIO_4, 0x000218), + REG(SYS_COUNT_DROP_YELLOW_PRIO_5, 0x00021c), + REG(SYS_COUNT_DROP_YELLOW_PRIO_6, 0x000220), + REG(SYS_COUNT_DROP_YELLOW_PRIO_7, 0x000224), + REG(SYS_COUNT_DROP_GREEN_PRIO_0, 0x000228), + REG(SYS_COUNT_DROP_GREEN_PRIO_1, 0x00022c), + REG(SYS_COUNT_DROP_GREEN_PRIO_2, 0x000230), + REG(SYS_COUNT_DROP_GREEN_PRIO_3, 0x000234), + REG(SYS_COUNT_DROP_GREEN_PRIO_4, 0x000238), + REG(SYS_COUNT_DROP_GREEN_PRIO_5, 0x00023c), + REG(SYS_COUNT_DROP_GREEN_PRIO_6, 0x000240), + REG(SYS_COUNT_DROP_GREEN_PRIO_7, 0x000244), REG(SYS_RESET_CFG, 0x000318), REG_RESERVED(SYS_SR_ETYPE_CFG), REG(SYS_VLAN_ETYPE_CFG, 0x000320), @@ -548,375 +617,375 @@ static const struct reg_field vsc9953_regfields[REGFIELD_MAX] = { static const struct ocelot_stat_layout vsc9953_stats_layout[OCELOT_NUM_STATS] = { [OCELOT_STAT_RX_OCTETS] = { .name = "rx_octets", - .offset = 0x00, + .reg = SYS_COUNT_RX_OCTETS, }, [OCELOT_STAT_RX_UNICAST] = { .name = "rx_unicast", - .offset = 0x01, + .reg = SYS_COUNT_RX_UNICAST, }, [OCELOT_STAT_RX_MULTICAST] = { .name = "rx_multicast", - .offset = 0x02, + .reg = SYS_COUNT_RX_MULTICAST, }, [OCELOT_STAT_RX_BROADCAST] = { .name = "rx_broadcast", - .offset = 0x03, + .reg = SYS_COUNT_RX_BROADCAST, }, [OCELOT_STAT_RX_SHORTS] = { .name = "rx_shorts", - .offset = 0x04, + .reg = SYS_COUNT_RX_SHORTS, }, [OCELOT_STAT_RX_FRAGMENTS] = { .name = "rx_fragments", - .offset = 0x05, + .reg = SYS_COUNT_RX_FRAGMENTS, }, [OCELOT_STAT_RX_JABBERS] = { .name = "rx_jabbers", - .offset = 0x06, + .reg = SYS_COUNT_RX_JABBERS, }, [OCELOT_STAT_RX_CRC_ALIGN_ERRS] = { .name = "rx_crc_align_errs", - .offset = 0x07, + .reg = SYS_COUNT_RX_CRC_ALIGN_ERRS, }, [OCELOT_STAT_RX_SYM_ERRS] = { .name = "rx_sym_errs", - .offset = 0x08, + .reg = SYS_COUNT_RX_SYM_ERRS, }, [OCELOT_STAT_RX_64] = { .name = "rx_frames_below_65_octets", - .offset = 0x09, + .reg = SYS_COUNT_RX_64, }, [OCELOT_STAT_RX_65_127] = { .name = "rx_frames_65_to_127_octets", - .offset = 0x0A, + .reg = SYS_COUNT_RX_65_127, }, [OCELOT_STAT_RX_128_255] = { .name = "rx_frames_128_to_255_octets", - .offset = 0x0B, + .reg = SYS_COUNT_RX_128_255, }, [OCELOT_STAT_RX_256_511] = { .name = "rx_frames_256_to_511_octets", - .offset = 0x0C, + .reg = SYS_COUNT_RX_256_511, }, [OCELOT_STAT_RX_512_1023] = { .name = "rx_frames_512_to_1023_octets", - .offset = 0x0D, + .reg = SYS_COUNT_RX_512_1023, }, [OCELOT_STAT_RX_1024_1526] = { .name = "rx_frames_1024_to_1526_octets", - .offset = 0x0E, + .reg = SYS_COUNT_RX_1024_1526, }, [OCELOT_STAT_RX_1527_MAX] = { .name = "rx_frames_over_1526_octets", - .offset = 0x0F, + .reg = SYS_COUNT_RX_1527_MAX, }, [OCELOT_STAT_RX_PAUSE] = { .name = "rx_pause", - .offset = 0x10, + .reg = SYS_COUNT_RX_PAUSE, }, [OCELOT_STAT_RX_CONTROL] = { .name = "rx_control", - .offset = 0x11, + .reg = SYS_COUNT_RX_CONTROL, }, [OCELOT_STAT_RX_LONGS] = { .name = "rx_longs", - .offset = 0x12, + .reg = SYS_COUNT_RX_LONGS, }, [OCELOT_STAT_RX_CLASSIFIED_DROPS] = { .name = "rx_classified_drops", - .offset = 0x13, + .reg = SYS_COUNT_RX_CLASSIFIED_DROPS, }, [OCELOT_STAT_RX_RED_PRIO_0] = { .name = "rx_red_prio_0", - .offset = 0x14, + .reg = SYS_COUNT_RX_RED_PRIO_0, }, [OCELOT_STAT_RX_RED_PRIO_1] = { .name = "rx_red_prio_1", - .offset = 0x15, + .reg = SYS_COUNT_RX_RED_PRIO_1, }, [OCELOT_STAT_RX_RED_PRIO_2] = { .name = "rx_red_prio_2", - .offset = 0x16, + .reg = SYS_COUNT_RX_RED_PRIO_2, }, [OCELOT_STAT_RX_RED_PRIO_3] = { .name = "rx_red_prio_3", - .offset = 0x17, + .reg = SYS_COUNT_RX_RED_PRIO_3, }, [OCELOT_STAT_RX_RED_PRIO_4] = { .name = "rx_red_prio_4", - .offset = 0x18, + .reg = SYS_COUNT_RX_RED_PRIO_4, }, [OCELOT_STAT_RX_RED_PRIO_5] = { .name = "rx_red_prio_5", - .offset = 0x19, + .reg = SYS_COUNT_RX_RED_PRIO_5, }, [OCELOT_STAT_RX_RED_PRIO_6] = { .name = "rx_red_prio_6", - .offset = 0x1A, + .reg = SYS_COUNT_RX_RED_PRIO_6, }, [OCELOT_STAT_RX_RED_PRIO_7] = { .name = "rx_red_prio_7", - .offset = 0x1B, + .reg = SYS_COUNT_RX_RED_PRIO_7, }, [OCELOT_STAT_RX_YELLOW_PRIO_0] = { .name = "rx_yellow_prio_0", - .offset = 0x1C, + .reg = SYS_COUNT_RX_YELLOW_PRIO_0, }, [OCELOT_STAT_RX_YELLOW_PRIO_1] = { .name = "rx_yellow_prio_1", - .offset = 0x1D, + .reg = SYS_COUNT_RX_YELLOW_PRIO_1, }, [OCELOT_STAT_RX_YELLOW_PRIO_2] = { .name = "rx_yellow_prio_2", - .offset = 0x1E, + .reg = SYS_COUNT_RX_YELLOW_PRIO_2, }, [OCELOT_STAT_RX_YELLOW_PRIO_3] = { .name = "rx_yellow_prio_3", - .offset = 0x1F, + .reg = SYS_COUNT_RX_YELLOW_PRIO_3, }, [OCELOT_STAT_RX_YELLOW_PRIO_4] = { .name = "rx_yellow_prio_4", - .offset = 0x20, + .reg = SYS_COUNT_RX_YELLOW_PRIO_4, }, [OCELOT_STAT_RX_YELLOW_PRIO_5] = { .name = "rx_yellow_prio_5", - .offset = 0x21, + .reg = SYS_COUNT_RX_YELLOW_PRIO_5, }, [OCELOT_STAT_RX_YELLOW_PRIO_6] = { .name = "rx_yellow_prio_6", - .offset = 0x22, + .reg = SYS_COUNT_RX_YELLOW_PRIO_6, }, [OCELOT_STAT_RX_YELLOW_PRIO_7] = { .name = "rx_yellow_prio_7", - .offset = 0x23, + .reg = SYS_COUNT_RX_YELLOW_PRIO_7, }, [OCELOT_STAT_RX_GREEN_PRIO_0] = { .name = "rx_green_prio_0", - .offset = 0x24, + .reg = SYS_COUNT_RX_GREEN_PRIO_0, }, [OCELOT_STAT_RX_GREEN_PRIO_1] = { .name = "rx_green_prio_1", - .offset = 0x25, + .reg = SYS_COUNT_RX_GREEN_PRIO_1, }, [OCELOT_STAT_RX_GREEN_PRIO_2] = { .name = "rx_green_prio_2", - .offset = 0x26, + .reg = SYS_COUNT_RX_GREEN_PRIO_2, }, [OCELOT_STAT_RX_GREEN_PRIO_3] = { .name = "rx_green_prio_3", - .offset = 0x27, + .reg = SYS_COUNT_RX_GREEN_PRIO_3, }, [OCELOT_STAT_RX_GREEN_PRIO_4] = { .name = "rx_green_prio_4", - .offset = 0x28, + .reg = SYS_COUNT_RX_GREEN_PRIO_4, }, [OCELOT_STAT_RX_GREEN_PRIO_5] = { .name = "rx_green_prio_5", - .offset = 0x29, + .reg = SYS_COUNT_RX_GREEN_PRIO_5, }, [OCELOT_STAT_RX_GREEN_PRIO_6] = { .name = "rx_green_prio_6", - .offset = 0x2A, + .reg = SYS_COUNT_RX_GREEN_PRIO_6, }, [OCELOT_STAT_RX_GREEN_PRIO_7] = { .name = "rx_green_prio_7", - .offset = 0x2B, + .reg = SYS_COUNT_RX_GREEN_PRIO_7, }, [OCELOT_STAT_TX_OCTETS] = { .name = "tx_octets", - .offset = 0x40, + .reg = SYS_COUNT_TX_OCTETS, }, [OCELOT_STAT_TX_UNICAST] = { .name = "tx_unicast", - .offset = 0x41, + .reg = SYS_COUNT_TX_UNICAST, }, [OCELOT_STAT_TX_MULTICAST] = { .name = "tx_multicast", - .offset = 0x42, + .reg = SYS_COUNT_TX_MULTICAST, }, [OCELOT_STAT_TX_BROADCAST] = { .name = "tx_broadcast", - .offset = 0x43, + .reg = SYS_COUNT_TX_BROADCAST, }, [OCELOT_STAT_TX_COLLISION] = { .name = "tx_collision", - .offset = 0x44, + .reg = SYS_COUNT_TX_COLLISION, }, [OCELOT_STAT_TX_DROPS] = { .name = "tx_drops", - .offset = 0x45, + .reg = SYS_COUNT_TX_DROPS, }, [OCELOT_STAT_TX_PAUSE] = { .name = "tx_pause", - .offset = 0x46, + .reg = SYS_COUNT_TX_PAUSE, }, [OCELOT_STAT_TX_64] = { .name = "tx_frames_below_65_octets", - .offset = 0x47, + .reg = SYS_COUNT_TX_64, }, [OCELOT_STAT_TX_65_127] = { .name = "tx_frames_65_to_127_octets", - .offset = 0x48, + .reg = SYS_COUNT_TX_65_127, }, [OCELOT_STAT_TX_128_255] = { .name = "tx_frames_128_255_octets", - .offset = 0x49, + .reg = SYS_COUNT_TX_128_255, }, [OCELOT_STAT_TX_256_511] = { .name = "tx_frames_256_511_octets", - .offset = 0x4A, + .reg = SYS_COUNT_TX_256_511, }, [OCELOT_STAT_TX_512_1023] = { .name = "tx_frames_512_1023_octets", - .offset = 0x4B, + .reg = SYS_COUNT_TX_512_1023, }, [OCELOT_STAT_TX_1024_1526] = { .name = "tx_frames_1024_1526_octets", - .offset = 0x4C, + .reg = SYS_COUNT_TX_1024_1526, }, [OCELOT_STAT_TX_1527_MAX] = { .name = "tx_frames_over_1526_octets", - .offset = 0x4D, + .reg = SYS_COUNT_TX_1527_MAX, }, [OCELOT_STAT_TX_YELLOW_PRIO_0] = { .name = "tx_yellow_prio_0", - .offset = 0x4E, + .reg = SYS_COUNT_TX_YELLOW_PRIO_0, }, [OCELOT_STAT_TX_YELLOW_PRIO_1] = { .name = "tx_yellow_prio_1", - .offset = 0x4F, + .reg = SYS_COUNT_TX_YELLOW_PRIO_1, }, [OCELOT_STAT_TX_YELLOW_PRIO_2] = { .name = "tx_yellow_prio_2", - .offset = 0x50, + .reg = SYS_COUNT_TX_YELLOW_PRIO_2, }, [OCELOT_STAT_TX_YELLOW_PRIO_3] = { .name = "tx_yellow_prio_3", - .offset = 0x51, + .reg = SYS_COUNT_TX_YELLOW_PRIO_3, }, [OCELOT_STAT_TX_YELLOW_PRIO_4] = { .name = "tx_yellow_prio_4", - .offset = 0x52, + .reg = SYS_COUNT_TX_YELLOW_PRIO_4, }, [OCELOT_STAT_TX_YELLOW_PRIO_5] = { .name = "tx_yellow_prio_5", - .offset = 0x53, + .reg = SYS_COUNT_TX_YELLOW_PRIO_5, }, [OCELOT_STAT_TX_YELLOW_PRIO_6] = { .name = "tx_yellow_prio_6", - .offset = 0x54, + .reg = SYS_COUNT_TX_YELLOW_PRIO_6, }, [OCELOT_STAT_TX_YELLOW_PRIO_7] = { .name = "tx_yellow_prio_7", - .offset = 0x55, + .reg = SYS_COUNT_TX_YELLOW_PRIO_7, }, [OCELOT_STAT_TX_GREEN_PRIO_0] = { .name = "tx_green_prio_0", - .offset = 0x56, + .reg = SYS_COUNT_TX_GREEN_PRIO_0, }, [OCELOT_STAT_TX_GREEN_PRIO_1] = { .name = "tx_green_prio_1", - .offset = 0x57, + .reg = SYS_COUNT_TX_GREEN_PRIO_1, }, [OCELOT_STAT_TX_GREEN_PRIO_2] = { .name = "tx_green_prio_2", - .offset = 0x58, + .reg = SYS_COUNT_TX_GREEN_PRIO_2, }, [OCELOT_STAT_TX_GREEN_PRIO_3] = { .name = "tx_green_prio_3", - .offset = 0x59, + .reg = SYS_COUNT_TX_GREEN_PRIO_3, }, [OCELOT_STAT_TX_GREEN_PRIO_4] = { .name = "tx_green_prio_4", - .offset = 0x5A, + .reg = SYS_COUNT_TX_GREEN_PRIO_4, }, [OCELOT_STAT_TX_GREEN_PRIO_5] = { .name = "tx_green_prio_5", - .offset = 0x5B, + .reg = SYS_COUNT_TX_GREEN_PRIO_5, }, [OCELOT_STAT_TX_GREEN_PRIO_6] = { .name = "tx_green_prio_6", - .offset = 0x5C, + .reg = SYS_COUNT_TX_GREEN_PRIO_6, }, [OCELOT_STAT_TX_GREEN_PRIO_7] = { .name = "tx_green_prio_7", - .offset = 0x5D, + .reg = SYS_COUNT_TX_GREEN_PRIO_7, }, [OCELOT_STAT_TX_AGED] = { .name = "tx_aged", - .offset = 0x5E, + .reg = SYS_COUNT_TX_AGING, }, [OCELOT_STAT_DROP_LOCAL] = { .name = "drop_local", - .offset = 0x80, + .reg = SYS_COUNT_DROP_LOCAL, }, [OCELOT_STAT_DROP_TAIL] = { .name = "drop_tail", - .offset = 0x81, + .reg = SYS_COUNT_DROP_TAIL, }, [OCELOT_STAT_DROP_YELLOW_PRIO_0] = { .name = "drop_yellow_prio_0", - .offset = 0x82, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_0, }, [OCELOT_STAT_DROP_YELLOW_PRIO_1] = { .name = "drop_yellow_prio_1", - .offset = 0x83, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_1, }, [OCELOT_STAT_DROP_YELLOW_PRIO_2] = { .name = "drop_yellow_prio_2", - .offset = 0x84, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_2, }, [OCELOT_STAT_DROP_YELLOW_PRIO_3] = { .name = "drop_yellow_prio_3", - .offset = 0x85, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_3, }, [OCELOT_STAT_DROP_YELLOW_PRIO_4] = { .name = "drop_yellow_prio_4", - .offset = 0x86, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_4, }, [OCELOT_STAT_DROP_YELLOW_PRIO_5] = { .name = "drop_yellow_prio_5", - .offset = 0x87, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_5, }, [OCELOT_STAT_DROP_YELLOW_PRIO_6] = { .name = "drop_yellow_prio_6", - .offset = 0x88, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_6, }, [OCELOT_STAT_DROP_YELLOW_PRIO_7] = { .name = "drop_yellow_prio_7", - .offset = 0x89, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_7, }, [OCELOT_STAT_DROP_GREEN_PRIO_0] = { .name = "drop_green_prio_0", - .offset = 0x8A, + .reg = SYS_COUNT_DROP_GREEN_PRIO_0, }, [OCELOT_STAT_DROP_GREEN_PRIO_1] = { .name = "drop_green_prio_1", - .offset = 0x8B, + .reg = SYS_COUNT_DROP_GREEN_PRIO_1, }, [OCELOT_STAT_DROP_GREEN_PRIO_2] = { .name = "drop_green_prio_2", - .offset = 0x8C, + .reg = SYS_COUNT_DROP_GREEN_PRIO_2, }, [OCELOT_STAT_DROP_GREEN_PRIO_3] = { .name = "drop_green_prio_3", - .offset = 0x8D, + .reg = SYS_COUNT_DROP_GREEN_PRIO_3, }, [OCELOT_STAT_DROP_GREEN_PRIO_4] = { .name = "drop_green_prio_4", - .offset = 0x8E, + .reg = SYS_COUNT_DROP_GREEN_PRIO_4, }, [OCELOT_STAT_DROP_GREEN_PRIO_5] = { .name = "drop_green_prio_5", - .offset = 0x8F, + .reg = SYS_COUNT_DROP_GREEN_PRIO_5, }, [OCELOT_STAT_DROP_GREEN_PRIO_6] = { .name = "drop_green_prio_6", - .offset = 0x90, + .reg = SYS_COUNT_DROP_GREEN_PRIO_6, }, [OCELOT_STAT_DROP_GREEN_PRIO_7] = { .name = "drop_green_prio_7", - .offset = 0x91, + .reg = SYS_COUNT_DROP_GREEN_PRIO_7, }, }; diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 68991b021c560..306026e6aa111 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1881,9 +1881,8 @@ static int ocelot_port_update_stats(struct ocelot *ocelot, int port) ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port), SYS_STAT_CFG); list_for_each_entry(region, &ocelot->stats_regions, node) { - err = ocelot_bulk_read_rix(ocelot, SYS_COUNT_RX_OCTETS, - region->offset, region->buf, - region->count); + err = ocelot_bulk_read(ocelot, region->base, region->buf, + region->count); if (err) return err; @@ -1978,7 +1977,7 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot) if (ocelot->stats_layout[i].name[0] == '\0') continue; - if (region && ocelot->stats_layout[i].offset == last + 1) { + if (region && ocelot->stats_layout[i].reg == last + 4) { region->count++; } else { region = devm_kzalloc(ocelot->dev, sizeof(*region), @@ -1986,12 +1985,12 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot) if (!region) return -ENOMEM; - region->offset = ocelot->stats_layout[i].offset; + region->base = ocelot->stats_layout[i].reg; region->count = 1; list_add_tail(®ion->node, &ocelot->stats_regions); } - last = ocelot->stats_layout[i].offset; + last = ocelot->stats_layout[i].reg; } list_for_each_entry(region, &ocelot->stats_regions, node) { diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 9ff9105600438..9c488953f541d 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -99,375 +99,375 @@ static const struct reg_field ocelot_regfields[REGFIELD_MAX] = { static const struct ocelot_stat_layout ocelot_stats_layout[OCELOT_NUM_STATS] = { [OCELOT_STAT_RX_OCTETS] = { .name = "rx_octets", - .offset = 0x00, + .reg = SYS_COUNT_RX_OCTETS, }, [OCELOT_STAT_RX_UNICAST] = { .name = "rx_unicast", - .offset = 0x01, + .reg = SYS_COUNT_RX_UNICAST, }, [OCELOT_STAT_RX_MULTICAST] = { .name = "rx_multicast", - .offset = 0x02, + .reg = SYS_COUNT_RX_MULTICAST, }, [OCELOT_STAT_RX_BROADCAST] = { .name = "rx_broadcast", - .offset = 0x03, + .reg = SYS_COUNT_RX_BROADCAST, }, [OCELOT_STAT_RX_SHORTS] = { .name = "rx_shorts", - .offset = 0x04, + .reg = SYS_COUNT_RX_SHORTS, }, [OCELOT_STAT_RX_FRAGMENTS] = { .name = "rx_fragments", - .offset = 0x05, + .reg = SYS_COUNT_RX_FRAGMENTS, }, [OCELOT_STAT_RX_JABBERS] = { .name = "rx_jabbers", - .offset = 0x06, + .reg = SYS_COUNT_RX_JABBERS, }, [OCELOT_STAT_RX_CRC_ALIGN_ERRS] = { .name = "rx_crc_align_errs", - .offset = 0x07, + .reg = SYS_COUNT_RX_CRC_ALIGN_ERRS, }, [OCELOT_STAT_RX_SYM_ERRS] = { .name = "rx_sym_errs", - .offset = 0x08, + .reg = SYS_COUNT_RX_SYM_ERRS, }, [OCELOT_STAT_RX_64] = { .name = "rx_frames_below_65_octets", - .offset = 0x09, + .reg = SYS_COUNT_RX_64, }, [OCELOT_STAT_RX_65_127] = { .name = "rx_frames_65_to_127_octets", - .offset = 0x0A, + .reg = SYS_COUNT_RX_65_127, }, [OCELOT_STAT_RX_128_255] = { .name = "rx_frames_128_to_255_octets", - .offset = 0x0B, + .reg = SYS_COUNT_RX_128_255, }, [OCELOT_STAT_RX_256_511] = { .name = "rx_frames_256_to_511_octets", - .offset = 0x0C, + .reg = SYS_COUNT_RX_256_511, }, [OCELOT_STAT_RX_512_1023] = { .name = "rx_frames_512_to_1023_octets", - .offset = 0x0D, + .reg = SYS_COUNT_RX_512_1023, }, [OCELOT_STAT_RX_1024_1526] = { .name = "rx_frames_1024_to_1526_octets", - .offset = 0x0E, + .reg = SYS_COUNT_RX_1024_1526, }, [OCELOT_STAT_RX_1527_MAX] = { .name = "rx_frames_over_1526_octets", - .offset = 0x0F, + .reg = SYS_COUNT_RX_1527_MAX, }, [OCELOT_STAT_RX_PAUSE] = { .name = "rx_pause", - .offset = 0x10, + .reg = SYS_COUNT_RX_PAUSE, }, [OCELOT_STAT_RX_CONTROL] = { .name = "rx_control", - .offset = 0x11, + .reg = SYS_COUNT_RX_CONTROL, }, [OCELOT_STAT_RX_LONGS] = { .name = "rx_longs", - .offset = 0x12, + .reg = SYS_COUNT_RX_LONGS, }, [OCELOT_STAT_RX_CLASSIFIED_DROPS] = { .name = "rx_classified_drops", - .offset = 0x13, + .reg = SYS_COUNT_RX_CLASSIFIED_DROPS, }, [OCELOT_STAT_RX_RED_PRIO_0] = { .name = "rx_red_prio_0", - .offset = 0x14, + .reg = SYS_COUNT_RX_RED_PRIO_0, }, [OCELOT_STAT_RX_RED_PRIO_1] = { .name = "rx_red_prio_1", - .offset = 0x15, + .reg = SYS_COUNT_RX_RED_PRIO_1, }, [OCELOT_STAT_RX_RED_PRIO_2] = { .name = "rx_red_prio_2", - .offset = 0x16, + .reg = SYS_COUNT_RX_RED_PRIO_2, }, [OCELOT_STAT_RX_RED_PRIO_3] = { .name = "rx_red_prio_3", - .offset = 0x17, + .reg = SYS_COUNT_RX_RED_PRIO_3, }, [OCELOT_STAT_RX_RED_PRIO_4] = { .name = "rx_red_prio_4", - .offset = 0x18, + .reg = SYS_COUNT_RX_RED_PRIO_4, }, [OCELOT_STAT_RX_RED_PRIO_5] = { .name = "rx_red_prio_5", - .offset = 0x19, + .reg = SYS_COUNT_RX_RED_PRIO_5, }, [OCELOT_STAT_RX_RED_PRIO_6] = { .name = "rx_red_prio_6", - .offset = 0x1A, + .reg = SYS_COUNT_RX_RED_PRIO_6, }, [OCELOT_STAT_RX_RED_PRIO_7] = { .name = "rx_red_prio_7", - .offset = 0x1B, + .reg = SYS_COUNT_RX_RED_PRIO_7, }, [OCELOT_STAT_RX_YELLOW_PRIO_0] = { .name = "rx_yellow_prio_0", - .offset = 0x1C, + .reg = SYS_COUNT_RX_YELLOW_PRIO_0, }, [OCELOT_STAT_RX_YELLOW_PRIO_1] = { .name = "rx_yellow_prio_1", - .offset = 0x1D, + .reg = SYS_COUNT_RX_YELLOW_PRIO_1, }, [OCELOT_STAT_RX_YELLOW_PRIO_2] = { .name = "rx_yellow_prio_2", - .offset = 0x1E, + .reg = SYS_COUNT_RX_YELLOW_PRIO_2, }, [OCELOT_STAT_RX_YELLOW_PRIO_3] = { .name = "rx_yellow_prio_3", - .offset = 0x1F, + .reg = SYS_COUNT_RX_YELLOW_PRIO_3, }, [OCELOT_STAT_RX_YELLOW_PRIO_4] = { .name = "rx_yellow_prio_4", - .offset = 0x20, + .reg = SYS_COUNT_RX_YELLOW_PRIO_4, }, [OCELOT_STAT_RX_YELLOW_PRIO_5] = { .name = "rx_yellow_prio_5", - .offset = 0x21, + .reg = SYS_COUNT_RX_YELLOW_PRIO_5, }, [OCELOT_STAT_RX_YELLOW_PRIO_6] = { .name = "rx_yellow_prio_6", - .offset = 0x22, + .reg = SYS_COUNT_RX_YELLOW_PRIO_6, }, [OCELOT_STAT_RX_YELLOW_PRIO_7] = { .name = "rx_yellow_prio_7", - .offset = 0x23, + .reg = SYS_COUNT_RX_YELLOW_PRIO_7, }, [OCELOT_STAT_RX_GREEN_PRIO_0] = { .name = "rx_green_prio_0", - .offset = 0x24, + .reg = SYS_COUNT_RX_GREEN_PRIO_0, }, [OCELOT_STAT_RX_GREEN_PRIO_1] = { .name = "rx_green_prio_1", - .offset = 0x25, + .reg = SYS_COUNT_RX_GREEN_PRIO_1, }, [OCELOT_STAT_RX_GREEN_PRIO_2] = { .name = "rx_green_prio_2", - .offset = 0x26, + .reg = SYS_COUNT_RX_GREEN_PRIO_2, }, [OCELOT_STAT_RX_GREEN_PRIO_3] = { .name = "rx_green_prio_3", - .offset = 0x27, + .reg = SYS_COUNT_RX_GREEN_PRIO_3, }, [OCELOT_STAT_RX_GREEN_PRIO_4] = { .name = "rx_green_prio_4", - .offset = 0x28, + .reg = SYS_COUNT_RX_GREEN_PRIO_4, }, [OCELOT_STAT_RX_GREEN_PRIO_5] = { .name = "rx_green_prio_5", - .offset = 0x29, + .reg = SYS_COUNT_RX_GREEN_PRIO_5, }, [OCELOT_STAT_RX_GREEN_PRIO_6] = { .name = "rx_green_prio_6", - .offset = 0x2A, + .reg = SYS_COUNT_RX_GREEN_PRIO_6, }, [OCELOT_STAT_RX_GREEN_PRIO_7] = { .name = "rx_green_prio_7", - .offset = 0x2B, + .reg = SYS_COUNT_RX_GREEN_PRIO_7, }, [OCELOT_STAT_TX_OCTETS] = { .name = "tx_octets", - .offset = 0x40, + .reg = SYS_COUNT_TX_OCTETS, }, [OCELOT_STAT_TX_UNICAST] = { .name = "tx_unicast", - .offset = 0x41, + .reg = SYS_COUNT_TX_UNICAST, }, [OCELOT_STAT_TX_MULTICAST] = { .name = "tx_multicast", - .offset = 0x42, + .reg = SYS_COUNT_TX_MULTICAST, }, [OCELOT_STAT_TX_BROADCAST] = { .name = "tx_broadcast", - .offset = 0x43, + .reg = SYS_COUNT_TX_BROADCAST, }, [OCELOT_STAT_TX_COLLISION] = { .name = "tx_collision", - .offset = 0x44, + .reg = SYS_COUNT_TX_COLLISION, }, [OCELOT_STAT_TX_DROPS] = { .name = "tx_drops", - .offset = 0x45, + .reg = SYS_COUNT_TX_DROPS, }, [OCELOT_STAT_TX_PAUSE] = { .name = "tx_pause", - .offset = 0x46, + .reg = SYS_COUNT_TX_PAUSE, }, [OCELOT_STAT_TX_64] = { .name = "tx_frames_below_65_octets", - .offset = 0x47, + .reg = SYS_COUNT_TX_64, }, [OCELOT_STAT_TX_65_127] = { .name = "tx_frames_65_to_127_octets", - .offset = 0x48, + .reg = SYS_COUNT_TX_65_127, }, [OCELOT_STAT_TX_128_255] = { .name = "tx_frames_128_255_octets", - .offset = 0x49, + .reg = SYS_COUNT_TX_128_255, }, [OCELOT_STAT_TX_256_511] = { .name = "tx_frames_256_511_octets", - .offset = 0x4A, + .reg = SYS_COUNT_TX_256_511, }, [OCELOT_STAT_TX_512_1023] = { .name = "tx_frames_512_1023_octets", - .offset = 0x4B, + .reg = SYS_COUNT_TX_512_1023, }, [OCELOT_STAT_TX_1024_1526] = { .name = "tx_frames_1024_1526_octets", - .offset = 0x4C, + .reg = SYS_COUNT_TX_1024_1526, }, [OCELOT_STAT_TX_1527_MAX] = { .name = "tx_frames_over_1526_octets", - .offset = 0x4D, + .reg = SYS_COUNT_TX_1527_MAX, }, [OCELOT_STAT_TX_YELLOW_PRIO_0] = { .name = "tx_yellow_prio_0", - .offset = 0x4E, + .reg = SYS_COUNT_TX_YELLOW_PRIO_0, }, [OCELOT_STAT_TX_YELLOW_PRIO_1] = { .name = "tx_yellow_prio_1", - .offset = 0x4F, + .reg = SYS_COUNT_TX_YELLOW_PRIO_1, }, [OCELOT_STAT_TX_YELLOW_PRIO_2] = { .name = "tx_yellow_prio_2", - .offset = 0x50, + .reg = SYS_COUNT_TX_YELLOW_PRIO_2, }, [OCELOT_STAT_TX_YELLOW_PRIO_3] = { .name = "tx_yellow_prio_3", - .offset = 0x51, + .reg = SYS_COUNT_TX_YELLOW_PRIO_3, }, [OCELOT_STAT_TX_YELLOW_PRIO_4] = { .name = "tx_yellow_prio_4", - .offset = 0x52, + .reg = SYS_COUNT_TX_YELLOW_PRIO_4, }, [OCELOT_STAT_TX_YELLOW_PRIO_5] = { .name = "tx_yellow_prio_5", - .offset = 0x53, + .reg = SYS_COUNT_TX_YELLOW_PRIO_5, }, [OCELOT_STAT_TX_YELLOW_PRIO_6] = { .name = "tx_yellow_prio_6", - .offset = 0x54, + .reg = SYS_COUNT_TX_YELLOW_PRIO_6, }, [OCELOT_STAT_TX_YELLOW_PRIO_7] = { .name = "tx_yellow_prio_7", - .offset = 0x55, + .reg = SYS_COUNT_TX_YELLOW_PRIO_7, }, [OCELOT_STAT_TX_GREEN_PRIO_0] = { .name = "tx_green_prio_0", - .offset = 0x56, + .reg = SYS_COUNT_TX_GREEN_PRIO_0, }, [OCELOT_STAT_TX_GREEN_PRIO_1] = { .name = "tx_green_prio_1", - .offset = 0x57, + .reg = SYS_COUNT_TX_GREEN_PRIO_1, }, [OCELOT_STAT_TX_GREEN_PRIO_2] = { .name = "tx_green_prio_2", - .offset = 0x58, + .reg = SYS_COUNT_TX_GREEN_PRIO_2, }, [OCELOT_STAT_TX_GREEN_PRIO_3] = { .name = "tx_green_prio_3", - .offset = 0x59, + .reg = SYS_COUNT_TX_GREEN_PRIO_3, }, [OCELOT_STAT_TX_GREEN_PRIO_4] = { .name = "tx_green_prio_4", - .offset = 0x5A, + .reg = SYS_COUNT_TX_GREEN_PRIO_4, }, [OCELOT_STAT_TX_GREEN_PRIO_5] = { .name = "tx_green_prio_5", - .offset = 0x5B, + .reg = SYS_COUNT_TX_GREEN_PRIO_5, }, [OCELOT_STAT_TX_GREEN_PRIO_6] = { .name = "tx_green_prio_6", - .offset = 0x5C, + .reg = SYS_COUNT_TX_GREEN_PRIO_6, }, [OCELOT_STAT_TX_GREEN_PRIO_7] = { .name = "tx_green_prio_7", - .offset = 0x5D, + .reg = SYS_COUNT_TX_GREEN_PRIO_7, }, [OCELOT_STAT_TX_AGED] = { .name = "tx_aged", - .offset = 0x5E, + .reg = SYS_COUNT_TX_AGING, }, [OCELOT_STAT_DROP_LOCAL] = { .name = "drop_local", - .offset = 0x80, + .reg = SYS_COUNT_DROP_LOCAL, }, [OCELOT_STAT_DROP_TAIL] = { .name = "drop_tail", - .offset = 0x81, + .reg = SYS_COUNT_DROP_TAIL, }, [OCELOT_STAT_DROP_YELLOW_PRIO_0] = { .name = "drop_yellow_prio_0", - .offset = 0x82, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_0, }, [OCELOT_STAT_DROP_YELLOW_PRIO_1] = { .name = "drop_yellow_prio_1", - .offset = 0x83, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_1, }, [OCELOT_STAT_DROP_YELLOW_PRIO_2] = { .name = "drop_yellow_prio_2", - .offset = 0x84, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_2, }, [OCELOT_STAT_DROP_YELLOW_PRIO_3] = { .name = "drop_yellow_prio_3", - .offset = 0x85, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_3, }, [OCELOT_STAT_DROP_YELLOW_PRIO_4] = { .name = "drop_yellow_prio_4", - .offset = 0x86, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_4, }, [OCELOT_STAT_DROP_YELLOW_PRIO_5] = { .name = "drop_yellow_prio_5", - .offset = 0x87, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_5, }, [OCELOT_STAT_DROP_YELLOW_PRIO_6] = { .name = "drop_yellow_prio_6", - .offset = 0x88, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_6, }, [OCELOT_STAT_DROP_YELLOW_PRIO_7] = { .name = "drop_yellow_prio_7", - .offset = 0x89, + .reg = SYS_COUNT_DROP_YELLOW_PRIO_7, }, [OCELOT_STAT_DROP_GREEN_PRIO_0] = { .name = "drop_green_prio_0", - .offset = 0x8A, + .reg = SYS_COUNT_DROP_GREEN_PRIO_0, }, [OCELOT_STAT_DROP_GREEN_PRIO_1] = { .name = "drop_green_prio_1", - .offset = 0x8B, + .reg = SYS_COUNT_DROP_GREEN_PRIO_1, }, [OCELOT_STAT_DROP_GREEN_PRIO_2] = { .name = "drop_green_prio_2", - .offset = 0x8C, + .reg = SYS_COUNT_DROP_GREEN_PRIO_2, }, [OCELOT_STAT_DROP_GREEN_PRIO_3] = { .name = "drop_green_prio_3", - .offset = 0x8D, + .reg = SYS_COUNT_DROP_GREEN_PRIO_3, }, [OCELOT_STAT_DROP_GREEN_PRIO_4] = { .name = "drop_green_prio_4", - .offset = 0x8E, + .reg = SYS_COUNT_DROP_GREEN_PRIO_4, }, [OCELOT_STAT_DROP_GREEN_PRIO_5] = { .name = "drop_green_prio_5", - .offset = 0x8F, + .reg = SYS_COUNT_DROP_GREEN_PRIO_5, }, [OCELOT_STAT_DROP_GREEN_PRIO_6] = { .name = "drop_green_prio_6", - .offset = 0x90, + .reg = SYS_COUNT_DROP_GREEN_PRIO_6, }, [OCELOT_STAT_DROP_GREEN_PRIO_7] = { .name = "drop_green_prio_7", - .offset = 0x91, + .reg = SYS_COUNT_DROP_GREEN_PRIO_7, }, }; diff --git a/drivers/net/ethernet/mscc/vsc7514_regs.c b/drivers/net/ethernet/mscc/vsc7514_regs.c index 8ff935f7f150c..9cf82ecf191cd 100644 --- a/drivers/net/ethernet/mscc/vsc7514_regs.c +++ b/drivers/net/ethernet/mscc/vsc7514_regs.c @@ -188,6 +188,30 @@ const u32 vsc7514_sys_regmap[] = { REG(SYS_COUNT_RX_CONTROL, 0x000044), REG(SYS_COUNT_RX_LONGS, 0x000048), REG(SYS_COUNT_RX_CLASSIFIED_DROPS, 0x00004c), + REG(SYS_COUNT_RX_RED_PRIO_0, 0x000050), + REG(SYS_COUNT_RX_RED_PRIO_1, 0x000054), + REG(SYS_COUNT_RX_RED_PRIO_2, 0x000058), + REG(SYS_COUNT_RX_RED_PRIO_3, 0x00005c), + REG(SYS_COUNT_RX_RED_PRIO_4, 0x000060), + REG(SYS_COUNT_RX_RED_PRIO_5, 0x000064), + REG(SYS_COUNT_RX_RED_PRIO_6, 0x000068), + REG(SYS_COUNT_RX_RED_PRIO_7, 0x00006c), + REG(SYS_COUNT_RX_YELLOW_PRIO_0, 0x000070), + REG(SYS_COUNT_RX_YELLOW_PRIO_1, 0x000074), + REG(SYS_COUNT_RX_YELLOW_PRIO_2, 0x000078), + REG(SYS_COUNT_RX_YELLOW_PRIO_3, 0x00007c), + REG(SYS_COUNT_RX_YELLOW_PRIO_4, 0x000080), + REG(SYS_COUNT_RX_YELLOW_PRIO_5, 0x000084), + REG(SYS_COUNT_RX_YELLOW_PRIO_6, 0x000088), + REG(SYS_COUNT_RX_YELLOW_PRIO_7, 0x00008c), + REG(SYS_COUNT_RX_GREEN_PRIO_0, 0x000090), + REG(SYS_COUNT_RX_GREEN_PRIO_1, 0x000094), + REG(SYS_COUNT_RX_GREEN_PRIO_2, 0x000098), + REG(SYS_COUNT_RX_GREEN_PRIO_3, 0x00009c), + REG(SYS_COUNT_RX_GREEN_PRIO_4, 0x0000a0), + REG(SYS_COUNT_RX_GREEN_PRIO_5, 0x0000a4), + REG(SYS_COUNT_RX_GREEN_PRIO_6, 0x0000a8), + REG(SYS_COUNT_RX_GREEN_PRIO_7, 0x0000ac), REG(SYS_COUNT_TX_OCTETS, 0x000100), REG(SYS_COUNT_TX_UNICAST, 0x000104), REG(SYS_COUNT_TX_MULTICAST, 0x000108), @@ -202,7 +226,41 @@ const u32 vsc7514_sys_regmap[] = { REG(SYS_COUNT_TX_512_1023, 0x00012c), REG(SYS_COUNT_TX_1024_1526, 0x000130), REG(SYS_COUNT_TX_1527_MAX, 0x000134), + REG(SYS_COUNT_TX_YELLOW_PRIO_0, 0x000138), + REG(SYS_COUNT_TX_YELLOW_PRIO_1, 0x00013c), + REG(SYS_COUNT_TX_YELLOW_PRIO_2, 0x000140), + REG(SYS_COUNT_TX_YELLOW_PRIO_3, 0x000144), + REG(SYS_COUNT_TX_YELLOW_PRIO_4, 0x000148), + REG(SYS_COUNT_TX_YELLOW_PRIO_5, 0x00014c), + REG(SYS_COUNT_TX_YELLOW_PRIO_6, 0x000150), + REG(SYS_COUNT_TX_YELLOW_PRIO_7, 0x000154), + REG(SYS_COUNT_TX_GREEN_PRIO_0, 0x000158), + REG(SYS_COUNT_TX_GREEN_PRIO_1, 0x00015c), + REG(SYS_COUNT_TX_GREEN_PRIO_2, 0x000160), + REG(SYS_COUNT_TX_GREEN_PRIO_3, 0x000164), + REG(SYS_COUNT_TX_GREEN_PRIO_4, 0x000168), + REG(SYS_COUNT_TX_GREEN_PRIO_5, 0x00016c), + REG(SYS_COUNT_TX_GREEN_PRIO_6, 0x000170), + REG(SYS_COUNT_TX_GREEN_PRIO_7, 0x000174), REG(SYS_COUNT_TX_AGING, 0x000178), + REG(SYS_COUNT_DROP_LOCAL, 0x000200), + REG(SYS_COUNT_DROP_TAIL, 0x000204), + REG(SYS_COUNT_DROP_YELLOW_PRIO_0, 0x000208), + REG(SYS_COUNT_DROP_YELLOW_PRIO_1, 0x00020c), + REG(SYS_COUNT_DROP_YELLOW_PRIO_2, 0x000210), + REG(SYS_COUNT_DROP_YELLOW_PRIO_3, 0x000214), + REG(SYS_COUNT_DROP_YELLOW_PRIO_4, 0x000218), + REG(SYS_COUNT_DROP_YELLOW_PRIO_5, 0x00021c), + REG(SYS_COUNT_DROP_YELLOW_PRIO_6, 0x000220), + REG(SYS_COUNT_DROP_YELLOW_PRIO_7, 0x000214), + REG(SYS_COUNT_DROP_GREEN_PRIO_0, 0x000218), + REG(SYS_COUNT_DROP_GREEN_PRIO_1, 0x00021c), + REG(SYS_COUNT_DROP_GREEN_PRIO_2, 0x000220), + REG(SYS_COUNT_DROP_GREEN_PRIO_3, 0x000224), + REG(SYS_COUNT_DROP_GREEN_PRIO_4, 0x000228), + REG(SYS_COUNT_DROP_GREEN_PRIO_5, 0x00022c), + REG(SYS_COUNT_DROP_GREEN_PRIO_6, 0x000230), + REG(SYS_COUNT_DROP_GREEN_PRIO_7, 0x000234), REG(SYS_RESET_CFG, 0x000508), REG(SYS_CMID, 0x00050c), REG(SYS_VLAN_ETYPE_CFG, 0x000510), diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 2428bc64cb1d6..2edea901bbd5a 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -338,6 +338,30 @@ enum ocelot_reg { SYS_COUNT_RX_CONTROL, SYS_COUNT_RX_LONGS, SYS_COUNT_RX_CLASSIFIED_DROPS, + SYS_COUNT_RX_RED_PRIO_0, + SYS_COUNT_RX_RED_PRIO_1, + SYS_COUNT_RX_RED_PRIO_2, + SYS_COUNT_RX_RED_PRIO_3, + SYS_COUNT_RX_RED_PRIO_4, + SYS_COUNT_RX_RED_PRIO_5, + SYS_COUNT_RX_RED_PRIO_6, + SYS_COUNT_RX_RED_PRIO_7, + SYS_COUNT_RX_YELLOW_PRIO_0, + SYS_COUNT_RX_YELLOW_PRIO_1, + SYS_COUNT_RX_YELLOW_PRIO_2, + SYS_COUNT_RX_YELLOW_PRIO_3, + SYS_COUNT_RX_YELLOW_PRIO_4, + SYS_COUNT_RX_YELLOW_PRIO_5, + SYS_COUNT_RX_YELLOW_PRIO_6, + SYS_COUNT_RX_YELLOW_PRIO_7, + SYS_COUNT_RX_GREEN_PRIO_0, + SYS_COUNT_RX_GREEN_PRIO_1, + SYS_COUNT_RX_GREEN_PRIO_2, + SYS_COUNT_RX_GREEN_PRIO_3, + SYS_COUNT_RX_GREEN_PRIO_4, + SYS_COUNT_RX_GREEN_PRIO_5, + SYS_COUNT_RX_GREEN_PRIO_6, + SYS_COUNT_RX_GREEN_PRIO_7, SYS_COUNT_TX_OCTETS, SYS_COUNT_TX_UNICAST, SYS_COUNT_TX_MULTICAST, @@ -352,7 +376,41 @@ enum ocelot_reg { SYS_COUNT_TX_512_1023, SYS_COUNT_TX_1024_1526, SYS_COUNT_TX_1527_MAX, + SYS_COUNT_TX_YELLOW_PRIO_0, + SYS_COUNT_TX_YELLOW_PRIO_1, + SYS_COUNT_TX_YELLOW_PRIO_2, + SYS_COUNT_TX_YELLOW_PRIO_3, + SYS_COUNT_TX_YELLOW_PRIO_4, + SYS_COUNT_TX_YELLOW_PRIO_5, + SYS_COUNT_TX_YELLOW_PRIO_6, + SYS_COUNT_TX_YELLOW_PRIO_7, + SYS_COUNT_TX_GREEN_PRIO_0, + SYS_COUNT_TX_GREEN_PRIO_1, + SYS_COUNT_TX_GREEN_PRIO_2, + SYS_COUNT_TX_GREEN_PRIO_3, + SYS_COUNT_TX_GREEN_PRIO_4, + SYS_COUNT_TX_GREEN_PRIO_5, + SYS_COUNT_TX_GREEN_PRIO_6, + SYS_COUNT_TX_GREEN_PRIO_7, SYS_COUNT_TX_AGING, + SYS_COUNT_DROP_LOCAL, + SYS_COUNT_DROP_TAIL, + SYS_COUNT_DROP_YELLOW_PRIO_0, + SYS_COUNT_DROP_YELLOW_PRIO_1, + SYS_COUNT_DROP_YELLOW_PRIO_2, + SYS_COUNT_DROP_YELLOW_PRIO_3, + SYS_COUNT_DROP_YELLOW_PRIO_4, + SYS_COUNT_DROP_YELLOW_PRIO_5, + SYS_COUNT_DROP_YELLOW_PRIO_6, + SYS_COUNT_DROP_YELLOW_PRIO_7, + SYS_COUNT_DROP_GREEN_PRIO_0, + SYS_COUNT_DROP_GREEN_PRIO_1, + SYS_COUNT_DROP_GREEN_PRIO_2, + SYS_COUNT_DROP_GREEN_PRIO_3, + SYS_COUNT_DROP_GREEN_PRIO_4, + SYS_COUNT_DROP_GREEN_PRIO_5, + SYS_COUNT_DROP_GREEN_PRIO_6, + SYS_COUNT_DROP_GREEN_PRIO_7, SYS_RESET_CFG, SYS_SR_ETYPE_CFG, SYS_VLAN_ETYPE_CFG, @@ -633,13 +691,13 @@ enum ocelot_stat { }; struct ocelot_stat_layout { - u32 offset; + u32 reg; char name[ETH_GSTRING_LEN]; }; struct ocelot_stats_region { struct list_head node; - u32 offset; + u32 base; int count; u32 *buf; }; @@ -877,8 +935,8 @@ struct ocelot_policer { u32 burst; /* bytes */ }; -#define ocelot_bulk_read_rix(ocelot, reg, ri, buf, count) \ - __ocelot_bulk_read_ix(ocelot, reg, reg##_RSZ * (ri), buf, count) +#define ocelot_bulk_read(ocelot, reg, buf, count) \ + __ocelot_bulk_read_ix(ocelot, reg, 0, buf, count) #define ocelot_read_ix(ocelot, reg, gi, ri) \ __ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi) + reg##_RSZ * (ri)) From e780e3193e889fd8358b862f7cd18ec5a4901caf Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 16 Aug 2022 16:53:52 +0300 Subject: [PATCH 360/427] net: mscc: ocelot: report ndo_get_stats64 from the wraparound-resistant ocelot->stats Rather than reading the stats64 counters directly from the 32-bit hardware, it's better to rely on the output produced by the periodic ocelot_port_update_stats(). It would be even better to call ocelot_port_update_stats() right from ocelot_get_stats64() to make sure we report the current values rather than the ones from 2 seconds ago. But we need to export ocelot_port_update_stats() from the switch lib towards the switchdev driver for that, and future work will largely undo that. There are more ocelot-based drivers waiting to be introduced, an example of which is the SPI-controlled VSC7512. In that driver's case, it will be impossible to call ocelot_port_update_stats() from ndo_get_stats64 context, since the latter is atomic, and reading the stats over SPI is sleepable. So the compromise taken here, which will also hold going forward, is to report 64-bit counters to stats64, which are not 100% up to date. Fixes: a556c76adc05 ("net: mscc: Add initial Ocelot switch support") Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mscc/ocelot_net.c | 53 +++++++++++++------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index 6b9d371388441..330d30841cdc4 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -725,41 +725,40 @@ static void ocelot_get_stats64(struct net_device *dev, struct ocelot_port_private *priv = netdev_priv(dev); struct ocelot *ocelot = priv->port.ocelot; int port = priv->port.index; + u64 *s; spin_lock(&ocelot->stats_lock); - /* Configure the port to read the stats from */ - ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port), - SYS_STAT_CFG); + s = &ocelot->stats[port * OCELOT_NUM_STATS]; /* Get Rx stats */ - stats->rx_bytes = ocelot_read(ocelot, SYS_COUNT_RX_OCTETS); - stats->rx_packets = ocelot_read(ocelot, SYS_COUNT_RX_SHORTS) + - ocelot_read(ocelot, SYS_COUNT_RX_FRAGMENTS) + - ocelot_read(ocelot, SYS_COUNT_RX_JABBERS) + - ocelot_read(ocelot, SYS_COUNT_RX_LONGS) + - ocelot_read(ocelot, SYS_COUNT_RX_64) + - ocelot_read(ocelot, SYS_COUNT_RX_65_127) + - ocelot_read(ocelot, SYS_COUNT_RX_128_255) + - ocelot_read(ocelot, SYS_COUNT_RX_256_511) + - ocelot_read(ocelot, SYS_COUNT_RX_512_1023) + - ocelot_read(ocelot, SYS_COUNT_RX_1024_1526) + - ocelot_read(ocelot, SYS_COUNT_RX_1527_MAX); - stats->multicast = ocelot_read(ocelot, SYS_COUNT_RX_MULTICAST); + stats->rx_bytes = s[OCELOT_STAT_RX_OCTETS]; + stats->rx_packets = s[OCELOT_STAT_RX_SHORTS] + + s[OCELOT_STAT_RX_FRAGMENTS] + + s[OCELOT_STAT_RX_JABBERS] + + s[OCELOT_STAT_RX_LONGS] + + s[OCELOT_STAT_RX_64] + + s[OCELOT_STAT_RX_65_127] + + s[OCELOT_STAT_RX_128_255] + + s[OCELOT_STAT_RX_256_511] + + s[OCELOT_STAT_RX_512_1023] + + s[OCELOT_STAT_RX_1024_1526] + + s[OCELOT_STAT_RX_1527_MAX]; + stats->multicast = s[OCELOT_STAT_RX_MULTICAST]; stats->rx_dropped = dev->stats.rx_dropped; /* Get Tx stats */ - stats->tx_bytes = ocelot_read(ocelot, SYS_COUNT_TX_OCTETS); - stats->tx_packets = ocelot_read(ocelot, SYS_COUNT_TX_64) + - ocelot_read(ocelot, SYS_COUNT_TX_65_127) + - ocelot_read(ocelot, SYS_COUNT_TX_128_255) + - ocelot_read(ocelot, SYS_COUNT_TX_256_511) + - ocelot_read(ocelot, SYS_COUNT_TX_512_1023) + - ocelot_read(ocelot, SYS_COUNT_TX_1024_1526) + - ocelot_read(ocelot, SYS_COUNT_TX_1527_MAX); - stats->tx_dropped = ocelot_read(ocelot, SYS_COUNT_TX_DROPS) + - ocelot_read(ocelot, SYS_COUNT_TX_AGING); - stats->collisions = ocelot_read(ocelot, SYS_COUNT_TX_COLLISION); + stats->tx_bytes = s[OCELOT_STAT_TX_OCTETS]; + stats->tx_packets = s[OCELOT_STAT_TX_64] + + s[OCELOT_STAT_TX_65_127] + + s[OCELOT_STAT_TX_128_255] + + s[OCELOT_STAT_TX_256_511] + + s[OCELOT_STAT_TX_512_1023] + + s[OCELOT_STAT_TX_1024_1526] + + s[OCELOT_STAT_TX_1527_MAX]; + stats->tx_dropped = s[OCELOT_STAT_TX_DROPS] + + s[OCELOT_STAT_TX_AGED]; + stats->collisions = s[OCELOT_STAT_TX_COLLISION]; spin_unlock(&ocelot->stats_lock); } From d515f38c1e6dac42db145a778bd87a241f89590c Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Tue, 16 Aug 2022 11:47:23 +0300 Subject: [PATCH 361/427] net/mlx5e: Allocate flow steering storage during uplink initialization IPsec code relies on valid priv->fs pointer that is the case in NIC flow, but not correct in uplink. Before commit that mentioned in the Fixes line, that pointer was valid in all flows as it was allocated together with priv struct. In addition, the cleanup representors routine called to that not-initialized priv->fs pointer and its internals which caused NULL deference. So, move FS allocation to be as early as possible. Fixes: af8bbf730068 ("net/mlx5e: Convert mlx5e_flow_steering member of mlx5e_priv to pointer") Signed-off-by: Leon Romanovsky Link: https://lore.kernel.org/r/ae46fa5bed3c67f937bfdfc0370101278f5422f1.1660639564.git.leonro@nvidia.com Signed-off-by: Jakub Kicinski --- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 4c1599de652c1..0c66774a1720c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -696,6 +696,13 @@ static int mlx5e_init_rep(struct mlx5_core_dev *mdev, { struct mlx5e_priv *priv = netdev_priv(netdev); + priv->fs = mlx5e_fs_init(priv->profile, mdev, + !test_bit(MLX5E_STATE_DESTROYING, &priv->state)); + if (!priv->fs) { + netdev_err(priv->netdev, "FS allocation failed\n"); + return -ENOMEM; + } + mlx5e_build_rep_params(netdev); mlx5e_timestamp_init(priv); @@ -708,12 +715,21 @@ static int mlx5e_init_ul_rep(struct mlx5_core_dev *mdev, struct mlx5e_priv *priv = netdev_priv(netdev); int err; + priv->fs = mlx5e_fs_init(priv->profile, mdev, + !test_bit(MLX5E_STATE_DESTROYING, &priv->state)); + if (!priv->fs) { + netdev_err(priv->netdev, "FS allocation failed\n"); + return -ENOMEM; + } + err = mlx5e_ipsec_init(priv); if (err) mlx5_core_err(mdev, "Uplink rep IPsec initialization failed, %d\n", err); mlx5e_vxlan_set_netdev_info(priv); - return mlx5e_init_rep(mdev, netdev); + mlx5e_build_rep_params(netdev); + mlx5e_timestamp_init(priv); + return 0; } static void mlx5e_cleanup_rep(struct mlx5e_priv *priv) @@ -836,13 +852,6 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv) struct mlx5_core_dev *mdev = priv->mdev; int err; - priv->fs = mlx5e_fs_init(priv->profile, mdev, - !test_bit(MLX5E_STATE_DESTROYING, &priv->state)); - if (!priv->fs) { - netdev_err(priv->netdev, "FS allocation failed\n"); - return -ENOMEM; - } - priv->rx_res = mlx5e_rx_res_alloc(); if (!priv->rx_res) { err = -ENOMEM; From a617ccc01608c3f422c65da1b6c7a31057f46f62 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 16 Aug 2022 16:16:15 +0200 Subject: [PATCH 362/427] net: ethernet: mtk_eth_soc: fix possible NULL pointer dereference in mtk_xdp_run Fix possible NULL pointer dereference in mtk_xdp_run() if the ebpf program returns XDP_TX and xdp_convert_buff_to_frame routine fails returning NULL. Fixes: 5886d26fd25bb ("net: ethernet: mtk_eth_soc: add xmit XDP support") Signed-off-by: Lorenzo Bianconi Link: https://lore.kernel.org/r/627a07d759020356b64473e09f0855960e02db28.1660659112.git.lorenzo@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index d9426b01f4628..8aff4c0c28bd7 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -1732,7 +1732,7 @@ static u32 mtk_xdp_run(struct mtk_eth *eth, struct mtk_rx_ring *ring, case XDP_TX: { struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp); - if (mtk_xdp_submit_frame(eth, xdpf, dev, false)) { + if (!xdpf || mtk_xdp_submit_frame(eth, xdpf, dev, false)) { count = &hw_stats->xdp_stats.rx_xdp_tx_errors; act = XDP_DROP; break; From 3f743e9bbb8fe20f4c477e4bf6341c4187a4a264 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Thu, 18 Aug 2022 12:38:34 +0100 Subject: [PATCH 363/427] io_uring/net: use right helpers for async_data There is another spot where we check ->async_data directly instead of using req_has_async_data(), which is the way to do it, fix it up. Fixes: 43e0bbbd0b0e3 ("io_uring: add netmsg cache") Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/42f33b9a81dd6ae65dda92f0372b0ff82d548517.1660822636.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- io_uring/net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/io_uring/net.c b/io_uring/net.c index f7cbd716817fe..f8cdf1dc3863b 100644 --- a/io_uring/net.c +++ b/io_uring/net.c @@ -152,9 +152,9 @@ static int io_setup_async_msg(struct io_kiocb *req, struct io_async_msghdr *kmsg, unsigned int issue_flags) { - struct io_async_msghdr *async_msg = req->async_data; + struct io_async_msghdr *async_msg; - if (async_msg) + if (req_has_async_data(req)) return -EAGAIN; async_msg = io_recvmsg_alloc_async(req, issue_flags); if (!async_msg) { From a8239f0342bae5a51acca967ba95b9a8ad56dd62 Mon Sep 17 00:00:00 2001 From: Yu Kuai Date: Thu, 18 Aug 2022 14:35:55 +0800 Subject: [PATCH 364/427] blk-mq: remove unused function blk_mq_queue_stopped() blk_mq_queue_stopped() doesn't have any caller, which was found by code coverage test, thus remove it. Signed-off-by: Yu Kuai Link: https://lore.kernel.org/r/20220818063555.3741222-1-yukuai1@huaweicloud.com Signed-off-by: Jens Axboe --- block/blk-mq.c | 20 -------------------- include/linux/blk-mq.h | 1 - 2 files changed, 21 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 5ee62b95f3e5d..5568c7d09114f 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -2229,26 +2229,6 @@ void blk_mq_delay_run_hw_queues(struct request_queue *q, unsigned long msecs) } EXPORT_SYMBOL(blk_mq_delay_run_hw_queues); -/** - * blk_mq_queue_stopped() - check whether one or more hctxs have been stopped - * @q: request queue. - * - * The caller is responsible for serializing this function against - * blk_mq_{start,stop}_hw_queue(). - */ -bool blk_mq_queue_stopped(struct request_queue *q) -{ - struct blk_mq_hw_ctx *hctx; - unsigned long i; - - queue_for_each_hw_ctx(q, hctx, i) - if (blk_mq_hctx_stopped(hctx)) - return true; - - return false; -} -EXPORT_SYMBOL(blk_mq_queue_stopped); - /* * This function is often used for pausing .queue_rq() by driver when * there isn't enough resource or some conditions aren't satisfied, and diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index effee1dc715a2..92294a5fb0836 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -857,7 +857,6 @@ void blk_mq_kick_requeue_list(struct request_queue *q); void blk_mq_delay_kick_requeue_list(struct request_queue *q, unsigned long msecs); void blk_mq_complete_request(struct request *rq); bool blk_mq_complete_request_remote(struct request *rq); -bool blk_mq_queue_stopped(struct request_queue *q); void blk_mq_stop_hw_queue(struct blk_mq_hw_ctx *hctx); void blk_mq_start_hw_queue(struct blk_mq_hw_ctx *hctx); void blk_mq_stop_hw_queues(struct request_queue *q); From d3b38596875dbc709b4e721a5873f4663d8a9ea2 Mon Sep 17 00:00:00 2001 From: Yufen Yu Date: Wed, 3 Aug 2022 10:33:55 +0800 Subject: [PATCH 365/427] blk-mq: run queue no matter whether the request is the last request We do test on a virtio scsi device (/dev/sda) and the default mq scheduler is 'none'. We found a IO hung as following: blk_finish_plug blk_mq_plug_issue_direct scsi_mq_get_budget //get budget_token fail and sdev->restarts=1 scsi_end_request scsi_run_queue_async //sdev->restart=0 and run queue blk_mq_request_bypass_insert //add request to hctx->dispatch list //continue to dispath plug list blk_mq_dispatch_plug_list blk_mq_try_issue_list_directly //success issue all requests from plug list After .get_budget fail, scsi_mq_get_budget will increase 'restarts'. Normally, it will run hw queue when io complete and set 'restarts' as 0. But if we run queue before adding request to the dispatch list and blk_mq_dispatch_plug_list also success issue all requests, then on one will run queue, and the request will be stall in the dispatch list and cannot complete forever. It is wrong to use last request of plug list to decide if run queue is needed since all the remained requests in plug list may be from other hctxs. To fix the bug, pass run_queue as true always to blk_mq_request_bypass_insert(). Fix-suggested-by: Ming Lei Signed-off-by: Yufen Yu Reviewed-by: Ming Lei Fixes: dc5fc361d891 ("block: attempt direct issue of plug list") Link: https://lore.kernel.org/r/20220803023355.3687360-1-yuyufen@huaweicloud.com Signed-off-by: Jens Axboe --- block/blk-mq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 5568c7d09114f..3c1e6b6d991d2 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -2550,7 +2550,7 @@ static void blk_mq_plug_issue_direct(struct blk_plug *plug, bool from_schedule) break; case BLK_STS_RESOURCE: case BLK_STS_DEV_RESOURCE: - blk_mq_request_bypass_insert(rq, false, last); + blk_mq_request_bypass_insert(rq, false, true); blk_mq_commit_rqs(hctx, &queued, from_schedule); return; default: From 573ae4f13f630d6660008f1974c0a8a29c30e18a Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Thu, 18 Aug 2022 13:08:59 +0200 Subject: [PATCH 366/427] tee: add overflow check in register_shm_helper() With special lengths supplied by user space, register_shm_helper() has an integer overflow when calculating the number of pages covered by a supplied user space memory region. This causes internal_get_user_pages_fast() a helper function of pin_user_pages_fast() to do a NULL pointer dereference: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010 Modules linked in: CPU: 1 PID: 173 Comm: optee_example_a Not tainted 5.19.0 #11 Hardware name: QEMU QEMU Virtual Machine, BIOS 0.0.0 02/06/2015 pc : internal_get_user_pages_fast+0x474/0xa80 Call trace: internal_get_user_pages_fast+0x474/0xa80 pin_user_pages_fast+0x24/0x4c register_shm_helper+0x194/0x330 tee_shm_register_user_buf+0x78/0x120 tee_ioctl+0xd0/0x11a0 __arm64_sys_ioctl+0xa8/0xec invoke_syscall+0x48/0x114 Fix this by adding an an explicit call to access_ok() in tee_shm_register_user_buf() to catch an invalid user space address early. Fixes: 033ddf12bcf5 ("tee: add register user memory") Cc: stable@vger.kernel.org Reported-by: Nimish Mishra Reported-by: Anirban Chakraborty Reported-by: Debdeep Mukhopadhyay Suggested-by: Jerome Forissier Signed-off-by: Jens Wiklander Signed-off-by: Linus Torvalds --- drivers/tee/tee_shm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index f2b1bcefcadd7..1175f3a46859f 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -326,6 +326,9 @@ struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx, void *ret; int id; + if (!access_ok((void __user *)addr, length)) + return ERR_PTR(-EFAULT); + mutex_lock(&teedev->mutex); id = idr_alloc(&teedev->idr, NULL, 1, 0, GFP_KERNEL); mutex_unlock(&teedev->mutex); From 5c23d6b717e4e956376f3852b90f58e262946b50 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 16 Aug 2022 16:23:57 +0200 Subject: [PATCH 367/427] stmmac: intel: Add a missing clk_disable_unprepare() call in intel_eth_pci_remove() Commit 09f012e64e4b ("stmmac: intel: Fix clock handling on error and remove paths") removed this clk_disable_unprepare() This was partly revert by commit ac322f86b56c ("net: stmmac: Fix clock handling on remove path") which removed this clk_disable_unprepare() because: " While unloading the dwmac-intel driver, clk_disable_unprepare() is being called twice in stmmac_dvr_remove() and intel_eth_pci_remove(). This causes kernel panic on the second call. " However later on, commit 5ec55823438e8 ("net: stmmac: add clocks management for gmac driver") has updated stmmac_dvr_remove() which do not call clk_disable_unprepare() anymore. So this call should now be called from intel_eth_pci_remove(). Fixes: 5ec55823438e8 ("net: stmmac: add clocks management for gmac driver") Signed-off-by: Christophe JAILLET Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/d7c8c1dadf40df3a7c9e643f76ffadd0ccc1ad1b.1660659689.git.christophe.jaillet@wanadoo.fr Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index 52f9ed8db9c98..4f2b82a884b91 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -1134,6 +1134,7 @@ static void intel_eth_pci_remove(struct pci_dev *pdev) stmmac_dvr_remove(&pdev->dev); + clk_disable_unprepare(priv->plat->stmmac_clk); clk_unregister_fixed_rate(priv->plat->stmmac_clk); pcim_iounmap_regions(pdev, BIT(0)); From 249801360db3dec4f73768c502192020bfddeacc Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 16 Aug 2022 09:19:39 -0700 Subject: [PATCH 368/427] net: genl: fix error path memory leak in policy dumping If construction of the array of policies fails when recording non-first policy we need to unwind. netlink_policy_dump_add_policy() itself also needs fixing as it currently gives up on error without recording the allocated pointer in the pstate pointer. Reported-by: syzbot+dc54d9ba8153b216cae0@syzkaller.appspotmail.com Fixes: 50a896cf2d6f ("genetlink: properly support per-op policy dumping") Link: https://lore.kernel.org/r/20220816161939.577583-1-kuba@kernel.org Signed-off-by: Jakub Kicinski --- net/netlink/genetlink.c | 6 +++++- net/netlink/policy.c | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 1afca2a6c2ac1..57010927e20a8 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -1174,13 +1174,17 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb) op.policy, op.maxattr); if (err) - return err; + goto err_free_state; } } if (!ctx->state) return -ENODATA; return 0; + +err_free_state: + netlink_policy_dump_free(ctx->state); + return err; } static void *ctrl_dumppolicy_prep(struct sk_buff *skb, diff --git a/net/netlink/policy.c b/net/netlink/policy.c index 8d7c900e27f4c..87e3de0fde896 100644 --- a/net/netlink/policy.c +++ b/net/netlink/policy.c @@ -144,7 +144,7 @@ int netlink_policy_dump_add_policy(struct netlink_policy_dump_state **pstate, err = add_policy(&state, policy, maxtype); if (err) - return err; + goto err_try_undo; for (policy_idx = 0; policy_idx < state->n_alloc && state->policies[policy_idx].policy; @@ -164,7 +164,7 @@ int netlink_policy_dump_add_policy(struct netlink_policy_dump_state **pstate, policy[type].nested_policy, policy[type].len); if (err) - return err; + goto err_try_undo; break; default: break; @@ -174,6 +174,16 @@ int netlink_policy_dump_add_policy(struct netlink_policy_dump_state **pstate, *pstate = state; return 0; + +err_try_undo: + /* Try to preserve reasonable unwind semantics - if we're starting from + * scratch clean up fully, otherwise record what we got and caller will. + */ + if (!*pstate) + netlink_policy_dump_free(state); + else + *pstate = state; + return err; } static bool From 8aa48ade7db4738bcc57447dccbf21db6618f64e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 17 Aug 2022 18:54:51 +0200 Subject: [PATCH 369/427] dt-bindings: Fix incorrect "the the" corrections Lots of double occurrences of "the" were replaced by single occurrences, but some of them should become "to the" instead. Fixes: 12e5bde18d7f6ca4 ("dt-bindings: Fix typo in comment") Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/c5743c0a1a24b3a8893797b52fed88b99e56b04b.1660755148.git.geert+renesas@glider.be Signed-off-by: Jakub Kicinski --- Documentation/devicetree/bindings/net/qcom-emac.txt | 2 +- Documentation/devicetree/bindings/thermal/rcar-thermal.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/net/qcom-emac.txt b/Documentation/devicetree/bindings/net/qcom-emac.txt index e6cb2291471c4..7ae8aa1486345 100644 --- a/Documentation/devicetree/bindings/net/qcom-emac.txt +++ b/Documentation/devicetree/bindings/net/qcom-emac.txt @@ -14,7 +14,7 @@ MAC node: - mac-address : The 6-byte MAC address. If present, it is the default MAC address. - internal-phy : phandle to the internal PHY node -- phy-handle : phandle the external PHY node +- phy-handle : phandle to the external PHY node Internal PHY node: - compatible : Should be "qcom,fsm9900-emac-sgmii" or "qcom,qdf2432-emac-sgmii". diff --git a/Documentation/devicetree/bindings/thermal/rcar-thermal.yaml b/Documentation/devicetree/bindings/thermal/rcar-thermal.yaml index 00dcbdd361442..119998d10ff41 100644 --- a/Documentation/devicetree/bindings/thermal/rcar-thermal.yaml +++ b/Documentation/devicetree/bindings/thermal/rcar-thermal.yaml @@ -42,7 +42,7 @@ properties: description: Address ranges of the thermal registers. If more then one range is given the first one must be the common registers followed by each sensor - according the datasheet. + according to the datasheet. minItems: 1 maxItems: 4 From 6faee3d4ee8be0f0367d0c3d826afb3571b7a5e0 Mon Sep 17 00:00:00 2001 From: Lin Ma Date: Wed, 17 Aug 2022 11:49:21 -0700 Subject: [PATCH 370/427] igb: Add lock to avoid data race The commit c23d92b80e0b ("igb: Teardown SR-IOV before unregister_netdev()") places the unregister_netdev() call after the igb_disable_sriov() call to avoid functionality issue. However, it introduces several race conditions when detaching a device. For example, when .remove() is called, the below interleaving leads to use-after-free. (FREE from device detaching) | (USE from netdev core) igb_remove | igb_ndo_get_vf_config igb_disable_sriov | vf >= adapter->vfs_allocated_count? kfree(adapter->vf_data) | adapter->vfs_allocated_count = 0 | | memcpy(... adapter->vf_data[vf] Moreover, the igb_disable_sriov() also suffers from data race with the requests from VF driver. (FREE from device detaching) | (USE from requests) igb_remove | igb_msix_other igb_disable_sriov | igb_msg_task kfree(adapter->vf_data) | vf < adapter->vfs_allocated_count adapter->vfs_allocated_count = 0 | To this end, this commit first eliminates the data races from netdev core by using rtnl_lock (similar to commit 719479230893 ("dpaa2-eth: add MAC/PHY support through phylink")). And then adds a spinlock to eliminate races from driver requests. (similar to commit 1e53834ce541 ("ixgbe: Add locking to prevent panic when setting sriov_numvfs to zero") Fixes: c23d92b80e0b ("igb: Teardown SR-IOV before unregister_netdev()") Signed-off-by: Lin Ma Tested-by: Konrad Jankowski Signed-off-by: Tony Nguyen Link: https://lore.kernel.org/r/20220817184921.735244-1-anthony.l.nguyen@intel.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/igb/igb.h | 2 ++ drivers/net/ethernet/intel/igb/igb_main.c | 12 +++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 2d3daf022651c..015b781441149 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -664,6 +664,8 @@ struct igb_adapter { struct igb_mac_addr *mac_table; struct vf_mac_filter vf_macs; struct vf_mac_filter *vf_mac_list; + /* lock for VF resources */ + spinlock_t vfs_lock; }; /* flags controlling PTP/1588 function */ diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index d8b836a85cc30..2796e81d27260 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -3637,6 +3637,7 @@ static int igb_disable_sriov(struct pci_dev *pdev) struct net_device *netdev = pci_get_drvdata(pdev); struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; + unsigned long flags; /* reclaim resources allocated to VFs */ if (adapter->vf_data) { @@ -3649,12 +3650,13 @@ static int igb_disable_sriov(struct pci_dev *pdev) pci_disable_sriov(pdev); msleep(500); } - + spin_lock_irqsave(&adapter->vfs_lock, flags); kfree(adapter->vf_mac_list); adapter->vf_mac_list = NULL; kfree(adapter->vf_data); adapter->vf_data = NULL; adapter->vfs_allocated_count = 0; + spin_unlock_irqrestore(&adapter->vfs_lock, flags); wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ); wrfl(); msleep(100); @@ -3814,7 +3816,9 @@ static void igb_remove(struct pci_dev *pdev) igb_release_hw_control(adapter); #ifdef CONFIG_PCI_IOV + rtnl_lock(); igb_disable_sriov(pdev); + rtnl_unlock(); #endif unregister_netdev(netdev); @@ -3974,6 +3978,9 @@ static int igb_sw_init(struct igb_adapter *adapter) spin_lock_init(&adapter->nfc_lock); spin_lock_init(&adapter->stats64_lock); + + /* init spinlock to avoid concurrency of VF resources */ + spin_lock_init(&adapter->vfs_lock); #ifdef CONFIG_PCI_IOV switch (hw->mac.type) { case e1000_82576: @@ -7958,8 +7965,10 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) static void igb_msg_task(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; + unsigned long flags; u32 vf; + spin_lock_irqsave(&adapter->vfs_lock, flags); for (vf = 0; vf < adapter->vfs_allocated_count; vf++) { /* process any reset requests */ if (!igb_check_for_rst(hw, vf)) @@ -7973,6 +7982,7 @@ static void igb_msg_task(struct igb_adapter *adapter) if (!igb_check_for_ack(hw, vf)) igb_rcv_ack_from_vf(adapter, vf); } + spin_unlock_irqrestore(&adapter->vfs_lock, flags); } /** From e9c6e79760265f019cde39d3f2c443dfbc1395b0 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Wed, 17 Aug 2022 12:54:42 -0700 Subject: [PATCH 371/427] tcp: fix sock skb accounting in tcp_read_skb() Before commit 965b57b469a5 ("net: Introduce a new proto_ops ->read_skb()"), skb was not dequeued from receive queue hence when we close TCP socket skb can be just flushed synchronously. After this commit, we have to uncharge skb immediately after being dequeued, otherwise it is still charged in the original sock. And we still need to retain skb->sk, as eBPF programs may extract sock information from skb->sk. Therefore, we have to call skb_set_owner_sk_safe() here. Fixes: 965b57b469a5 ("net: Introduce a new proto_ops ->read_skb()") Reported-and-tested-by: syzbot+a0e6f8738b58f7654417@syzkaller.appspotmail.com Tested-by: Stanislav Fomichev Cc: Eric Dumazet Cc: John Fastabend Cc: Jakub Sitnicki Signed-off-by: Cong Wang Signed-off-by: Jakub Kicinski --- net/ipv4/tcp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 970e9a2cca4ae..05da5cac080b5 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1760,6 +1760,7 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) int used; __skb_unlink(skb, &sk->sk_receive_queue); + WARN_ON(!skb_set_owner_sk_safe(skb, sk)); used = recv_actor(sk, skb); if (used <= 0) { if (!copied) From c457985aaa92e1fda2ce837cabf90bf687b92dcb Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Wed, 17 Aug 2022 12:54:43 -0700 Subject: [PATCH 372/427] tcp: fix tcp_cleanup_rbuf() for tcp_read_skb() tcp_cleanup_rbuf() retrieves the skb from sk_receive_queue, it assumes the skb is not yet dequeued. This is no longer true for tcp_read_skb() case where we dequeue the skb first. Fix this by introducing a helper __tcp_cleanup_rbuf() which does not require any skb and calling it in tcp_read_skb(). Fixes: 04919bed948d ("tcp: Introduce tcp_read_skb()") Cc: Eric Dumazet Cc: John Fastabend Cc: Jakub Sitnicki Signed-off-by: Cong Wang Signed-off-by: Jakub Kicinski --- net/ipv4/tcp.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 05da5cac080b5..181a0d3501233 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1567,17 +1567,11 @@ static int tcp_peek_sndq(struct sock *sk, struct msghdr *msg, int len) * calculation of whether or not we must ACK for the sake of * a window update. */ -void tcp_cleanup_rbuf(struct sock *sk, int copied) +static void __tcp_cleanup_rbuf(struct sock *sk, int copied) { struct tcp_sock *tp = tcp_sk(sk); bool time_to_ack = false; - struct sk_buff *skb = skb_peek(&sk->sk_receive_queue); - - WARN(skb && !before(tp->copied_seq, TCP_SKB_CB(skb)->end_seq), - "cleanup rbuf bug: copied %X seq %X rcvnxt %X\n", - tp->copied_seq, TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt); - if (inet_csk_ack_scheduled(sk)) { const struct inet_connection_sock *icsk = inet_csk(sk); @@ -1623,6 +1617,17 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied) tcp_send_ack(sk); } +void tcp_cleanup_rbuf(struct sock *sk, int copied) +{ + struct sk_buff *skb = skb_peek(&sk->sk_receive_queue); + struct tcp_sock *tp = tcp_sk(sk); + + WARN(skb && !before(tp->copied_seq, TCP_SKB_CB(skb)->end_seq), + "cleanup rbuf bug: copied %X seq %X rcvnxt %X\n", + tp->copied_seq, TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt); + __tcp_cleanup_rbuf(sk, copied); +} + static void tcp_eat_recv_skb(struct sock *sk, struct sk_buff *skb) { __skb_unlink(skb, &sk->sk_receive_queue); @@ -1771,20 +1776,19 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) copied += used; if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) { - consume_skb(skb); ++seq; break; } - consume_skb(skb); break; } + consume_skb(skb); WRITE_ONCE(tp->copied_seq, seq); tcp_rcv_space_adjust(sk); /* Clean up data we have read: This will do ACK frames. */ if (copied > 0) - tcp_cleanup_rbuf(sk, copied); + __tcp_cleanup_rbuf(sk, copied); return copied; } From a8688821f3854f37fe0198b8945f9cfc051ab2cf Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Wed, 17 Aug 2022 12:54:44 -0700 Subject: [PATCH 373/427] tcp: refactor tcp_read_skb() a bit As tcp_read_skb() only reads one skb at a time, the while loop is unnecessary, we can turn it into an if. This also simplifies the code logic. Cc: Eric Dumazet Cc: John Fastabend Cc: Jakub Sitnicki Signed-off-by: Cong Wang Signed-off-by: Jakub Kicinski --- net/ipv4/tcp.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 181a0d3501233..56a554b49caa6 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1761,25 +1761,17 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) if (sk->sk_state == TCP_LISTEN) return -ENOTCONN; - while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) { - int used; - - __skb_unlink(skb, &sk->sk_receive_queue); - WARN_ON(!skb_set_owner_sk_safe(skb, sk)); - used = recv_actor(sk, skb); - if (used <= 0) { - if (!copied) - copied = used; - break; - } - seq += used; - copied += used; + skb = tcp_recv_skb(sk, seq, &offset); + if (!skb) + return 0; - if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) { + __skb_unlink(skb, &sk->sk_receive_queue); + WARN_ON(!skb_set_owner_sk_safe(skb, sk)); + copied = recv_actor(sk, skb); + if (copied > 0) { + seq += copied; + if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) ++seq; - break; - } - break; } consume_skb(skb); WRITE_ONCE(tp->copied_seq, seq); From 2e23acd99efacfd2a63cb9725afbc65e4e964fb7 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Wed, 17 Aug 2022 12:54:45 -0700 Subject: [PATCH 374/427] tcp: handle pure FIN case correctly When skb->len==0, the recv_actor() returns 0 too, but we also use 0 for error conditions. This patch amends this by propagating the errors to tcp_read_skb() so that we can distinguish skb->len==0 case from error cases. Fixes: 04919bed948d ("tcp: Introduce tcp_read_skb()") Reported-by: Eric Dumazet Cc: John Fastabend Cc: Jakub Sitnicki Signed-off-by: Cong Wang Signed-off-by: Jakub Kicinski --- net/core/skmsg.c | 5 +++-- net/ipv4/tcp.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/net/core/skmsg.c b/net/core/skmsg.c index f47338d89d5d5..59e75ffcc1f40 100644 --- a/net/core/skmsg.c +++ b/net/core/skmsg.c @@ -1194,8 +1194,9 @@ static int sk_psock_verdict_recv(struct sock *sk, struct sk_buff *skb) ret = bpf_prog_run_pin_on_cpu(prog, skb); ret = sk_psock_map_verd(ret, skb_bpf_redirect_fetch(skb)); } - if (sk_psock_verdict_apply(psock, skb, ret) < 0) - len = 0; + ret = sk_psock_verdict_apply(psock, skb, ret); + if (ret < 0) + len = ret; out: rcu_read_unlock(); return len; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 56a554b49caa6..bbe2187536620 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1768,7 +1768,7 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) __skb_unlink(skb, &sk->sk_receive_queue); WARN_ON(!skb_set_owner_sk_safe(skb, sk)); copied = recv_actor(sk, skb); - if (copied > 0) { + if (copied >= 0) { seq += copied; if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) ++seq; From f4693b81ea3802d2c28c868e1639e580d0da2d1f Mon Sep 17 00:00:00 2001 From: Sergei Antonov Date: Thu, 18 Aug 2022 12:23:17 +0300 Subject: [PATCH 375/427] net: moxa: MAC address reading, generating, validity checking This device does not remember its MAC address, so add a possibility to get it from the platform. If it fails, generate a random address. This will provide a MAC address early during boot without user space being involved. Also remove extra calls to is_valid_ether_addr(). Made after suggestions by Andrew Lunn: 1) Use eth_hw_addr_random() to assign a random MAC address during probe. 2) Remove is_valid_ether_addr() from moxart_mac_open() 3) Add a call to platform_get_ethdev_address() during probe 4) Remove is_valid_ether_addr() from moxart_set_mac_address(). The core does this v1 -> v2: Handle EPROBE_DEFER returned from platform_get_ethdev_address(). Move MAC reading code to the beginning of the probe function. Signed-off-by: Sergei Antonov Suggested-by: Andrew Lunn CC: Yang Yingliang CC: Pavel Skripkin CC: Guobin Huang CC: Yang Wei CC: Christophe JAILLET Reviewed-by: Andrew Lunn Reviewed-by: Vladimir Oltean Link: https://lore.kernel.org/r/20220818092317.529557-1-saproj@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/moxa/moxart_ether.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c index f11f1cb92025f..19009a6bd33ae 100644 --- a/drivers/net/ethernet/moxa/moxart_ether.c +++ b/drivers/net/ethernet/moxa/moxart_ether.c @@ -62,9 +62,6 @@ static int moxart_set_mac_address(struct net_device *ndev, void *addr) { struct sockaddr *address = addr; - if (!is_valid_ether_addr(address->sa_data)) - return -EADDRNOTAVAIL; - eth_hw_addr_set(ndev, address->sa_data); moxart_update_mac_address(ndev); @@ -172,9 +169,6 @@ static int moxart_mac_open(struct net_device *ndev) { struct moxart_mac_priv_t *priv = netdev_priv(ndev); - if (!is_valid_ether_addr(ndev->dev_addr)) - return -EADDRNOTAVAIL; - napi_enable(&priv->napi); moxart_mac_reset(ndev); @@ -488,6 +482,13 @@ static int moxart_mac_probe(struct platform_device *pdev) } ndev->base_addr = res->start; + ret = platform_get_ethdev_address(p_dev, ndev); + if (ret == -EPROBE_DEFER) + goto init_fail; + if (ret) + eth_hw_addr_random(ndev); + moxart_update_mac_address(ndev); + spin_lock_init(&priv->txlock); priv->tx_buf_size = TX_BUF_SIZE; From 96264230a6817bcd4a7ae0fc30c60bfb46499f68 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Fri, 12 Aug 2022 15:35:32 +0100 Subject: [PATCH 376/427] perf: riscv legacy: fix kerneldoc comment warning Fix the warning: drivers/perf/riscv_pmu_legacy.c:76: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst Fixes: 9b3e150e310e ("RISC-V: Add a simple platform driver for RISC-V legacy perf") Signed-off-by: Conor Dooley Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20220812143532.1962623-1-conor.dooley@microchip.com Signed-off-by: Palmer Dabbelt --- drivers/perf/riscv_pmu_legacy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/perf/riscv_pmu_legacy.c b/drivers/perf/riscv_pmu_legacy.c index 342778782359f..2c20b0de8cb09 100644 --- a/drivers/perf/riscv_pmu_legacy.c +++ b/drivers/perf/riscv_pmu_legacy.c @@ -72,7 +72,7 @@ static void pmu_legacy_ctr_start(struct perf_event *event, u64 ival) local64_set(&hwc->prev_count, initial_val); } -/** +/* * This is just a simple implementation to allow legacy implementations * compatible with new RISC-V PMU driver framework. * This driver only allows reading two counters i.e CYCLE & INSTRET. From 4ba4f41942745f1906c06868a4acc6c926463f53 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Tue, 16 Aug 2022 05:39:35 +0000 Subject: [PATCH 377/427] KVM: Properly unwind VM creation if creating debugfs fails Properly unwind VM creation if kvm_create_vm_debugfs() fails. A recent change to invoke kvm_create_vm_debug() in kvm_create_vm() was led astray by buggy try_get_module() handling adding by commit 5f6de5cbebee ("KVM: Prevent module exit until all VMs are freed"). The debugfs error path effectively inherits the bad error path of try_module_get(), e.g. KVM leaves the to-be-free VM on vm_list even though KVM appears to do the right thing by calling module_put() and falling through. Opportunistically hoist kvm_create_vm_debugfs() above the call to kvm_arch_post_init_vm() so that the "post-init" arch hook is actually invoked after the VM is initialized (ignoring kvm_coalesced_mmio_init() for the moment). x86 is the only non-nop implementation of the post-init hook, and it doesn't allocate/initialize any objects that are reachable via debugfs code (spawns a kthread worker for the NX huge page mitigation). Leave the buggy try_get_module() alone for now, it will be fixed in a separate commit. Fixes: b74ed7a68ec1 ("KVM: Actually create debugfs in kvm_create_vm()") Reported-by: syzbot+744e173caec2e1627ee0@syzkaller.appspotmail.com Cc: Oliver Upton Signed-off-by: Sean Christopherson Reviewed-by: Oliver Upton Message-Id: <20220816053937.2477106-2-seanjc@google.com> Signed-off-by: Paolo Bonzini --- virt/kvm/kvm_main.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 515dfe9d3bcfb..ee5f48cc100b1 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1211,9 +1211,13 @@ static struct kvm *kvm_create_vm(unsigned long type, const char *fdname) if (r) goto out_err_no_mmu_notifier; + r = kvm_create_vm_debugfs(kvm, fdname); + if (r) + goto out_err_no_debugfs; + r = kvm_arch_post_init_vm(kvm); if (r) - goto out_err_mmu_notifier; + goto out_err; mutex_lock(&kvm_lock); list_add(&kvm->vm_list, &vm_list); @@ -1229,18 +1233,14 @@ static struct kvm *kvm_create_vm(unsigned long type, const char *fdname) */ if (!try_module_get(kvm_chardev_ops.owner)) { r = -ENODEV; - goto out_err_mmu_notifier; - } - - r = kvm_create_vm_debugfs(kvm, fdname); - if (r) goto out_err; + } return kvm; out_err: - module_put(kvm_chardev_ops.owner); -out_err_mmu_notifier: + kvm_destroy_vm_debugfs(kvm); +out_err_no_debugfs: #if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER) if (kvm->mmu_notifier.ops) mmu_notifier_unregister(&kvm->mmu_notifier, current->mm); From 405294f29faee5de8c10cb9d4a90e229c2835279 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Tue, 16 Aug 2022 05:39:36 +0000 Subject: [PATCH 378/427] KVM: Unconditionally get a ref to /dev/kvm module when creating a VM Unconditionally get a reference to the /dev/kvm module when creating a VM instead of using try_get_module(), which will fail if the module is in the process of being forcefully unloaded. The error handling when try_get_module() fails doesn't properly unwind all that has been done, e.g. doesn't call kvm_arch_pre_destroy_vm() and doesn't remove the VM from the global list. Not removing VMs from the global list tends to be fatal, e.g. leads to use-after-free explosions. The obvious alternative would be to add proper unwinding, but the justification for using try_get_module(), "rmmod --wait", is completely bogus as support for "rmmod --wait", i.e. delete_module() without O_NONBLOCK, was removed by commit 3f2b9c9cdf38 ("module: remove rmmod --wait option.") nearly a decade ago. It's still possible for try_get_module() to fail due to the module dying (more like being killed), as the module will be tagged MODULE_STATE_GOING by "rmmod --force", i.e. delete_module(..., O_TRUNC), but playing nice with forced unloading is an exercise in futility and gives a falsea sense of security. Using try_get_module() only prevents acquiring _new_ references, it doesn't magically put the references held by other VMs, and forced unloading doesn't wait, i.e. "rmmod --force" on KVM is all but guaranteed to cause spectacular fireworks; the window where KVM will fail try_get_module() is tiny compared to the window where KVM is building and running the VM with an elevated module refcount. Addressing KVM's inability to play nice with "rmmod --force" is firmly out-of-scope. Forcefully unloading any module taints kernel (for obvious reasons) _and_ requires the kernel to be built with CONFIG_MODULE_FORCE_UNLOAD=y, which is off by default and comes with the amusing disclaimer that it's "mainly for kernel developers and desperate users". In other words, KVM is free to scoff at bug reports due to using "rmmod --force" while VMs may be running. Fixes: 5f6de5cbebee ("KVM: Prevent module exit until all VMs are freed") Cc: stable@vger.kernel.org Cc: David Matlack Signed-off-by: Sean Christopherson Message-Id: <20220816053937.2477106-3-seanjc@google.com> Signed-off-by: Paolo Bonzini --- virt/kvm/kvm_main.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index ee5f48cc100b1..15e304e059d47 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1134,6 +1134,9 @@ static struct kvm *kvm_create_vm(unsigned long type, const char *fdname) if (!kvm) return ERR_PTR(-ENOMEM); + /* KVM is pinned via open("/dev/kvm"), the fd passed to this ioctl(). */ + __module_get(kvm_chardev_ops.owner); + KVM_MMU_LOCK_INIT(kvm); mmgrab(current->mm); kvm->mm = current->mm; @@ -1226,16 +1229,6 @@ static struct kvm *kvm_create_vm(unsigned long type, const char *fdname) preempt_notifier_inc(); kvm_init_pm_notifier(kvm); - /* - * When the fd passed to this ioctl() is opened it pins the module, - * but try_module_get() also prevents getting a reference if the module - * is in MODULE_STATE_GOING (e.g. if someone ran "rmmod --wait"). - */ - if (!try_module_get(kvm_chardev_ops.owner)) { - r = -ENODEV; - goto out_err; - } - return kvm; out_err: @@ -1259,6 +1252,7 @@ static struct kvm *kvm_create_vm(unsigned long type, const char *fdname) out_err_no_srcu: kvm_arch_free_vm(kvm); mmdrop(current->mm); + module_put(kvm_chardev_ops.owner); return ERR_PTR(r); } From c2b823970192882fe033d0d9f919003747d3e26f Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Tue, 16 Aug 2022 05:39:37 +0000 Subject: [PATCH 379/427] KVM: Move coalesced MMIO initialization (back) into kvm_create_vm() Invoke kvm_coalesced_mmio_init() from kvm_create_vm() now that allocating and initializing coalesced MMIO objects is separate from registering any associated devices. Moving coalesced MMIO cleans up the last oddity where KVM does VM creation/initialization after kvm_create_vm(), and more importantly after kvm_arch_post_init_vm() is called and the VM is added to the global vm_list, i.e. after the VM is fully created as far as KVM is concerned. Originally, kvm_coalesced_mmio_init() was called by kvm_create_vm(), but the original implementation was completely devoid of error handling. Commit 6ce5a090a9a0 ("KVM: coalesced_mmio: fix kvm_coalesced_mmio_init()'s error handling" fixed the various bugs, and in doing so rightly moved the call to after kvm_create_vm() because kvm_coalesced_mmio_init() also registered the coalesced MMIO device. Commit 2b3c246a682c ("KVM: Make coalesced mmio use a device per zone") cleaned up that mess by having each zone register a separate device, i.e. moved device registration to its logical home in kvm_vm_ioctl_register_coalesced_mmio(). As a result, kvm_coalesced_mmio_init() is now a "pure" initialization helper and can be safely called from kvm_create_vm(). Opportunstically drop the #ifdef, KVM provides stubs for kvm_coalesced_mmio_{init,free}() when CONFIG_KVM_MMIO=n (s390). Signed-off-by: Sean Christopherson Message-Id: <20220816053937.2477106-4-seanjc@google.com> Signed-off-by: Paolo Bonzini --- virt/kvm/kvm_main.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 15e304e059d47..44b92d773156f 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1214,6 +1214,10 @@ static struct kvm *kvm_create_vm(unsigned long type, const char *fdname) if (r) goto out_err_no_mmu_notifier; + r = kvm_coalesced_mmio_init(kvm); + if (r < 0) + goto out_no_coalesced_mmio; + r = kvm_create_vm_debugfs(kvm, fdname); if (r) goto out_err_no_debugfs; @@ -1234,6 +1238,8 @@ static struct kvm *kvm_create_vm(unsigned long type, const char *fdname) out_err: kvm_destroy_vm_debugfs(kvm); out_err_no_debugfs: + kvm_coalesced_mmio_free(kvm); +out_no_coalesced_mmio: #if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER) if (kvm->mmu_notifier.ops) mmu_notifier_unregister(&kvm->mmu_notifier, current->mm); @@ -4907,11 +4913,6 @@ static int kvm_dev_ioctl_create_vm(unsigned long type) goto put_fd; } -#ifdef CONFIG_KVM_MMIO - r = kvm_coalesced_mmio_init(kvm); - if (r < 0) - goto put_kvm; -#endif file = anon_inode_getfile("kvm-vm", &kvm_vm_fops, kvm, O_RDWR); if (IS_ERR(file)) { r = PTR_ERR(file); From b075450868dbc0950f0942617f222eeb989cad10 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 19 Aug 2022 04:04:28 -0400 Subject: [PATCH 380/427] KVM: MIPS: remove unnecessary definition of KVM_PRIVATE_MEM_SLOTS KVM_PRIVATE_MEM_SLOTS defaults to zero, so it is not necessary to define it in MIPS's asm/kvm_host.h. Signed-off-by: Paolo Bonzini --- arch/mips/include/asm/kvm_host.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h index 717716cc51c57..5cedb28e8a408 100644 --- a/arch/mips/include/asm/kvm_host.h +++ b/arch/mips/include/asm/kvm_host.h @@ -84,8 +84,6 @@ #define KVM_MAX_VCPUS 16 -/* memory slots that does not exposed to userspace */ -#define KVM_PRIVATE_MEM_SLOTS 0 #define KVM_HALT_POLL_NS_DEFAULT 500000 From bdd1c37a315bc50ab14066c4852bc8dcf070451e Mon Sep 17 00:00:00 2001 From: Chao Peng Date: Tue, 16 Aug 2022 20:53:21 +0800 Subject: [PATCH 381/427] KVM: Rename KVM_PRIVATE_MEM_SLOTS to KVM_INTERNAL_MEM_SLOTS KVM_INTERNAL_MEM_SLOTS better reflects the fact those slots are KVM internally used (invisible to userspace) and avoids confusion to future private slots that can have different meaning. Signed-off-by: Chao Peng Message-Id: <20220816125322.1110439-2-chao.p.peng@linux.intel.com> Signed-off-by: Paolo Bonzini --- arch/x86/include/asm/kvm_host.h | 2 +- include/linux/kvm_host.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 5ffa578cafe1c..2c96c43c313a2 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -53,7 +53,7 @@ #define KVM_MAX_VCPU_IDS (KVM_MAX_VCPUS * KVM_VCPU_ID_RATIO) /* memory slots that are not exposed to userspace */ -#define KVM_PRIVATE_MEM_SLOTS 3 +#define KVM_INTERNAL_MEM_SLOTS 3 #define KVM_HALT_POLL_NS_DEFAULT 200000 diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 1c480b1821e18..fd5c3b4715f84 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -656,12 +656,12 @@ struct kvm_irq_routing_table { }; #endif -#ifndef KVM_PRIVATE_MEM_SLOTS -#define KVM_PRIVATE_MEM_SLOTS 0 +#ifndef KVM_INTERNAL_MEM_SLOTS +#define KVM_INTERNAL_MEM_SLOTS 0 #endif #define KVM_MEM_SLOTS_NUM SHRT_MAX -#define KVM_USER_MEM_SLOTS (KVM_MEM_SLOTS_NUM - KVM_PRIVATE_MEM_SLOTS) +#define KVM_USER_MEM_SLOTS (KVM_MEM_SLOTS_NUM - KVM_INTERNAL_MEM_SLOTS) #ifndef __KVM_VCPU_MULTIPLE_ADDRESS_SPACE static inline int kvm_arch_vcpu_memslots_id(struct kvm_vcpu *vcpu) From 20ec3ebd707c77fb9b11b37193449193d4649f33 Mon Sep 17 00:00:00 2001 From: Chao Peng Date: Tue, 16 Aug 2022 20:53:22 +0800 Subject: [PATCH 382/427] KVM: Rename mmu_notifier_* to mmu_invalidate_* The motivation of this renaming is to make these variables and related helper functions less mmu_notifier bound and can also be used for non mmu_notifier based page invalidation. mmu_invalidate_* was chosen to better describe the purpose of 'invalidating' a page that those variables are used for. - mmu_notifier_seq/range_start/range_end are renamed to mmu_invalidate_seq/range_start/range_end. - mmu_notifier_retry{_hva} helper functions are renamed to mmu_invalidate_retry{_hva}. - mmu_notifier_count is renamed to mmu_invalidate_in_progress to avoid confusion with mn_active_invalidate_count. - While here, also update kvm_inc/dec_notifier_count() to kvm_mmu_invalidate_begin/end() to match the change for mmu_notifier_count. No functional change intended. Signed-off-by: Chao Peng Message-Id: <20220816125322.1110439-3-chao.p.peng@linux.intel.com> Signed-off-by: Paolo Bonzini --- arch/arm64/kvm/mmu.c | 8 ++-- arch/mips/kvm/mmu.c | 12 ++--- arch/powerpc/include/asm/kvm_book3s_64.h | 2 +- arch/powerpc/kvm/book3s_64_mmu_host.c | 4 +- arch/powerpc/kvm/book3s_64_mmu_hv.c | 4 +- arch/powerpc/kvm/book3s_64_mmu_radix.c | 6 +-- arch/powerpc/kvm/book3s_hv_nested.c | 2 +- arch/powerpc/kvm/book3s_hv_rm_mmu.c | 8 ++-- arch/powerpc/kvm/e500_mmu_host.c | 4 +- arch/riscv/kvm/mmu.c | 4 +- arch/x86/kvm/mmu/mmu.c | 14 +++--- arch/x86/kvm/mmu/paging_tmpl.h | 4 +- include/linux/kvm_host.h | 60 ++++++++++++------------ virt/kvm/kvm_main.c | 52 ++++++++++---------- virt/kvm/pfncache.c | 17 +++---- 15 files changed, 103 insertions(+), 98 deletions(-) diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 87f1cd0df36ea..c9a13e487187c 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -993,7 +993,7 @@ transparent_hugepage_adjust(struct kvm *kvm, struct kvm_memory_slot *memslot, * THP doesn't start to split while we are adjusting the * refcounts. * - * We are sure this doesn't happen, because mmu_notifier_retry + * We are sure this doesn't happen, because mmu_invalidate_retry * was successful and we are holding the mmu_lock, so if this * THP is trying to split, it will be blocked in the mmu * notifier before touching any of the pages, specifically @@ -1188,9 +1188,9 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, return ret; } - mmu_seq = vcpu->kvm->mmu_notifier_seq; + mmu_seq = vcpu->kvm->mmu_invalidate_seq; /* - * Ensure the read of mmu_notifier_seq happens before we call + * Ensure the read of mmu_invalidate_seq happens before we call * gfn_to_pfn_prot (which calls get_user_pages), so that we don't risk * the page we just got a reference to gets unmapped before we have a * chance to grab the mmu_lock, which ensure that if the page gets @@ -1246,7 +1246,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, else write_lock(&kvm->mmu_lock); pgt = vcpu->arch.hw_mmu->pgt; - if (mmu_notifier_retry(kvm, mmu_seq)) + if (mmu_invalidate_retry(kvm, mmu_seq)) goto out_unlock; /* diff --git a/arch/mips/kvm/mmu.c b/arch/mips/kvm/mmu.c index db17e870bdff5..74cd64a24d059 100644 --- a/arch/mips/kvm/mmu.c +++ b/arch/mips/kvm/mmu.c @@ -615,17 +615,17 @@ static int kvm_mips_map_page(struct kvm_vcpu *vcpu, unsigned long gpa, * Used to check for invalidations in progress, of the pfn that is * returned by pfn_to_pfn_prot below. */ - mmu_seq = kvm->mmu_notifier_seq; + mmu_seq = kvm->mmu_invalidate_seq; /* - * Ensure the read of mmu_notifier_seq isn't reordered with PTE reads in - * gfn_to_pfn_prot() (which calls get_user_pages()), so that we don't + * Ensure the read of mmu_invalidate_seq isn't reordered with PTE reads + * in gfn_to_pfn_prot() (which calls get_user_pages()), so that we don't * risk the page we get a reference to getting unmapped before we have a - * chance to grab the mmu_lock without mmu_notifier_retry() noticing. + * chance to grab the mmu_lock without mmu_invalidate_retry() noticing. * * This smp_rmb() pairs with the effective smp_wmb() of the combination * of the pte_unmap_unlock() after the PTE is zapped, and the * spin_lock() in kvm_mmu_notifier_invalidate_() before - * mmu_notifier_seq is incremented. + * mmu_invalidate_seq is incremented. */ smp_rmb(); @@ -638,7 +638,7 @@ static int kvm_mips_map_page(struct kvm_vcpu *vcpu, unsigned long gpa, spin_lock(&kvm->mmu_lock); /* Check if an invalidation has taken place since we got pfn */ - if (mmu_notifier_retry(kvm, mmu_seq)) { + if (mmu_invalidate_retry(kvm, mmu_seq)) { /* * This can happen when mappings are changed asynchronously, but * also synchronously if a COW is triggered by diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h index 4def2bd17b9b8..d49065af08e95 100644 --- a/arch/powerpc/include/asm/kvm_book3s_64.h +++ b/arch/powerpc/include/asm/kvm_book3s_64.h @@ -666,7 +666,7 @@ static inline pte_t *find_kvm_host_pte(struct kvm *kvm, unsigned long mmu_seq, VM_WARN(!spin_is_locked(&kvm->mmu_lock), "%s called with kvm mmu_lock not held \n", __func__); - if (mmu_notifier_retry(kvm, mmu_seq)) + if (mmu_invalidate_retry(kvm, mmu_seq)) return NULL; pte = __find_linux_pte(kvm->mm->pgd, ea, NULL, hshift); diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c index 1ae09992c9ea3..bc6a381b53463 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_host.c +++ b/arch/powerpc/kvm/book3s_64_mmu_host.c @@ -90,7 +90,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte, unsigned long pfn; /* used to check for invalidations in progress */ - mmu_seq = kvm->mmu_notifier_seq; + mmu_seq = kvm->mmu_invalidate_seq; smp_rmb(); /* Get host physical address for gpa */ @@ -151,7 +151,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte, cpte = kvmppc_mmu_hpte_cache_next(vcpu); spin_lock(&kvm->mmu_lock); - if (!cpte || mmu_notifier_retry(kvm, mmu_seq)) { + if (!cpte || mmu_invalidate_retry(kvm, mmu_seq)) { r = -EAGAIN; goto out_unlock; } diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index 514fd45c19947..e9744b41a226c 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c @@ -578,7 +578,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_vcpu *vcpu, return -EFAULT; /* used to check for invalidations in progress */ - mmu_seq = kvm->mmu_notifier_seq; + mmu_seq = kvm->mmu_invalidate_seq; smp_rmb(); ret = -EFAULT; @@ -693,7 +693,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_vcpu *vcpu, /* Check if we might have been invalidated; let the guest retry if so */ ret = RESUME_GUEST; - if (mmu_notifier_retry(vcpu->kvm, mmu_seq)) { + if (mmu_invalidate_retry(vcpu->kvm, mmu_seq)) { unlock_rmap(rmap); goto out_unlock; } diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c index 9d4b3feda3b6c..5d5e12f3bf864 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_radix.c +++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c @@ -640,7 +640,7 @@ int kvmppc_create_pte(struct kvm *kvm, pgd_t *pgtable, pte_t pte, /* Check if we might have been invalidated; let the guest retry if so */ spin_lock(&kvm->mmu_lock); ret = -EAGAIN; - if (mmu_notifier_retry(kvm, mmu_seq)) + if (mmu_invalidate_retry(kvm, mmu_seq)) goto out_unlock; /* Now traverse again under the lock and change the tree */ @@ -830,7 +830,7 @@ int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu, bool large_enable; /* used to check for invalidations in progress */ - mmu_seq = kvm->mmu_notifier_seq; + mmu_seq = kvm->mmu_invalidate_seq; smp_rmb(); /* @@ -1191,7 +1191,7 @@ void kvmppc_radix_flush_memslot(struct kvm *kvm, * Increase the mmu notifier sequence number to prevent any page * fault that read the memslot earlier from writing a PTE. */ - kvm->mmu_notifier_seq++; + kvm->mmu_invalidate_seq++; spin_unlock(&kvm->mmu_lock); } diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c index be8249cc61078..5a64a1341e6f1 100644 --- a/arch/powerpc/kvm/book3s_hv_nested.c +++ b/arch/powerpc/kvm/book3s_hv_nested.c @@ -1580,7 +1580,7 @@ static long int __kvmhv_nested_page_fault(struct kvm_vcpu *vcpu, /* 2. Find the host pte for this L1 guest real address */ /* Used to check for invalidations in progress */ - mmu_seq = kvm->mmu_notifier_seq; + mmu_seq = kvm->mmu_invalidate_seq; smp_rmb(); /* See if can find translation in our partition scoped tables for L1 */ diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index 2257fb18cb72e..5a05953ae13fe 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c @@ -219,7 +219,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, g_ptel = ptel; /* used later to detect if we might have been invalidated */ - mmu_seq = kvm->mmu_notifier_seq; + mmu_seq = kvm->mmu_invalidate_seq; smp_rmb(); /* Find the memslot (if any) for this address */ @@ -366,7 +366,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, rmap = real_vmalloc_addr(rmap); lock_rmap(rmap); /* Check for pending invalidations under the rmap chain lock */ - if (mmu_notifier_retry(kvm, mmu_seq)) { + if (mmu_invalidate_retry(kvm, mmu_seq)) { /* inval in progress, write a non-present HPTE */ pteh |= HPTE_V_ABSENT; pteh &= ~HPTE_V_VALID; @@ -932,7 +932,7 @@ static long kvmppc_do_h_page_init_zero(struct kvm_vcpu *vcpu, int i; /* Used later to detect if we might have been invalidated */ - mmu_seq = kvm->mmu_notifier_seq; + mmu_seq = kvm->mmu_invalidate_seq; smp_rmb(); arch_spin_lock(&kvm->mmu_lock.rlock.raw_lock); @@ -960,7 +960,7 @@ static long kvmppc_do_h_page_init_copy(struct kvm_vcpu *vcpu, long ret = H_SUCCESS; /* Used later to detect if we might have been invalidated */ - mmu_seq = kvm->mmu_notifier_seq; + mmu_seq = kvm->mmu_invalidate_seq; smp_rmb(); arch_spin_lock(&kvm->mmu_lock.rlock.raw_lock); diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c index 7f16afc331efd..05668e9641406 100644 --- a/arch/powerpc/kvm/e500_mmu_host.c +++ b/arch/powerpc/kvm/e500_mmu_host.c @@ -339,7 +339,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, unsigned long flags; /* used to check for invalidations in progress */ - mmu_seq = kvm->mmu_notifier_seq; + mmu_seq = kvm->mmu_invalidate_seq; smp_rmb(); /* @@ -460,7 +460,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, } spin_lock(&kvm->mmu_lock); - if (mmu_notifier_retry(kvm, mmu_seq)) { + if (mmu_invalidate_retry(kvm, mmu_seq)) { ret = -EAGAIN; goto out; } diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c index 3a35b2d95697c..3620ecac2fa14 100644 --- a/arch/riscv/kvm/mmu.c +++ b/arch/riscv/kvm/mmu.c @@ -666,7 +666,7 @@ int kvm_riscv_gstage_map(struct kvm_vcpu *vcpu, return ret; } - mmu_seq = kvm->mmu_notifier_seq; + mmu_seq = kvm->mmu_invalidate_seq; hfn = gfn_to_pfn_prot(kvm, gfn, is_write, &writable); if (hfn == KVM_PFN_ERR_HWPOISON) { @@ -686,7 +686,7 @@ int kvm_riscv_gstage_map(struct kvm_vcpu *vcpu, spin_lock(&kvm->mmu_lock); - if (mmu_notifier_retry(kvm, mmu_seq)) + if (mmu_invalidate_retry(kvm, mmu_seq)) goto out_unlock; if (writable) { diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index eccddb1369542..126fa9aec64cd 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -2914,7 +2914,7 @@ static void direct_pte_prefetch(struct kvm_vcpu *vcpu, u64 *sptep) * If addresses are being invalidated, skip prefetching to avoid * accidentally prefetching those addresses. */ - if (unlikely(vcpu->kvm->mmu_notifier_count)) + if (unlikely(vcpu->kvm->mmu_invalidate_in_progress)) return; __direct_pte_prefetch(vcpu, sp, sptep); @@ -2928,7 +2928,7 @@ static void direct_pte_prefetch(struct kvm_vcpu *vcpu, u64 *sptep) * * There are several ways to safely use this helper: * - * - Check mmu_notifier_retry_hva() after grabbing the mapping level, before + * - Check mmu_invalidate_retry_hva() after grabbing the mapping level, before * consuming it. In this case, mmu_lock doesn't need to be held during the * lookup, but it does need to be held while checking the MMU notifier. * @@ -3056,7 +3056,7 @@ void kvm_mmu_hugepage_adjust(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault return; /* - * mmu_notifier_retry() was successful and mmu_lock is held, so + * mmu_invalidate_retry() was successful and mmu_lock is held, so * the pmd can't be split from under us. */ fault->goal_level = fault->req_level; @@ -4203,7 +4203,7 @@ static bool is_page_fault_stale(struct kvm_vcpu *vcpu, return true; return fault->slot && - mmu_notifier_retry_hva(vcpu->kvm, mmu_seq, fault->hva); + mmu_invalidate_retry_hva(vcpu->kvm, mmu_seq, fault->hva); } static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault) @@ -4227,7 +4227,7 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault if (r) return r; - mmu_seq = vcpu->kvm->mmu_notifier_seq; + mmu_seq = vcpu->kvm->mmu_invalidate_seq; smp_rmb(); r = kvm_faultin_pfn(vcpu, fault); @@ -6055,7 +6055,7 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end) write_lock(&kvm->mmu_lock); - kvm_inc_notifier_count(kvm, gfn_start, gfn_end); + kvm_mmu_invalidate_begin(kvm, gfn_start, gfn_end); flush = kvm_rmap_zap_gfn_range(kvm, gfn_start, gfn_end); @@ -6069,7 +6069,7 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end) kvm_flush_remote_tlbs_with_address(kvm, gfn_start, gfn_end - gfn_start); - kvm_dec_notifier_count(kvm, gfn_start, gfn_end); + kvm_mmu_invalidate_end(kvm, gfn_start, gfn_end); write_unlock(&kvm->mmu_lock); } diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h index f5958071220c9..39e0205e7300a 100644 --- a/arch/x86/kvm/mmu/paging_tmpl.h +++ b/arch/x86/kvm/mmu/paging_tmpl.h @@ -589,7 +589,7 @@ static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, struct guest_walker *gw, * If addresses are being invalidated, skip prefetching to avoid * accidentally prefetching those addresses. */ - if (unlikely(vcpu->kvm->mmu_notifier_count)) + if (unlikely(vcpu->kvm->mmu_invalidate_in_progress)) return; if (sp->role.direct) @@ -838,7 +838,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault else fault->max_level = walker.level; - mmu_seq = vcpu->kvm->mmu_notifier_seq; + mmu_seq = vcpu->kvm->mmu_invalidate_seq; smp_rmb(); r = kvm_faultin_pfn(vcpu, fault); diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index fd5c3b4715f84..f4519d3689e10 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -765,10 +765,10 @@ struct kvm { #if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER) struct mmu_notifier mmu_notifier; - unsigned long mmu_notifier_seq; - long mmu_notifier_count; - unsigned long mmu_notifier_range_start; - unsigned long mmu_notifier_range_end; + unsigned long mmu_invalidate_seq; + long mmu_invalidate_in_progress; + unsigned long mmu_invalidate_range_start; + unsigned long mmu_invalidate_range_end; #endif struct list_head devices; u64 manual_dirty_log_protect; @@ -1357,10 +1357,10 @@ void kvm_mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc); void *kvm_mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc); #endif -void kvm_inc_notifier_count(struct kvm *kvm, unsigned long start, - unsigned long end); -void kvm_dec_notifier_count(struct kvm *kvm, unsigned long start, - unsigned long end); +void kvm_mmu_invalidate_begin(struct kvm *kvm, unsigned long start, + unsigned long end); +void kvm_mmu_invalidate_end(struct kvm *kvm, unsigned long start, + unsigned long end); long kvm_arch_dev_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg); @@ -1907,42 +1907,44 @@ extern const struct kvm_stats_header kvm_vcpu_stats_header; extern const struct _kvm_stats_desc kvm_vcpu_stats_desc[]; #if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER) -static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq) +static inline int mmu_invalidate_retry(struct kvm *kvm, unsigned long mmu_seq) { - if (unlikely(kvm->mmu_notifier_count)) + if (unlikely(kvm->mmu_invalidate_in_progress)) return 1; /* - * Ensure the read of mmu_notifier_count happens before the read - * of mmu_notifier_seq. This interacts with the smp_wmb() in - * mmu_notifier_invalidate_range_end to make sure that the caller - * either sees the old (non-zero) value of mmu_notifier_count or - * the new (incremented) value of mmu_notifier_seq. - * PowerPC Book3s HV KVM calls this under a per-page lock - * rather than under kvm->mmu_lock, for scalability, so - * can't rely on kvm->mmu_lock to keep things ordered. + * Ensure the read of mmu_invalidate_in_progress happens before + * the read of mmu_invalidate_seq. This interacts with the + * smp_wmb() in mmu_notifier_invalidate_range_end to make sure + * that the caller either sees the old (non-zero) value of + * mmu_invalidate_in_progress or the new (incremented) value of + * mmu_invalidate_seq. + * + * PowerPC Book3s HV KVM calls this under a per-page lock rather + * than under kvm->mmu_lock, for scalability, so can't rely on + * kvm->mmu_lock to keep things ordered. */ smp_rmb(); - if (kvm->mmu_notifier_seq != mmu_seq) + if (kvm->mmu_invalidate_seq != mmu_seq) return 1; return 0; } -static inline int mmu_notifier_retry_hva(struct kvm *kvm, - unsigned long mmu_seq, - unsigned long hva) +static inline int mmu_invalidate_retry_hva(struct kvm *kvm, + unsigned long mmu_seq, + unsigned long hva) { lockdep_assert_held(&kvm->mmu_lock); /* - * If mmu_notifier_count is non-zero, then the range maintained by - * kvm_mmu_notifier_invalidate_range_start contains all addresses that - * might be being invalidated. Note that it may include some false + * If mmu_invalidate_in_progress is non-zero, then the range maintained + * by kvm_mmu_notifier_invalidate_range_start contains all addresses + * that might be being invalidated. Note that it may include some false * positives, due to shortcuts when handing concurrent invalidations. */ - if (unlikely(kvm->mmu_notifier_count) && - hva >= kvm->mmu_notifier_range_start && - hva < kvm->mmu_notifier_range_end) + if (unlikely(kvm->mmu_invalidate_in_progress) && + hva >= kvm->mmu_invalidate_range_start && + hva < kvm->mmu_invalidate_range_end) return 1; - if (kvm->mmu_notifier_seq != mmu_seq) + if (kvm->mmu_invalidate_seq != mmu_seq) return 1; return 0; } diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 44b92d773156f..5142c054b03c7 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -702,30 +702,31 @@ static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn, /* * .change_pte() must be surrounded by .invalidate_range_{start,end}(). - * If mmu_notifier_count is zero, then no in-progress invalidations, - * including this one, found a relevant memslot at start(); rechecking - * memslots here is unnecessary. Note, a false positive (count elevated - * by a different invalidation) is sub-optimal but functionally ok. + * If mmu_invalidate_in_progress is zero, then no in-progress + * invalidations, including this one, found a relevant memslot at + * start(); rechecking memslots here is unnecessary. Note, a false + * positive (count elevated by a different invalidation) is sub-optimal + * but functionally ok. */ WARN_ON_ONCE(!READ_ONCE(kvm->mn_active_invalidate_count)); - if (!READ_ONCE(kvm->mmu_notifier_count)) + if (!READ_ONCE(kvm->mmu_invalidate_in_progress)) return; kvm_handle_hva_range(mn, address, address + 1, pte, kvm_set_spte_gfn); } -void kvm_inc_notifier_count(struct kvm *kvm, unsigned long start, - unsigned long end) +void kvm_mmu_invalidate_begin(struct kvm *kvm, unsigned long start, + unsigned long end) { /* * The count increase must become visible at unlock time as no * spte can be established without taking the mmu_lock and * count is also read inside the mmu_lock critical section. */ - kvm->mmu_notifier_count++; - if (likely(kvm->mmu_notifier_count == 1)) { - kvm->mmu_notifier_range_start = start; - kvm->mmu_notifier_range_end = end; + kvm->mmu_invalidate_in_progress++; + if (likely(kvm->mmu_invalidate_in_progress == 1)) { + kvm->mmu_invalidate_range_start = start; + kvm->mmu_invalidate_range_end = end; } else { /* * Fully tracking multiple concurrent ranges has diminishing @@ -736,10 +737,10 @@ void kvm_inc_notifier_count(struct kvm *kvm, unsigned long start, * accumulate and persist until all outstanding invalidates * complete. */ - kvm->mmu_notifier_range_start = - min(kvm->mmu_notifier_range_start, start); - kvm->mmu_notifier_range_end = - max(kvm->mmu_notifier_range_end, end); + kvm->mmu_invalidate_range_start = + min(kvm->mmu_invalidate_range_start, start); + kvm->mmu_invalidate_range_end = + max(kvm->mmu_invalidate_range_end, end); } } @@ -752,7 +753,7 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn, .end = range->end, .pte = __pte(0), .handler = kvm_unmap_gfn_range, - .on_lock = kvm_inc_notifier_count, + .on_lock = kvm_mmu_invalidate_begin, .on_unlock = kvm_arch_guest_memory_reclaimed, .flush_on_ret = true, .may_block = mmu_notifier_range_blockable(range), @@ -763,7 +764,7 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn, /* * Prevent memslot modification between range_start() and range_end() * so that conditionally locking provides the same result in both - * functions. Without that guarantee, the mmu_notifier_count + * functions. Without that guarantee, the mmu_invalidate_in_progress * adjustments will be imbalanced. * * Pairs with the decrement in range_end(). @@ -779,7 +780,8 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn, * any given time, and the caches themselves can check for hva overlap, * i.e. don't need to rely on memslot overlap checks for performance. * Because this runs without holding mmu_lock, the pfn caches must use - * mn_active_invalidate_count (see above) instead of mmu_notifier_count. + * mn_active_invalidate_count (see above) instead of + * mmu_invalidate_in_progress. */ gfn_to_pfn_cache_invalidate_start(kvm, range->start, range->end, hva_range.may_block); @@ -789,22 +791,22 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn, return 0; } -void kvm_dec_notifier_count(struct kvm *kvm, unsigned long start, - unsigned long end) +void kvm_mmu_invalidate_end(struct kvm *kvm, unsigned long start, + unsigned long end) { /* * This sequence increase will notify the kvm page fault that * the page that is going to be mapped in the spte could have * been freed. */ - kvm->mmu_notifier_seq++; + kvm->mmu_invalidate_seq++; smp_wmb(); /* * The above sequence increase must be visible before the * below count decrease, which is ensured by the smp_wmb above - * in conjunction with the smp_rmb in mmu_notifier_retry(). + * in conjunction with the smp_rmb in mmu_invalidate_retry(). */ - kvm->mmu_notifier_count--; + kvm->mmu_invalidate_in_progress--; } static void kvm_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn, @@ -816,7 +818,7 @@ static void kvm_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn, .end = range->end, .pte = __pte(0), .handler = (void *)kvm_null_fn, - .on_lock = kvm_dec_notifier_count, + .on_lock = kvm_mmu_invalidate_end, .on_unlock = (void *)kvm_null_fn, .flush_on_ret = false, .may_block = mmu_notifier_range_blockable(range), @@ -837,7 +839,7 @@ static void kvm_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn, if (wake) rcuwait_wake_up(&kvm->mn_memslots_update_rcuwait); - BUG_ON(kvm->mmu_notifier_count < 0); + BUG_ON(kvm->mmu_invalidate_in_progress < 0); } static int kvm_mmu_notifier_clear_flush_young(struct mmu_notifier *mn, diff --git a/virt/kvm/pfncache.c b/virt/kvm/pfncache.c index ab519f72f2cd0..68ff41d395452 100644 --- a/virt/kvm/pfncache.c +++ b/virt/kvm/pfncache.c @@ -112,27 +112,28 @@ static inline bool mmu_notifier_retry_cache(struct kvm *kvm, unsigned long mmu_s { /* * mn_active_invalidate_count acts for all intents and purposes - * like mmu_notifier_count here; but the latter cannot be used - * here because the invalidation of caches in the mmu_notifier - * event occurs _before_ mmu_notifier_count is elevated. + * like mmu_invalidate_in_progress here; but the latter cannot + * be used here because the invalidation of caches in the + * mmu_notifier event occurs _before_ mmu_invalidate_in_progress + * is elevated. * * Note, it does not matter that mn_active_invalidate_count * is not protected by gpc->lock. It is guaranteed to * be elevated before the mmu_notifier acquires gpc->lock, and - * isn't dropped until after mmu_notifier_seq is updated. + * isn't dropped until after mmu_invalidate_seq is updated. */ if (kvm->mn_active_invalidate_count) return true; /* * Ensure mn_active_invalidate_count is read before - * mmu_notifier_seq. This pairs with the smp_wmb() in + * mmu_invalidate_seq. This pairs with the smp_wmb() in * mmu_notifier_invalidate_range_end() to guarantee either the * old (non-zero) value of mn_active_invalidate_count or the - * new (incremented) value of mmu_notifier_seq is observed. + * new (incremented) value of mmu_invalidate_seq is observed. */ smp_rmb(); - return kvm->mmu_notifier_seq != mmu_seq; + return kvm->mmu_invalidate_seq != mmu_seq; } static kvm_pfn_t hva_to_pfn_retry(struct kvm *kvm, struct gfn_to_pfn_cache *gpc) @@ -155,7 +156,7 @@ static kvm_pfn_t hva_to_pfn_retry(struct kvm *kvm, struct gfn_to_pfn_cache *gpc) gpc->valid = false; do { - mmu_seq = kvm->mmu_notifier_seq; + mmu_seq = kvm->mmu_invalidate_seq; smp_rmb(); write_unlock_irq(&gpc->lock); From e27e5bea956ce4d3eb15112de5fa5a3b77c2f488 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Thu, 18 Aug 2022 14:39:27 -0700 Subject: [PATCH 383/427] x86/ibt, objtool: Add IBT_NOSEAL() Add a macro which prevents a function from getting sealed if there are no compile-time references to it. Signed-off-by: Josh Poimboeuf Message-Id: <20220818213927.e44fmxkoq4yj6ybn@treble> Signed-off-by: Paolo Bonzini --- arch/x86/include/asm/ibt.h | 11 +++++++++++ tools/objtool/check.c | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/ibt.h b/arch/x86/include/asm/ibt.h index 689880eca9bab..9b08082a5d9f5 100644 --- a/arch/x86/include/asm/ibt.h +++ b/arch/x86/include/asm/ibt.h @@ -31,6 +31,16 @@ #define __noendbr __attribute__((nocf_check)) +/* + * Create a dummy function pointer reference to prevent objtool from marking + * the function as needing to be "sealed" (i.e. ENDBR converted to NOP by + * apply_ibt_endbr()). + */ +#define IBT_NOSEAL(fname) \ + ".pushsection .discard.ibt_endbr_noseal\n\t" \ + _ASM_PTR fname "\n\t" \ + ".popsection\n\t" + static inline __attribute_const__ u32 gen_endbr(void) { u32 endbr; @@ -84,6 +94,7 @@ extern __noendbr void ibt_restore(u64 save); #ifndef __ASSEMBLY__ #define ASM_ENDBR +#define IBT_NOSEAL(name) #define __noendbr diff --git a/tools/objtool/check.c b/tools/objtool/check.c index 0cec74da7ffea..91678252a9b67 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -4096,7 +4096,8 @@ static int validate_ibt(struct objtool_file *file) * These sections can reference text addresses, but not with * the intent to indirect branch to them. */ - if (!strncmp(sec->name, ".discard", 8) || + if ((!strncmp(sec->name, ".discard", 8) && + strcmp(sec->name, ".discard.ibt_endbr_noseal")) || !strncmp(sec->name, ".debug", 6) || !strcmp(sec->name, ".altinstructions") || !strcmp(sec->name, ".ibt_endbr_seal") || From 22472d12606c1dd3e92312f7329734e489b371ff Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Thu, 18 Aug 2022 08:53:42 -0700 Subject: [PATCH 384/427] x86/kvm: Simplify FOP_SETCC() SETCC_ALIGN and FOP_ALIGN are both 16. Remove the special casing for FOP_SETCC() and just make it a normal fastop. Signed-off-by: Josh Poimboeuf Message-Id: <7c13d94d1a775156f7e36eed30509b274a229140.1660837839.git.jpoimboe@kernel.org> Signed-off-by: Paolo Bonzini --- arch/x86/kvm/emulate.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index b4eeb7c75dfad..205d566ebd72b 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -446,27 +446,12 @@ static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop); FOP_END /* Special case for SETcc - 1 instruction per cc */ - -/* - * Depending on .config the SETcc functions look like: - * - * ENDBR [4 bytes; CONFIG_X86_KERNEL_IBT] - * SETcc %al [3 bytes] - * RET | JMP __x86_return_thunk [1,5 bytes; CONFIG_RETHUNK] - * INT3 [1 byte; CONFIG_SLS] - */ -#define SETCC_ALIGN 16 - #define FOP_SETCC(op) \ - ".align " __stringify(SETCC_ALIGN) " \n\t" \ - ".type " #op ", @function \n\t" \ - #op ": \n\t" \ - ASM_ENDBR \ + FOP_FUNC(op) \ #op " %al \n\t" \ - __FOP_RET(#op) \ - ".skip " __stringify(SETCC_ALIGN) " - (.-" #op "), 0xcc \n\t" + FOP_RET(op) -__FOP_START(setcc, SETCC_ALIGN) +FOP_START(setcc) FOP_SETCC(seto) FOP_SETCC(setno) FOP_SETCC(setc) @@ -1079,7 +1064,7 @@ static int em_bsr_c(struct x86_emulate_ctxt *ctxt) static __always_inline u8 test_cc(unsigned int condition, unsigned long flags) { u8 rc; - void (*fop)(void) = (void *)em_setcc + SETCC_ALIGN * (condition & 0xf); + void (*fop)(void) = (void *)em_setcc + FASTOP_SIZE * (condition & 0xf); flags = (flags & EFLAGS_MASK) | X86_EFLAGS_IF; asm("push %[flags]; popf; " CALL_NOSPEC From 3d9606b0e0f3aed4dfb61d0853ebf432fead7bba Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Thu, 18 Aug 2022 08:53:43 -0700 Subject: [PATCH 385/427] x86/kvm: Fix "missing ENDBR" BUG for fastop functions The following BUG was reported: traps: Missing ENDBR: andw_ax_dx+0x0/0x10 [kvm] ------------[ cut here ]------------ kernel BUG at arch/x86/kernel/traps.c:253! invalid opcode: 0000 [#1] PREEMPT SMP NOPTI asm_exc_control_protection+0x2b/0x30 RIP: 0010:andw_ax_dx+0x0/0x10 [kvm] Code: c3 cc cc cc cc 0f 1f 44 00 00 66 0f 1f 00 48 19 d0 c3 cc cc cc cc 0f 1f 40 00 f3 0f 1e fa 20 d0 c3 cc cc cc cc 0f 1f 44 00 00 <66> 0f 1f 00 66 21 d0 c3 cc cc cc cc 0f 1f 40 00 66 0f 1f 00 21 d0 ? andb_al_dl+0x10/0x10 [kvm] ? fastop+0x5d/0xa0 [kvm] x86_emulate_insn+0x822/0x1060 [kvm] x86_emulate_instruction+0x46f/0x750 [kvm] complete_emulated_mmio+0x216/0x2c0 [kvm] kvm_arch_vcpu_ioctl_run+0x604/0x650 [kvm] kvm_vcpu_ioctl+0x2f4/0x6b0 [kvm] ? wake_up_q+0xa0/0xa0 The BUG occurred because the ENDBR in the andw_ax_dx() fastop function had been incorrectly "sealed" (converted to a NOP) by apply_ibt_endbr(). Objtool marked it to be sealed because KVM has no compile-time references to the function. Instead KVM calculates its address at runtime. Prevent objtool from annotating fastop functions as sealable by creating throwaway dummy compile-time references to the functions. Fixes: 6649fa876da4 ("x86/ibt,kvm: Add ENDBR to fastops") Reported-by: Pengfei Xu Debugged-by: Peter Zijlstra Signed-off-by: Josh Poimboeuf Message-Id: <0d4116f90e9d0c1b754bb90c585e6f0415a1c508.1660837839.git.jpoimboe@kernel.org> Signed-off-by: Paolo Bonzini --- arch/x86/kvm/emulate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 205d566ebd72b..f092c54d1a2f2 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -326,7 +326,8 @@ static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop); ".align " __stringify(FASTOP_SIZE) " \n\t" \ ".type " name ", @function \n\t" \ name ":\n\t" \ - ASM_ENDBR + ASM_ENDBR \ + IBT_NOSEAL(name) #define FOP_FUNC(name) \ __FOP_FUNC(#name) From 2824913976a851f049bc8ab929b5c8d3b6ee269b Mon Sep 17 00:00:00 2001 From: Li kunyu Date: Fri, 19 Aug 2022 10:28:04 +0800 Subject: [PATCH 386/427] KVM: Drop unnecessary initialization of "npages" in hva_to_pfn_slow() The variable is initialized but it is only used after its assignment. Reviewed-by: Sean Christopherson Signed-off-by: Li kunyu Message-Id: <20220819022804.483914-1-kunyu@nfschina.com> Signed-off-by: Paolo Bonzini --- virt/kvm/kvm_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 5142c054b03c7..c916c4c8801c0 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2518,7 +2518,7 @@ static int hva_to_pfn_slow(unsigned long addr, bool *async, bool write_fault, { unsigned int flags = FOLL_HWPOISON; struct page *page; - int npages = 0; + int npages; might_sleep(); From eceb6e1d530046f964b0e371d4fad02a5b6b42d1 Mon Sep 17 00:00:00 2001 From: Li kunyu Date: Fri, 19 Aug 2022 10:15:35 +0800 Subject: [PATCH 387/427] KVM: Drop unnecessary initialization of "ops" in kvm_ioctl_create_device() The variable is initialized but it is only used after its assignment. Reviewed-by: Sean Christopherson Signed-off-by: Li kunyu Message-Id: <20220819021535.483702-1-kunyu@nfschina.com> Signed-off-by: Paolo Bonzini --- virt/kvm/kvm_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index c916c4c8801c0..584a5bab3af39 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -4380,7 +4380,7 @@ void kvm_unregister_device_ops(u32 type) static int kvm_ioctl_create_device(struct kvm *kvm, struct kvm_create_device *cd) { - const struct kvm_device_ops *ops = NULL; + const struct kvm_device_ops *ops; struct kvm_device *dev; bool test = cd->flags & KVM_CREATE_DEVICE_TEST; int type; From 88e0a74902f894fbbc55ad3ad2cb23b4bfba555c Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Fri, 19 Aug 2022 10:30:01 +0800 Subject: [PATCH 388/427] x86/mm: Use proper mask when setting PUD mapping Commit c164fbb40c43f("x86/mm: thread pgprot_t through init_memory_mapping()") mistakenly used __pgprot() which doesn't respect __default_kernel_pte_mask when setting PUD mapping. Fix it by only setting the one bit we actually need (PSE) and leaving the other bits (that have been properly masked) alone. Fixes: c164fbb40c43 ("x86/mm: thread pgprot_t through init_memory_mapping()") Signed-off-by: Aaron Lu Cc: stable@kernel.org Signed-off-by: Linus Torvalds --- arch/x86/mm/init_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 39c5246964a91..0fe690ebc269b 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -645,7 +645,7 @@ phys_pud_init(pud_t *pud_page, unsigned long paddr, unsigned long paddr_end, pages++; spin_lock(&init_mm.page_table_lock); - prot = __pgprot(pgprot_val(prot) | __PAGE_KERNEL_LARGE); + prot = __pgprot(pgprot_val(prot) | _PAGE_PSE); set_pte_init((pte_t *)pud, pfn_pte((paddr & PUD_MASK) >> PAGE_SHIFT, From e989bc3d0f3f93aab7c5018affc3f87b74716b37 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 14 Jun 2022 07:33:48 -0700 Subject: [PATCH 389/427] perf cpumap: Const map for max() Allows max() to be used with 'const struct perf_cpu_maps *'. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Alexey Bayduraev Cc: Athira Jajeev Cc: Colin Ian King Cc: Dave Marchevsky Cc: German Gomez Cc: Gustavo A. R. Silva Cc: Ingo Molnar Cc: James Clark Cc: Kees Kook Cc: Leo Yan Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Riccardo Mancini Cc: Song Liu Cc: Stephane Eranian Link: https://lore.kernel.org/r/20220614143353.1559597-2-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/perf/cpumap.c | 2 +- tools/lib/perf/include/perf/cpumap.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/lib/perf/cpumap.c b/tools/lib/perf/cpumap.c index 384d5e076ee43..6cd0be7c1bb43 100644 --- a/tools/lib/perf/cpumap.c +++ b/tools/lib/perf/cpumap.c @@ -309,7 +309,7 @@ bool perf_cpu_map__has(const struct perf_cpu_map *cpus, struct perf_cpu cpu) return perf_cpu_map__idx(cpus, cpu) != -1; } -struct perf_cpu perf_cpu_map__max(struct perf_cpu_map *map) +struct perf_cpu perf_cpu_map__max(const struct perf_cpu_map *map) { struct perf_cpu result = { .cpu = -1 diff --git a/tools/lib/perf/include/perf/cpumap.h b/tools/lib/perf/include/perf/cpumap.h index 24de795b09bb3..03aceb72a783c 100644 --- a/tools/lib/perf/include/perf/cpumap.h +++ b/tools/lib/perf/include/perf/cpumap.h @@ -23,7 +23,7 @@ LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map); LIBPERF_API struct perf_cpu perf_cpu_map__cpu(const struct perf_cpu_map *cpus, int idx); LIBPERF_API int perf_cpu_map__nr(const struct perf_cpu_map *cpus); LIBPERF_API bool perf_cpu_map__empty(const struct perf_cpu_map *map); -LIBPERF_API struct perf_cpu perf_cpu_map__max(struct perf_cpu_map *map); +LIBPERF_API struct perf_cpu perf_cpu_map__max(const struct perf_cpu_map *map); LIBPERF_API bool perf_cpu_map__has(const struct perf_cpu_map *map, struct perf_cpu cpu); #define perf_cpu_map__for_each_cpu(cpu, idx, cpus) \ From 35ae6f09d8fd02add781e452a6d2ba6ea3a5482e Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 14 Jun 2022 07:33:49 -0700 Subject: [PATCH 390/427] perf cpumap: Synthetic events and const/static Make the cpumap arguments const to make it clearer they are in rather than out arguments. Make two functions static and remove external declarations. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Alexey Bayduraev Cc: Athira Jajeev Cc: Colin Ian King Cc: Dave Marchevsky Cc: German Gomez Cc: Gustavo A. R. Silva Cc: Ingo Molnar Cc: James Clark Cc: Kees Kook Cc: Leo Yan Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Riccardo Mancini Cc: Song Liu Cc: Stephane Eranian Link: https://lore.kernel.org/r/20220614143353.1559597-3-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/event.h | 4 ---- tools/perf/util/synthetic-events.c | 20 +++++++++++--------- tools/perf/util/synthetic-events.h | 2 +- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index a7b0931d51379..4e0d8dd3b7a07 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -463,10 +463,6 @@ size_t perf_event__fprintf(union perf_event *event, struct machine *machine, FIL int kallsyms__get_function_start(const char *kallsyms_filename, const char *symbol_name, u64 *addr); -void *cpu_map_data__alloc(struct perf_cpu_map *map, size_t *size, u16 *type, int *max); -void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, struct perf_cpu_map *map, - u16 type, int max); - void event_attr_init(struct perf_event_attr *attr); int perf_event_paranoid(void); diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c index 2ae59c03ae774..b3e03a4c66524 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -1185,7 +1185,7 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool, } static void synthesize_cpus(struct cpu_map_entries *cpus, - struct perf_cpu_map *map) + const struct perf_cpu_map *map) { int i, map_nr = perf_cpu_map__nr(map); @@ -1196,7 +1196,7 @@ static void synthesize_cpus(struct cpu_map_entries *cpus, } static void synthesize_mask(struct perf_record_record_cpu_map *mask, - struct perf_cpu_map *map, int max) + const struct perf_cpu_map *map, int max) { int i; @@ -1207,12 +1207,12 @@ static void synthesize_mask(struct perf_record_record_cpu_map *mask, set_bit(perf_cpu_map__cpu(map, i).cpu, mask->mask); } -static size_t cpus_size(struct perf_cpu_map *map) +static size_t cpus_size(const struct perf_cpu_map *map) { return sizeof(struct cpu_map_entries) + perf_cpu_map__nr(map) * sizeof(u16); } -static size_t mask_size(struct perf_cpu_map *map, int *max) +static size_t mask_size(const struct perf_cpu_map *map, int *max) { int i; @@ -1229,7 +1229,8 @@ static size_t mask_size(struct perf_cpu_map *map, int *max) return sizeof(struct perf_record_record_cpu_map) + BITS_TO_LONGS(*max) * sizeof(long); } -void *cpu_map_data__alloc(struct perf_cpu_map *map, size_t *size, u16 *type, int *max) +static void *cpu_map_data__alloc(const struct perf_cpu_map *map, size_t *size, + u16 *type, int *max) { size_t size_cpus, size_mask; bool is_dummy = perf_cpu_map__empty(map); @@ -1263,8 +1264,9 @@ void *cpu_map_data__alloc(struct perf_cpu_map *map, size_t *size, u16 *type, int return zalloc(*size); } -void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, struct perf_cpu_map *map, - u16 type, int max) +static void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, + const struct perf_cpu_map *map, + u16 type, int max) { data->type = type; @@ -1279,7 +1281,7 @@ void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, struct perf } } -static struct perf_record_cpu_map *cpu_map_event__new(struct perf_cpu_map *map) +static struct perf_record_cpu_map *cpu_map_event__new(const struct perf_cpu_map *map) { size_t size = sizeof(struct perf_record_cpu_map); struct perf_record_cpu_map *event; @@ -1299,7 +1301,7 @@ static struct perf_record_cpu_map *cpu_map_event__new(struct perf_cpu_map *map) } int perf_event__synthesize_cpu_map(struct perf_tool *tool, - struct perf_cpu_map *map, + const struct perf_cpu_map *map, perf_event__handler_t process, struct machine *machine) { diff --git a/tools/perf/util/synthetic-events.h b/tools/perf/util/synthetic-events.h index 81cb3d6af0b96..53737d1619a41 100644 --- a/tools/perf/util/synthetic-events.h +++ b/tools/perf/util/synthetic-events.h @@ -46,7 +46,7 @@ typedef int (*perf_event__handler_t)(struct perf_tool *tool, union perf_event *e int perf_event__synthesize_attrs(struct perf_tool *tool, struct evlist *evlist, perf_event__handler_t process); int perf_event__synthesize_attr(struct perf_tool *tool, struct perf_event_attr *attr, u32 ids, u64 *id, perf_event__handler_t process); int perf_event__synthesize_build_id(struct perf_tool *tool, struct dso *pos, u16 misc, perf_event__handler_t process, struct machine *machine); -int perf_event__synthesize_cpu_map(struct perf_tool *tool, struct perf_cpu_map *cpus, perf_event__handler_t process, struct machine *machine); +int perf_event__synthesize_cpu_map(struct perf_tool *tool, const struct perf_cpu_map *cpus, perf_event__handler_t process, struct machine *machine); int perf_event__synthesize_event_update_cpus(struct perf_tool *tool, struct evsel *evsel, perf_event__handler_t process); int perf_event__synthesize_event_update_name(struct perf_tool *tool, struct evsel *evsel, perf_event__handler_t process); int perf_event__synthesize_event_update_scale(struct perf_tool *tool, struct evsel *evsel, perf_event__handler_t process); From 28526478ccae88680645405f4e849d9ed4fbce7f Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 14 Jun 2022 07:33:50 -0700 Subject: [PATCH 391/427] perf cpumap: Compute mask size in constant time perf_cpu_map__max() computes the cpumap's maximum value, no need to iterate over all values. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Alexey Bayduraev Cc: Athira Jajeev Cc: Colin Ian King Cc: Dave Marchevsky Cc: German Gomez Cc: Gustavo A. R. Silva Cc: Ingo Molnar Cc: James Clark Cc: Kees Kook Cc: Leo Yan Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Riccardo Mancini Cc: Song Liu Cc: Stephane Eranian Link: https://lore.kernel.org/r/20220614143353.1559597-4-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/synthetic-events.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c index b3e03a4c66524..3ae7c0f54157a 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -1214,18 +1214,7 @@ static size_t cpus_size(const struct perf_cpu_map *map) static size_t mask_size(const struct perf_cpu_map *map, int *max) { - int i; - - *max = 0; - - for (i = 0; i < perf_cpu_map__nr(map); i++) { - /* bit position of the cpu is + 1 */ - int bit = perf_cpu_map__cpu(map, i).cpu + 1; - - if (bit > *max) - *max = bit; - } - + *max = perf_cpu_map__max(map).cpu; return sizeof(struct perf_record_record_cpu_map) + BITS_TO_LONGS(*max) * sizeof(long); } From ca08d0eac020d48a3141dbec0a3cf64fbdb17cde Mon Sep 17 00:00:00 2001 From: Zhang Xiaoxu Date: Thu, 18 Aug 2022 21:50:44 +0800 Subject: [PATCH 392/427] cifs: Fix memory leak on the deferred close xfstests on smb21 report kmemleak as below: unreferenced object 0xffff8881767d6200 (size 64): comm "xfs_io", pid 1284, jiffies 4294777434 (age 20.789s) hex dump (first 32 bytes): 80 5a d0 11 81 88 ff ff 78 8a aa 63 81 88 ff ff .Z......x..c.... 00 71 99 76 81 88 ff ff 00 00 00 00 00 00 00 00 .q.v............ backtrace: [<00000000ad04e6ea>] cifs_close+0x92/0x2c0 [<0000000028b93c82>] __fput+0xff/0x3f0 [<00000000d8116851>] task_work_run+0x85/0xc0 [<0000000027e14f9e>] do_exit+0x5e5/0x1240 [<00000000fb492b95>] do_group_exit+0x58/0xe0 [<00000000129a32d9>] __x64_sys_exit_group+0x28/0x30 [<00000000e3f7d8e9>] do_syscall_64+0x35/0x80 [<00000000102e8a0b>] entry_SYSCALL_64_after_hwframe+0x46/0xb0 When cancel the deferred close work, we should also cleanup the struct cifs_deferred_close. Fixes: 9e992755be8f2 ("cifs: Call close synchronously during unlink/rename/lease break.") Fixes: e3fc065682ebb ("cifs: Deferred close performance improvements") Cc: stable@vger.kernel.org Reviewed-by: Shyam Prasad N Signed-off-by: Zhang Xiaoxu Signed-off-by: Steve French --- fs/cifs/misc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 1f2628ffe9d79..87f60f7367315 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -737,6 +737,8 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode) list_for_each_entry(cfile, &cifs_inode->openFileList, flist) { if (delayed_work_pending(&cfile->deferred)) { if (cancel_delayed_work(&cfile->deferred)) { + cifs_del_deferred_close(cfile); + tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); if (tmp_list == NULL) break; @@ -766,6 +768,8 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon) list_for_each_entry(cfile, &tcon->openFileList, tlist) { if (delayed_work_pending(&cfile->deferred)) { if (cancel_delayed_work(&cfile->deferred)) { + cifs_del_deferred_close(cfile); + tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); if (tmp_list == NULL) break; @@ -799,6 +803,8 @@ cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path) if (strstr(full_path, path)) { if (delayed_work_pending(&cfile->deferred)) { if (cancel_delayed_work(&cfile->deferred)) { + cifs_del_deferred_close(cfile); + tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); if (tmp_list == NULL) break; From 13609a8b3ac6b0af38127a2b97fe62c0d06a8282 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 18 Aug 2022 23:01:41 +0200 Subject: [PATCH 393/427] cifs: move from strlcpy with unused retval to strscpy Follow the advice of the below link and prefer 'strscpy' in this subsystem. Conversion is 1:1 because the return value is not used. Generated by a coccinelle script. Link: https://lore.kernel.org/r/CAHk-=wgfRnXz0W3D37d01q3JFkr_i_uTL=V6A6G1oUZcprmknw@mail.gmail.com/ Signed-off-by: Wolfram Sang Signed-off-by: Steve French --- fs/cifs/cifsroot.c | 2 +- fs/cifs/connect.c | 2 +- fs/cifs/smb2pdu.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/cifs/cifsroot.c b/fs/cifs/cifsroot.c index 9e91a5a40aaec..56ec1b233f52e 100644 --- a/fs/cifs/cifsroot.c +++ b/fs/cifs/cifsroot.c @@ -59,7 +59,7 @@ static int __init cifs_root_setup(char *line) pr_err("Root-CIFS: UNC path too long\n"); return 1; } - strlcpy(root_dev, line, len); + strscpy(root_dev, line, len); srvaddr = parse_srvaddr(&line[2], s); if (*s) { int n = snprintf(root_opts, diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 9111c025bcb8e..3da5da9f16b0c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3994,7 +3994,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, } bcc_ptr += length + 1; bytes_left -= (length + 1); - strlcpy(tcon->treeName, tree, sizeof(tcon->treeName)); + strscpy(tcon->treeName, tree, sizeof(tcon->treeName)); /* mostly informational -- no need to fail on error here */ kfree(tcon->nativeFileSystem); diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 918152fb8582b..91cfc5b47ac7c 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -1928,7 +1928,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, tcon->capabilities = rsp->Capabilities; /* we keep caps little endian */ tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess); tcon->tid = le32_to_cpu(rsp->hdr.Id.SyncId.TreeId); - strlcpy(tcon->treeName, tree, sizeof(tcon->treeName)); + strscpy(tcon->treeName, tree, sizeof(tcon->treeName)); if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) From b2f10cd4e805eb647773df273eb1a6ff9e6ea45d Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 14 Jun 2022 07:33:51 -0700 Subject: [PATCH 394/427] perf cpumap: Fix alignment for masks in event encoding A mask encoding of a cpu map is laid out as: u16 nr u16 long_size unsigned long mask[]; However, the mask may be 8-byte aligned meaning there is a 4-byte pad after long_size. This means 32-bit and 64-bit builds see the mask as being at different offsets. On top of this the structure is in the byte data[] encoded as: u16 type char data[] This means the mask's struct isn't the required 4 or 8 byte aligned, but is offset by 2. Consequently the long reads and writes are causing undefined behavior as the alignment is broken. Fix the mask struct by creating explicit 32 and 64-bit variants, use a union to avoid data[] and casts; the struct must be packed so the layout matches the existing perf.data layout. Taking an address of a member of a packed struct breaks alignment so pass the packed perf_record_cpu_map_data to functions, so they can access variables with the right alignment. As the 64-bit version has 4 bytes of padding, optimizing writing to only write the 32-bit version. Committer notes: Disable warnings about 'packed' that break the build in some arches like riscv64, but just around that specific struct. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Alexey Bayduraev Cc: Athira Jajeev Cc: Colin Ian King Cc: Dave Marchevsky Cc: German Gomez Cc: Gustavo A. R. Silva Cc: Ingo Molnar Cc: James Clark Cc: Kees Kook Cc: Leo Yan Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Riccardo Mancini Cc: Song Liu Cc: Stephane Eranian Link: https://lore.kernel.org/r/20220614143353.1559597-5-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/perf/include/perf/event.h | 47 +++++++++++++++-- tools/perf/tests/cpumap.c | 19 ++++--- tools/perf/util/cpumap.c | 80 +++++++++++++++++++++++------ tools/perf/util/cpumap.h | 4 +- tools/perf/util/session.c | 30 +++++------ tools/perf/util/synthetic-events.c | 34 +++++++----- 6 files changed, 154 insertions(+), 60 deletions(-) diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/perf/event.h index 556bb06798f27..57f54781f5ede 100644 --- a/tools/lib/perf/include/perf/event.h +++ b/tools/lib/perf/include/perf/event.h @@ -6,6 +6,7 @@ #include #include #include +#include #include /* pid_t */ #define event_contains(obj, mem) ((obj).header.size > offsetof(typeof(obj), mem)) @@ -153,22 +154,60 @@ enum { PERF_CPU_MAP__MASK = 1, }; +/* + * Array encoding of a perf_cpu_map where nr is the number of entries in cpu[] + * and each entry is a value for a CPU in the map. + */ struct cpu_map_entries { __u16 nr; __u16 cpu[]; }; -struct perf_record_record_cpu_map { +/* Bitmap encoding of a perf_cpu_map where bitmap entries are 32-bit. */ +struct perf_record_mask_cpu_map32 { + /* Number of mask values. */ __u16 nr; + /* Constant 4. */ __u16 long_size; - unsigned long mask[]; + /* Bitmap data. */ + __u32 mask[]; }; -struct perf_record_cpu_map_data { +/* Bitmap encoding of a perf_cpu_map where bitmap entries are 64-bit. */ +struct perf_record_mask_cpu_map64 { + /* Number of mask values. */ + __u16 nr; + /* Constant 8. */ + __u16 long_size; + /* Legacy padding. */ + char __pad[4]; + /* Bitmap data. */ + __u64 mask[]; +}; + +/* + * 'struct perf_record_cpu_map_data' is packed as unfortunately an earlier + * version had unaligned data and we wish to retain file format compatibility. + * -irogers + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpacked" +#pragma GCC diagnostic ignored "-Wattributes" + +struct __packed perf_record_cpu_map_data { __u16 type; - char data[]; + union { + /* Used when type == PERF_CPU_MAP__CPUS. */ + struct cpu_map_entries cpus_data; + /* Used when type == PERF_CPU_MAP__MASK and long_size == 4. */ + struct perf_record_mask_cpu_map32 mask32_data; + /* Used when type == PERF_CPU_MAP__MASK and long_size == 8. */ + struct perf_record_mask_cpu_map64 mask64_data; + }; }; +#pragma GCC diagnostic pop + struct perf_record_cpu_map { struct perf_event_header header; struct perf_record_cpu_map_data data; diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c index f94929ebb54bd..7ea150cdc137d 100644 --- a/tools/perf/tests/cpumap.c +++ b/tools/perf/tests/cpumap.c @@ -17,21 +17,23 @@ static int process_event_mask(struct perf_tool *tool __maybe_unused, struct machine *machine __maybe_unused) { struct perf_record_cpu_map *map_event = &event->cpu_map; - struct perf_record_record_cpu_map *mask; struct perf_record_cpu_map_data *data; struct perf_cpu_map *map; int i; + unsigned int long_size; data = &map_event->data; TEST_ASSERT_VAL("wrong type", data->type == PERF_CPU_MAP__MASK); - mask = (struct perf_record_record_cpu_map *)data->data; + long_size = data->mask32_data.long_size; - TEST_ASSERT_VAL("wrong nr", mask->nr == 1); + TEST_ASSERT_VAL("wrong long_size", long_size == 4 || long_size == 8); + + TEST_ASSERT_VAL("wrong nr", data->mask32_data.nr == 1); for (i = 0; i < 20; i++) { - TEST_ASSERT_VAL("wrong cpu", test_bit(i, mask->mask)); + TEST_ASSERT_VAL("wrong cpu", perf_record_cpu_map_data__test_bit(i, data)); } map = cpu_map__new_data(data); @@ -51,7 +53,6 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused, struct machine *machine __maybe_unused) { struct perf_record_cpu_map *map_event = &event->cpu_map; - struct cpu_map_entries *cpus; struct perf_record_cpu_map_data *data; struct perf_cpu_map *map; @@ -59,11 +60,9 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused, TEST_ASSERT_VAL("wrong type", data->type == PERF_CPU_MAP__CPUS); - cpus = (struct cpu_map_entries *)data->data; - - TEST_ASSERT_VAL("wrong nr", cpus->nr == 2); - TEST_ASSERT_VAL("wrong cpu", cpus->cpu[0] == 1); - TEST_ASSERT_VAL("wrong cpu", cpus->cpu[1] == 256); + TEST_ASSERT_VAL("wrong nr", data->cpus_data.nr == 2); + TEST_ASSERT_VAL("wrong cpu", data->cpus_data.cpu[0] == 1); + TEST_ASSERT_VAL("wrong cpu", data->cpus_data.cpu[1] == 256); map = cpu_map__new_data(data); TEST_ASSERT_VAL("wrong nr", perf_cpu_map__nr(map) == 2); diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 12b2243222b0e..ae43fb88f444e 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -22,54 +22,102 @@ static int max_node_num; */ static int *cpunode_map; -static struct perf_cpu_map *cpu_map__from_entries(struct cpu_map_entries *cpus) +bool perf_record_cpu_map_data__test_bit(int i, + const struct perf_record_cpu_map_data *data) +{ + int bit_word32 = i / 32; + __u32 bit_mask32 = 1U << (i & 31); + int bit_word64 = i / 64; + __u64 bit_mask64 = ((__u64)1) << (i & 63); + + return (data->mask32_data.long_size == 4) + ? (bit_word32 < data->mask32_data.nr) && + (data->mask32_data.mask[bit_word32] & bit_mask32) != 0 + : (bit_word64 < data->mask64_data.nr) && + (data->mask64_data.mask[bit_word64] & bit_mask64) != 0; +} + +/* Read ith mask value from data into the given 64-bit sized bitmap */ +static void perf_record_cpu_map_data__read_one_mask(const struct perf_record_cpu_map_data *data, + int i, unsigned long *bitmap) +{ +#if __SIZEOF_LONG__ == 8 + if (data->mask32_data.long_size == 4) + bitmap[0] = data->mask32_data.mask[i]; + else + bitmap[0] = data->mask64_data.mask[i]; +#else + if (data->mask32_data.long_size == 4) { + bitmap[0] = data->mask32_data.mask[i]; + bitmap[1] = 0; + } else { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + bitmap[0] = (unsigned long)(data->mask64_data.mask[i] >> 32); + bitmap[1] = (unsigned long)data->mask64_data.mask[i]; +#else + bitmap[0] = (unsigned long)data->mask64_data.mask[i]; + bitmap[1] = (unsigned long)(data->mask64_data.mask[i] >> 32); +#endif + } +#endif +} +static struct perf_cpu_map *cpu_map__from_entries(const struct perf_record_cpu_map_data *data) { struct perf_cpu_map *map; - map = perf_cpu_map__empty_new(cpus->nr); + map = perf_cpu_map__empty_new(data->cpus_data.nr); if (map) { unsigned i; - for (i = 0; i < cpus->nr; i++) { + for (i = 0; i < data->cpus_data.nr; i++) { /* * Special treatment for -1, which is not real cpu number, * and we need to use (int) -1 to initialize map[i], * otherwise it would become 65535. */ - if (cpus->cpu[i] == (u16) -1) + if (data->cpus_data.cpu[i] == (u16) -1) map->map[i].cpu = -1; else - map->map[i].cpu = (int) cpus->cpu[i]; + map->map[i].cpu = (int) data->cpus_data.cpu[i]; } } return map; } -static struct perf_cpu_map *cpu_map__from_mask(struct perf_record_record_cpu_map *mask) +static struct perf_cpu_map *cpu_map__from_mask(const struct perf_record_cpu_map_data *data) { + DECLARE_BITMAP(local_copy, 64); + int weight = 0, mask_nr = data->mask32_data.nr; struct perf_cpu_map *map; - int nr, nbits = mask->nr * mask->long_size * BITS_PER_BYTE; - nr = bitmap_weight(mask->mask, nbits); + for (int i = 0; i < mask_nr; i++) { + perf_record_cpu_map_data__read_one_mask(data, i, local_copy); + weight += bitmap_weight(local_copy, 64); + } + + map = perf_cpu_map__empty_new(weight); + if (!map) + return NULL; - map = perf_cpu_map__empty_new(nr); - if (map) { - int cpu, i = 0; + for (int i = 0, j = 0; i < mask_nr; i++) { + int cpus_per_i = (i * data->mask32_data.long_size * BITS_PER_BYTE); + int cpu; - for_each_set_bit(cpu, mask->mask, nbits) - map->map[i++].cpu = cpu; + perf_record_cpu_map_data__read_one_mask(data, i, local_copy); + for_each_set_bit(cpu, local_copy, 64) + map->map[j++].cpu = cpu + cpus_per_i; } return map; } -struct perf_cpu_map *cpu_map__new_data(struct perf_record_cpu_map_data *data) +struct perf_cpu_map *cpu_map__new_data(const struct perf_record_cpu_map_data *data) { if (data->type == PERF_CPU_MAP__CPUS) - return cpu_map__from_entries((struct cpu_map_entries *)data->data); + return cpu_map__from_entries(data); else - return cpu_map__from_mask((struct perf_record_record_cpu_map *)data->data); + return cpu_map__from_mask(data); } size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp) diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 703ae6d3386e3..fa8a5acdcae12 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h @@ -37,9 +37,11 @@ struct cpu_aggr_map { struct perf_record_cpu_map_data; +bool perf_record_cpu_map_data__test_bit(int i, const struct perf_record_cpu_map_data *data); + struct perf_cpu_map *perf_cpu_map__empty_new(int nr); -struct perf_cpu_map *cpu_map__new_data(struct perf_record_cpu_map_data *data); +struct perf_cpu_map *cpu_map__new_data(const struct perf_record_cpu_map_data *data); size_t cpu_map__snprint(struct perf_cpu_map *map, char *buf, size_t size); size_t cpu_map__snprint_mask(struct perf_cpu_map *map, char *buf, size_t size); size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 98e16659a1495..61bb9675e044d 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -916,30 +916,30 @@ static void perf_event__cpu_map_swap(union perf_event *event, bool sample_id_all __maybe_unused) { struct perf_record_cpu_map_data *data = &event->cpu_map.data; - struct cpu_map_entries *cpus; - struct perf_record_record_cpu_map *mask; - unsigned i; data->type = bswap_16(data->type); switch (data->type) { case PERF_CPU_MAP__CPUS: - cpus = (struct cpu_map_entries *)data->data; - - cpus->nr = bswap_16(cpus->nr); + data->cpus_data.nr = bswap_16(data->cpus_data.nr); - for (i = 0; i < cpus->nr; i++) - cpus->cpu[i] = bswap_16(cpus->cpu[i]); + for (unsigned i = 0; i < data->cpus_data.nr; i++) + data->cpus_data.cpu[i] = bswap_16(data->cpus_data.cpu[i]); break; case PERF_CPU_MAP__MASK: - mask = (struct perf_record_record_cpu_map *)data->data; - - mask->nr = bswap_16(mask->nr); - mask->long_size = bswap_16(mask->long_size); + data->mask32_data.long_size = bswap_16(data->mask32_data.long_size); - switch (mask->long_size) { - case 4: mem_bswap_32(&mask->mask, mask->nr); break; - case 8: mem_bswap_64(&mask->mask, mask->nr); break; + switch (data->mask32_data.long_size) { + case 4: + data->mask32_data.nr = bswap_16(data->mask32_data.nr); + for (unsigned i = 0; i < data->mask32_data.nr; i++) + data->mask32_data.mask[i] = bswap_32(data->mask32_data.mask[i]); + break; + case 8: + data->mask64_data.nr = bswap_16(data->mask64_data.nr); + for (unsigned i = 0; i < data->mask64_data.nr; i++) + data->mask64_data.mask[i] = bswap_64(data->mask64_data.mask[i]); + break; default: pr_err("cpu_map swap: unsupported long size\n"); } diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c index 3ae7c0f54157a..59747c440bd5d 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -1184,27 +1184,33 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool, return err; } -static void synthesize_cpus(struct cpu_map_entries *cpus, +static void synthesize_cpus(struct perf_record_cpu_map_data *data, const struct perf_cpu_map *map) { int i, map_nr = perf_cpu_map__nr(map); - cpus->nr = map_nr; + data->cpus_data.nr = map_nr; for (i = 0; i < map_nr; i++) - cpus->cpu[i] = perf_cpu_map__cpu(map, i).cpu; + data->cpus_data.cpu[i] = perf_cpu_map__cpu(map, i).cpu; } -static void synthesize_mask(struct perf_record_record_cpu_map *mask, +static void synthesize_mask(struct perf_record_cpu_map_data *data, const struct perf_cpu_map *map, int max) { - int i; + int idx; + struct perf_cpu cpu; + + /* Due to padding, the 4bytes per entry mask variant is always smaller. */ + data->mask32_data.nr = BITS_TO_U32(max); + data->mask32_data.long_size = 4; - mask->nr = BITS_TO_LONGS(max); - mask->long_size = sizeof(long); + perf_cpu_map__for_each_cpu(cpu, idx, map) { + int bit_word = cpu.cpu / 32; + __u32 bit_mask = 1U << (cpu.cpu & 31); - for (i = 0; i < perf_cpu_map__nr(map); i++) - set_bit(perf_cpu_map__cpu(map, i).cpu, mask->mask); + data->mask32_data.mask[bit_word] |= bit_mask; + } } static size_t cpus_size(const struct perf_cpu_map *map) @@ -1215,7 +1221,7 @@ static size_t cpus_size(const struct perf_cpu_map *map) static size_t mask_size(const struct perf_cpu_map *map, int *max) { *max = perf_cpu_map__max(map).cpu; - return sizeof(struct perf_record_record_cpu_map) + BITS_TO_LONGS(*max) * sizeof(long); + return sizeof(struct perf_record_mask_cpu_map32) + BITS_TO_U32(*max) * sizeof(__u32); } static void *cpu_map_data__alloc(const struct perf_cpu_map *map, size_t *size, @@ -1248,7 +1254,7 @@ static void *cpu_map_data__alloc(const struct perf_cpu_map *map, size_t *size, *type = PERF_CPU_MAP__MASK; } - *size += sizeof(struct perf_record_cpu_map_data); + *size += sizeof(__u16); /* For perf_record_cpu_map_data.type. */ *size = PERF_ALIGN(*size, sizeof(u64)); return zalloc(*size); } @@ -1261,10 +1267,10 @@ static void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, switch (type) { case PERF_CPU_MAP__CPUS: - synthesize_cpus((struct cpu_map_entries *) data->data, map); + synthesize_cpus(data, map); break; case PERF_CPU_MAP__MASK: - synthesize_mask((struct perf_record_record_cpu_map *)data->data, map, max); + synthesize_mask(data, map, max); default: break; } @@ -1272,7 +1278,7 @@ static void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, static struct perf_record_cpu_map *cpu_map_event__new(const struct perf_cpu_map *map) { - size_t size = sizeof(struct perf_record_cpu_map); + size_t size = sizeof(struct perf_event_header); struct perf_record_cpu_map *event; int max; u16 type; From cf1258ac37afe80dbf277add5f1464477b46c9f0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 19 Jun 2021 10:09:08 -0300 Subject: [PATCH 395/427] perf beauty: Update copy of linux/socket.h with the kernel sources To pick the changes in: 7fa875b8e53c288d ("net: copy from user before calling __copy_msghdr") ebe73a284f4de8c5 ("net: Allow custom iter handler in msghdr") 7c701d92b2b5e517 ("skbuff: carry external ubuf_info in msghdr") c04245328dd7e915 ("net: make __sys_accept4_file() static") That don't result in any changes in the tables generated from that header. This silences this perf build warning: Warning: Kernel ABI header at 'tools/perf/trace/beauty/include/linux/socket.h' differs from latest version at 'include/linux/socket.h' diff -u tools/perf/trace/beauty/include/linux/socket.h include/linux/socket.h Cc: David Ahern Cc: David S. Miller Cc: Dylan Yudaken Cc: Jakub Kicinski Cc: Jens Axboe Cc: Pavel Begunkov Cc: Yajun Deng Link: https://lore.kernel.org/lkml/YvzYs+F+Xzq8Hvvp@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/trace/beauty/include/linux/socket.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/perf/trace/beauty/include/linux/socket.h b/tools/perf/trace/beauty/include/linux/socket.h index 17311ad9f9af2..de3701a2a2129 100644 --- a/tools/perf/trace/beauty/include/linux/socket.h +++ b/tools/perf/trace/beauty/include/linux/socket.h @@ -14,6 +14,8 @@ struct file; struct pid; struct cred; struct socket; +struct sock; +struct sk_buff; #define __sockaddr_check_size(size) \ BUILD_BUG_ON(((size) > sizeof(struct __kernel_sockaddr_storage))) @@ -69,6 +71,9 @@ struct msghdr { unsigned int msg_flags; /* flags on received message */ __kernel_size_t msg_controllen; /* ancillary data buffer length */ struct kiocb *msg_iocb; /* ptr to iocb for async requests */ + struct ubuf_info *msg_ubuf; + int (*sg_from_iter)(struct sock *sk, struct sk_buff *skb, + struct iov_iter *from, size_t length); }; struct user_msghdr { @@ -416,10 +421,9 @@ extern int recvmsg_copy_msghdr(struct msghdr *msg, struct user_msghdr __user *umsg, unsigned flags, struct sockaddr __user **uaddr, struct iovec **iov); -extern int __copy_msghdr_from_user(struct msghdr *kmsg, - struct user_msghdr __user *umsg, - struct sockaddr __user **save_addr, - struct iovec __user **uiov, size_t *nsegs); +extern int __copy_msghdr(struct msghdr *kmsg, + struct user_msghdr *umsg, + struct sockaddr __user **save_addr); /* helpers which do the actual work for syscalls */ extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size, @@ -428,10 +432,6 @@ extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size, extern int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags, struct sockaddr __user *addr, int addr_len); -extern int __sys_accept4_file(struct file *file, unsigned file_flags, - struct sockaddr __user *upeer_sockaddr, - int __user *upeer_addrlen, int flags, - unsigned long nofile); extern struct file *do_accept(struct file *file, unsigned file_flags, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen, int flags); From 7f7f86a7bdd694bfb214479afb6a1f7266bb4d22 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 7 Aug 2020 08:45:47 -0300 Subject: [PATCH 396/427] tools arch x86: Sync the msr-index.h copy with the kernel sources To pick up the changes in: 2b1299322016731d ("x86/speculation: Add RSB VM Exit protections") 4af184ee8b2c0a69 ("tools/power turbostat: dump secondary Turbo-Ratio-Limit") 4ad3278df6fe2b08 ("x86/speculation: Disable RRSBA behavior") d7caac991feeef1b ("x86/cpu/amd: Add Spectral Chicken") 6ad0ad2bf8a67e27 ("x86/bugs: Report Intel retbleed vulnerability") c59a1f106f5cd484 ("KVM: x86/pmu: Add IA32_PEBS_ENABLE MSR emulation for extended PEBS") 465932db25f36648 ("x86/cpu: Add new VMX feature, Tertiary VM-Execution control") 027bbb884be006b0 ("KVM: x86/speculation: Disable Fill buffer clear within guests") 51802186158c74a0 ("x86/speculation/mmio: Enumerate Processor MMIO Stale Data bug") Addressing these tools/perf build warnings: diff -u tools/arch/x86/include/asm/msr-index.h arch/x86/include/asm/msr-index.h Warning: Kernel ABI header at 'tools/arch/x86/include/asm/msr-index.h' differs from latest version at 'arch/x86/include/asm/msr-index.h' That makes the beautification scripts to pick some new entries: $ tools/perf/trace/beauty/tracepoints/x86_msr.sh > before $ cp arch/x86/include/asm/msr-index.h tools/arch/x86/include/asm/msr-index.h $ tools/perf/trace/beauty/tracepoints/x86_msr.sh > after $ diff -u before after --- before 2022-08-17 09:05:13.938246475 -0300 +++ after 2022-08-17 09:05:22.221455851 -0300 @@ -161,6 +161,7 @@ [0x0000048f] = "IA32_VMX_TRUE_EXIT_CTLS", [0x00000490] = "IA32_VMX_TRUE_ENTRY_CTLS", [0x00000491] = "IA32_VMX_VMFUNC", + [0x00000492] = "IA32_VMX_PROCBASED_CTLS3", [0x000004c1] = "IA32_PMC0", [0x000004d0] = "IA32_MCG_EXT_CTL", [0x00000560] = "IA32_RTIT_OUTPUT_BASE", @@ -212,6 +213,7 @@ [0x0000064D] = "PLATFORM_ENERGY_STATUS", [0x0000064e] = "PPERF", [0x0000064f] = "PERF_LIMIT_REASONS", + [0x00000650] = "SECONDARY_TURBO_RATIO_LIMIT", [0x00000658] = "PKG_WEIGHTED_CORE_C0_RES", [0x00000659] = "PKG_ANY_CORE_C0_RES", [0x0000065A] = "PKG_ANY_GFXE_C0_RES", $ Now one can trace systemwide asking to see backtraces to where those MSRs are being read/written, see this example with a previous update: # perf trace -e msr:*_msr/max-stack=32/ --filter="msr>=IA32_U_CET && msr<=IA32_INT_SSP_TAB" ^C# If we use -v (verbose mode) we can see what it does behind the scenes: # perf trace -v -e msr:*_msr/max-stack=32/ --filter="msr>=IA32_U_CET && msr<=IA32_INT_SSP_TAB" Using CPUID AuthenticAMD-25-21-0 0x6a0 0x6a8 New filter for msr:read_msr: (msr>=0x6a0 && msr<=0x6a8) && (common_pid != 597499 && common_pid != 3313) 0x6a0 0x6a8 New filter for msr:write_msr: (msr>=0x6a0 && msr<=0x6a8) && (common_pid != 597499 && common_pid != 3313) mmap size 528384B ^C# Example with a frequent msr: # perf trace -v -e msr:*_msr/max-stack=32/ --filter="msr==IA32_SPEC_CTRL" --max-events 2 Using CPUID AuthenticAMD-25-21-0 0x48 New filter for msr:read_msr: (msr==0x48) && (common_pid != 2612129 && common_pid != 3841) 0x48 New filter for msr:write_msr: (msr==0x48) && (common_pid != 2612129 && common_pid != 3841) mmap size 528384B Looking at the vmlinux_path (8 entries long) symsrc__init: build id mismatch for vmlinux. Using /proc/kcore for kernel data Using /proc/kallsyms for symbols 0.000 Timer/2525383 msr:write_msr(msr: IA32_SPEC_CTRL, val: 6) do_trace_write_msr ([kernel.kallsyms]) do_trace_write_msr ([kernel.kallsyms]) __switch_to_xtra ([kernel.kallsyms]) __switch_to ([kernel.kallsyms]) __schedule ([kernel.kallsyms]) schedule ([kernel.kallsyms]) futex_wait_queue_me ([kernel.kallsyms]) futex_wait ([kernel.kallsyms]) do_futex ([kernel.kallsyms]) __x64_sys_futex ([kernel.kallsyms]) do_syscall_64 ([kernel.kallsyms]) entry_SYSCALL_64_after_hwframe ([kernel.kallsyms]) __futex_abstimed_wait_common64 (/usr/lib64/libpthread-2.33.so) 0.030 :0/0 msr:write_msr(msr: IA32_SPEC_CTRL, val: 2) do_trace_write_msr ([kernel.kallsyms]) do_trace_write_msr ([kernel.kallsyms]) __switch_to_xtra ([kernel.kallsyms]) __switch_to ([kernel.kallsyms]) __schedule ([kernel.kallsyms]) schedule_idle ([kernel.kallsyms]) do_idle ([kernel.kallsyms]) cpu_startup_entry ([kernel.kallsyms]) secondary_startup_64_no_verify ([kernel.kallsyms]) # Cc: Adrian Hunter Cc: Daniel Sneddon Cc: Ian Rogers Cc: Jiri Olsa Cc: Len Brown Cc: Like Xu Cc: Namhyung Kim Cc: Paolo Bonzini Cc: Pawan Gupta Cc: Peter Zijlstra Cc: Robert Hoo Signed-off-by: Arnaldo Carvalho de Melo Link: https://lore.kernel.org/lkml/YvzbT24m2o5U%2F7+q@kernel.org/ Signed-off-by: Arnaldo Carvalho de Melo --- tools/arch/x86/include/asm/msr-index.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/arch/x86/include/asm/msr-index.h b/tools/arch/x86/include/asm/msr-index.h index e057e039173cb..6674bdb096f34 100644 --- a/tools/arch/x86/include/asm/msr-index.h +++ b/tools/arch/x86/include/asm/msr-index.h @@ -235,6 +235,12 @@ #define PERF_CAP_PT_IDX 16 #define MSR_PEBS_LD_LAT_THRESHOLD 0x000003f6 +#define PERF_CAP_PEBS_TRAP BIT_ULL(6) +#define PERF_CAP_ARCH_REG BIT_ULL(7) +#define PERF_CAP_PEBS_FORMAT 0xf00 +#define PERF_CAP_PEBS_BASELINE BIT_ULL(14) +#define PERF_CAP_PEBS_MASK (PERF_CAP_PEBS_TRAP | PERF_CAP_ARCH_REG | \ + PERF_CAP_PEBS_FORMAT | PERF_CAP_PEBS_BASELINE) #define MSR_IA32_RTIT_CTL 0x00000570 #define RTIT_CTL_TRACEEN BIT(0) @@ -392,6 +398,7 @@ #define MSR_TURBO_ACTIVATION_RATIO 0x0000064C #define MSR_PLATFORM_ENERGY_STATUS 0x0000064D +#define MSR_SECONDARY_TURBO_RATIO_LIMIT 0x00000650 #define MSR_PKG_WEIGHTED_CORE_C0_RES 0x00000658 #define MSR_PKG_ANY_CORE_C0_RES 0x00000659 @@ -1022,6 +1029,7 @@ #define MSR_IA32_VMX_TRUE_EXIT_CTLS 0x0000048f #define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x00000490 #define MSR_IA32_VMX_VMFUNC 0x00000491 +#define MSR_IA32_VMX_PROCBASED_CTLS3 0x00000492 /* VMX_BASIC bits and bitmasks */ #define VMX_BASIC_VMCS_SIZE_SHIFT 32 From fabe0c61d842637b722344bcd49bfb1b76e2cc68 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 17 Dec 2020 14:58:51 -0300 Subject: [PATCH 397/427] tools headers UAPI: Sync linux/fscrypt.h with the kernel sources To pick the changes from: 6b2a51ff03bf0c54 ("fscrypt: Add HCTR2 support for filename encryption") That don't result in any changes in tooling, just causes this to be rebuilt: CC /tmp/build/perf-urgent/trace/beauty/sync_file_range.o LD /tmp/build/perf-urgent/trace/beauty/perf-in.o addressing this perf build warning: Warning: Kernel ABI header at 'tools/include/uapi/linux/fscrypt.h' differs from latest version at 'include/uapi/linux/fscrypt.h' diff -u tools/include/uapi/linux/fscrypt.h include/uapi/linux/fscrypt.h Cc: Adrian Hunter Cc: Herbert Xu Cc: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Cc: Nathan Huckleberry Link: https://lore.kernel.org/lkml/Yvzl8C7O1b+hf9GS@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/uapi/linux/fscrypt.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/include/uapi/linux/fscrypt.h b/tools/include/uapi/linux/fscrypt.h index 9f4428be3e362..a756b29afcc23 100644 --- a/tools/include/uapi/linux/fscrypt.h +++ b/tools/include/uapi/linux/fscrypt.h @@ -27,7 +27,8 @@ #define FSCRYPT_MODE_AES_128_CBC 5 #define FSCRYPT_MODE_AES_128_CTS 6 #define FSCRYPT_MODE_ADIANTUM 9 -/* If adding a mode number > 9, update FSCRYPT_MODE_MAX in fscrypt_private.h */ +#define FSCRYPT_MODE_AES_256_HCTR2 10 +/* If adding a mode number > 10, update FSCRYPT_MODE_MAX in fscrypt_private.h */ /* * Legacy policy version; ad-hoc KDF and no key verification. From 62ed93d1996b3aaeadda59b25ac5b70be59b8a61 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 1 Jul 2021 13:39:15 -0300 Subject: [PATCH 398/427] tools headers cpufeatures: Sync with the kernel sources To pick the changes from: 2b1299322016731d ("x86/speculation: Add RSB VM Exit protections") 28a99e95f55c6185 ("x86/amd: Use IBPB for firmware calls") 4ad3278df6fe2b08 ("x86/speculation: Disable RRSBA behavior") 26aae8ccbc197223 ("x86/cpu/amd: Enumerate BTC_NO") 9756bba28470722d ("x86/speculation: Fill RSB on vmexit for IBRS") 3ebc170068885b6f ("x86/bugs: Add retbleed=ibpb") 2dbb887e875b1de3 ("x86/entry: Add kernel IBRS implementation") 6b80b59b35557065 ("x86/bugs: Report AMD retbleed vulnerability") a149180fbcf336e9 ("x86: Add magic AMD return-thunk") 15e67227c49a5783 ("x86: Undo return-thunk damage") a883d624aed463c8 ("x86/cpufeatures: Move RETPOLINE flags to word 11") aae99a7c9ab371b2 ("x86/cpufeatures: Introduce x2AVIC CPUID bit") 6f33a9daff9f0790 ("x86: Fix comment for X86_FEATURE_ZEN") 51802186158c74a0 ("x86/speculation/mmio: Enumerate Processor MMIO Stale Data bug") This only causes these perf files to be rebuilt: CC /tmp/build/perf/bench/mem-memcpy-x86-64-asm.o CC /tmp/build/perf/bench/mem-memset-x86-64-asm.o And addresses this perf build warning: Warning: Kernel ABI header at 'tools/arch/x86/include/asm/cpufeatures.h' differs from latest version at 'arch/x86/include/asm/cpufeatures.h' diff -u tools/arch/x86/include/asm/cpufeatures.h arch/x86/include/asm/cpufeatures.h Cc: Adrian Hunter Cc: Alexandre Chartre Cc: Andrew Cooper Cc: Borislav Petkov Cc: Daniel Sneddon Cc: Dave Hansen Cc: Ian Rogers Cc: Jiri Olsa Cc: Josh Poimboeuf Cc: Namhyung Kim Cc: Paolo Bonzini Cc: Pawan Gupta Cc: Peter Zijlstra Cc: Suravee Suthikulpanit Cc: Wyes Karny Link: https://lore.kernel.org/lkml/Yvznmu5oHv0ZDN2w@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/arch/x86/include/asm/cpufeatures.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h index 8323ac5b7eee5..235dc85c91c3e 100644 --- a/tools/arch/x86/include/asm/cpufeatures.h +++ b/tools/arch/x86/include/asm/cpufeatures.h @@ -219,7 +219,7 @@ #define X86_FEATURE_IBRS ( 7*32+25) /* Indirect Branch Restricted Speculation */ #define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */ #define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */ -#define X86_FEATURE_ZEN ( 7*32+28) /* "" CPU is AMD family 0x17 or above (Zen) */ +#define X86_FEATURE_ZEN (7*32+28) /* "" CPU based on Zen microarchitecture */ #define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* "" L1TF workaround PTE inversion */ #define X86_FEATURE_IBRS_ENHANCED ( 7*32+30) /* Enhanced IBRS */ #define X86_FEATURE_MSR_IA32_FEAT_CTL ( 7*32+31) /* "" MSR IA32_FEAT_CTL configured */ @@ -303,7 +303,7 @@ #define X86_FEATURE_RETHUNK (11*32+14) /* "" Use REturn THUNK */ #define X86_FEATURE_UNRET (11*32+15) /* "" AMD BTB untrain return */ #define X86_FEATURE_USE_IBPB_FW (11*32+16) /* "" Use IBPB during runtime firmware calls */ -#define X86_FEATURE_RSB_VMEXIT_LITE (11*32+17) /* "" Fill RSB on VM-Exit when EIBRS is enabled */ +#define X86_FEATURE_RSB_VMEXIT_LITE (11*32+17) /* "" Fill RSB on VM exit when EIBRS is enabled */ /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */ #define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */ @@ -354,6 +354,7 @@ #define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */ #define X86_FEATURE_V_VMSAVE_VMLOAD (15*32+15) /* Virtual VMSAVE VMLOAD */ #define X86_FEATURE_VGIF (15*32+16) /* Virtual GIF */ +#define X86_FEATURE_X2AVIC (15*32+18) /* Virtual x2apic */ #define X86_FEATURE_V_SPEC_CTRL (15*32+20) /* Virtual SPEC_CTRL */ #define X86_FEATURE_SVME_ADDR_CHK (15*32+28) /* "" SVME addr check */ @@ -457,5 +458,6 @@ #define X86_BUG_SRBDS X86_BUG(24) /* CPU may leak RNG bits if not mitigated */ #define X86_BUG_MMIO_STALE_DATA X86_BUG(25) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */ #define X86_BUG_RETBLEED X86_BUG(26) /* CPU is affected by RETBleed */ +#define X86_BUG_EIBRS_PBRSB X86_BUG(27) /* EIBRS is vulnerable to Post Barrier RSB Predictions */ #endif /* _ASM_X86_CPUFEATURES_H */ From 54cd4cde7c1edb869603073167cabab0b760fff6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 13 Nov 2021 11:08:31 -0300 Subject: [PATCH 399/427] tools headers UAPI: Sync drm/i915_drm.h with the kernel sources To pick up the changes in: a913bde810fc464d ("drm/i915: Update i915 uapi documentation") 525e93f6317a08a0 ("drm/i915/uapi: add NEEDS_CPU_ACCESS hint") 141f733bb3abb000 ("drm/i915/uapi: expose the avail tracking") 3f4309cbdc849637 ("drm/i915/uapi: add probed_cpu_visible_size") a50794f26f52c66c ("uapi/drm/i915: Document memory residency and Flat-CCS capability of obj") That don't add any new ioctl, so no changes in tooling. This silences this perf build warning: Warning: Kernel ABI header at 'tools/include/uapi/drm/i915_drm.h' differs from latest version at 'include/uapi/drm/i915_drm.h' diff -u tools/include/uapi/drm/i915_drm.h include/uapi/drm/i915_drm.h Cc: Adrian Hunter Cc: Ian Rogers Cc: Jiri Olsa Cc: Matthew Auld Cc: Matt Roper Cc: Namhyung Kim Cc: Niranjana Vishwanathapura Cc: Ramalingam C Link: http://lore.kernel.org/lkml/Yvzrp9RFIeEkb5fI@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/uapi/drm/i915_drm.h | 387 +++++++++++++++++++++++------- 1 file changed, 300 insertions(+), 87 deletions(-) diff --git a/tools/include/uapi/drm/i915_drm.h b/tools/include/uapi/drm/i915_drm.h index b28ff5d881457..520ad2691a99d 100644 --- a/tools/include/uapi/drm/i915_drm.h +++ b/tools/include/uapi/drm/i915_drm.h @@ -751,14 +751,27 @@ typedef struct drm_i915_irq_wait { /* Must be kept compact -- no holes and well documented */ -typedef struct drm_i915_getparam { +/** + * struct drm_i915_getparam - Driver parameter query structure. + */ +struct drm_i915_getparam { + /** @param: Driver parameter to query. */ __s32 param; - /* + + /** + * @value: Address of memory where queried value should be put. + * * WARNING: Using pointers instead of fixed-size u64 means we need to write * compat32 code. Don't repeat this mistake. */ int __user *value; -} drm_i915_getparam_t; +}; + +/** + * typedef drm_i915_getparam_t - Driver parameter query structure. + * See struct drm_i915_getparam. + */ +typedef struct drm_i915_getparam drm_i915_getparam_t; /* Ioctl to set kernel params: */ @@ -1239,76 +1252,119 @@ struct drm_i915_gem_exec_object2 { __u64 rsvd2; }; +/** + * struct drm_i915_gem_exec_fence - An input or output fence for the execbuf + * ioctl. + * + * The request will wait for input fence to signal before submission. + * + * The returned output fence will be signaled after the completion of the + * request. + */ struct drm_i915_gem_exec_fence { - /** - * User's handle for a drm_syncobj to wait on or signal. - */ + /** @handle: User's handle for a drm_syncobj to wait on or signal. */ __u32 handle; + /** + * @flags: Supported flags are: + * + * I915_EXEC_FENCE_WAIT: + * Wait for the input fence before request submission. + * + * I915_EXEC_FENCE_SIGNAL: + * Return request completion fence as output + */ + __u32 flags; #define I915_EXEC_FENCE_WAIT (1<<0) #define I915_EXEC_FENCE_SIGNAL (1<<1) #define __I915_EXEC_FENCE_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SIGNAL << 1)) - __u32 flags; }; -/* - * See drm_i915_gem_execbuffer_ext_timeline_fences. - */ -#define DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES 0 - -/* +/** + * struct drm_i915_gem_execbuffer_ext_timeline_fences - Timeline fences + * for execbuf ioctl. + * * This structure describes an array of drm_syncobj and associated points for * timeline variants of drm_syncobj. It is invalid to append this structure to * the execbuf if I915_EXEC_FENCE_ARRAY is set. */ struct drm_i915_gem_execbuffer_ext_timeline_fences { +#define DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES 0 + /** @base: Extension link. See struct i915_user_extension. */ struct i915_user_extension base; /** - * Number of element in the handles_ptr & value_ptr arrays. + * @fence_count: Number of elements in the @handles_ptr & @value_ptr + * arrays. */ __u64 fence_count; /** - * Pointer to an array of struct drm_i915_gem_exec_fence of length - * fence_count. + * @handles_ptr: Pointer to an array of struct drm_i915_gem_exec_fence + * of length @fence_count. */ __u64 handles_ptr; /** - * Pointer to an array of u64 values of length fence_count. Values - * must be 0 for a binary drm_syncobj. A Value of 0 for a timeline - * drm_syncobj is invalid as it turns a drm_syncobj into a binary one. + * @values_ptr: Pointer to an array of u64 values of length + * @fence_count. + * Values must be 0 for a binary drm_syncobj. A Value of 0 for a + * timeline drm_syncobj is invalid as it turns a drm_syncobj into a + * binary one. */ __u64 values_ptr; }; +/** + * struct drm_i915_gem_execbuffer2 - Structure for DRM_I915_GEM_EXECBUFFER2 + * ioctl. + */ struct drm_i915_gem_execbuffer2 { - /** - * List of gem_exec_object2 structs - */ + /** @buffers_ptr: Pointer to a list of gem_exec_object2 structs */ __u64 buffers_ptr; + + /** @buffer_count: Number of elements in @buffers_ptr array */ __u32 buffer_count; - /** Offset in the batchbuffer to start execution from. */ + /** + * @batch_start_offset: Offset in the batchbuffer to start execution + * from. + */ __u32 batch_start_offset; - /** Bytes used in batchbuffer from batch_start_offset */ + + /** + * @batch_len: Length in bytes of the batch buffer, starting from the + * @batch_start_offset. If 0, length is assumed to be the batch buffer + * object size. + */ __u32 batch_len; + + /** @DR1: deprecated */ __u32 DR1; + + /** @DR4: deprecated */ __u32 DR4; + + /** @num_cliprects: See @cliprects_ptr */ __u32 num_cliprects; + /** - * This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY - * & I915_EXEC_USE_EXTENSIONS are not set. + * @cliprects_ptr: Kernel clipping was a DRI1 misfeature. + * + * It is invalid to use this field if I915_EXEC_FENCE_ARRAY or + * I915_EXEC_USE_EXTENSIONS flags are not set. * * If I915_EXEC_FENCE_ARRAY is set, then this is a pointer to an array - * of struct drm_i915_gem_exec_fence and num_cliprects is the length - * of the array. + * of &drm_i915_gem_exec_fence and @num_cliprects is the length of the + * array. * * If I915_EXEC_USE_EXTENSIONS is set, then this is a pointer to a - * single struct i915_user_extension and num_cliprects is 0. + * single &i915_user_extension and num_cliprects is 0. */ __u64 cliprects_ptr; + + /** @flags: Execbuf flags */ + __u64 flags; #define I915_EXEC_RING_MASK (0x3f) #define I915_EXEC_DEFAULT (0<<0) #define I915_EXEC_RENDER (1<<0) @@ -1326,10 +1382,6 @@ struct drm_i915_gem_execbuffer2 { #define I915_EXEC_CONSTANTS_REL_GENERAL (0<<6) /* default */ #define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6) #define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */ - __u64 flags; - __u64 rsvd1; /* now used for context info */ - __u64 rsvd2; -}; /** Resets the SO write offset registers for transform feedback on gen7. */ #define I915_EXEC_GEN7_SOL_RESET (1<<8) @@ -1432,9 +1484,23 @@ struct drm_i915_gem_execbuffer2 { * drm_i915_gem_execbuffer_ext enum. */ #define I915_EXEC_USE_EXTENSIONS (1 << 21) - #define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_USE_EXTENSIONS << 1)) + /** @rsvd1: Context id */ + __u64 rsvd1; + + /** + * @rsvd2: in and out sync_file file descriptors. + * + * When I915_EXEC_FENCE_IN or I915_EXEC_FENCE_SUBMIT flag is set, the + * lower 32 bits of this field will have the in sync_file fd (input). + * + * When I915_EXEC_FENCE_OUT flag is set, the upper 32 bits of this + * field will have the out sync_file fd (output). + */ + __u64 rsvd2; +}; + #define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) #define i915_execbuffer2_set_context_id(eb2, context) \ (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK @@ -1814,19 +1880,58 @@ struct drm_i915_gem_context_create { __u32 pad; }; +/** + * struct drm_i915_gem_context_create_ext - Structure for creating contexts. + */ struct drm_i915_gem_context_create_ext { - __u32 ctx_id; /* output: id of new context*/ + /** @ctx_id: Id of the created context (output) */ + __u32 ctx_id; + + /** + * @flags: Supported flags are: + * + * I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS: + * + * Extensions may be appended to this structure and driver must check + * for those. See @extensions. + * + * I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE + * + * Created context will have single timeline. + */ __u32 flags; #define I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS (1u << 0) #define I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE (1u << 1) #define I915_CONTEXT_CREATE_FLAGS_UNKNOWN \ (-(I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE << 1)) + + /** + * @extensions: Zero-terminated chain of extensions. + * + * I915_CONTEXT_CREATE_EXT_SETPARAM: + * Context parameter to set or query during context creation. + * See struct drm_i915_gem_context_create_ext_setparam. + * + * I915_CONTEXT_CREATE_EXT_CLONE: + * This extension has been removed. On the off chance someone somewhere + * has attempted to use it, never re-use this extension number. + */ __u64 extensions; +#define I915_CONTEXT_CREATE_EXT_SETPARAM 0 +#define I915_CONTEXT_CREATE_EXT_CLONE 1 }; +/** + * struct drm_i915_gem_context_param - Context parameter to set or query. + */ struct drm_i915_gem_context_param { + /** @ctx_id: Context id */ __u32 ctx_id; + + /** @size: Size of the parameter @value */ __u32 size; + + /** @param: Parameter to set or query */ __u64 param; #define I915_CONTEXT_PARAM_BAN_PERIOD 0x1 /* I915_CONTEXT_PARAM_NO_ZEROMAP has been removed. On the off chance @@ -1973,6 +2078,7 @@ struct drm_i915_gem_context_param { #define I915_CONTEXT_PARAM_PROTECTED_CONTENT 0xd /* Must be kept compact -- no holes and well documented */ + /** @value: Context parameter value to be set or queried */ __u64 value; }; @@ -2371,23 +2477,29 @@ struct i915_context_param_engines { struct i915_engine_class_instance engines[N__]; \ } __attribute__((packed)) name__ +/** + * struct drm_i915_gem_context_create_ext_setparam - Context parameter + * to set or query during context creation. + */ struct drm_i915_gem_context_create_ext_setparam { -#define I915_CONTEXT_CREATE_EXT_SETPARAM 0 + /** @base: Extension link. See struct i915_user_extension. */ struct i915_user_extension base; + + /** + * @param: Context parameter to set or query. + * See struct drm_i915_gem_context_param. + */ struct drm_i915_gem_context_param param; }; -/* This API has been removed. On the off chance someone somewhere has - * attempted to use it, never re-use this extension number. - */ -#define I915_CONTEXT_CREATE_EXT_CLONE 1 - struct drm_i915_gem_context_destroy { __u32 ctx_id; __u32 pad; }; -/* +/** + * struct drm_i915_gem_vm_control - Structure to create or destroy VM. + * * DRM_I915_GEM_VM_CREATE - * * Create a new virtual memory address space (ppGTT) for use within a context @@ -2397,20 +2509,23 @@ struct drm_i915_gem_context_destroy { * The id of new VM (bound to the fd) for use with I915_CONTEXT_PARAM_VM is * returned in the outparam @id. * - * No flags are defined, with all bits reserved and must be zero. - * * An extension chain maybe provided, starting with @extensions, and terminated * by the @next_extension being 0. Currently, no extensions are defined. * * DRM_I915_GEM_VM_DESTROY - * - * Destroys a previously created VM id, specified in @id. + * Destroys a previously created VM id, specified in @vm_id. * * No extensions or flags are allowed currently, and so must be zero. */ struct drm_i915_gem_vm_control { + /** @extensions: Zero-terminated chain of extensions. */ __u64 extensions; + + /** @flags: reserved for future usage, currently MBZ */ __u32 flags; + + /** @vm_id: Id of the VM created or to be destroyed */ __u32 vm_id; }; @@ -3207,36 +3322,6 @@ struct drm_i915_gem_memory_class_instance { * struct drm_i915_memory_region_info - Describes one region as known to the * driver. * - * Note that we reserve some stuff here for potential future work. As an example - * we might want expose the capabilities for a given region, which could include - * things like if the region is CPU mappable/accessible, what are the supported - * mapping types etc. - * - * Note that to extend struct drm_i915_memory_region_info and struct - * drm_i915_query_memory_regions in the future the plan is to do the following: - * - * .. code-block:: C - * - * struct drm_i915_memory_region_info { - * struct drm_i915_gem_memory_class_instance region; - * union { - * __u32 rsvd0; - * __u32 new_thing1; - * }; - * ... - * union { - * __u64 rsvd1[8]; - * struct { - * __u64 new_thing2; - * __u64 new_thing3; - * ... - * }; - * }; - * }; - * - * With this things should remain source compatible between versions for - * userspace, even as we add new fields. - * * Note this is using both struct drm_i915_query_item and struct drm_i915_query. * For this new query we are adding the new query id DRM_I915_QUERY_MEMORY_REGIONS * at &drm_i915_query_item.query_id. @@ -3248,14 +3333,81 @@ struct drm_i915_memory_region_info { /** @rsvd0: MBZ */ __u32 rsvd0; - /** @probed_size: Memory probed by the driver (-1 = unknown) */ + /** + * @probed_size: Memory probed by the driver + * + * Note that it should not be possible to ever encounter a zero value + * here, also note that no current region type will ever return -1 here. + * Although for future region types, this might be a possibility. The + * same applies to the other size fields. + */ __u64 probed_size; - /** @unallocated_size: Estimate of memory remaining (-1 = unknown) */ + /** + * @unallocated_size: Estimate of memory remaining + * + * Requires CAP_PERFMON or CAP_SYS_ADMIN to get reliable accounting. + * Without this (or if this is an older kernel) the value here will + * always equal the @probed_size. Note this is only currently tracked + * for I915_MEMORY_CLASS_DEVICE regions (for other types the value here + * will always equal the @probed_size). + */ __u64 unallocated_size; - /** @rsvd1: MBZ */ - __u64 rsvd1[8]; + union { + /** @rsvd1: MBZ */ + __u64 rsvd1[8]; + struct { + /** + * @probed_cpu_visible_size: Memory probed by the driver + * that is CPU accessible. + * + * This will be always be <= @probed_size, and the + * remainder (if there is any) will not be CPU + * accessible. + * + * On systems without small BAR, the @probed_size will + * always equal the @probed_cpu_visible_size, since all + * of it will be CPU accessible. + * + * Note this is only tracked for + * I915_MEMORY_CLASS_DEVICE regions (for other types the + * value here will always equal the @probed_size). + * + * Note that if the value returned here is zero, then + * this must be an old kernel which lacks the relevant + * small-bar uAPI support (including + * I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS), but on + * such systems we should never actually end up with a + * small BAR configuration, assuming we are able to load + * the kernel module. Hence it should be safe to treat + * this the same as when @probed_cpu_visible_size == + * @probed_size. + */ + __u64 probed_cpu_visible_size; + + /** + * @unallocated_cpu_visible_size: Estimate of CPU + * visible memory remaining. + * + * Note this is only tracked for + * I915_MEMORY_CLASS_DEVICE regions (for other types the + * value here will always equal the + * @probed_cpu_visible_size). + * + * Requires CAP_PERFMON or CAP_SYS_ADMIN to get reliable + * accounting. Without this the value here will always + * equal the @probed_cpu_visible_size. Note this is only + * currently tracked for I915_MEMORY_CLASS_DEVICE + * regions (for other types the value here will also + * always equal the @probed_cpu_visible_size). + * + * If this is an older kernel the value here will be + * zero, see also @probed_cpu_visible_size. + */ + __u64 unallocated_cpu_visible_size; + }; + }; }; /** @@ -3329,11 +3481,11 @@ struct drm_i915_query_memory_regions { * struct drm_i915_gem_create_ext - Existing gem_create behaviour, with added * extension support using struct i915_user_extension. * - * Note that in the future we want to have our buffer flags here, at least for - * the stuff that is immutable. Previously we would have two ioctls, one to - * create the object with gem_create, and another to apply various parameters, - * however this creates some ambiguity for the params which are considered - * immutable. Also in general we're phasing out the various SET/GET ioctls. + * Note that new buffer flags should be added here, at least for the stuff that + * is immutable. Previously we would have two ioctls, one to create the object + * with gem_create, and another to apply various parameters, however this + * creates some ambiguity for the params which are considered immutable. Also in + * general we're phasing out the various SET/GET ioctls. */ struct drm_i915_gem_create_ext { /** @@ -3341,7 +3493,6 @@ struct drm_i915_gem_create_ext { * * The (page-aligned) allocated size for the object will be returned. * - * * DG2 64K min page size implications: * * On discrete platforms, starting from DG2, we have to contend with GTT @@ -3353,7 +3504,9 @@ struct drm_i915_gem_create_ext { * * Note that the returned size here will always reflect any required * rounding up done by the kernel, i.e 4K will now become 64K on devices - * such as DG2. + * such as DG2. The kernel will always select the largest minimum + * page-size for the set of possible placements as the value to use when + * rounding up the @size. * * Special DG2 GTT address alignment requirement: * @@ -3377,14 +3530,58 @@ struct drm_i915_gem_create_ext { * is deemed to be a good compromise. */ __u64 size; + /** * @handle: Returned handle for the object. * * Object handles are nonzero. */ __u32 handle; - /** @flags: MBZ */ + + /** + * @flags: Optional flags. + * + * Supported values: + * + * I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS - Signal to the kernel that + * the object will need to be accessed via the CPU. + * + * Only valid when placing objects in I915_MEMORY_CLASS_DEVICE, and only + * strictly required on configurations where some subset of the device + * memory is directly visible/mappable through the CPU (which we also + * call small BAR), like on some DG2+ systems. Note that this is quite + * undesirable, but due to various factors like the client CPU, BIOS etc + * it's something we can expect to see in the wild. See + * &drm_i915_memory_region_info.probed_cpu_visible_size for how to + * determine if this system applies. + * + * Note that one of the placements MUST be I915_MEMORY_CLASS_SYSTEM, to + * ensure the kernel can always spill the allocation to system memory, + * if the object can't be allocated in the mappable part of + * I915_MEMORY_CLASS_DEVICE. + * + * Also note that since the kernel only supports flat-CCS on objects + * that can *only* be placed in I915_MEMORY_CLASS_DEVICE, we therefore + * don't support I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS together with + * flat-CCS. + * + * Without this hint, the kernel will assume that non-mappable + * I915_MEMORY_CLASS_DEVICE is preferred for this object. Note that the + * kernel can still migrate the object to the mappable part, as a last + * resort, if userspace ever CPU faults this object, but this might be + * expensive, and so ideally should be avoided. + * + * On older kernels which lack the relevant small-bar uAPI support (see + * also &drm_i915_memory_region_info.probed_cpu_visible_size), + * usage of the flag will result in an error, but it should NEVER be + * possible to end up with a small BAR configuration, assuming we can + * also successfully load the i915 kernel module. In such cases the + * entire I915_MEMORY_CLASS_DEVICE region will be CPU accessible, and as + * such there are zero restrictions on where the object can be placed. + */ +#define I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS (1 << 0) __u32 flags; + /** * @extensions: The chain of extensions to apply to this object. * @@ -3443,6 +3640,22 @@ struct drm_i915_gem_create_ext { * At which point we get the object handle in &drm_i915_gem_create_ext.handle, * along with the final object size in &drm_i915_gem_create_ext.size, which * should account for any rounding up, if required. + * + * Note that userspace has no means of knowing the current backing region + * for objects where @num_regions is larger than one. The kernel will only + * ensure that the priority order of the @regions array is honoured, either + * when initially placing the object, or when moving memory around due to + * memory pressure + * + * On Flat-CCS capable HW, compression is supported for the objects residing + * in I915_MEMORY_CLASS_DEVICE. When such objects (compressed) have other + * memory class in @regions and migrated (by i915, due to memory + * constraints) to the non I915_MEMORY_CLASS_DEVICE region, then i915 needs to + * decompress the content. But i915 doesn't have the required information to + * decompress the userspace compressed objects. + * + * So i915 supports Flat-CCS, on the objects which can reside only on + * I915_MEMORY_CLASS_DEVICE regions. */ struct drm_i915_gem_create_ext_memory_regions { /** @base: Extension link. See struct i915_user_extension. */ From bf465ca8090a1aa4f88d87e003302158c772c3de Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 9 May 2021 09:39:02 -0300 Subject: [PATCH 400/427] tools headers UAPI: Sync linux/kvm.h with the kernel sources MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To pick the changes in: 8a061562e2f2b32b ("RISC-V: KVM: Add extensible CSR emulation framework") f5ecfee944934757 ("KVM: s390: resetting the Topology-Change-Report") 450a563924ae9437 ("KVM: stats: Fix value for KVM_STATS_UNIT_MAX for boolean stats") 1b870fa5573e260b ("kvm: stats: tell userspace which values are boolean") db1c875e0539518e ("KVM: s390: add KVM_S390_ZPCI_OP to manage guest zPCI devices") 94dfc73e7cf4a31d ("treewide: uapi: Replace zero-length arrays with flexible-array members") 084cc29f8bbb034c ("KVM: x86/MMU: Allow NX huge pages to be disabled on a per-vm basis") 2f4073e08f4cc5a4 ("KVM: VMX: Enable Notify VM exit") ed2351174e38ad4f ("KVM: x86: Extend KVM_{G,S}ET_VCPU_EVENTS to support pending triple fault") e9bf3acb23f0a6e1 ("KVM: s390: Add KVM_CAP_S390_PROTECTED_DUMP") 8aba09588d2af37c ("KVM: s390: Add CPU dump functionality") 0460eb35b443f73f ("KVM: s390: Add configuration dump functionality") fe9a93e07ba4f29d ("KVM: s390: pv: Add query dump information") 35d02493dba1ae63 ("KVM: s390: pv: Add query interface") c24a950ec7d60c4d ("KVM, SEV: Add KVM_EXIT_SHUTDOWN metadata for SEV-ES") ffbb61d09fc56c85 ("KVM: x86: Accept KVM_[GS]ET_TSC_KHZ as a VM ioctl.") 661a20fab7d156cf ("KVM: x86/xen: Advertise and document KVM_XEN_HVM_CONFIG_EVTCHN_SEND") fde0451be8fb3208 ("KVM: x86/xen: Support per-vCPU event channel upcall via local APIC") 28d1629f751c4a5f ("KVM: x86/xen: Kernel acceleration for XENVER_version") 536395260582be74 ("KVM: x86/xen: handle PV timers oneshot mode") 942c2490c23f2800 ("KVM: x86/xen: Add KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID") 2fd6df2f2b47d430 ("KVM: x86/xen: intercept EVTCHNOP_send from guests") 35025735a79eaa89 ("KVM: x86/xen: Support direct injection of event channel events") That just rebuilds perf, as these patches add just an ioctl that is S390 specific and may clash with other arches, so are so far being excluded in the harvester script: $ tools/perf/trace/beauty/kvm_ioctl.sh > before $ cp include/uapi/linux/kvm.h tools/include/uapi/linux/kvm.h $ tools/perf/trace/beauty/kvm_ioctl.sh > after $ diff -u before after $ grep 390 tools/perf/trace/beauty/kvm_ioctl.sh egrep -v " ((ARM|PPC|S390)_|[GS]ET_(DEBUGREGS|PIT2|XSAVE|TSC_KHZ)|CREATE_SPAPR_TCE_64)" | \ $ This is also by now used by tools/testing/selftests/kvm/, a simple test build succeeded. This silences this perf build warning: Warning: Kernel ABI header at 'tools/include/uapi/linux/kvm.h' differs from latest version at 'include/uapi/linux/kvm.h' diff -u tools/include/uapi/linux/kvm.h include/uapi/linux/kvm.h Cc: Anup Patel Cc: Ben Gardon Cc: Chenyi Qiang Cc: Christian Borntraeger Cc: David Woodhouse Cc: Gustavo A. R. Silva Cc: Janosch Frank Cc: João Martins Cc: Matthew Rosato Cc: Oliver Upton Cc: Paolo Bonzini Cc: Peter Gonda Cc: Pierre Morel Cc: Tao Xu Link: https://lore.kernel.org/lkml/YvzuryClcn%2FvA0Gn@kernel.org/ Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/uapi/linux/kvm.h | 108 +++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h index cb6e3846d27b9..eed0315a77a6d 100644 --- a/tools/include/uapi/linux/kvm.h +++ b/tools/include/uapi/linux/kvm.h @@ -270,6 +270,8 @@ struct kvm_xen_exit { #define KVM_EXIT_X86_BUS_LOCK 33 #define KVM_EXIT_XEN 34 #define KVM_EXIT_RISCV_SBI 35 +#define KVM_EXIT_RISCV_CSR 36 +#define KVM_EXIT_NOTIFY 37 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -496,6 +498,18 @@ struct kvm_run { unsigned long args[6]; unsigned long ret[2]; } riscv_sbi; + /* KVM_EXIT_RISCV_CSR */ + struct { + unsigned long csr_num; + unsigned long new_value; + unsigned long write_mask; + unsigned long ret_value; + } riscv_csr; + /* KVM_EXIT_NOTIFY */ + struct { +#define KVM_NOTIFY_CONTEXT_INVALID (1 << 0) + __u32 flags; + } notify; /* Fix the size of the union. */ char padding[256]; }; @@ -1157,6 +1171,12 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_VM_TSC_CONTROL 214 #define KVM_CAP_SYSTEM_EVENT_DATA 215 #define KVM_CAP_ARM_SYSTEM_SUSPEND 216 +#define KVM_CAP_S390_PROTECTED_DUMP 217 +#define KVM_CAP_X86_TRIPLE_FAULT_EVENT 218 +#define KVM_CAP_X86_NOTIFY_VMEXIT 219 +#define KVM_CAP_VM_DISABLE_NX_HUGE_PAGES 220 +#define KVM_CAP_S390_ZPCI_OP 221 +#define KVM_CAP_S390_CPU_TOPOLOGY 222 #ifdef KVM_CAP_IRQ_ROUTING @@ -1660,6 +1680,55 @@ struct kvm_s390_pv_unp { __u64 tweak; }; +enum pv_cmd_dmp_id { + KVM_PV_DUMP_INIT, + KVM_PV_DUMP_CONFIG_STOR_STATE, + KVM_PV_DUMP_COMPLETE, + KVM_PV_DUMP_CPU, +}; + +struct kvm_s390_pv_dmp { + __u64 subcmd; + __u64 buff_addr; + __u64 buff_len; + __u64 gaddr; /* For dump storage state */ + __u64 reserved[4]; +}; + +enum pv_cmd_info_id { + KVM_PV_INFO_VM, + KVM_PV_INFO_DUMP, +}; + +struct kvm_s390_pv_info_dump { + __u64 dump_cpu_buffer_len; + __u64 dump_config_mem_buffer_per_1m; + __u64 dump_config_finalize_len; +}; + +struct kvm_s390_pv_info_vm { + __u64 inst_calls_list[4]; + __u64 max_cpus; + __u64 max_guests; + __u64 max_guest_addr; + __u64 feature_indication; +}; + +struct kvm_s390_pv_info_header { + __u32 id; + __u32 len_max; + __u32 len_written; + __u32 reserved; +}; + +struct kvm_s390_pv_info { + struct kvm_s390_pv_info_header header; + union { + struct kvm_s390_pv_info_dump dump; + struct kvm_s390_pv_info_vm vm; + }; +}; + enum pv_cmd_id { KVM_PV_ENABLE, KVM_PV_DISABLE, @@ -1668,6 +1737,8 @@ enum pv_cmd_id { KVM_PV_VERIFY, KVM_PV_PREP_RESET, KVM_PV_UNSHARE_ALL, + KVM_PV_INFO, + KVM_PV_DUMP, }; struct kvm_pv_cmd { @@ -2119,4 +2190,41 @@ struct kvm_stats_desc { /* Available with KVM_CAP_XSAVE2 */ #define KVM_GET_XSAVE2 _IOR(KVMIO, 0xcf, struct kvm_xsave) +/* Available with KVM_CAP_S390_PROTECTED_DUMP */ +#define KVM_S390_PV_CPU_COMMAND _IOWR(KVMIO, 0xd0, struct kvm_pv_cmd) + +/* Available with KVM_CAP_X86_NOTIFY_VMEXIT */ +#define KVM_X86_NOTIFY_VMEXIT_ENABLED (1ULL << 0) +#define KVM_X86_NOTIFY_VMEXIT_USER (1ULL << 1) + +/* Available with KVM_CAP_S390_ZPCI_OP */ +#define KVM_S390_ZPCI_OP _IOW(KVMIO, 0xd1, struct kvm_s390_zpci_op) + +struct kvm_s390_zpci_op { + /* in */ + __u32 fh; /* target device */ + __u8 op; /* operation to perform */ + __u8 pad[3]; + union { + /* for KVM_S390_ZPCIOP_REG_AEN */ + struct { + __u64 ibv; /* Guest addr of interrupt bit vector */ + __u64 sb; /* Guest addr of summary bit */ + __u32 flags; + __u32 noi; /* Number of interrupts */ + __u8 isc; /* Guest interrupt subclass */ + __u8 sbo; /* Offset of guest summary bit vector */ + __u16 pad; + } reg_aen; + __u64 reserved[8]; + } u; +}; + +/* types for kvm_s390_zpci_op->op */ +#define KVM_S390_ZPCIOP_REG_AEN 0 +#define KVM_S390_ZPCIOP_DEREG_AEN 1 + +/* flags for kvm_s390_zpci_op->u.reg_aen.flags */ +#define KVM_S390_ZPCIOP_REGAEN_HOST (1 << 0) + #endif /* __LINUX_KVM_H */ From 25f308951703be599f82c44229b6f74c4ad86ed4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 12 Aug 2020 08:52:32 -0300 Subject: [PATCH 401/427] tools headers kvm s390: Sync headers with the kernel sources To pick the changes in: f5ecfee944934757 ("KVM: s390: resetting the Topology-Change-Report") None of them trigger any changes in tooling, this time this is just to silence these perf build warnings: Warning: Kernel ABI header at 'tools/arch/s390/include/uapi/asm/kvm.h' differs from latest version at 'arch/s390/include/uapi/asm/kvm.h' diff -u tools/arch/s390/include/uapi/asm/kvm.h arch/s390/include/uapi/asm/kvm.h Cc: Janosch Frank Cc: Pierre Morel Link: http://lore.kernel.org/lkml/YvzwMXzaIzOU4WAY@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/arch/s390/include/uapi/asm/kvm.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/arch/s390/include/uapi/asm/kvm.h b/tools/arch/s390/include/uapi/asm/kvm.h index 7a6b14874d65c..a73cf01a16066 100644 --- a/tools/arch/s390/include/uapi/asm/kvm.h +++ b/tools/arch/s390/include/uapi/asm/kvm.h @@ -74,6 +74,7 @@ struct kvm_s390_io_adapter_req { #define KVM_S390_VM_CRYPTO 2 #define KVM_S390_VM_CPU_MODEL 3 #define KVM_S390_VM_MIGRATION 4 +#define KVM_S390_VM_CPU_TOPOLOGY 5 /* kvm attributes for mem_ctrl */ #define KVM_S390_VM_MEM_ENABLE_CMMA 0 From 898d24034605d2a0b16f6ca349d2e74124b5e043 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 14 Apr 2020 09:12:55 -0300 Subject: [PATCH 402/427] tools include UAPI: Sync linux/vhost.h with the kernel sources MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To get the changes in: f345a0143b4dd1cf ("vhost-vdpa: uAPI to suspend the device") Silencing this perf build warning: Warning: Kernel ABI header at 'tools/include/uapi/linux/vhost.h' differs from latest version at 'include/uapi/linux/vhost.h' diff -u tools/include/uapi/linux/vhost.h include/uapi/linux/vhost.h To pick up these changes and support them: $ tools/perf/trace/beauty/vhost_virtio_ioctl.sh > before $ cp include/uapi/linux/vhost.h tools/include/uapi/linux/vhost.h $ tools/perf/trace/beauty/vhost_virtio_ioctl.sh > after $ diff -u before after --- before 2022-08-18 09:46:12.355958316 -0300 +++ after 2022-08-18 09:46:19.701182822 -0300 @@ -29,6 +29,7 @@ [0x75] = "VDPA_SET_VRING_ENABLE", [0x77] = "VDPA_SET_CONFIG_CALL", [0x7C] = "VDPA_SET_GROUP_ASID", + [0x7D] = "VDPA_SUSPEND", }; = { [0x00] = "GET_FEATURES", $ For instance, see how those 'cmd' ioctl arguments get translated, now VDPA_SUSPEND will be as well: # perf trace -a -e ioctl --max-events=10 0.000 ( 0.011 ms): pipewire/2261 ioctl(fd: 60, cmd: SNDRV_PCM_HWSYNC, arg: 0x1) = 0 21.353 ( 0.014 ms): pipewire/2261 ioctl(fd: 60, cmd: SNDRV_PCM_HWSYNC, arg: 0x1) = 0 25.766 ( 0.014 ms): gnome-shell/2196 ioctl(fd: 14, cmd: DRM_I915_IRQ_WAIT, arg: 0x7ffe4a22c740) = 0 25.845 ( 0.034 ms): gnome-shel:cs0/2212 ioctl(fd: 14, cmd: DRM_I915_IRQ_EMIT, arg: 0x7fd43915dc70) = 0 25.916 ( 0.011 ms): gnome-shell/2196 ioctl(fd: 9, cmd: DRM_MODE_ADDFB2, arg: 0x7ffe4a22c8a0) = 0 25.941 ( 0.025 ms): gnome-shell/2196 ioctl(fd: 9, cmd: DRM_MODE_ATOMIC, arg: 0x7ffe4a22c840) = 0 32.915 ( 0.009 ms): gnome-shell/2196 ioctl(fd: 9, cmd: DRM_MODE_RMFB, arg: 0x7ffe4a22cf9c) = 0 42.522 ( 0.013 ms): gnome-shell/2196 ioctl(fd: 14, cmd: DRM_I915_IRQ_WAIT, arg: 0x7ffe4a22c740) = 0 42.579 ( 0.031 ms): gnome-shel:cs0/2212 ioctl(fd: 14, cmd: DRM_I915_IRQ_EMIT, arg: 0x7fd43915dc70) = 0 42.644 ( 0.010 ms): gnome-shell/2196 ioctl(fd: 9, cmd: DRM_MODE_ADDFB2, arg: 0x7ffe4a22c8a0) = 0 # Cc: Adrian Hunter Cc: Eugenio Pérez Cc: Ian Rogers Cc: Jiri Olsa Cc: Michael S. Tsirkin Cc: Namhyung Kim Link: https://lore.kernel.org/lkml/Yv6Kb4OESuNJuH6X@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/uapi/linux/vhost.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/include/uapi/linux/vhost.h b/tools/include/uapi/linux/vhost.h index cab645d4a6455..f9f115a7c75b8 100644 --- a/tools/include/uapi/linux/vhost.h +++ b/tools/include/uapi/linux/vhost.h @@ -171,4 +171,13 @@ #define VHOST_VDPA_SET_GROUP_ASID _IOW(VHOST_VIRTIO, 0x7C, \ struct vhost_vring_state) +/* Suspend a device so it does not process virtqueue requests anymore + * + * After the return of ioctl the device must preserve all the necessary state + * (the virtqueue vring base plus the possible device specific states) that is + * required for restoring in the future. The device must not change its + * configuration after that point. + */ +#define VHOST_VDPA_SUSPEND _IO(VHOST_VIRTIO, 0x7D) + #endif From eea085d11449bc6514dca9850cdd3a996ec1217e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 2 Mar 2021 17:20:08 -0300 Subject: [PATCH 403/427] tools headers UAPI: Sync KVM's vmx.h header with the kernel sources To pick the changes in: 2f4073e08f4cc5a4 ("KVM: VMX: Enable Notify VM exit") That makes 'perf kvm-stat' aware of this new NOTIFY exit reason, thus addressing the following perf build warning: Warning: Kernel ABI header at 'tools/arch/x86/include/uapi/asm/vmx.h' differs from latest version at 'arch/x86/include/uapi/asm/vmx.h' diff -u tools/arch/x86/include/uapi/asm/vmx.h arch/x86/include/uapi/asm/vmx.h Cc: Adrian Hunter Cc: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paolo Bonzini Cc: Tao Xu Link: http://lore.kernel.org/lkml/Yv6LavXMZ+njijpq@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/arch/x86/include/uapi/asm/vmx.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/arch/x86/include/uapi/asm/vmx.h b/tools/arch/x86/include/uapi/asm/vmx.h index 946d761adbd3d..a5faf6d88f1bf 100644 --- a/tools/arch/x86/include/uapi/asm/vmx.h +++ b/tools/arch/x86/include/uapi/asm/vmx.h @@ -91,6 +91,7 @@ #define EXIT_REASON_UMWAIT 67 #define EXIT_REASON_TPAUSE 68 #define EXIT_REASON_BUS_LOCK 74 +#define EXIT_REASON_NOTIFY 75 #define VMX_EXIT_REASONS \ { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \ @@ -153,7 +154,8 @@ { EXIT_REASON_XRSTORS, "XRSTORS" }, \ { EXIT_REASON_UMWAIT, "UMWAIT" }, \ { EXIT_REASON_TPAUSE, "TPAUSE" }, \ - { EXIT_REASON_BUS_LOCK, "BUS_LOCK" } + { EXIT_REASON_BUS_LOCK, "BUS_LOCK" }, \ + { EXIT_REASON_NOTIFY, "NOTIFY" } #define VMX_EXIT_REASON_FLAGS \ { VMX_EXIT_REASONS_FAILED_VMENTRY, "FAILED_VMENTRY" } From e5bc0deae57615324ca843827873b39a34acc82e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 10 Sep 2021 11:46:54 -0300 Subject: [PATCH 404/427] tools headers UAPI: Sync x86's asm/kvm.h with the kernel sources To pick the changes in: 43bb9e000ea4c621 ("KVM: x86: Tweak name of MONITOR/MWAIT #UD quirk to make it #UD specific") 94dfc73e7cf4a31d ("treewide: uapi: Replace zero-length arrays with flexible-array members") bfbcc81bb82cbbad ("KVM: x86: Add a quirk for KVM's "MONITOR/MWAIT are NOPs!" behavior") b172862241b48499 ("KVM: x86: PIT: Preserve state of speaker port data bit") ed2351174e38ad4f ("KVM: x86: Extend KVM_{G,S}ET_VCPU_EVENTS to support pending triple fault") That just rebuilds kvm-stat.c on x86, no change in functionality. This silences these perf build warning: Warning: Kernel ABI header at 'tools/arch/x86/include/uapi/asm/kvm.h' differs from latest version at 'arch/x86/include/uapi/asm/kvm.h' diff -u tools/arch/x86/include/uapi/asm/kvm.h arch/x86/include/uapi/asm/kvm.h Cc: Chenyi Qiang Cc: Sean Christopherson Cc: Gustavo A. R. Silva Cc: Paolo Bonzini Cc: Paul Durrant Link: https://lore.kernel.org/lkml/Yv6OMPKYqYSbUxwZ@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/arch/x86/include/uapi/asm/kvm.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include/uapi/asm/kvm.h index ec53c9fa1da96..46de10a809ecb 100644 --- a/tools/arch/x86/include/uapi/asm/kvm.h +++ b/tools/arch/x86/include/uapi/asm/kvm.h @@ -306,7 +306,8 @@ struct kvm_pit_state { struct kvm_pit_channel_state channels[3]; }; -#define KVM_PIT_FLAGS_HPET_LEGACY 0x00000001 +#define KVM_PIT_FLAGS_HPET_LEGACY 0x00000001 +#define KVM_PIT_FLAGS_SPEAKER_DATA_ON 0x00000002 struct kvm_pit_state2 { struct kvm_pit_channel_state channels[3]; @@ -325,6 +326,7 @@ struct kvm_reinject_control { #define KVM_VCPUEVENT_VALID_SHADOW 0x00000004 #define KVM_VCPUEVENT_VALID_SMM 0x00000008 #define KVM_VCPUEVENT_VALID_PAYLOAD 0x00000010 +#define KVM_VCPUEVENT_VALID_TRIPLE_FAULT 0x00000020 /* Interrupt shadow states */ #define KVM_X86_SHADOW_INT_MOV_SS 0x01 @@ -359,7 +361,10 @@ struct kvm_vcpu_events { __u8 smm_inside_nmi; __u8 latched_init; } smi; - __u8 reserved[27]; + struct { + __u8 pending; + } triple_fault; + __u8 reserved[26]; __u8 exception_has_payload; __u64 exception_payload; }; @@ -434,6 +439,7 @@ struct kvm_sync_regs { #define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3) #define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4) #define KVM_X86_QUIRK_FIX_HYPERCALL_INSN (1 << 5) +#define KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS (1 << 6) #define KVM_STATE_NESTED_FORMAT_VMX 0 #define KVM_STATE_NESTED_FORMAT_SVM 1 From 65ba872a6971c11ceb342c3330f059289c0e6bdb Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 18 Aug 2022 17:36:41 -0700 Subject: [PATCH 405/427] tools headers UAPI: Sync linux/perf_event.h with the kernel sources To pick the trivial change in: 119a784c81270eb8 ("perf/core: Add a new read format to get a number of lost samples") Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Ian Rogers Cc: Ingo Molnar Cc: Peter Zijlstra Link: https://lore.kernel.org/r/20220819003644.508916-2-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/include/uapi/linux/perf_event.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h index e2b77fbca91e9..581ed4bdc0621 100644 --- a/tools/include/uapi/linux/perf_event.h +++ b/tools/include/uapi/linux/perf_event.h @@ -301,6 +301,7 @@ enum { * { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED * { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING * { u64 id; } && PERF_FORMAT_ID + * { u64 lost; } && PERF_FORMAT_LOST * } && !PERF_FORMAT_GROUP * * { u64 nr; @@ -308,6 +309,7 @@ enum { * { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING * { u64 value; * { u64 id; } && PERF_FORMAT_ID + * { u64 lost; } && PERF_FORMAT_LOST * } cntr[nr]; * } && PERF_FORMAT_GROUP * }; @@ -317,8 +319,9 @@ enum perf_event_read_format { PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1, PERF_FORMAT_ID = 1U << 2, PERF_FORMAT_GROUP = 1U << 3, + PERF_FORMAT_LOST = 1U << 4, - PERF_FORMAT_MAX = 1U << 4, /* non-ABI */ + PERF_FORMAT_MAX = 1U << 5, /* non-ABI */ }; #define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */ From 89e3106fa25fb1b626a7123dba870159d453e785 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 18 Aug 2022 17:36:42 -0700 Subject: [PATCH 406/427] libperf: Handle read format in perf_evsel__read() The perf_counts_values should be increased to read the new lost data. Also adjust values after read according the read format. This supports PERF_FORMAT_GROUP which has a different data format but it's only available for leader events. Currently it doesn't have an API to read sibling (member) events in the group. But users may read the sibling event directly. Also reading from mmap would be disabled when the read format has ID or LOST bit as it's not exposed via mmap. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Ian Rogers Cc: Ingo Molnar Cc: Peter Zijlstra Link: https://lore.kernel.org/r/20220819003644.508916-3-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/perf/evsel.c | 79 ++++++++++++++++++++++++++++- tools/lib/perf/include/perf/event.h | 3 +- tools/lib/perf/include/perf/evsel.h | 4 +- 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/tools/lib/perf/evsel.c b/tools/lib/perf/evsel.c index 952f3520d5c26..8ce5bbd096666 100644 --- a/tools/lib/perf/evsel.c +++ b/tools/lib/perf/evsel.c @@ -305,6 +305,9 @@ int perf_evsel__read_size(struct perf_evsel *evsel) if (read_format & PERF_FORMAT_ID) entry += sizeof(u64); + if (read_format & PERF_FORMAT_LOST) + entry += sizeof(u64); + if (read_format & PERF_FORMAT_GROUP) { nr = evsel->nr_members; size += sizeof(u64); @@ -314,24 +317,98 @@ int perf_evsel__read_size(struct perf_evsel *evsel) return size; } +/* This only reads values for the leader */ +static int perf_evsel__read_group(struct perf_evsel *evsel, int cpu_map_idx, + int thread, struct perf_counts_values *count) +{ + size_t size = perf_evsel__read_size(evsel); + int *fd = FD(evsel, cpu_map_idx, thread); + u64 read_format = evsel->attr.read_format; + u64 *data; + int idx = 1; + + if (fd == NULL || *fd < 0) + return -EINVAL; + + data = calloc(1, size); + if (data == NULL) + return -ENOMEM; + + if (readn(*fd, data, size) <= 0) { + free(data); + return -errno; + } + + /* + * This reads only the leader event intentionally since we don't have + * perf counts values for sibling events. + */ + if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) + count->ena = data[idx++]; + if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) + count->run = data[idx++]; + + /* value is always available */ + count->val = data[idx++]; + if (read_format & PERF_FORMAT_ID) + count->id = data[idx++]; + if (read_format & PERF_FORMAT_LOST) + count->lost = data[idx++]; + + free(data); + return 0; +} + +/* + * The perf read format is very flexible. It needs to set the proper + * values according to the read format. + */ +static void perf_evsel__adjust_values(struct perf_evsel *evsel, u64 *buf, + struct perf_counts_values *count) +{ + u64 read_format = evsel->attr.read_format; + int n = 0; + + count->val = buf[n++]; + + if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) + count->ena = buf[n++]; + + if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) + count->run = buf[n++]; + + if (read_format & PERF_FORMAT_ID) + count->id = buf[n++]; + + if (read_format & PERF_FORMAT_LOST) + count->lost = buf[n++]; +} + int perf_evsel__read(struct perf_evsel *evsel, int cpu_map_idx, int thread, struct perf_counts_values *count) { size_t size = perf_evsel__read_size(evsel); int *fd = FD(evsel, cpu_map_idx, thread); + u64 read_format = evsel->attr.read_format; + struct perf_counts_values buf; memset(count, 0, sizeof(*count)); if (fd == NULL || *fd < 0) return -EINVAL; + if (read_format & PERF_FORMAT_GROUP) + return perf_evsel__read_group(evsel, cpu_map_idx, thread, count); + if (MMAP(evsel, cpu_map_idx, thread) && + !(read_format & (PERF_FORMAT_ID | PERF_FORMAT_LOST)) && !perf_mmap__read_self(MMAP(evsel, cpu_map_idx, thread), count)) return 0; - if (readn(*fd, count->values, size) <= 0) + if (readn(*fd, buf.values, size) <= 0) return -errno; + perf_evsel__adjust_values(evsel, buf.values, count); return 0; } diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/perf/event.h index 57f54781f5ede..93bf93a59c99b 100644 --- a/tools/lib/perf/include/perf/event.h +++ b/tools/lib/perf/include/perf/event.h @@ -77,7 +77,7 @@ struct perf_record_lost_samples { }; /* - * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID + * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID | PERF_FORMAT_LOST */ struct perf_record_read { struct perf_event_header header; @@ -86,6 +86,7 @@ struct perf_record_read { __u64 time_enabled; __u64 time_running; __u64 id; + __u64 lost; }; struct perf_record_throttle { diff --git a/tools/lib/perf/include/perf/evsel.h b/tools/lib/perf/include/perf/evsel.h index 699c0ed97d34e..6f92204075c24 100644 --- a/tools/lib/perf/include/perf/evsel.h +++ b/tools/lib/perf/include/perf/evsel.h @@ -18,8 +18,10 @@ struct perf_counts_values { uint64_t val; uint64_t ena; uint64_t run; + uint64_t id; + uint64_t lost; }; - uint64_t values[3]; + uint64_t values[5]; }; }; From 6d395a513556e61dc22c6abdf9b419deb46f1908 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 18 Aug 2022 17:36:43 -0700 Subject: [PATCH 407/427] libperf: Add a test case for read formats It checks a various combination of the read format settings and verify it return the value in a proper position. The test uses task-clock software events to guarantee it's always active and sets enabled/running time. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Ian Rogers Cc: Ingo Molnar Cc: Peter Zijlstra Link: https://lore.kernel.org/r/20220819003644.508916-4-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/perf/tests/test-evsel.c | 161 ++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) diff --git a/tools/lib/perf/tests/test-evsel.c b/tools/lib/perf/tests/test-evsel.c index 89be89afb24d9..a11fc51bfb688 100644 --- a/tools/lib/perf/tests/test-evsel.c +++ b/tools/lib/perf/tests/test-evsel.c @@ -1,10 +1,13 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include #include +#include #include #include #include +#include #include #include "tests.h" @@ -189,6 +192,163 @@ static int test_stat_user_read(int event) return 0; } +static int test_stat_read_format_single(struct perf_event_attr *attr, struct perf_thread_map *threads) +{ + struct perf_evsel *evsel; + struct perf_counts_values counts; + volatile int count = 0x100000; + int err; + + evsel = perf_evsel__new(attr); + __T("failed to create evsel", evsel); + + /* skip old kernels that don't support the format */ + err = perf_evsel__open(evsel, NULL, threads); + if (err < 0) + return 0; + + while (count--) ; + + memset(&counts, -1, sizeof(counts)); + perf_evsel__read(evsel, 0, 0, &counts); + + __T("failed to read value", counts.val); + if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) + __T("failed to read TOTAL_TIME_ENABLED", counts.ena); + if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) + __T("failed to read TOTAL_TIME_RUNNING", counts.run); + if (attr->read_format & PERF_FORMAT_ID) + __T("failed to read ID", counts.id); + if (attr->read_format & PERF_FORMAT_LOST) + __T("failed to read LOST", counts.lost == 0); + + perf_evsel__close(evsel); + perf_evsel__delete(evsel); + return 0; +} + +static int test_stat_read_format_group(struct perf_event_attr *attr, struct perf_thread_map *threads) +{ + struct perf_evsel *leader, *member; + struct perf_counts_values counts; + volatile int count = 0x100000; + int err; + + attr->read_format |= PERF_FORMAT_GROUP; + leader = perf_evsel__new(attr); + __T("failed to create leader", leader); + + attr->read_format &= ~PERF_FORMAT_GROUP; + member = perf_evsel__new(attr); + __T("failed to create member", member); + + member->leader = leader; + leader->nr_members = 2; + + /* skip old kernels that don't support the format */ + err = perf_evsel__open(leader, NULL, threads); + if (err < 0) + return 0; + err = perf_evsel__open(member, NULL, threads); + if (err < 0) + return 0; + + while (count--) ; + + memset(&counts, -1, sizeof(counts)); + perf_evsel__read(leader, 0, 0, &counts); + + __T("failed to read leader value", counts.val); + if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) + __T("failed to read leader TOTAL_TIME_ENABLED", counts.ena); + if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) + __T("failed to read leader TOTAL_TIME_RUNNING", counts.run); + if (attr->read_format & PERF_FORMAT_ID) + __T("failed to read leader ID", counts.id); + if (attr->read_format & PERF_FORMAT_LOST) + __T("failed to read leader LOST", counts.lost == 0); + + memset(&counts, -1, sizeof(counts)); + perf_evsel__read(member, 0, 0, &counts); + + __T("failed to read member value", counts.val); + if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) + __T("failed to read member TOTAL_TIME_ENABLED", counts.ena); + if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) + __T("failed to read member TOTAL_TIME_RUNNING", counts.run); + if (attr->read_format & PERF_FORMAT_ID) + __T("failed to read member ID", counts.id); + if (attr->read_format & PERF_FORMAT_LOST) + __T("failed to read member LOST", counts.lost == 0); + + perf_evsel__close(member); + perf_evsel__close(leader); + perf_evsel__delete(member); + perf_evsel__delete(leader); + return 0; +} + +static int test_stat_read_format(void) +{ + struct perf_thread_map *threads; + struct perf_event_attr attr = { + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_TASK_CLOCK, + }; + int err, i; + +#define FMT(_fmt) PERF_FORMAT_ ## _fmt +#define FMT_TIME (FMT(TOTAL_TIME_ENABLED) | FMT(TOTAL_TIME_RUNNING)) + + uint64_t test_formats [] = { + 0, + FMT_TIME, + FMT(ID), + FMT(LOST), + FMT_TIME | FMT(ID), + FMT_TIME | FMT(LOST), + FMT_TIME | FMT(ID) | FMT(LOST), + FMT(ID) | FMT(LOST), + }; + +#undef FMT +#undef FMT_TIME + + threads = perf_thread_map__new_dummy(); + __T("failed to create threads", threads); + + perf_thread_map__set_pid(threads, 0, 0); + + for (i = 0; i < (int)ARRAY_SIZE(test_formats); i++) { + attr.read_format = test_formats[i]; + __T_VERBOSE("testing single read with read_format: %lx\n", + (unsigned long)test_formats[i]); + + err = test_stat_read_format_single(&attr, threads); + __T("failed to read single format", err == 0); + } + + perf_thread_map__put(threads); + + threads = perf_thread_map__new_array(2, NULL); + __T("failed to create threads", threads); + + perf_thread_map__set_pid(threads, 0, 0); + perf_thread_map__set_pid(threads, 1, 0); + + for (i = 0; i < (int)ARRAY_SIZE(test_formats); i++) { + attr.read_format = test_formats[i]; + __T_VERBOSE("testing group read with read_format: %lx\n", + (unsigned long)test_formats[i]); + + err = test_stat_read_format_group(&attr, threads); + __T("failed to read group format", err == 0); + } + + perf_thread_map__put(threads); + return 0; +} + int test_evsel(int argc, char **argv) { __T_START; @@ -200,6 +360,7 @@ int test_evsel(int argc, char **argv) test_stat_thread_enable(); test_stat_user_read(PERF_COUNT_HW_INSTRUCTIONS); test_stat_user_read(PERF_COUNT_HW_CPU_CYCLES); + test_stat_read_format(); __T_END; return tests_failed == 0 ? 0 : -1; From f52679b78877f17e95a317e18a4c9c46cc3d845a Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 18 Aug 2022 17:36:44 -0700 Subject: [PATCH 408/427] perf tools: Support reading PERF_FORMAT_LOST The recent kernel added lost count can be read from either read(2) or ring buffer data with PERF_SAMPLE_READ. As it's a variable length data we need to access it according to the format info. But for perf tools use cases, PERF_FORMAT_ID is always set. So we can only check PERF_FORMAT_LOST bit to determine the data format. Add sample_read_value_size() and next_sample_read_value() helpers to make it a bit easier to access. Use them in all places where it reads the struct sample_read_value. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Cc: Ian Rogers Cc: Ingo Molnar Cc: Peter Zijlstra Link: https://lore.kernel.org/r/20220819003644.508916-5-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/sample-parsing.c | 14 +++++--- tools/perf/util/event.h | 21 ++++++++++- tools/perf/util/evsel.c | 29 +++++++++------ .../scripting-engines/trace-event-python.c | 19 +++++++--- tools/perf/util/session.c | 35 +++++++++++-------- tools/perf/util/synthetic-events.c | 32 +++++++++++++---- 6 files changed, 108 insertions(+), 42 deletions(-) diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c index 07f2411b0ad45..20930dd48ee03 100644 --- a/tools/perf/tests/sample-parsing.c +++ b/tools/perf/tests/sample-parsing.c @@ -86,10 +86,15 @@ static bool samples_same(const struct perf_sample *s1, COMP(read.time_running); /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */ if (read_format & PERF_FORMAT_GROUP) { - for (i = 0; i < s1->read.group.nr; i++) - MCOMP(read.group.values[i]); + for (i = 0; i < s1->read.group.nr; i++) { + /* FIXME: check values without LOST */ + if (read_format & PERF_FORMAT_LOST) + MCOMP(read.group.values[i]); + } } else { COMP(read.one.id); + if (read_format & PERF_FORMAT_LOST) + COMP(read.one.lost); } } @@ -263,7 +268,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) .data = (void *)aux_data, }, }; - struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},}; + struct sample_read_value values[] = {{1, 5, 0}, {9, 3, 0}, {2, 7, 0}, {6, 4, 1},}; struct perf_sample sample_out, sample_out_endian; size_t i, sz, bufsz; int err, ret = -1; @@ -286,6 +291,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) } else { sample.read.one.value = 0x08789faeb786aa87ULL; sample.read.one.id = 99; + sample.read.one.lost = 1; } sz = perf_event__sample_event_size(&sample, sample_type, read_format); @@ -370,7 +376,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) */ static int test__sample_parsing(struct test_suite *test __maybe_unused, int subtest __maybe_unused) { - const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15}; + const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 28, 29, 30, 31}; u64 sample_type; u64 sample_regs; size_t i; diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 4e0d8dd3b7a07..12eae69170225 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -65,7 +65,8 @@ struct stack_dump { struct sample_read_value { u64 value; - u64 id; + u64 id; /* only if PERF_FORMAT_ID */ + u64 lost; /* only if PERF_FORMAT_LOST */ }; struct sample_read { @@ -80,6 +81,24 @@ struct sample_read { }; }; +static inline size_t sample_read_value_size(u64 read_format) +{ + /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */ + if (read_format & PERF_FORMAT_LOST) + return sizeof(struct sample_read_value); + else + return offsetof(struct sample_read_value, lost); +} + +static inline struct sample_read_value * +next_sample_read_value(struct sample_read_value *v, u64 read_format) +{ + return (void *)v + sample_read_value_size(read_format); +} + +#define sample_read_group__for_each(v, nr, rf) \ + for (int __i = 0; __i < (int)nr; v = next_sample_read_value(v, rf), __i++) + struct ip_callchain { u64 nr; u64 ips[]; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 4852089e1d79f..18c3eb864d558 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1541,7 +1541,7 @@ static int evsel__read_one(struct evsel *evsel, int cpu_map_idx, int thread) } static void evsel__set_count(struct evsel *counter, int cpu_map_idx, int thread, - u64 val, u64 ena, u64 run) + u64 val, u64 ena, u64 run, u64 lost) { struct perf_counts_values *count; @@ -1550,6 +1550,7 @@ static void evsel__set_count(struct evsel *counter, int cpu_map_idx, int thread, count->val = val; count->ena = ena; count->run = run; + count->lost = lost; perf_counts__set_loaded(counter->counts, cpu_map_idx, thread, true); } @@ -1558,7 +1559,7 @@ static int evsel__process_group_data(struct evsel *leader, int cpu_map_idx, int { u64 read_format = leader->core.attr.read_format; struct sample_read_value *v; - u64 nr, ena = 0, run = 0, i; + u64 nr, ena = 0, run = 0, lost = 0; nr = *data++; @@ -1571,18 +1572,18 @@ static int evsel__process_group_data(struct evsel *leader, int cpu_map_idx, int if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) run = *data++; - v = (struct sample_read_value *) data; - - evsel__set_count(leader, cpu_map_idx, thread, v[0].value, ena, run); - - for (i = 1; i < nr; i++) { + v = (void *)data; + sample_read_group__for_each(v, nr, read_format) { struct evsel *counter; - counter = evlist__id2evsel(leader->evlist, v[i].id); + counter = evlist__id2evsel(leader->evlist, v->id); if (!counter) return -EINVAL; - evsel__set_count(counter, cpu_map_idx, thread, v[i].value, ena, run); + if (read_format & PERF_FORMAT_LOST) + lost = v->lost; + + evsel__set_count(counter, cpu_map_idx, thread, v->value, ena, run, lost); } return 0; @@ -2475,8 +2476,8 @@ int evsel__parse_sample(struct evsel *evsel, union perf_event *event, if (data->read.group.nr > max_group_nr) return -EFAULT; - sz = data->read.group.nr * - sizeof(struct sample_read_value); + + sz = data->read.group.nr * sample_read_value_size(read_format); OVERFLOW_CHECK(array, sz, max_size); data->read.group.values = (struct sample_read_value *)array; @@ -2485,6 +2486,12 @@ int evsel__parse_sample(struct evsel *evsel, union perf_event *event, OVERFLOW_CHECK_u64(array); data->read.one.id = *array; array++; + + if (read_format & PERF_FORMAT_LOST) { + OVERFLOW_CHECK_u64(array); + data->read.one.lost = *array; + array++; + } } } diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 9ef2406e0ede7..1f2040f36d4e9 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -642,15 +642,19 @@ static PyObject *python_process_brstacksym(struct perf_sample *sample, return pylist; } -static PyObject *get_sample_value_as_tuple(struct sample_read_value *value) +static PyObject *get_sample_value_as_tuple(struct sample_read_value *value, + u64 read_format) { PyObject *t; - t = PyTuple_New(2); + t = PyTuple_New(3); if (!t) Py_FatalError("couldn't create Python tuple"); PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id)); PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value)); + if (read_format & PERF_FORMAT_LOST) + PyTuple_SetItem(t, 2, PyLong_FromUnsignedLongLong(value->lost)); + return t; } @@ -681,12 +685,17 @@ static void set_sample_read_in_dict(PyObject *dict_sample, Py_FatalError("couldn't create Python list"); if (read_format & PERF_FORMAT_GROUP) { - for (i = 0; i < sample->read.group.nr; i++) { - PyObject *t = get_sample_value_as_tuple(&sample->read.group.values[i]); + struct sample_read_value *v = sample->read.group.values; + + i = 0; + sample_read_group__for_each(v, sample->read.group.nr, read_format) { + PyObject *t = get_sample_value_as_tuple(v, read_format); PyList_SET_ITEM(values, i, t); + i++; } } else { - PyObject *t = get_sample_value_as_tuple(&sample->read.one); + PyObject *t = get_sample_value_as_tuple(&sample->read.one, + read_format); PyList_SET_ITEM(values, 0, t); } pydict_set_item_string_decref(dict_sample, "values", values); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 61bb9675e044d..192c9274f7ade 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1283,21 +1283,25 @@ static void sample_read__printf(struct perf_sample *sample, u64 read_format) sample->read.time_running); if (read_format & PERF_FORMAT_GROUP) { - u64 i; + struct sample_read_value *value = sample->read.group.values; printf(".... group nr %" PRIu64 "\n", sample->read.group.nr); - for (i = 0; i < sample->read.group.nr; i++) { - struct sample_read_value *value; - - value = &sample->read.group.values[i]; + sample_read_group__for_each(value, sample->read.group.nr, read_format) { printf("..... id %016" PRIx64 - ", value %016" PRIx64 "\n", + ", value %016" PRIx64, value->id, value->value); + if (read_format & PERF_FORMAT_LOST) + printf(", lost %" PRIu64, value->lost); + printf("\n"); } - } else - printf("..... id %016" PRIx64 ", value %016" PRIx64 "\n", + } else { + printf("..... id %016" PRIx64 ", value %016" PRIx64, sample->read.one.id, sample->read.one.value); + if (read_format & PERF_FORMAT_LOST) + printf(", lost %" PRIu64, sample->read.one.lost); + printf("\n"); + } } static void dump_event(struct evlist *evlist, union perf_event *event, @@ -1411,6 +1415,9 @@ static void dump_read(struct evsel *evsel, union perf_event *event) if (read_format & PERF_FORMAT_ID) printf("... id : %" PRI_lu64 "\n", read_event->id); + + if (read_format & PERF_FORMAT_LOST) + printf("... lost : %" PRI_lu64 "\n", read_event->lost); } static struct machine *machines__find_for_cpumode(struct machines *machines, @@ -1479,14 +1486,14 @@ static int deliver_sample_group(struct evlist *evlist, struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct machine *machine) + struct machine *machine, + u64 read_format) { int ret = -EINVAL; - u64 i; + struct sample_read_value *v = sample->read.group.values; - for (i = 0; i < sample->read.group.nr; i++) { - ret = deliver_sample_value(evlist, tool, event, sample, - &sample->read.group.values[i], + sample_read_group__for_each(v, sample->read.group.nr, read_format) { + ret = deliver_sample_value(evlist, tool, event, sample, v, machine); if (ret) break; @@ -1510,7 +1517,7 @@ static int evlist__deliver_sample(struct evlist *evlist, struct perf_tool *tool, /* For PERF_SAMPLE_READ we have either single or group mode. */ if (read_format & PERF_FORMAT_GROUP) return deliver_sample_group(evlist, tool, event, sample, - machine); + machine, read_format); else return deliver_sample_value(evlist, tool, event, sample, &sample->read.one, machine); diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c index 59747c440bd5d..812424dbf2d5b 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -1429,11 +1429,12 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, result += sizeof(u64); /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */ if (read_format & PERF_FORMAT_GROUP) { - sz = sample->read.group.nr * - sizeof(struct sample_read_value); - result += sz; + sz = sample_read_value_size(read_format); + result += sz * sample->read.group.nr; } else { result += sizeof(u64); + if (read_format & PERF_FORMAT_LOST) + result += sizeof(u64); } } @@ -1518,6 +1519,20 @@ void __weak arch_perf_synthesize_sample_weight(const struct perf_sample *data, *array = data->weight; } +static __u64 *copy_read_group_values(__u64 *array, __u64 read_format, + const struct perf_sample *sample) +{ + size_t sz = sample_read_value_size(read_format); + struct sample_read_value *v = sample->read.group.values; + + sample_read_group__for_each(v, sample->read.group.nr, read_format) { + /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */ + memcpy(array, v, sz); + array = (void *)array + sz; + } + return array; +} + int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_format, const struct perf_sample *sample) { @@ -1599,13 +1614,16 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_fo /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */ if (read_format & PERF_FORMAT_GROUP) { - sz = sample->read.group.nr * - sizeof(struct sample_read_value); - memcpy(array, sample->read.group.values, sz); - array = (void *)array + sz; + array = copy_read_group_values(array, read_format, + sample); } else { *array = sample->read.one.id; array++; + + if (read_format & PERF_FORMAT_LOST) { + *array = sample->read.one.lost; + array++; + } } } From a357f7b4583ebf81d19c95aef57497ae81c5f63c Mon Sep 17 00:00:00 2001 From: John Garry Date: Wed, 17 Aug 2022 23:20:08 +0800 Subject: [PATCH 409/427] ata: libata: Set __ATA_BASE_SHT max_sectors Commit 0568e6122574 ("ata: libata-scsi: cap ata_device->max_sectors according to shost->max_sectors") inadvertently capped the max_sectors value for some SATA disks to a value which is lower than we would want. For a device which supports LBA48, we would previously have request queue max_sectors_kb and max_hw_sectors_kb values of 1280 and 32767 respectively. For AHCI controllers, the value chosen for shost max sectors comes from the minimum of the SCSI host default max sectors in SCSI_DEFAULT_MAX_SECTORS (1024) and the shost DMA device mapping limit. This means that we would now set the max_sectors_kb and max_hw_sectors_kb values for a disk which supports LBA48 at 512, ignoring DMA mapping limit. As report by Oliver at [0], this caused a performance regression. Fix by picking a large enough max sectors value for ATA host controllers such that we don't needlessly reduce max_sectors_kb for LBA48 disks. [0] https://lore.kernel.org/linux-ide/YvsGbidf3na5FpGb@xsang-OptiPlex-9020/T/#m22d9fc5ad15af66066dd9fecf3d50f1b1ef11da3 Fixes: 0568e6122574 ("ata: libata-scsi: cap ata_device->max_sectors according to shost->max_sectors") Reported-by: Oliver Sang Signed-off-by: John Garry Signed-off-by: Damien Le Moal --- include/linux/libata.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/libata.h b/include/linux/libata.h index 0269ff114f5a7..698032e5ef2d3 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1382,7 +1382,8 @@ extern const struct attribute_group *ata_common_sdev_groups[]; .proc_name = drv_name, \ .slave_destroy = ata_scsi_slave_destroy, \ .bios_param = ata_std_bios_param, \ - .unlock_native_capacity = ata_scsi_unlock_native_capacity + .unlock_native_capacity = ata_scsi_unlock_native_capacity,\ + .max_sectors = ATA_MAX_SECTORS_LBA48 #define ATA_SUBBASE_SHT(drv_name) \ __ATA_BASE_SHT(drv_name), \ From 5b8a9a8fd1f0c3d55d407cf759d54ca68798d9ad Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 9 Aug 2022 23:11:17 +0900 Subject: [PATCH 410/427] modpost: fix module versioning when a symbol lacks valid CRC Since commit 7b4537199a4a ("kbuild: link symbol CRCs at final link, removing CONFIG_MODULE_REL_CRCS"), module versioning is broken on some architectures. Loading a module fails with "disagrees about version of symbol module_layout". On such architectures (e.g. ARCH=sparc build with sparc64_defconfig), modpost shows a warning, like follows: WARNING: modpost: EXPORT symbol "_mcount" [vmlinux] version generation failed, symbol will not be versioned. Is "_mcount" prototyped in ? Previously, it was a harmless warning (CRC check was just skipped), but now wrong CRCs are used for comparison because invalid CRCs are just skipped. $ sparc64-linux-gnu-nm -n vmlinux [snip] 0000000000c2cea0 r __ksymtab__kstrtol 0000000000c2ceb8 r __ksymtab__kstrtoul 0000000000c2ced0 r __ksymtab__local_bh_enable 0000000000c2cee8 r __ksymtab__mcount 0000000000c2cf00 r __ksymtab__printk 0000000000c2cf18 r __ksymtab__raw_read_lock 0000000000c2cf30 r __ksymtab__raw_read_lock_bh [snip] 0000000000c53b34 D __crc__kstrtol 0000000000c53b38 D __crc__kstrtoul 0000000000c53b3c D __crc__local_bh_enable 0000000000c53b40 D __crc__printk 0000000000c53b44 D __crc__raw_read_lock 0000000000c53b48 D __crc__raw_read_lock_bh Please notice __crc__mcount is missing here. When the module subsystem looks up a CRC that comes after, it results in reading out a wrong address. For example, when __crc__printk is needed, the module subsystem reads 0xc53b44 instead of 0xc53b40. All CRC entries must be output for correct index accessing. Invalid CRCs will be unused, but are needed to keep the one-to-one mapping between __ksymtab_* and __crc_*. The best is to fix all modpost warnings, but several warnings are still remaining on less popular architectures. Fixes: 7b4537199a4a ("kbuild: link symbol CRCs at final link, removing CONFIG_MODULE_REL_CRCS") Reported-by: matoro Signed-off-by: Masahiro Yamada Tested-by: matoro --- scripts/mod/modpost.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 55e32af2e53f0..2c80da0220c32 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2021,13 +2021,11 @@ static void add_exported_symbols(struct buffer *buf, struct module *mod) /* record CRCs for exported symbols */ buf_printf(buf, "\n"); list_for_each_entry(sym, &mod->exported_symbols, list) { - if (!sym->crc_valid) { + if (!sym->crc_valid) warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n" "Is \"%s\" prototyped in ?\n", sym->name, mod->name, mod->is_vmlinux ? "" : ".ko", sym->name); - continue; - } buf_printf(buf, "SYMBOL_CRC(%s, 0x%08x, \"%s\");\n", sym->name, sym->crc, sym->is_gpl_only ? "_gpl" : ""); From 0df499eaf3c1a43ebb0a84ac854262e3fa731bcf Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 10 Aug 2022 11:26:03 +0200 Subject: [PATCH 411/427] kbuild: dummy-tools: pretend we understand __LONG_DOUBLE_128__ There is a test in powerpc's Kconfig which checks __LONG_DOUBLE_128__ and sets CONFIG_PPC_LONG_DOUBLE_128 if it is understood by the compiler. We currently don't handle it, so this results in PPC_LONG_DOUBLE_128 not being in super-config generated by dummy-tools. So take this into account in the gcc script and preprocess __LONG_DOUBLE_128__ as "1". Signed-off-by: Jiri Slaby Signed-off-by: Masahiro Yamada --- scripts/dummy-tools/gcc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/dummy-tools/gcc b/scripts/dummy-tools/gcc index 7db8258434355..1db1889f6d81e 100755 --- a/scripts/dummy-tools/gcc +++ b/scripts/dummy-tools/gcc @@ -59,7 +59,7 @@ fi if arg_contain -E "$@"; then # For scripts/cc-version.sh; This emulates GCC 20.0.0 if arg_contain - "$@"; then - sed -n '/^GCC/{s/__GNUC__/20/; s/__GNUC_MINOR__/0/; s/__GNUC_PATCHLEVEL__/0/; p;}' + sed -n '/^GCC/{s/__GNUC__/20/; s/__GNUC_MINOR__/0/; s/__GNUC_PATCHLEVEL__/0/; p;}; s/__LONG_DOUBLE_128__/1/ p' exit 0 else echo "no input files" >&2 From 370655bc183b1824ba623e621b58e8c2616c839c Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Wed, 10 Aug 2022 16:01:33 -0700 Subject: [PATCH 412/427] scripts/Makefile.extrawarn: Do not disable clang's -Wformat-zero-length There are no instances of this warning in the tree across several difference architectures and configurations. This was added by commit 26ea6bb1fef0 ("kbuild, LLVMLinux: Supress warnings unless W=1-3") back in 2014, where it might have been necessary, but there are no instances of it now so stop disabling it to increase warning coverage for clang. Signed-off-by: Nathan Chancellor Signed-off-by: Masahiro Yamada --- scripts/Makefile.extrawarn | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index f5f0d6f09053f..0621c39a39556 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn @@ -49,7 +49,6 @@ ifdef CONFIG_CC_IS_CLANG KBUILD_CFLAGS += -Wno-initializer-overrides KBUILD_CFLAGS += -Wno-format KBUILD_CFLAGS += -Wno-sign-compare -KBUILD_CFLAGS += -Wno-format-zero-length KBUILD_CFLAGS += $(call cc-disable-warning, pointer-to-enum-cast) KBUILD_CFLAGS += -Wno-tautological-constant-out-of-range-compare KBUILD_CFLAGS += $(call cc-disable-warning, unaligned-access) From 113147510b48e764e624e3d0e6707a1e48bc05a9 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 14 Aug 2022 08:09:28 +0900 Subject: [PATCH 413/427] kbuild: fix the modules order between drivers and libs Commit b2c885549122 ("kbuild: update modules.order only when contained modules are updated") accidentally changed the modules order. Prior to that commit, the modules order was determined based on vmlinux-dirs, which lists core-y/m, drivers-y/m, libs-y/m, in this order. Now, subdir-modorder lists them in a different order: core-y/m, libs-y/m, drivers-y/m. Presumably, there was no practical issue because the modules in drivers and libs are orthogonal, but there is no reason to have this distortion. Get back to the original order. Fixes: b2c885549122 ("kbuild: update modules.order only when contained modules are updated") Signed-off-by: Masahiro Yamada --- Makefile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index f09673b6c11d7..697ab397fe31f 100644 --- a/Makefile +++ b/Makefile @@ -1113,13 +1113,11 @@ vmlinux-alldirs := $(sort $(vmlinux-dirs) Documentation \ $(patsubst %/,%,$(filter %/, $(core-) \ $(drivers-) $(libs-)))) -subdir-modorder := $(addsuffix modules.order,$(filter %/, \ - $(core-y) $(core-m) $(libs-y) $(libs-m) \ - $(drivers-y) $(drivers-m))) - build-dirs := $(vmlinux-dirs) clean-dirs := $(vmlinux-alldirs) +subdir-modorder := $(addsuffix /modules.order, $(build-dirs)) + # Externally visible symbols (used by link-vmlinux.sh) KBUILD_VMLINUX_OBJS := $(head-y) $(patsubst %/,%/built-in.a, $(core-y)) KBUILD_VMLINUX_OBJS += $(addsuffix built-in.a, $(filter %/, $(libs-y))) From 4be72c1b9f298b4ad42391322eaddef64b282716 Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Thu, 4 Aug 2022 10:46:14 -0700 Subject: [PATCH 414/427] scripts/clang-tools: Remove DeprecatedOrUnsafeBufferHandling check This `clang-analyzer` check flags the use of memset(), suggesting a more secure version of the API, such as memset_s(), which does not exist in the kernel: warning: Call to function 'memset' is insecure as it does not provide security checks introduced in the C11 standard. Replace with analogous functions that support length arguments or provides boundary checks such as 'memset_s' in case of C11 [clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling] Signed-off-by: Guru Das Srinagesh Reviewed-by: Nick Desaulniers Signed-off-by: Masahiro Yamada --- scripts/clang-tools/run-clang-tools.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/clang-tools/run-clang-tools.py b/scripts/clang-tools/run-clang-tools.py index f754415af398b..1337cedca096d 100755 --- a/scripts/clang-tools/run-clang-tools.py +++ b/scripts/clang-tools/run-clang-tools.py @@ -51,6 +51,7 @@ def run_analysis(entry): checks += "linuxkernel-*" else: checks += "clang-analyzer-*" + checks += ",-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling" p = subprocess.run(["clang-tidy", "-p", args.path, checks, entry["file"]], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, From 3df71d7064cbb19a3ac0e5dc25ece2bbf3a4d9af Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 18 Aug 2022 22:31:13 +0200 Subject: [PATCH 415/427] Revert "i2c: scmi: Replace open coded device_get_match_data()" This reverts commit 9ae551ded5ba55f96a83cd0811f7ef8c2f329d0c. We got a regression report, so ensure this machine boots again. We will come back with a better version hopefully. Reported-by: Josef Johansson Link: https://lore.kernel.org/r/4d2d5b04-0b6c-1cb1-a63f-dc06dfe1b5da@oderland.se Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-scmi.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-scmi.c b/drivers/i2c/busses/i2c-scmi.c index 79798fc7462ad..6746aa46d96c8 100644 --- a/drivers/i2c/busses/i2c-scmi.c +++ b/drivers/i2c/busses/i2c-scmi.c @@ -30,7 +30,7 @@ struct acpi_smbus_cmi { u8 cap_info:1; u8 cap_read:1; u8 cap_write:1; - const struct smbus_methods_t *methods; + struct smbus_methods_t *methods; }; static const struct smbus_methods_t smbus_methods = { @@ -361,6 +361,7 @@ static acpi_status acpi_smbus_cmi_query_methods(acpi_handle handle, u32 level, static int acpi_smbus_cmi_add(struct acpi_device *device) { struct acpi_smbus_cmi *smbus_cmi; + const struct acpi_device_id *id; int ret; smbus_cmi = kzalloc(sizeof(struct acpi_smbus_cmi), GFP_KERNEL); @@ -368,7 +369,6 @@ static int acpi_smbus_cmi_add(struct acpi_device *device) return -ENOMEM; smbus_cmi->handle = device->handle; - smbus_cmi->methods = device_get_match_data(&device->dev); strcpy(acpi_device_name(device), ACPI_SMBUS_HC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_SMBUS_HC_CLASS); device->driver_data = smbus_cmi; @@ -376,6 +376,11 @@ static int acpi_smbus_cmi_add(struct acpi_device *device) smbus_cmi->cap_read = 0; smbus_cmi->cap_write = 0; + for (id = acpi_smbus_cmi_ids; id->id[0]; id++) + if (!strcmp(id->id, acpi_device_hid(device))) + smbus_cmi->methods = + (struct smbus_methods_t *) id->driver_data; + acpi_walk_namespace(ACPI_TYPE_METHOD, smbus_cmi->handle, 1, acpi_smbus_cmi_query_methods, NULL, smbus_cmi, NULL); From d98bdd3a5b50446d8e010be5b04ce81c4eabf728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 20 Jul 2022 17:09:33 +0200 Subject: [PATCH 416/427] i2c: imx: Make sure to unregister adapter on remove() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If for whatever reasons pm_runtime_resume_and_get() fails and .remove() is exited early, the i2c adapter stays around and the irq still calls its handler, while the driver data and the register mapping go away. So if later the i2c adapter is accessed or the irq triggers this results in havoc accessing freed memory and unmapped registers. So unregister the software resources even if resume failed, and only skip the hardware access in that case. Fixes: 588eb93ea49f ("i2c: imx: add runtime pm support to improve the performance") Signed-off-by: Uwe Kleine-König Acked-by: Oleksij Rempel Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-imx.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 78fb1a4274a6c..e47fa34656717 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -1572,9 +1572,7 @@ static int i2c_imx_remove(struct platform_device *pdev) struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev); int irq, ret; - ret = pm_runtime_resume_and_get(&pdev->dev); - if (ret < 0) - return ret; + ret = pm_runtime_get_sync(&pdev->dev); hrtimer_cancel(&i2c_imx->slave_timer); @@ -1585,17 +1583,21 @@ static int i2c_imx_remove(struct platform_device *pdev) if (i2c_imx->dma) i2c_imx_dma_free(i2c_imx); - /* setup chip registers to defaults */ - imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR); - imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IFDR); - imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR); - imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR); + if (ret == 0) { + /* setup chip registers to defaults */ + imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR); + imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IFDR); + imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR); + imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR); + clk_disable(i2c_imx->clk); + } clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb); irq = platform_get_irq(pdev, 0); if (irq >= 0) free_irq(irq, i2c_imx); - clk_disable_unprepare(i2c_imx->clk); + + clk_unprepare(i2c_imx->clk); pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); From a0a12c3ed057af57552bf6c0aeaca6835693df04 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Fri, 19 Aug 2022 12:06:40 -0700 Subject: [PATCH 417/427] asm goto: eradicate CC_HAS_ASM_GOTO GCC has supported asm goto since 4.5, and Clang has since version 9.0.0. The minimum supported versions of these tools for the build according to Documentation/process/changes.rst are 5.1 and 11.0.0 respectively. Remove the feature detection script, Kconfig option, and clean up some fallback code that is no longer supported. The removed script was also testing for a GCC specific bug that was fixed in the 4.7 release. Also remove workarounds for bpftrace using clang older than 9.0.0, since other BPF backend fixes are required at this point. Link: https://lore.kernel.org/lkml/CAK7LNATSr=BXKfkdW8f-H5VT_w=xBpT2ZQcZ7rm6JfkdE+QnmA@mail.gmail.com/ Link: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48637 Acked-by: Borislav Petkov Suggested-by: Masahiro Yamada Suggested-by: Alexei Starovoitov Signed-off-by: Nick Desaulniers Reviewed-by: Ingo Molnar Reviewed-by: Nathan Chancellor Reviewed-by: Alexandre Belloni Signed-off-by: Linus Torvalds --- Documentation/kbuild/kconfig-language.rst | 4 ++-- arch/Kconfig | 3 +-- arch/um/include/asm/cpufeature.h | 15 --------------- arch/x86/Makefile | 4 ---- arch/x86/include/asm/cpufeature.h | 15 --------------- arch/x86/include/asm/rmwcc.h | 6 +++--- arch/x86/kvm/emulate.c | 2 +- init/Kconfig | 4 ---- scripts/gcc-goto.sh | 22 ---------------------- tools/arch/x86/include/asm/rmwcc.h | 21 --------------------- 10 files changed, 7 insertions(+), 89 deletions(-) delete mode 100755 scripts/gcc-goto.sh diff --git a/Documentation/kbuild/kconfig-language.rst b/Documentation/kbuild/kconfig-language.rst index 7fb398649f510..858ed5d80defe 100644 --- a/Documentation/kbuild/kconfig-language.rst +++ b/Documentation/kbuild/kconfig-language.rst @@ -525,8 +525,8 @@ followed by a test macro:: If you need to expose a compiler capability to makefiles and/or C source files, `CC_HAS_` is the recommended prefix for the config option:: - config CC_HAS_ASM_GOTO - def_bool $(success,$(srctree)/scripts/gcc-goto.sh $(CC)) + config CC_HAS_FOO + def_bool $(success,$(srctree)/scripts/cc-check-foo.sh $(CC)) Build as module only ~~~~~~~~~~~~~~~~~~~~ diff --git a/arch/Kconfig b/arch/Kconfig index f330410da63a6..5dbf11a5ba4e8 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -53,7 +53,6 @@ config KPROBES config JUMP_LABEL bool "Optimize very unlikely/likely branches" depends on HAVE_ARCH_JUMP_LABEL - depends on CC_HAS_ASM_GOTO select OBJTOOL if HAVE_JUMP_LABEL_HACK help This option enables a transparent branch optimization that @@ -1361,7 +1360,7 @@ config HAVE_PREEMPT_DYNAMIC_CALL config HAVE_PREEMPT_DYNAMIC_KEY bool - depends on HAVE_ARCH_JUMP_LABEL && CC_HAS_ASM_GOTO + depends on HAVE_ARCH_JUMP_LABEL select HAVE_PREEMPT_DYNAMIC help An architecture should select this if it can handle the preemption diff --git a/arch/um/include/asm/cpufeature.h b/arch/um/include/asm/cpufeature.h index 19cd7ed6ec3cd..4b6d1b526bc12 100644 --- a/arch/um/include/asm/cpufeature.h +++ b/arch/um/include/asm/cpufeature.h @@ -65,20 +65,6 @@ extern void setup_clear_cpu_cap(unsigned int bit); #define setup_force_cpu_bug(bit) setup_force_cpu_cap(bit) -#if defined(__clang__) && !defined(CONFIG_CC_HAS_ASM_GOTO) - -/* - * Workaround for the sake of BPF compilation which utilizes kernel - * headers, but clang does not support ASM GOTO and fails the build. - */ -#ifndef __BPF_TRACING__ -#warning "Compiler lacks ASM_GOTO support. Add -D __BPF_TRACING__ to your compiler arguments" -#endif - -#define static_cpu_has(bit) boot_cpu_has(bit) - -#else - /* * Static testing of CPU features. Used the same as boot_cpu_has(). It * statically patches the target code for additional performance. Use @@ -137,7 +123,6 @@ static __always_inline bool _static_cpu_has(u16 bit) boot_cpu_has(bit) : \ _static_cpu_has(bit) \ ) -#endif #define cpu_has_bug(c, bit) cpu_has(c, (bit)) #define set_cpu_bug(c, bit) set_cpu_cap(c, (bit)) diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 7854685c5f25b..bafbd905e6e7c 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -286,10 +286,6 @@ vdso_install: archprepare: checkbin checkbin: -ifndef CONFIG_CC_HAS_ASM_GOTO - @echo Compiler lacks asm-goto support. - @exit 1 -endif ifdef CONFIG_RETPOLINE ifeq ($(RETPOLINE_CFLAGS),) @echo "You are building kernel with non-retpoline compiler." >&2 diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index ea34cc31b0474..1a85e1fb09226 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -155,20 +155,6 @@ extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit); #define setup_force_cpu_bug(bit) setup_force_cpu_cap(bit) -#if defined(__clang__) && !defined(CONFIG_CC_HAS_ASM_GOTO) - -/* - * Workaround for the sake of BPF compilation which utilizes kernel - * headers, but clang does not support ASM GOTO and fails the build. - */ -#ifndef __BPF_TRACING__ -#warning "Compiler lacks ASM_GOTO support. Add -D __BPF_TRACING__ to your compiler arguments" -#endif - -#define static_cpu_has(bit) boot_cpu_has(bit) - -#else - /* * Static testing of CPU features. Used the same as boot_cpu_has(). It * statically patches the target code for additional performance. Use @@ -208,7 +194,6 @@ static __always_inline bool _static_cpu_has(u16 bit) boot_cpu_has(bit) : \ _static_cpu_has(bit) \ ) -#endif #define cpu_has_bug(c, bit) cpu_has(c, (bit)) #define set_cpu_bug(c, bit) set_cpu_cap(c, (bit)) diff --git a/arch/x86/include/asm/rmwcc.h b/arch/x86/include/asm/rmwcc.h index 8a9eba1915169..7fa6112164172 100644 --- a/arch/x86/include/asm/rmwcc.h +++ b/arch/x86/include/asm/rmwcc.h @@ -11,7 +11,7 @@ #define __CLOBBERS_MEM(clb...) "memory", ## clb -#if !defined(__GCC_ASM_FLAG_OUTPUTS__) && defined(CONFIG_CC_HAS_ASM_GOTO) +#ifndef __GCC_ASM_FLAG_OUTPUTS__ /* Use asm goto */ @@ -27,7 +27,7 @@ cc_label: c = true; \ c; \ }) -#else /* defined(__GCC_ASM_FLAG_OUTPUTS__) || !defined(CONFIG_CC_HAS_ASM_GOTO) */ +#else /* defined(__GCC_ASM_FLAG_OUTPUTS__) */ /* Use flags output or a set instruction */ @@ -40,7 +40,7 @@ cc_label: c = true; \ c; \ }) -#endif /* defined(__GCC_ASM_FLAG_OUTPUTS__) || !defined(CONFIG_CC_HAS_ASM_GOTO) */ +#endif /* defined(__GCC_ASM_FLAG_OUTPUTS__) */ #define GEN_UNARY_RMWcc_4(op, var, cc, arg0) \ __GEN_RMWcc(op " " arg0, var, cc, __CLOBBERS_MEM()) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index f092c54d1a2f2..d5ec3a2ed5a44 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -479,7 +479,7 @@ FOP_END; /* * XXX: inoutclob user must know where the argument is being expanded. - * Relying on CONFIG_CC_HAS_ASM_GOTO would allow us to remove _fault. + * Using asm goto would allow us to remove _fault. */ #define asm_safe(insn, inoutclob...) \ ({ \ diff --git a/init/Kconfig b/init/Kconfig index 80fe60fa77fba..532362fcfe31f 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -70,11 +70,7 @@ config CC_CAN_LINK_STATIC default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(m64-flag) -static) if 64BIT default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(m32-flag) -static) -config CC_HAS_ASM_GOTO - def_bool $(success,$(srctree)/scripts/gcc-goto.sh $(CC)) - config CC_HAS_ASM_GOTO_OUTPUT - depends on CC_HAS_ASM_GOTO def_bool $(success,echo 'int foo(int x) { asm goto ("": "=r"(x) ::: bar); return x; bar: return 0; }' | $(CC) -x c - -c -o /dev/null) config CC_HAS_ASM_GOTO_TIED_OUTPUT diff --git a/scripts/gcc-goto.sh b/scripts/gcc-goto.sh deleted file mode 100755 index 8b980fb2270a3..0000000000000 --- a/scripts/gcc-goto.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 -# Test for gcc 'asm goto' support -# Copyright (C) 2010, Jason Baron - -cat << "END" | $@ -x c - -fno-PIE -c -o /dev/null -int main(void) -{ -#if defined(__arm__) || defined(__aarch64__) - /* - * Not related to asm goto, but used by jump label - * and broken on some ARM GCC versions (see GCC Bug 48637). - */ - static struct { int dummy; int state; } tp; - asm (".long %c0" :: "i" (&tp.state)); -#endif - -entry: - asm goto ("" :::: entry); - return 0; -} -END diff --git a/tools/arch/x86/include/asm/rmwcc.h b/tools/arch/x86/include/asm/rmwcc.h index fee7983a90b4f..11ff975242cac 100644 --- a/tools/arch/x86/include/asm/rmwcc.h +++ b/tools/arch/x86/include/asm/rmwcc.h @@ -2,8 +2,6 @@ #ifndef _TOOLS_LINUX_ASM_X86_RMWcc #define _TOOLS_LINUX_ASM_X86_RMWcc -#ifdef CONFIG_CC_HAS_ASM_GOTO - #define __GEN_RMWcc(fullop, var, cc, ...) \ do { \ asm_volatile_goto (fullop "; j" cc " %l[cc_label]" \ @@ -20,23 +18,4 @@ cc_label: \ #define GEN_BINARY_RMWcc(op, var, vcon, val, arg0, cc) \ __GEN_RMWcc(op " %1, " arg0, var, cc, vcon (val)) -#else /* !CONFIG_CC_HAS_ASM_GOTO */ - -#define __GEN_RMWcc(fullop, var, cc, ...) \ -do { \ - char c; \ - asm volatile (fullop "; set" cc " %1" \ - : "+m" (var), "=qm" (c) \ - : __VA_ARGS__ : "memory"); \ - return c != 0; \ -} while (0) - -#define GEN_UNARY_RMWcc(op, var, arg0, cc) \ - __GEN_RMWcc(op " " arg0, var, cc) - -#define GEN_BINARY_RMWcc(op, var, vcon, val, arg0, cc) \ - __GEN_RMWcc(op " %2, " arg0, var, cc, vcon (val)) - -#endif /* CONFIG_CC_HAS_ASM_GOTO */ - #endif /* _TOOLS_LINUX_ASM_X86_RMWcc */ From d8a64313c171464aedd6289378a51c8f0f524acb Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Thu, 11 Aug 2022 09:17:34 +0200 Subject: [PATCH 418/427] tracing: React to error return from traceprobe_parse_event_name() The function traceprobe_parse_event_name() may set the first two function arguments to a non-null value and still return -EINVAL to indicate an unsuccessful completion of the function. Hence, it is not sufficient to just check the result of the two function arguments for being not null, but the return value also needs to be checked. Commit 95c104c378dc ("tracing: Auto generate event name when creating a group of events") changed the error-return-value checking of the second traceprobe_parse_event_name() invocation in __trace_eprobe_create() and removed checking the return value to jump to the error handling case. Reinstate using the return value in the error-return-value checking. Link: https://lkml.kernel.org/r/20220811071734.20700-1-lukas.bulwahn@gmail.com Fixes: 95c104c378dc ("tracing: Auto generate event name when creating a group of events") Acked-by: Linyu Yuan Signed-off-by: Lukas Bulwahn Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_eprobe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c index 4a0e9d927443c..550671985fd15 100644 --- a/kernel/trace/trace_eprobe.c +++ b/kernel/trace/trace_eprobe.c @@ -883,7 +883,7 @@ static int __trace_eprobe_create(int argc, const char *argv[]) trace_probe_log_set_index(1); sys_event = argv[1]; ret = traceprobe_parse_event_name(&sys_event, &sys_name, buf2, 0); - if (!sys_event || !sys_name) { + if (ret || !sys_event || !sys_name) { trace_probe_log_err(0, NO_EVENT_INFO); goto parse_error; } From 7249921d94ff64f67b733eca0b68853a62032b3d Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Tue, 16 Aug 2022 19:28:17 -0400 Subject: [PATCH 419/427] tracing/perf: Fix double put of trace event when init fails If in perf_trace_event_init(), the perf_trace_event_open() fails, then it will call perf_trace_event_unreg() which will not only unregister the perf trace event, but will also call the put() function of the tp_event. The problem here is that the trace_event_try_get_ref() is called by the caller of perf_trace_event_init() and if perf_trace_event_init() returns a failure, it will then call trace_event_put(). But since the perf_trace_event_unreg() already called the trace_event_put() function, it triggers a WARN_ON(). WARNING: CPU: 1 PID: 30309 at kernel/trace/trace_dynevent.c:46 trace_event_dyn_put_ref+0x15/0x20 If perf_trace_event_reg() does not call the trace_event_try_get_ref() then the perf_trace_event_unreg() should not be calling trace_event_put(). This breaks symmetry and causes bugs like these. Pull out the trace_event_put() from perf_trace_event_unreg() and call it in the locations that perf_trace_event_unreg() is called. This not only fixes this bug, but also brings back the proper symmetry of the reg/unreg vs get/put logic. Link: https://lore.kernel.org/all/cover.1660347763.git.kjlx@templeofstupid.com/ Link: https://lkml.kernel.org/r/20220816192817.43d5e17f@gandalf.local.home Cc: stable@vger.kernel.org Fixes: 1d18538e6a092 ("tracing: Have dynamic events have a ref counter") Reported-by: Krister Johansen Reviewed-by: Krister Johansen Tested-by: Krister Johansen Acked-by: Jiri Olsa Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_event_perf.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index a114549720d63..61e3a2620fa3c 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -157,7 +157,7 @@ static void perf_trace_event_unreg(struct perf_event *p_event) int i; if (--tp_event->perf_refcount > 0) - goto out; + return; tp_event->class->reg(tp_event, TRACE_REG_PERF_UNREGISTER, NULL); @@ -176,8 +176,6 @@ static void perf_trace_event_unreg(struct perf_event *p_event) perf_trace_buf[i] = NULL; } } -out: - trace_event_put_ref(tp_event); } static int perf_trace_event_open(struct perf_event *p_event) @@ -241,6 +239,7 @@ void perf_trace_destroy(struct perf_event *p_event) mutex_lock(&event_mutex); perf_trace_event_close(p_event); perf_trace_event_unreg(p_event); + trace_event_put_ref(p_event->tp_event); mutex_unlock(&event_mutex); } @@ -292,6 +291,7 @@ void perf_kprobe_destroy(struct perf_event *p_event) mutex_lock(&event_mutex); perf_trace_event_close(p_event); perf_trace_event_unreg(p_event); + trace_event_put_ref(p_event->tp_event); mutex_unlock(&event_mutex); destroy_local_trace_kprobe(p_event->tp_event); @@ -347,6 +347,7 @@ void perf_uprobe_destroy(struct perf_event *p_event) mutex_lock(&event_mutex); perf_trace_event_close(p_event); perf_trace_event_unreg(p_event); + trace_event_put_ref(p_event->tp_event); mutex_unlock(&event_mutex); destroy_local_trace_uprobe(p_event->tp_event); } From c3b0f72e805f0801f05fa2aa52011c4bfc694c44 Mon Sep 17 00:00:00 2001 From: Yang Jihong Date: Thu, 18 Aug 2022 11:26:59 +0800 Subject: [PATCH 420/427] ftrace: Fix NULL pointer dereference in is_ftrace_trampoline when ftrace is dead ftrace_startup does not remove ops from ftrace_ops_list when ftrace_startup_enable fails: register_ftrace_function ftrace_startup __register_ftrace_function ... add_ftrace_ops(&ftrace_ops_list, ops) ... ... ftrace_startup_enable // if ftrace failed to modify, ftrace_disabled is set to 1 ... return 0 // ops is in the ftrace_ops_list. When ftrace_disabled = 1, unregister_ftrace_function simply returns without doing anything: unregister_ftrace_function ftrace_shutdown if (unlikely(ftrace_disabled)) return -ENODEV; // return here, __unregister_ftrace_function is not executed, // as a result, ops is still in the ftrace_ops_list __unregister_ftrace_function ... If ops is dynamically allocated, it will be free later, in this case, is_ftrace_trampoline accesses NULL pointer: is_ftrace_trampoline ftrace_ops_trampoline do_for_each_ftrace_op(op, ftrace_ops_list) // OOPS! op may be NULL! Syzkaller reports as follows: [ 1203.506103] BUG: kernel NULL pointer dereference, address: 000000000000010b [ 1203.508039] #PF: supervisor read access in kernel mode [ 1203.508798] #PF: error_code(0x0000) - not-present page [ 1203.509558] PGD 800000011660b067 P4D 800000011660b067 PUD 130fb8067 PMD 0 [ 1203.510560] Oops: 0000 [#1] SMP KASAN PTI [ 1203.511189] CPU: 6 PID: 29532 Comm: syz-executor.2 Tainted: G B W 5.10.0 #8 [ 1203.512324] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014 [ 1203.513895] RIP: 0010:is_ftrace_trampoline+0x26/0xb0 [ 1203.514644] Code: ff eb d3 90 41 55 41 54 49 89 fc 55 53 e8 f2 00 fd ff 48 8b 1d 3b 35 5d 03 e8 e6 00 fd ff 48 8d bb 90 00 00 00 e8 2a 81 26 00 <48> 8b ab 90 00 00 00 48 85 ed 74 1d e8 c9 00 fd ff 48 8d bb 98 00 [ 1203.518838] RSP: 0018:ffffc900012cf960 EFLAGS: 00010246 [ 1203.520092] RAX: 0000000000000000 RBX: 000000000000007b RCX: ffffffff8a331866 [ 1203.521469] RDX: 0000000000000000 RSI: 0000000000000008 RDI: 000000000000010b [ 1203.522583] RBP: 0000000000000000 R08: 0000000000000000 R09: ffffffff8df18b07 [ 1203.523550] R10: fffffbfff1be3160 R11: 0000000000000001 R12: 0000000000478399 [ 1203.524596] R13: 0000000000000000 R14: ffff888145088000 R15: 0000000000000008 [ 1203.525634] FS: 00007f429f5f4700(0000) GS:ffff8881daf00000(0000) knlGS:0000000000000000 [ 1203.526801] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1203.527626] CR2: 000000000000010b CR3: 0000000170e1e001 CR4: 00000000003706e0 [ 1203.528611] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 1203.529605] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Therefore, when ftrace_startup_enable fails, we need to rollback registration process and remove ops from ftrace_ops_list. Link: https://lkml.kernel.org/r/20220818032659.56209-1-yangjihong1@huawei.com Suggested-by: Steven Rostedt Signed-off-by: Yang Jihong Signed-off-by: Steven Rostedt (Google) --- kernel/trace/ftrace.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 601ccf1b2f091..4baa99363b166 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -2937,6 +2937,16 @@ int ftrace_startup(struct ftrace_ops *ops, int command) ftrace_startup_enable(command); + /* + * If ftrace is in an undefined state, we just remove ops from list + * to prevent the NULL pointer, instead of totally rolling it back and + * free trampoline, because those actions could cause further damage. + */ + if (unlikely(ftrace_disabled)) { + __unregister_ftrace_function(ops); + return -ENODEV; + } + ops->flags &= ~FTRACE_OPS_FL_ADDING; return 0; From 2673c60ee67e71f2ebe34386e62d348f71edee47 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Sat, 20 Aug 2022 09:43:17 -0400 Subject: [PATCH 421/427] tracing/eprobes: Do not allow eprobes to use $stack, or % for regs While playing with event probes (eprobes), I tried to see what would happen if I attempted to retrieve the instruction pointer (%rip) knowing that event probes do not use pt_regs. The result was: BUG: kernel NULL pointer dereference, address: 0000000000000024 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 [#1] PREEMPT SMP PTI CPU: 1 PID: 1847 Comm: trace-cmd Not tainted 5.19.0-rc5-test+ #309 Hardware name: Hewlett-Packard HP Compaq Pro 6300 SFF/339A, BIOS K01 v03.03 07/14/2016 RIP: 0010:get_event_field.isra.0+0x0/0x50 Code: ff 48 c7 c7 c0 8f 74 a1 e8 3d 8b f5 ff e8 88 09 f6 ff 4c 89 e7 e8 50 6a 13 00 48 89 ef 5b 5d 41 5c 41 5d e9 42 6a 13 00 66 90 <48> 63 47 24 8b 57 2c 48 01 c6 8b 47 28 83 f8 02 74 0e 83 f8 04 74 RSP: 0018:ffff916c394bbaf0 EFLAGS: 00010086 RAX: ffff916c854041d8 RBX: ffff916c8d9fbf50 RCX: ffff916c255d2000 RDX: 0000000000000000 RSI: ffff916c255d2008 RDI: 0000000000000000 RBP: 0000000000000000 R08: ffff916c3a2a0c08 R09: ffff916c394bbda8 R10: 0000000000000000 R11: 0000000000000000 R12: ffff916c854041d8 R13: ffff916c854041b0 R14: 0000000000000000 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff916c9ea40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000024 CR3: 000000011b60a002 CR4: 00000000001706e0 Call Trace: get_eprobe_size+0xb4/0x640 ? __mod_node_page_state+0x72/0xc0 __eprobe_trace_func+0x59/0x1a0 ? __mod_lruvec_page_state+0xaa/0x1b0 ? page_remove_file_rmap+0x14/0x230 ? page_remove_rmap+0xda/0x170 event_triggers_call+0x52/0xe0 trace_event_buffer_commit+0x18f/0x240 trace_event_raw_event_sched_wakeup_template+0x7a/0xb0 try_to_wake_up+0x260/0x4c0 __wake_up_common+0x80/0x180 __wake_up_common_lock+0x7c/0xc0 do_notify_parent+0x1c9/0x2a0 exit_notify+0x1a9/0x220 do_exit+0x2ba/0x450 do_group_exit+0x2d/0x90 __x64_sys_exit_group+0x14/0x20 do_syscall_64+0x3b/0x90 entry_SYSCALL_64_after_hwframe+0x46/0xb0 Obviously this is not the desired result. Move the testing for TPARG_FL_TPOINT which is only used for event probes to the top of the "$" variable check, as all the other variables are not used for event probes. Also add a check in the register parsing "%" to fail if an event probe is used. Link: https://lkml.kernel.org/r/20220820134400.564426983@goodmis.org Cc: stable@vger.kernel.org Cc: Ingo Molnar Cc: Andrew Morton Cc: Tzvetomir Stoyanov Cc: Tom Zanussi Fixes: 7491e2c44278 ("tracing: Add a probe that attaches to trace events") Acked-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_probe.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index 850a88abd33ba..dec657af363cb 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -283,7 +283,14 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t, int ret = 0; int len; - if (strcmp(arg, "retval") == 0) { + if (flags & TPARG_FL_TPOINT) { + if (code->data) + return -EFAULT; + code->data = kstrdup(arg, GFP_KERNEL); + if (!code->data) + return -ENOMEM; + code->op = FETCH_OP_TP_ARG; + } else if (strcmp(arg, "retval") == 0) { if (flags & TPARG_FL_RETURN) { code->op = FETCH_OP_RETVAL; } else { @@ -323,13 +330,6 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t, code->op = FETCH_OP_ARG; code->param = (unsigned int)param - 1; #endif - } else if (flags & TPARG_FL_TPOINT) { - if (code->data) - return -EFAULT; - code->data = kstrdup(arg, GFP_KERNEL); - if (!code->data) - return -ENOMEM; - code->op = FETCH_OP_TP_ARG; } else goto inval_var; @@ -384,6 +384,11 @@ parse_probe_arg(char *arg, const struct fetch_type *type, break; case '%': /* named register */ + if (flags & TPARG_FL_TPOINT) { + /* eprobes do not handle registers */ + trace_probe_log_err(offs, BAD_VAR); + break; + } ret = regs_query_register_offset(arg + 1); if (ret >= 0) { code->op = FETCH_OP_REG; From 02333de90e5945e2fe7fc75b15b4eb9aee187f0a Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Sat, 20 Aug 2022 09:43:18 -0400 Subject: [PATCH 422/427] tracing/eprobes: Do not hardcode $comm as a string The variable $comm is hard coded as a string, which is true for both kprobes and uprobes, but for event probes (eprobes) it is a field name. In most cases the "comm" field would be a string, but there's no guarantee of that fact. Do not assume that comm is a string. Not to mention, it currently forces comm fields to fault, as string processing for event probes is currently broken. Link: https://lkml.kernel.org/r/20220820134400.756152112@goodmis.org Cc: stable@vger.kernel.org Cc: Ingo Molnar Cc: Andrew Morton Cc: Masami Hiramatsu Cc: Tzvetomir Stoyanov Cc: Tom Zanussi Fixes: 7491e2c44278 ("tracing: Add a probe that attaches to trace events") Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_probe.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index dec657af363cb..4daabbb8b7727 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -622,9 +622,10 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size, /* * Since $comm and immediate string can not be dereferenced, - * we can find those by strcmp. + * we can find those by strcmp. But ignore for eprobes. */ - if (strcmp(arg, "$comm") == 0 || strncmp(arg, "\\\"", 2) == 0) { + if (!(flags & TPARG_FL_TPOINT) && + (strcmp(arg, "$comm") == 0 || strncmp(arg, "\\\"", 2) == 0)) { /* The type of $comm must be "string", and not an array. */ if (parg->count || (t && strcmp(t, "string"))) goto out; From f04dec93466a0481763f3b56cdadf8076e28bfbf Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Sat, 20 Aug 2022 09:43:19 -0400 Subject: [PATCH 423/427] tracing/eprobes: Fix reading of string fields Currently when an event probe (eprobe) hooks to a string field, it does not display it as a string, but instead as a number. This makes the field rather useless. Handle the different kinds of strings, dynamic, static, relational/dynamic etc. Now when a string field is used, the ":string" type can be used to display it: echo "e:sw sched/sched_switch comm=$next_comm:string" > dynamic_events Link: https://lkml.kernel.org/r/20220820134400.959640191@goodmis.org Cc: stable@vger.kernel.org Cc: Ingo Molnar Cc: Andrew Morton Cc: Tzvetomir Stoyanov Cc: Tom Zanussi Fixes: 7491e2c44278 ("tracing: Add a probe that attaches to trace events") Acked-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_eprobe.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c index 550671985fd15..a1d3423ab74f9 100644 --- a/kernel/trace/trace_eprobe.c +++ b/kernel/trace/trace_eprobe.c @@ -311,6 +311,27 @@ static unsigned long get_event_field(struct fetch_insn *code, void *rec) addr = rec + field->offset; + if (is_string_field(field)) { + switch (field->filter_type) { + case FILTER_DYN_STRING: + val = (unsigned long)(rec + (*(unsigned int *)addr & 0xffff)); + break; + case FILTER_RDYN_STRING: + val = (unsigned long)(addr + (*(unsigned int *)addr & 0xffff)); + break; + case FILTER_STATIC_STRING: + val = (unsigned long)addr; + break; + case FILTER_PTR_STRING: + val = (unsigned long)(*(char *)addr); + break; + default: + WARN_ON_ONCE(1); + return 0; + } + return val; + } + switch (field->size) { case 1: if (field->is_signed) From 6a832ec3d680b3a4f4fad5752672827d71bae501 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Sat, 20 Aug 2022 09:43:20 -0400 Subject: [PATCH 424/427] tracing/eprobes: Have event probes be consistent with kprobes and uprobes Currently, if a symbol "@" is attempted to be used with an event probe (eprobes), it will cause a NULL pointer dereference crash. Both kprobes and uprobes can reference data other than the main registers. Such as immediate address, symbols and the current task name. Have eprobes do the same thing. For "comm", if "comm" is used and the event being attached to does not have the "comm" field, then make it the "$comm" that kprobes has. This is consistent to the way histograms and filters work. Link: https://lkml.kernel.org/r/20220820134401.136924220@goodmis.org Cc: stable@vger.kernel.org Cc: Ingo Molnar Cc: Andrew Morton Cc: Masami Hiramatsu Cc: Tzvetomir Stoyanov Cc: Tom Zanussi Fixes: 7491e2c44278 ("tracing: Add a probe that attaches to trace events") Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_eprobe.c | 70 +++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c index a1d3423ab74f9..1783e34789124 100644 --- a/kernel/trace/trace_eprobe.c +++ b/kernel/trace/trace_eprobe.c @@ -227,6 +227,7 @@ static int trace_eprobe_tp_arg_update(struct trace_eprobe *ep, int i) struct probe_arg *parg = &ep->tp.args[i]; struct ftrace_event_field *field; struct list_head *head; + int ret = -ENOENT; head = trace_get_fields(ep->event); list_for_each_entry(field, head, link) { @@ -236,9 +237,20 @@ static int trace_eprobe_tp_arg_update(struct trace_eprobe *ep, int i) return 0; } } + + /* + * Argument not found on event. But allow for comm and COMM + * to be used to get the current->comm. + */ + if (strcmp(parg->code->data, "COMM") == 0 || + strcmp(parg->code->data, "comm") == 0) { + parg->code->op = FETCH_OP_COMM; + ret = 0; + } + kfree(parg->code->data); parg->code->data = NULL; - return -ENOENT; + return ret; } static int eprobe_event_define_fields(struct trace_event_call *event_call) @@ -363,16 +375,38 @@ static unsigned long get_event_field(struct fetch_insn *code, void *rec) static int get_eprobe_size(struct trace_probe *tp, void *rec) { + struct fetch_insn *code; struct probe_arg *arg; int i, len, ret = 0; for (i = 0; i < tp->nr_args; i++) { arg = tp->args + i; - if (unlikely(arg->dynamic)) { + if (arg->dynamic) { unsigned long val; - val = get_event_field(arg->code, rec); - len = process_fetch_insn_bottom(arg->code + 1, val, NULL, NULL); + code = arg->code; + retry: + switch (code->op) { + case FETCH_OP_TP_ARG: + val = get_event_field(code, rec); + break; + case FETCH_OP_IMM: + val = code->immediate; + break; + case FETCH_OP_COMM: + val = (unsigned long)current->comm; + break; + case FETCH_OP_DATA: + val = (unsigned long)code->data; + break; + case FETCH_NOP_SYMBOL: /* Ignore a place holder */ + code++; + goto retry; + default: + continue; + } + code++; + len = process_fetch_insn_bottom(code, val, NULL, NULL); if (len > 0) ret += len; } @@ -390,8 +424,28 @@ process_fetch_insn(struct fetch_insn *code, void *rec, void *dest, { unsigned long val; - val = get_event_field(code, rec); - return process_fetch_insn_bottom(code + 1, val, dest, base); + retry: + switch (code->op) { + case FETCH_OP_TP_ARG: + val = get_event_field(code, rec); + break; + case FETCH_OP_IMM: + val = code->immediate; + break; + case FETCH_OP_COMM: + val = (unsigned long)current->comm; + break; + case FETCH_OP_DATA: + val = (unsigned long)code->data; + break; + case FETCH_NOP_SYMBOL: /* Ignore a place holder */ + code++; + goto retry; + default: + return -EILSEQ; + } + code++; + return process_fetch_insn_bottom(code, val, dest, base); } NOKPROBE_SYMBOL(process_fetch_insn) @@ -866,6 +920,10 @@ static int trace_eprobe_tp_update_arg(struct trace_eprobe *ep, const char *argv[ trace_probe_log_err(0, BAD_ATTACH_ARG); } + /* Handle symbols "@" */ + if (!ret) + ret = traceprobe_update_arg(&ep->tp.args[i]); + return ret; } From ab8384442ee512fc0fc72deeb036110843d0e7ff Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Sat, 20 Aug 2022 09:43:21 -0400 Subject: [PATCH 425/427] tracing/probes: Have kprobes and uprobes use $COMM too Both $comm and $COMM can be used to get current->comm in eprobes and the filtering and histogram logic. Make kprobes and uprobes consistent in this regard and allow both $comm and $COMM as well. Currently kprobes and uprobes only handle $comm, which is inconsistent with the other utilities, and can be confusing to users. Link: https://lkml.kernel.org/r/20220820134401.317014913@goodmis.org Link: https://lore.kernel.org/all/20220820220442.776e1ddaf8836e82edb34d01@kernel.org/ Cc: stable@vger.kernel.org Cc: Ingo Molnar Cc: Andrew Morton Cc: Tzvetomir Stoyanov Cc: Tom Zanussi Fixes: 533059281ee5 ("tracing: probeevent: Introduce new argument fetching code") Suggested-by: Masami Hiramatsu (Google) Acked-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_probe.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index 4daabbb8b7727..36dff277de464 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -314,7 +314,7 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t, } } else goto inval_var; - } else if (strcmp(arg, "comm") == 0) { + } else if (strcmp(arg, "comm") == 0 || strcmp(arg, "COMM") == 0) { code->op = FETCH_OP_COMM; #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API } else if (((flags & TPARG_FL_MASK) == @@ -625,7 +625,8 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size, * we can find those by strcmp. But ignore for eprobes. */ if (!(flags & TPARG_FL_TPOINT) && - (strcmp(arg, "$comm") == 0 || strncmp(arg, "\\\"", 2) == 0)) { + (strcmp(arg, "$comm") == 0 || strcmp(arg, "$COMM") == 0 || + strncmp(arg, "\\\"", 2) == 0)) { /* The type of $comm must be "string", and not an array. */ if (parg->count || (t && strcmp(t, "string"))) goto out; From b2380577d4fe1c0ef3fa50417f1e441c016e4cbe Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Sat, 20 Aug 2022 09:43:22 -0400 Subject: [PATCH 426/427] tracing: Have filter accept "common_cpu" to be consistent Make filtering consistent with histograms. As "cpu" can be a field of an event, allow for "common_cpu" to keep it from being confused with the "cpu" field of the event. Link: https://lkml.kernel.org/r/20220820134401.513062765@goodmis.org Link: https://lore.kernel.org/all/20220820220920.e42fa32b70505b1904f0a0ad@kernel.org/ Cc: stable@vger.kernel.org Cc: Ingo Molnar Cc: Andrew Morton Cc: Tzvetomir Stoyanov Cc: Tom Zanussi Fixes: 1e3bac71c5053 ("tracing/histogram: Rename "cpu" to "common_cpu"") Suggested-by: Masami Hiramatsu (Google) Acked-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_events.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 181f08186d32c..0356cae0cf74e 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -176,6 +176,7 @@ static int trace_define_generic_fields(void) __generic_field(int, CPU, FILTER_CPU); __generic_field(int, cpu, FILTER_CPU); + __generic_field(int, common_cpu, FILTER_CPU); __generic_field(char *, COMM, FILTER_COMM); __generic_field(char *, comm, FILTER_COMM); From 1c23f9e627a7b412978b4e852793c5e3c3efc555 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 21 Aug 2022 17:32:54 -0700 Subject: [PATCH 427/427] Linux 6.0-rc2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 697ab397fe31f..c7705f7496012 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 6 PATCHLEVEL = 0 SUBLEVEL = 0 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc2 NAME = Hurr durr I'ma ninja sloth # *DOCUMENTATION*