From b8a30b4171b9a3c22ef0605ed74a21544d00c680 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 18:35:49 +0300 Subject: fs/ntfs3: Remove unnecesarry mount option noatime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove unnecesarry mount option noatime because this will be handled by VFS. Our option parser will never get opt like this. Acked-by: Christian Brauner Reviewed-by: Christoph Hellwig Reviewed-by: Pali Rohár Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- Documentation/filesystems/ntfs3.rst | 4 ---- fs/ntfs3/super.c | 7 ------- 2 files changed, 11 deletions(-) diff --git a/Documentation/filesystems/ntfs3.rst b/Documentation/filesystems/ntfs3.rst index ffe9ea0c1499..af7158de6fde 100644 --- a/Documentation/filesystems/ntfs3.rst +++ b/Documentation/filesystems/ntfs3.rst @@ -85,10 +85,6 @@ acl Support POSIX ACLs (Access Control Lists). Effective if supported by Kernel. Not to be confused with NTFS ACLs. The option specified as acl enables support for POSIX ACLs. -noatime All files and directories will not update their last access - time attribute if a partition is mounted with this parameter. - This option can speed up file system operation. - =============================================================================== ToDo list diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 55bbc9200a10..a18b99a3e3b5 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -223,7 +223,6 @@ enum Opt { Opt_nohidden, Opt_showmeta, Opt_acl, - Opt_noatime, Opt_nls, Opt_prealloc, Opt_no_acs_rules, @@ -242,7 +241,6 @@ static const match_table_t ntfs_tokens = { { Opt_sparse, "sparse" }, { Opt_nohidden, "nohidden" }, { Opt_acl, "acl" }, - { Opt_noatime, "noatime" }, { Opt_showmeta, "showmeta" }, { Opt_nls, "nls=%s" }, { Opt_prealloc, "prealloc" }, @@ -333,9 +331,6 @@ static noinline int ntfs_parse_options(struct super_block *sb, char *options, ntfs_err(sb, "support for ACL not compiled in!"); return -EINVAL; #endif - case Opt_noatime: - sb->s_flags |= SB_NOATIME; - break; case Opt_showmeta: opts->showmeta = 1; break; @@ -587,8 +582,6 @@ static int ntfs_show_options(struct seq_file *m, struct dentry *root) seq_puts(m, ",prealloc"); if (sb->s_flags & SB_POSIXACL) seq_puts(m, ",acl"); - if (sb->s_flags & SB_NOATIME) - seq_puts(m, ",noatime"); return 0; } -- cgit From c2c389fd6c6b0393549578997744b03822dd2b24 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 18:35:50 +0300 Subject: fs/ntfs3: Remove unnecesarry remount flag handling Remove unnecesarry remount flag handling. This does not do anything for this driver. We have already set SB_NODIRATIME when we fill super. Also noatime should be set from mount option. Now for some reson we try to set it when remounting. Lazytime part looks like it is copied from f2fs and there is own mount parameter for it. That is why they use it. We do not set lazytime anywhere in our code. So basically this just blocks lazytime when remounting. Acked-by: Christian Brauner Reviewed-by: Christoph Hellwig Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index a18b99a3e3b5..6cb689605089 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -417,8 +417,6 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *data) clear_mount_options(&old_opts); - *flags = (*flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME) | - SB_NODIRATIME | SB_NOATIME; ntfs_info(sb, "re-mounted. Opts: %s", orig_data); err = 0; goto out; -- cgit From 564c97bdfa39c7d1f331841fb24da6e714693037 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 18:35:51 +0300 Subject: fs/ntfs3: Convert mount options to pointer in sbi Use pointer to mount options. We want to do this because we will use new mount api which will benefit that we have spi and mount options in different allocations. When we remount we do not have to make whole new spi it is enough that we will allocate just mount options. Please note that we can do example remount lot cleaner but things will change in next patch so this should be just functional. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 2 +- fs/ntfs3/dir.c | 8 ++++---- fs/ntfs3/file.c | 4 ++-- fs/ntfs3/inode.c | 12 ++++++------ fs/ntfs3/ntfs_fs.h | 2 +- fs/ntfs3/super.c | 31 +++++++++++++++++++------------ fs/ntfs3/xattr.c | 2 +- 7 files changed, 34 insertions(+), 27 deletions(-) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 34c4cbf7e29b..b1055b284c60 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -529,7 +529,7 @@ add_alloc_in_same_attr_seg: } else if (pre_alloc == -1) { pre_alloc = 0; if (type == ATTR_DATA && !name_len && - sbi->options.prealloc) { + sbi->options->prealloc) { CLST new_alen2 = bytes_to_cluster( sbi, get_pre_allocated(new_size)); pre_alloc = new_alen2 - new_alen; diff --git a/fs/ntfs3/dir.c b/fs/ntfs3/dir.c index 93f6d485564e..40440df021ef 100644 --- a/fs/ntfs3/dir.c +++ b/fs/ntfs3/dir.c @@ -24,7 +24,7 @@ int ntfs_utf16_to_nls(struct ntfs_sb_info *sbi, const struct le_str *uni, int ret, uni_len, warn; const __le16 *ip; u8 *op; - struct nls_table *nls = sbi->options.nls; + struct nls_table *nls = sbi->options->nls; static_assert(sizeof(wchar_t) == sizeof(__le16)); @@ -186,7 +186,7 @@ int ntfs_nls_to_utf16(struct ntfs_sb_info *sbi, const u8 *name, u32 name_len, { int ret, slen; const u8 *end; - struct nls_table *nls = sbi->options.nls; + struct nls_table *nls = sbi->options->nls; u16 *uname = uni->name; static_assert(sizeof(wchar_t) == sizeof(u16)); @@ -301,10 +301,10 @@ static inline int ntfs_filldir(struct ntfs_sb_info *sbi, struct ntfs_inode *ni, return 0; /* Skip meta files. Unless option to show metafiles is set. */ - if (!sbi->options.showmeta && ntfs_is_meta_file(sbi, ino)) + if (!sbi->options->showmeta && ntfs_is_meta_file(sbi, ino)) return 0; - if (sbi->options.nohidden && (fname->dup.fa & FILE_ATTRIBUTE_HIDDEN)) + if (sbi->options->nohidden && (fname->dup.fa & FILE_ATTRIBUTE_HIDDEN)) return 0; name_len = ntfs_utf16_to_nls(sbi, (struct le_str *)&fname->name_len, diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 424450e77ad5..fef57141b161 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -737,7 +737,7 @@ int ntfs3_setattr(struct user_namespace *mnt_userns, struct dentry *dentry, umode_t mode = inode->i_mode; int err; - if (sbi->options.no_acs_rules) { + if (sbi->options->no_acs_rules) { /* "No access rules" - Force any changes of time etc. */ attr->ia_valid |= ATTR_FORCE; /* and disable for editing some attributes. */ @@ -1185,7 +1185,7 @@ static int ntfs_file_release(struct inode *inode, struct file *file) int err = 0; /* If we are last writer on the inode, drop the block reservation. */ - if (sbi->options.prealloc && ((file->f_mode & FMODE_WRITE) && + if (sbi->options->prealloc && ((file->f_mode & FMODE_WRITE) && atomic_read(&inode->i_writecount) == 1)) { ni_lock(ni); down_write(&ni->file.run_lock); diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index db2a5a4c38e4..9f740fd301b2 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -49,8 +49,8 @@ static struct inode *ntfs_read_mft(struct inode *inode, inode->i_op = NULL; /* Setup 'uid' and 'gid' */ - inode->i_uid = sbi->options.fs_uid; - inode->i_gid = sbi->options.fs_gid; + inode->i_uid = sbi->options->fs_uid; + inode->i_gid = sbi->options->fs_gid; err = mi_init(&ni->mi, sbi, ino); if (err) @@ -229,7 +229,7 @@ next_attr: t32 = le16_to_cpu(attr->nres.run_off); } - mode = S_IFREG | (0777 & sbi->options.fs_fmask_inv); + mode = S_IFREG | (0777 & sbi->options->fs_fmask_inv); if (!attr->non_res) { ni->ni_flags |= NI_FLAG_RESIDENT; @@ -272,7 +272,7 @@ next_attr: goto out; mode = sb->s_root - ? (S_IFDIR | (0777 & sbi->options.fs_dmask_inv)) + ? (S_IFDIR | (0777 & sbi->options->fs_dmask_inv)) : (S_IFDIR | 0777); goto next_attr; @@ -443,7 +443,7 @@ end_enum: goto out; } - if ((sbi->options.sys_immutable && + if ((sbi->options->sys_immutable && (std5->fa & FILE_ATTRIBUTE_SYSTEM)) && !S_ISFIFO(mode) && !S_ISSOCK(mode) && !S_ISLNK(mode)) { inode->i_flags |= S_IMMUTABLE; @@ -1244,7 +1244,7 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns, * } */ } else if (S_ISREG(mode)) { - if (sbi->options.sparse) { + if (sbi->options->sparse) { /* Sparsed regular file, cause option 'sparse'. */ fa = FILE_ATTRIBUTE_SPARSE_FILE | FILE_ATTRIBUTE_ARCHIVE; diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 97e682ebcfb9..98c90c399ee2 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -279,7 +279,7 @@ struct ntfs_sb_info { #endif } compress; - struct ntfs_mount_options options; + struct ntfs_mount_options *options; struct ratelimit_state msg_ratelimit; }; diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 6cb689605089..0f3820342051 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -389,11 +389,11 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *data) return -ENOMEM; /* Store original options. */ - memcpy(&old_opts, &sbi->options, sizeof(old_opts)); - clear_mount_options(&sbi->options); - memset(&sbi->options, 0, sizeof(sbi->options)); + memcpy(&old_opts, sbi->options, sizeof(old_opts)); + clear_mount_options(sbi->options); + memset(sbi->options, 0, sizeof(old_opts)); - err = ntfs_parse_options(sb, data, 0, &sbi->options); + err = ntfs_parse_options(sb, data, 0, sbi->options); if (err) goto restore_opts; @@ -409,7 +409,7 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *data) sync_filesystem(sb); if (ro_rw && (sbi->volume.flags & VOLUME_FLAG_DIRTY) && - !sbi->options.force) { + !sbi->options->force) { ntfs_warn(sb, "volume is dirty and \"force\" flag is not set!"); err = -EINVAL; goto restore_opts; @@ -422,8 +422,8 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *data) goto out; restore_opts: - clear_mount_options(&sbi->options); - memcpy(&sbi->options, &old_opts, sizeof(old_opts)); + clear_mount_options(sbi->options); + memcpy(sbi->options, &old_opts, sizeof(old_opts)); out: kfree(orig_data); @@ -506,7 +506,8 @@ static noinline void put_ntfs(struct ntfs_sb_info *sbi) xpress_free_decompressor(sbi->compress.xpress); lzx_free_decompressor(sbi->compress.lzx); #endif - clear_mount_options(&sbi->options); + clear_mount_options(sbi->options); + kfree(sbi->options); kfree(sbi); } @@ -545,7 +546,7 @@ static int ntfs_show_options(struct seq_file *m, struct dentry *root) { struct super_block *sb = root->d_sb; struct ntfs_sb_info *sbi = sb->s_fs_info; - struct ntfs_mount_options *opts = &sbi->options; + struct ntfs_mount_options *opts = sbi->options; struct user_namespace *user_ns = seq_user_ns(m); if (opts->uid) @@ -930,6 +931,12 @@ static int ntfs_fill_super(struct super_block *sb, void *data, int silent) if (!sbi) return -ENOMEM; + sbi->options = kzalloc(sizeof(struct ntfs_mount_options), GFP_NOFS); + if (!sbi->options) { + kfree(sbi); + return -ENOMEM; + } + sb->s_fs_info = sbi; sbi->sb = sb; sb->s_flags |= SB_NODIRATIME; @@ -942,7 +949,7 @@ static int ntfs_fill_super(struct super_block *sb, void *data, int silent) ratelimit_state_init(&sbi->msg_ratelimit, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); - err = ntfs_parse_options(sb, data, silent, &sbi->options); + err = ntfs_parse_options(sb, data, silent, sbi->options); if (err) goto out; @@ -1074,7 +1081,7 @@ static int ntfs_fill_super(struct super_block *sb, void *data, int silent) goto out; } } else if (sbi->volume.flags & VOLUME_FLAG_DIRTY) { - if (!is_ro && !sbi->options.force) { + if (!is_ro && !sbi->options->force) { ntfs_warn( sb, "volume is dirty and \"force\" flag is not set!"); @@ -1394,7 +1401,7 @@ int ntfs_discard(struct ntfs_sb_info *sbi, CLST lcn, CLST len) if (sbi->flags & NTFS_FLAGS_NODISCARD) return -EOPNOTSUPP; - if (!sbi->options.discard) + if (!sbi->options->discard) return -EOPNOTSUPP; lbo = (u64)lcn << sbi->cluster_bits; diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index b15d532e4a17..ac4b37bf8832 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -769,7 +769,7 @@ int ntfs_acl_chmod(struct user_namespace *mnt_userns, struct inode *inode) int ntfs_permission(struct user_namespace *mnt_userns, struct inode *inode, int mask) { - if (ntfs_sb(inode->i_sb)->options.no_acs_rules) { + if (ntfs_sb(inode->i_sb)->options->no_acs_rules) { /* "No access rules" mode - Allow all changes. */ return 0; } -- cgit From 610f8f5a7baf998e70a61c63e53869b676d9b04c Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 18:35:52 +0300 Subject: fs/ntfs3: Use new api for mounting We have now new mount api as described in Documentation/filesystems. We should use it as it gives us some benefits which are desribed here lore.kernel.org/linux-fsdevel/159646178122.1784947.11705396571718464082.stgit@warthog.procyon.org.uk/ Nls loading is changed a to load with string. This did make code also little cleaner. Also try to use fsparam_flag_no as much as possible. This is just nice little touch and is not mandatory but it should not make any harm. It is just convenient that we can use example acl/noacl mount options. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/ntfs_fs.h | 1 + fs/ntfs3/super.c | 433 ++++++++++++++++++++++++++++------------------------- 2 files changed, 229 insertions(+), 205 deletions(-) diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 98c90c399ee2..aa18f12b7096 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -52,6 +52,7 @@ // clang-format on struct ntfs_mount_options { + char *nls_name; struct nls_table *nls; kuid_t fs_uid; diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 0f3820342051..befa78d3cb26 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -28,11 +28,12 @@ #include #include #include +#include +#include #include #include #include #include -#include #include #include @@ -205,9 +206,11 @@ void *ntfs_put_shared(void *ptr) return ret; } -static inline void clear_mount_options(struct ntfs_mount_options *options) +static inline void put_mount_options(struct ntfs_mount_options *options) { + kfree(options->nls_name); unload_nls(options->nls); + kfree(options); } enum Opt { @@ -229,205 +232,171 @@ enum Opt { Opt_err, }; -static const match_table_t ntfs_tokens = { - { Opt_uid, "uid=%u" }, - { Opt_gid, "gid=%u" }, - { Opt_umask, "umask=%o" }, - { Opt_dmask, "dmask=%o" }, - { Opt_fmask, "fmask=%o" }, - { Opt_immutable, "sys_immutable" }, - { Opt_discard, "discard" }, - { Opt_force, "force" }, - { Opt_sparse, "sparse" }, - { Opt_nohidden, "nohidden" }, - { Opt_acl, "acl" }, - { Opt_showmeta, "showmeta" }, - { Opt_nls, "nls=%s" }, - { Opt_prealloc, "prealloc" }, - { Opt_no_acs_rules, "no_acs_rules" }, - { Opt_err, NULL }, +static const struct fs_parameter_spec ntfs_fs_parameters[] = { + fsparam_u32("uid", Opt_uid), + fsparam_u32("gid", Opt_gid), + fsparam_u32oct("umask", Opt_umask), + fsparam_u32oct("dmask", Opt_dmask), + fsparam_u32oct("fmask", Opt_fmask), + fsparam_flag_no("sys_immutable", Opt_immutable), + fsparam_flag_no("discard", Opt_discard), + fsparam_flag_no("force", Opt_force), + fsparam_flag_no("sparse", Opt_sparse), + fsparam_flag("nohidden", Opt_nohidden), + fsparam_flag_no("acl", Opt_acl), + fsparam_flag_no("showmeta", Opt_showmeta), + fsparam_string("nls", Opt_nls), + fsparam_flag_no("prealloc", Opt_prealloc), + fsparam_flag("no_acs_rules", Opt_no_acs_rules), + {} }; -static noinline int ntfs_parse_options(struct super_block *sb, char *options, - int silent, - struct ntfs_mount_options *opts) +/* + * Load nls table or if @nls is utf8 then return NULL. + */ +static struct nls_table *ntfs_load_nls(char *nls) { - char *p; - substring_t args[MAX_OPT_ARGS]; - int option; - char nls_name[30]; - struct nls_table *nls; + struct nls_table *ret; - opts->fs_uid = current_uid(); - opts->fs_gid = current_gid(); - opts->fs_fmask_inv = opts->fs_dmask_inv = ~current_umask(); - nls_name[0] = 0; + if (!nls) + nls = CONFIG_NLS_DEFAULT; - if (!options) - goto out; + if (strcmp(nls, "utf8") == 0) + return NULL; - while ((p = strsep(&options, ","))) { - int token; + if (strcmp(nls, CONFIG_NLS_DEFAULT) == 0) + return load_nls_default(); - if (!*p) - continue; + ret = load_nls(nls); + if (ret) + return ret; - token = match_token(p, ntfs_tokens, args); - switch (token) { - case Opt_immutable: - opts->sys_immutable = 1; - break; - case Opt_uid: - if (match_int(&args[0], &option)) - return -EINVAL; - opts->fs_uid = make_kuid(current_user_ns(), option); - if (!uid_valid(opts->fs_uid)) - return -EINVAL; - opts->uid = 1; - break; - case Opt_gid: - if (match_int(&args[0], &option)) - return -EINVAL; - opts->fs_gid = make_kgid(current_user_ns(), option); - if (!gid_valid(opts->fs_gid)) - return -EINVAL; - opts->gid = 1; - break; - case Opt_umask: - if (match_octal(&args[0], &option)) - return -EINVAL; - opts->fs_fmask_inv = opts->fs_dmask_inv = ~option; - opts->fmask = opts->dmask = 1; - break; - case Opt_dmask: - if (match_octal(&args[0], &option)) - return -EINVAL; - opts->fs_dmask_inv = ~option; - opts->dmask = 1; - break; - case Opt_fmask: - if (match_octal(&args[0], &option)) - return -EINVAL; - opts->fs_fmask_inv = ~option; - opts->fmask = 1; - break; - case Opt_discard: - opts->discard = 1; - break; - case Opt_force: - opts->force = 1; - break; - case Opt_sparse: - opts->sparse = 1; - break; - case Opt_nohidden: - opts->nohidden = 1; - break; - case Opt_acl: + return ERR_PTR(-EINVAL); +} + +static int ntfs_fs_parse_param(struct fs_context *fc, + struct fs_parameter *param) +{ + struct ntfs_mount_options *opts = fc->fs_private; + struct fs_parse_result result; + int opt; + + opt = fs_parse(fc, ntfs_fs_parameters, param, &result); + if (opt < 0) + return opt; + + switch (opt) { + case Opt_uid: + opts->fs_uid = make_kuid(current_user_ns(), result.uint_32); + if (!uid_valid(opts->fs_uid)) + return invalf(fc, "ntfs3: Invalid value for uid."); + opts->uid = 1; + break; + case Opt_gid: + opts->fs_gid = make_kgid(current_user_ns(), result.uint_32); + if (!gid_valid(opts->fs_gid)) + return invalf(fc, "ntfs3: Invalid value for gid."); + opts->gid = 1; + break; + case Opt_umask: + if (result.uint_32 & ~07777) + return invalf(fc, "ntfs3: Invalid value for umask."); + opts->fs_fmask_inv = ~result.uint_32; + opts->fs_dmask_inv = ~result.uint_32; + opts->fmask = 1; + opts->dmask = 1; + break; + case Opt_dmask: + if (result.uint_32 & ~07777) + return invalf(fc, "ntfs3: Invalid value for dmask."); + opts->fs_dmask_inv = ~result.uint_32; + opts->dmask = 1; + break; + case Opt_fmask: + if (result.uint_32 & ~07777) + return invalf(fc, "ntfs3: Invalid value for fmask."); + opts->fs_fmask_inv = ~result.uint_32; + opts->fmask = 1; + break; + case Opt_immutable: + opts->sys_immutable = result.negated ? 0 : 1; + break; + case Opt_discard: + opts->discard = result.negated ? 0 : 1; + break; + case Opt_force: + opts->force = result.negated ? 0 : 1; + break; + case Opt_sparse: + opts->sparse = result.negated ? 0 : 1; + break; + case Opt_nohidden: + opts->nohidden = 1; + break; + case Opt_acl: + if (!result.negated) #ifdef CONFIG_NTFS3_FS_POSIX_ACL - sb->s_flags |= SB_POSIXACL; - break; + fc->sb_flags |= SB_POSIXACL; #else - ntfs_err(sb, "support for ACL not compiled in!"); - return -EINVAL; + return invalf(fc, "ntfs3: Support for ACL not compiled in!"); #endif - case Opt_showmeta: - opts->showmeta = 1; - break; - case Opt_nls: - match_strlcpy(nls_name, &args[0], sizeof(nls_name)); - break; - case Opt_prealloc: - opts->prealloc = 1; - break; - case Opt_no_acs_rules: - opts->no_acs_rules = 1; - break; - default: - if (!silent) - ntfs_err( - sb, - "Unrecognized mount option \"%s\" or missing value", - p); - //return -EINVAL; - } - } - -out: - if (!strcmp(nls_name[0] ? nls_name : CONFIG_NLS_DEFAULT, "utf8")) { - /* - * For UTF-8 use utf16s_to_utf8s()/utf8s_to_utf16s() - * instead of NLS. - */ - nls = NULL; - } else if (nls_name[0]) { - nls = load_nls(nls_name); - if (!nls) { - ntfs_err(sb, "failed to load \"%s\"", nls_name); - return -EINVAL; - } - } else { - nls = load_nls_default(); - if (!nls) { - ntfs_err(sb, "failed to load default nls"); - return -EINVAL; - } + else + fc->sb_flags &= ~SB_POSIXACL; + break; + case Opt_showmeta: + opts->showmeta = result.negated ? 0 : 1; + break; + case Opt_nls: + kfree(opts->nls_name); + opts->nls_name = param->string; + param->string = NULL; + break; + case Opt_prealloc: + opts->prealloc = result.negated ? 0 : 1; + break; + case Opt_no_acs_rules: + opts->no_acs_rules = 1; + break; + default: + /* Should not be here unless we forget add case. */ + return -EINVAL; } - opts->nls = nls; - return 0; } -static int ntfs_remount(struct super_block *sb, int *flags, char *data) +static int ntfs_fs_reconfigure(struct fs_context *fc) { - int err, ro_rw; + struct super_block *sb = fc->root->d_sb; struct ntfs_sb_info *sbi = sb->s_fs_info; - struct ntfs_mount_options old_opts; - char *orig_data = kstrdup(data, GFP_KERNEL); - - if (data && !orig_data) - return -ENOMEM; - - /* Store original options. */ - memcpy(&old_opts, sbi->options, sizeof(old_opts)); - clear_mount_options(sbi->options); - memset(sbi->options, 0, sizeof(old_opts)); - - err = ntfs_parse_options(sb, data, 0, sbi->options); - if (err) - goto restore_opts; + struct ntfs_mount_options *new_opts = fc->fs_private; + int ro_rw; - ro_rw = sb_rdonly(sb) && !(*flags & SB_RDONLY); + ro_rw = sb_rdonly(sb) && !(fc->sb_flags & SB_RDONLY); if (ro_rw && (sbi->flags & NTFS_FLAGS_NEED_REPLAY)) { - ntfs_warn( - sb, - "Couldn't remount rw because journal is not replayed. Please umount/remount instead\n"); - err = -EINVAL; - goto restore_opts; + errorf(fc, "ntfs3: Couldn't remount rw because journal is not replayed. Please umount/remount instead\n"); + return -EINVAL; + } + + new_opts->nls = ntfs_load_nls(new_opts->nls_name); + if (IS_ERR(new_opts->nls)) { + new_opts->nls = NULL; + errorf(fc, "ntfs3: Cannot load nls %s", new_opts->nls_name); + return -EINVAL; } + if (new_opts->nls != sbi->options->nls) + return invalf(fc, "ntfs3: Cannot use different nls when remounting!"); sync_filesystem(sb); if (ro_rw && (sbi->volume.flags & VOLUME_FLAG_DIRTY) && - !sbi->options->force) { - ntfs_warn(sb, "volume is dirty and \"force\" flag is not set!"); - err = -EINVAL; - goto restore_opts; + !new_opts->force) { + errorf(fc, "ntfs3: Volume is dirty and \"force\" flag is not set!"); + return -EINVAL; } - clear_mount_options(&old_opts); - - ntfs_info(sb, "re-mounted. Opts: %s", orig_data); - err = 0; - goto out; - -restore_opts: - clear_mount_options(sbi->options); - memcpy(sbi->options, &old_opts, sizeof(old_opts)); + memcpy(sbi->options, new_opts, sizeof(*new_opts)); -out: - kfree(orig_data); - return err; + return 0; } static struct kmem_cache *ntfs_inode_cachep; @@ -506,9 +475,6 @@ static noinline void put_ntfs(struct ntfs_sb_info *sbi) xpress_free_decompressor(sbi->compress.xpress); lzx_free_decompressor(sbi->compress.lzx); #endif - clear_mount_options(sbi->options); - kfree(sbi->options); - kfree(sbi); } @@ -519,7 +485,9 @@ static void ntfs_put_super(struct super_block *sb) /* Mark rw ntfs as clear, if possible. */ ntfs_set_state(sbi, NTFS_DIRTY_CLEAR); + put_mount_options(sbi->options); put_ntfs(sbi); + sb->s_fs_info = NULL; sync_blockdev(sb->s_bdev); } @@ -635,7 +603,6 @@ static const struct super_operations ntfs_sops = { .statfs = ntfs_statfs, .show_options = ntfs_show_options, .sync_fs = ntfs_sync_fs, - .remount_fs = ntfs_remount, .write_inode = ntfs3_write_inode, }; @@ -905,10 +872,10 @@ out: /* * ntfs_fill_super - Try to mount. */ -static int ntfs_fill_super(struct super_block *sb, void *data, int silent) +static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) { int err; - struct ntfs_sb_info *sbi; + struct ntfs_sb_info *sbi = sb->s_fs_info; struct block_device *bdev = sb->s_bdev; struct inode *bd_inode = bdev->bd_inode; struct request_queue *rq = bdev_get_queue(bdev); @@ -927,17 +894,6 @@ static int ntfs_fill_super(struct super_block *sb, void *data, int silent) ref.high = 0; - sbi = kzalloc(sizeof(struct ntfs_sb_info), GFP_NOFS); - if (!sbi) - return -ENOMEM; - - sbi->options = kzalloc(sizeof(struct ntfs_mount_options), GFP_NOFS); - if (!sbi->options) { - kfree(sbi); - return -ENOMEM; - } - - sb->s_fs_info = sbi; sbi->sb = sb; sb->s_flags |= SB_NODIRATIME; sb->s_magic = 0x7366746e; // "ntfs" @@ -949,9 +905,12 @@ static int ntfs_fill_super(struct super_block *sb, void *data, int silent) ratelimit_state_init(&sbi->msg_ratelimit, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); - err = ntfs_parse_options(sb, data, silent, sbi->options); - if (err) - goto out; + sbi->options->nls = ntfs_load_nls(sbi->options->nls_name); + if (IS_ERR(sbi->options->nls)) { + sbi->options->nls = NULL; + errorf(fc, "Cannot load nls %s", sbi->options->nls_name); + return -EINVAL; + } if (!rq || !blk_queue_discard(rq) || !rq->limits.discard_granularity) { ; @@ -1344,6 +1303,9 @@ load_root: goto out; } + fc->fs_private = NULL; + fc->s_fs_info = NULL; + return 0; out: @@ -1354,9 +1316,6 @@ out: sb->s_root = NULL; } - put_ntfs(sbi); - - sb->s_fs_info = NULL; return err; } @@ -1426,19 +1385,83 @@ int ntfs_discard(struct ntfs_sb_info *sbi, CLST lcn, CLST len) return err; } -static struct dentry *ntfs_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) +static int ntfs_fs_get_tree(struct fs_context *fc) +{ + return get_tree_bdev(fc, ntfs_fill_super); +} + +/* + * ntfs_fs_free - Free fs_context. + * + * Note that this will be called after fill_super and reconfigure + * even when they pass. So they have to take pointers if they pass. + */ +static void ntfs_fs_free(struct fs_context *fc) +{ + struct ntfs_mount_options *opts = fc->fs_private; + struct ntfs_sb_info *sbi = fc->s_fs_info; + + if (sbi) + put_ntfs(sbi); + + if (opts) + put_mount_options(opts); +} + +static const struct fs_context_operations ntfs_context_ops = { + .parse_param = ntfs_fs_parse_param, + .get_tree = ntfs_fs_get_tree, + .reconfigure = ntfs_fs_reconfigure, + .free = ntfs_fs_free, +}; + +/* + * ntfs_init_fs_context - Initialize spi and opts + * + * This will called when mount/remount. We will first initiliaze + * options so that if remount we can use just that. + */ +static int ntfs_init_fs_context(struct fs_context *fc) { - return mount_bdev(fs_type, flags, dev_name, data, ntfs_fill_super); + struct ntfs_mount_options *opts; + struct ntfs_sb_info *sbi; + + opts = kzalloc(sizeof(struct ntfs_mount_options), GFP_NOFS); + if (!opts) + return -ENOMEM; + + /* Default options. */ + opts->fs_uid = current_uid(); + opts->fs_gid = current_gid(); + opts->fs_fmask_inv = ~current_umask(); + opts->fs_dmask_inv = ~current_umask(); + + if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) + goto ok; + + sbi = kzalloc(sizeof(struct ntfs_sb_info), GFP_NOFS); + if (!sbi) { + kfree(opts); + return -ENOMEM; + } + + sbi->options = opts; + fc->s_fs_info = sbi; +ok: + fc->fs_private = opts; + fc->ops = &ntfs_context_ops; + + return 0; } // clang-format off static struct file_system_type ntfs_fs_type = { - .owner = THIS_MODULE, - .name = "ntfs3", - .mount = ntfs_mount, - .kill_sb = kill_block_super, - .fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP, + .owner = THIS_MODULE, + .name = "ntfs3", + .init_fs_context = ntfs_init_fs_context, + .parameters = ntfs_fs_parameters, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP, }; // clang-format on -- cgit From 27fac77707a1d99deef33fd5f3f5f2ed96bfbf6a Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 18:35:53 +0300 Subject: fs/ntfs3: Init spi more in init_fs_context than fill_super init_fs_context() is meant to initialize s_fs_info (spi). Move spi initializing code there which we can initialize before fill_super(). Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index befa78d3cb26..420cd1409170 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -887,7 +887,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) const struct VOLUME_INFO *info; u32 idx, done, bytes; struct ATTR_DEF_ENTRY *t; - u16 *upcase = NULL; + u16 *upcase; u16 *shared; bool is_ro; struct MFT_REF ref; @@ -902,9 +902,6 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_time_gran = NTFS_TIME_GRAN; // 100 nsec sb->s_xattr = ntfs_xattr_handlers; - ratelimit_state_init(&sbi->msg_ratelimit, DEFAULT_RATELIMIT_INTERVAL, - DEFAULT_RATELIMIT_BURST); - sbi->options->nls = ntfs_load_nls(sbi->options->nls_name); if (IS_ERR(sbi->options->nls)) { sbi->options->nls = NULL; @@ -934,12 +931,6 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_maxbytes = 0xFFFFFFFFull << sbi->cluster_bits; #endif - mutex_init(&sbi->compress.mtx_lznt); -#ifdef CONFIG_NTFS3_LZX_XPRESS - mutex_init(&sbi->compress.mtx_xpress); - mutex_init(&sbi->compress.mtx_lzx); -#endif - /* * Load $Volume. This should be done before $LogFile * 'cause 'sbi->volume.ni' is used 'ntfs_set_state'. @@ -1224,11 +1215,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) goto out; } - sbi->upcase = upcase = kvmalloc(0x10000 * sizeof(short), GFP_KERNEL); - if (!upcase) { - err = -ENOMEM; - goto out; - } + upcase = sbi->upcase; for (idx = 0; idx < (0x10000 * sizeof(short) >> PAGE_SHIFT); idx++) { const __le16 *src; @@ -1440,10 +1427,21 @@ static int ntfs_init_fs_context(struct fs_context *fc) goto ok; sbi = kzalloc(sizeof(struct ntfs_sb_info), GFP_NOFS); - if (!sbi) { - kfree(opts); - return -ENOMEM; - } + if (!sbi) + goto free_opts; + + sbi->upcase = kvmalloc(0x10000 * sizeof(short), GFP_KERNEL); + if (!sbi->upcase) + goto free_sbi; + + ratelimit_state_init(&sbi->msg_ratelimit, DEFAULT_RATELIMIT_INTERVAL, + DEFAULT_RATELIMIT_BURST); + + mutex_init(&sbi->compress.mtx_lznt); +#ifdef CONFIG_NTFS3_LZX_XPRESS + mutex_init(&sbi->compress.mtx_xpress); + mutex_init(&sbi->compress.mtx_lzx); +#endif sbi->options = opts; fc->s_fs_info = sbi; @@ -1452,6 +1450,11 @@ ok: fc->ops = &ntfs_context_ops; return 0; +free_opts: + kfree(opts); +free_sbi: + kfree(sbi); + return -ENOMEM; } // clang-format off -- cgit From 9d1939f4575f3fda70dd94542dbd4d775e104132 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 18:35:54 +0300 Subject: fs/ntfs3: Make mount option nohidden more universal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we call Opt_nohidden with just keyword hidden, then we can use hidden/nohidden when mounting. We already use this method for almoust all other parameters so it is just logical that this will use same method. Acked-by: Christian Brauner Reviewed-by: Christoph Hellwig Reviewed-by: Pali Rohár Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 420cd1409170..729ead6f2fac 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -242,7 +242,7 @@ static const struct fs_parameter_spec ntfs_fs_parameters[] = { fsparam_flag_no("discard", Opt_discard), fsparam_flag_no("force", Opt_force), fsparam_flag_no("sparse", Opt_sparse), - fsparam_flag("nohidden", Opt_nohidden), + fsparam_flag_no("hidden", Opt_nohidden), fsparam_flag_no("acl", Opt_acl), fsparam_flag_no("showmeta", Opt_showmeta), fsparam_string("nls", Opt_nls), @@ -331,7 +331,7 @@ static int ntfs_fs_parse_param(struct fs_context *fc, opts->sparse = result.negated ? 0 : 1; break; case Opt_nohidden: - opts->nohidden = 1; + opts->nohidden = result.negated ? 1 : 0; break; case Opt_acl: if (!result.negated) -- cgit From e274cde8c7550cac46eb7aba3a77aff44ae0b301 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 18:35:55 +0300 Subject: fs/ntfs3: Add iocharset= mount option as alias for nls= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Other fs drivers are using iocharset= mount option for specifying charset. So add it also for ntfs3 and mark old nls= mount option as deprecated. Reviewed-by: Pali Rohár Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- Documentation/filesystems/ntfs3.rst | 4 ++-- fs/ntfs3/super.c | 18 +++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Documentation/filesystems/ntfs3.rst b/Documentation/filesystems/ntfs3.rst index af7158de6fde..ded706474825 100644 --- a/Documentation/filesystems/ntfs3.rst +++ b/Documentation/filesystems/ntfs3.rst @@ -32,12 +32,12 @@ generic ones. =============================================================================== -nls=name This option informs the driver how to interpret path +iocharset=name This option informs the driver how to interpret path strings and translate them to Unicode and back. If this option is not set, the default codepage will be used (CONFIG_NLS_DEFAULT). Examples: - 'nls=utf8' + 'iocharset=utf8' uid= gid= diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 729ead6f2fac..503e2e23f711 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -226,7 +226,7 @@ enum Opt { Opt_nohidden, Opt_showmeta, Opt_acl, - Opt_nls, + Opt_iocharset, Opt_prealloc, Opt_no_acs_rules, Opt_err, @@ -245,9 +245,13 @@ static const struct fs_parameter_spec ntfs_fs_parameters[] = { fsparam_flag_no("hidden", Opt_nohidden), fsparam_flag_no("acl", Opt_acl), fsparam_flag_no("showmeta", Opt_showmeta), - fsparam_string("nls", Opt_nls), fsparam_flag_no("prealloc", Opt_prealloc), fsparam_flag("no_acs_rules", Opt_no_acs_rules), + fsparam_string("iocharset", Opt_iocharset), + + __fsparam(fs_param_is_string, + "nls", Opt_iocharset, + fs_param_deprecated, NULL), {} }; @@ -346,7 +350,7 @@ static int ntfs_fs_parse_param(struct fs_context *fc, case Opt_showmeta: opts->showmeta = result.negated ? 0 : 1; break; - case Opt_nls: + case Opt_iocharset: kfree(opts->nls_name); opts->nls_name = param->string; param->string = NULL; @@ -380,11 +384,11 @@ static int ntfs_fs_reconfigure(struct fs_context *fc) new_opts->nls = ntfs_load_nls(new_opts->nls_name); if (IS_ERR(new_opts->nls)) { new_opts->nls = NULL; - errorf(fc, "ntfs3: Cannot load nls %s", new_opts->nls_name); + errorf(fc, "ntfs3: Cannot load iocharset %s", new_opts->nls_name); return -EINVAL; } if (new_opts->nls != sbi->options->nls) - return invalf(fc, "ntfs3: Cannot use different nls when remounting!"); + return invalf(fc, "ntfs3: Cannot use different iocharset when remounting!"); sync_filesystem(sb); @@ -528,9 +532,9 @@ static int ntfs_show_options(struct seq_file *m, struct dentry *root) if (opts->dmask) seq_printf(m, ",dmask=%04o", ~opts->fs_dmask_inv); if (opts->nls) - seq_printf(m, ",nls=%s", opts->nls->charset); + seq_printf(m, ",iocharset=%s", opts->nls->charset); else - seq_puts(m, ",nls=utf8"); + seq_puts(m, ",iocharset=utf8"); if (opts->sys_immutable) seq_puts(m, ",sys_immutable"); if (opts->discard) -- cgit From 28a941ffc1404b66d67228cbe8392bbadb94af0d Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 18:35:56 +0300 Subject: fs/ntfs3: Rename mount option no_acs_rules > (no)acsrules Rename mount option no_acs_rules to (no)acsrules. This allow us to use possibility to mount with options noaclrules or aclrules. Acked-by: Christian Brauner Reviewed-by: Christoph Hellwig Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- Documentation/filesystems/ntfs3.rst | 2 +- fs/ntfs3/file.c | 2 +- fs/ntfs3/ntfs_fs.h | 2 +- fs/ntfs3/super.c | 12 ++++++------ fs/ntfs3/xattr.c | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Documentation/filesystems/ntfs3.rst b/Documentation/filesystems/ntfs3.rst index ded706474825..7b6afe452197 100644 --- a/Documentation/filesystems/ntfs3.rst +++ b/Documentation/filesystems/ntfs3.rst @@ -73,7 +73,7 @@ prealloc Preallocate space for files excessively when file size is increasing on writes. Decreases fragmentation in case of parallel write operations to different files. -no_acs_rules "No access rules" mount option sets access rights for +noacsrules "No access rules" mount option sets access rights for files/folders to 777 and owner/group to root. This mount option absorbs all other permissions: - permissions change for files/folders will be reported diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index fef57141b161..0743d806c567 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -737,7 +737,7 @@ int ntfs3_setattr(struct user_namespace *mnt_userns, struct dentry *dentry, umode_t mode = inode->i_mode; int err; - if (sbi->options->no_acs_rules) { + if (sbi->options->noacsrules) { /* "No access rules" - Force any changes of time etc. */ attr->ia_valid |= ATTR_FORCE; /* and disable for editing some attributes. */ diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index aa18f12b7096..15bab48bc1ad 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -70,7 +70,7 @@ struct ntfs_mount_options { showmeta : 1, /* Show meta files. */ nohidden : 1, /* Do not show hidden files. */ force : 1, /* Rw mount dirty volume. */ - no_acs_rules : 1, /*Exclude acs rules. */ + noacsrules : 1, /*Exclude acs rules. */ prealloc : 1 /* Preallocate space when file is growing. */ ; }; diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 503e2e23f711..0690e7e4f00d 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -228,7 +228,7 @@ enum Opt { Opt_acl, Opt_iocharset, Opt_prealloc, - Opt_no_acs_rules, + Opt_noacsrules, Opt_err, }; @@ -246,7 +246,7 @@ static const struct fs_parameter_spec ntfs_fs_parameters[] = { fsparam_flag_no("acl", Opt_acl), fsparam_flag_no("showmeta", Opt_showmeta), fsparam_flag_no("prealloc", Opt_prealloc), - fsparam_flag("no_acs_rules", Opt_no_acs_rules), + fsparam_flag_no("acsrules", Opt_noacsrules), fsparam_string("iocharset", Opt_iocharset), __fsparam(fs_param_is_string, @@ -358,8 +358,8 @@ static int ntfs_fs_parse_param(struct fs_context *fc, case Opt_prealloc: opts->prealloc = result.negated ? 0 : 1; break; - case Opt_no_acs_rules: - opts->no_acs_rules = 1; + case Opt_noacsrules: + opts->noacsrules = result.negated ? 1 : 0; break; default: /* Should not be here unless we forget add case. */ @@ -547,8 +547,8 @@ static int ntfs_show_options(struct seq_file *m, struct dentry *root) seq_puts(m, ",nohidden"); if (opts->force) seq_puts(m, ",force"); - if (opts->no_acs_rules) - seq_puts(m, ",no_acs_rules"); + if (opts->noacsrules) + seq_puts(m, ",noacsrules"); if (opts->prealloc) seq_puts(m, ",prealloc"); if (sb->s_flags & SB_POSIXACL) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index ac4b37bf8832..6f88cb77a17f 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -769,7 +769,7 @@ int ntfs_acl_chmod(struct user_namespace *mnt_userns, struct inode *inode) int ntfs_permission(struct user_namespace *mnt_userns, struct inode *inode, int mask) { - if (ntfs_sb(inode->i_sb)->options->no_acs_rules) { + if (ntfs_sb(inode->i_sb)->options->noacsrules) { /* "No access rules" mode - Allow all changes. */ return 0; } -- cgit From 15b2ae776044ac52cddda8a3e6c9fecd15226b8c Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 18:35:57 +0300 Subject: fs/ntfs3: Show uid/gid always in show_options() Show options should show option according documentation when some value is not default or when ever coder wants. Uid/gid are problematic because it is hard to know which are defaults. In file system there is many different implementation for this problem. Some file systems show uid/gid when they are different than root, some when user has set them and some show them always. There is also problem that what if root uid/gid change. This code just choose to show them always. This way we do not need to think this any more. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/ntfs_fs.h | 23 ++++++++++------------- fs/ntfs3/super.c | 12 ++++-------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 15bab48bc1ad..372cda697dd4 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -60,19 +60,16 @@ struct ntfs_mount_options { u16 fs_fmask_inv; u16 fs_dmask_inv; - unsigned uid : 1, /* uid was set. */ - gid : 1, /* gid was set. */ - fmask : 1, /* fmask was set. */ - dmask : 1, /* dmask was set. */ - sys_immutable : 1, /* Immutable system files. */ - discard : 1, /* Issue discard requests on deletions. */ - sparse : 1, /* Create sparse files. */ - showmeta : 1, /* Show meta files. */ - nohidden : 1, /* Do not show hidden files. */ - force : 1, /* Rw mount dirty volume. */ - noacsrules : 1, /*Exclude acs rules. */ - prealloc : 1 /* Preallocate space when file is growing. */ - ; + unsigned fmask : 1; /* fmask was set. */ + unsigned dmask : 1; /*dmask was set. */ + unsigned sys_immutable : 1; /* Immutable system files. */ + unsigned discard : 1; /* Issue discard requests on deletions. */ + unsigned sparse : 1; /* Create sparse files. */ + unsigned showmeta : 1; /* Show meta files. */ + unsigned nohidden : 1; /* Do not show hidden files. */ + unsigned force : 1; /* RW mount dirty volume. */ + unsigned noacsrules : 1; /* Exclude acs rules. */ + unsigned prealloc : 1; /* Preallocate space when file is growing. */ }; /* Special value to unpack and deallocate. */ diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 0690e7e4f00d..3cba0b5e7ac7 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -294,13 +294,11 @@ static int ntfs_fs_parse_param(struct fs_context *fc, opts->fs_uid = make_kuid(current_user_ns(), result.uint_32); if (!uid_valid(opts->fs_uid)) return invalf(fc, "ntfs3: Invalid value for uid."); - opts->uid = 1; break; case Opt_gid: opts->fs_gid = make_kgid(current_user_ns(), result.uint_32); if (!gid_valid(opts->fs_gid)) return invalf(fc, "ntfs3: Invalid value for gid."); - opts->gid = 1; break; case Opt_umask: if (result.uint_32 & ~07777) @@ -521,12 +519,10 @@ static int ntfs_show_options(struct seq_file *m, struct dentry *root) struct ntfs_mount_options *opts = sbi->options; struct user_namespace *user_ns = seq_user_ns(m); - if (opts->uid) - seq_printf(m, ",uid=%u", - from_kuid_munged(user_ns, opts->fs_uid)); - if (opts->gid) - seq_printf(m, ",gid=%u", - from_kgid_munged(user_ns, opts->fs_gid)); + seq_printf(m, ",uid=%u", + from_kuid_munged(user_ns, opts->fs_uid)); + seq_printf(m, ",gid=%u", + from_kgid_munged(user_ns, opts->fs_gid)); if (opts->fmask) seq_printf(m, ",fmask=%04o", ~opts->fs_fmask_inv); if (opts->dmask) -- cgit From 0327c6d01a97a3242cf10717819994aa6e095a1d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 3 Sep 2021 14:24:58 +0100 Subject: fs/ntfs3: Remove redundant initialization of variable err The variable err is being initialized with a value that is never read, it is being updated later on. The assignment is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Reviewed-by: Kari Argillander 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 0daca9adc54c..b1175542d854 100644 --- a/fs/ntfs3/index.c +++ b/fs/ntfs3/index.c @@ -1401,7 +1401,7 @@ ok: static int indx_create_allocate(struct ntfs_index *indx, struct ntfs_inode *ni, CLST *vbn) { - int err = -ENOMEM; + int err; struct ntfs_sb_info *sbi = ni->mi.sbi; struct ATTRIB *bitmap; struct ATTRIB *alloc; -- cgit From cde81f13ef63d47c3f0742fbe6f17a5123cf6ca4 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 2 Sep 2021 19:15:21 +0300 Subject: fs/ntfs3. Add forward declarations for structs to debug.h Add forward declarations for structs so that we can include this file without warnings even without linux/fs.h Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/debug.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/ntfs3/debug.h b/fs/ntfs3/debug.h index 31120569a87b..53ef7489c75f 100644 --- a/fs/ntfs3/debug.h +++ b/fs/ntfs3/debug.h @@ -11,6 +11,9 @@ #ifndef _LINUX_NTFS3_DEBUG_H #define _LINUX_NTFS3_DEBUG_H +struct super_block; +struct inode; + #ifndef Add2Ptr #define Add2Ptr(P, I) ((void *)((u8 *)(P) + (I))) #define PtrOffset(B, O) ((size_t)((size_t)(O) - (size_t)(B))) -- cgit From 4dfe83320e1e9665b986840b426742ea764e08d7 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 2 Sep 2021 19:15:22 +0300 Subject: fs/ntfs3: Add missing header files to ntfs.h We do not have header files at all in this file. Add following headers and there is also explanation which for it was added. Note that explanation might not be complete, but it just proofs it is needed. // SECTOR_SHIFT // static_assert() // cpu_to_le64, cpu_to_le32, ALIGN // offsetof() // memcmp() //__le32, __le16 "debug.h" // PtrOffset(), Add2Ptr() Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/ntfs.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/ntfs3/ntfs.h b/fs/ntfs3/ntfs.h index 6bb3e595263b..695b684bce20 100644 --- a/fs/ntfs3/ntfs.h +++ b/fs/ntfs3/ntfs.h @@ -10,6 +10,15 @@ #ifndef _LINUX_NTFS3_NTFS_H #define _LINUX_NTFS3_NTFS_H +#include +#include +#include +#include +#include +#include + +#include "debug.h" + /* TODO: Check 4K MFT record and 512 bytes cluster. */ /* Activate this define to use binary search in indexes. */ -- cgit From f239b3a95dd4f7daba26ea17f339a5b19a7d40a1 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 2 Sep 2021 19:15:23 +0300 Subject: fs/ntfs3: Add missing headers and forward declarations to ntfs_fs.h We do not have headers at all in this file. We should have them so that not every .c file needs to include all of the stuff which this file need for building. This way we can remove some headers from other files and get better picture what is needed. This can save some compilation time. And this can help if we sometimes want to separate this one big header. Also use forward declarations for structs and enums when it not included straight with include and it is used in function declarations input. This will prevent possible compiler warning: xxx declared inside parameter list will not be visible outside of this definition or declaration Here is list which I made when parsing this. There is not necessarily all example from this header file, but this just proofs we need it. SECTOR_SHIFT sb_bread(), put_bh put_page() struct inode (Just struct ntfs_inode need it) kunmap(), kmap() cpu_to_leXX() ALIGN kvfree() struct mutex, mutex_(un/try)lock() PageError() read_mapping_page() struct rb_root struct rw_semaphore krfree(), kzalloc() memset() struct timespec64 uXX, __leXX kuid_t, kgid_t do_div() PAGE_SIZE "debug.h" ntfs_err() (Just one entry. Maybe we can drop this) "ntfs.h" Do you even ask? Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/ntfs_fs.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 372cda697dd4..dae6dd4ac619 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -9,6 +9,37 @@ #ifndef _LINUX_NTFS3_NTFS_FS_H #define _LINUX_NTFS3_NTFS_FS_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "ntfs.h" + +struct dentry; +struct fiemap_extent_info; +struct user_namespace; +struct page; +struct writeback_control; +enum utf16_endian; + + #define MINUS_ONE_T ((size_t)(-1)) /* Biggest MFT / smallest cluster */ #define MAXIMUM_BYTES_PER_MFT 4096 -- cgit From b6ba81034b1b74cf426abcece4becda2611504a4 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 2 Sep 2021 19:15:24 +0300 Subject: fs/ntfs3: Add missing header and guards to lib/ headers size_t needs header. Add missing header guards so that compiler will only include these ones. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/lib/decompress_common.h | 5 +++++ fs/ntfs3/lib/lib.h | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/fs/ntfs3/lib/decompress_common.h b/fs/ntfs3/lib/decompress_common.h index 2d70ae42f1b5..dd7ced000d0e 100644 --- a/fs/ntfs3/lib/decompress_common.h +++ b/fs/ntfs3/lib/decompress_common.h @@ -5,6 +5,9 @@ * Copyright (C) 2015 Eric Biggers */ +#ifndef _LINUX_NTFS3_LIB_DECOMPRESS_COMMON_H +#define _LINUX_NTFS3_LIB_DECOMPRESS_COMMON_H + #include #include #include @@ -336,3 +339,5 @@ static forceinline u8 *lz_copy(u8 *dst, u32 length, u32 offset, const u8 *bufend return dst; } + +#endif /* _LINUX_NTFS3_LIB_DECOMPRESS_COMMON_H */ diff --git a/fs/ntfs3/lib/lib.h b/fs/ntfs3/lib/lib.h index f508fbad2e71..90309a5ae59c 100644 --- a/fs/ntfs3/lib/lib.h +++ b/fs/ntfs3/lib/lib.h @@ -7,6 +7,10 @@ * - linux kernel code style */ +#ifndef _LINUX_NTFS3_LIB_LIB_H +#define _LINUX_NTFS3_LIB_LIB_H + +#include /* globals from xpress_decompress.c */ struct xpress_decompressor *xpress_allocate_decompressor(void); @@ -24,3 +28,5 @@ int lzx_decompress(struct lzx_decompressor *__restrict d, const void *__restrict compressed_data, size_t compressed_size, void *__restrict uncompressed_data, size_t uncompressed_size); + +#endif /* _LINUX_NTFS3_LIB_LIB_H */ -- cgit From c632f639d1d9bb3e379741a30c6882342d859daf Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 2 Sep 2021 19:15:25 +0300 Subject: fs/ntfs3: Change right headers to bitfunc.c We only need linux/types.h for types like u8 etc. So we can remove rest and help compiler a little bit. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/bitfunc.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/fs/ntfs3/bitfunc.c b/fs/ntfs3/bitfunc.c index ce304d40b5e1..bf10e2da5c6e 100644 --- a/fs/ntfs3/bitfunc.c +++ b/fs/ntfs3/bitfunc.c @@ -5,13 +5,8 @@ * */ -#include -#include -#include -#include +#include -#include "debug.h" -#include "ntfs.h" #include "ntfs_fs.h" #define BITS_IN_SIZE_T (sizeof(size_t) * 8) -- cgit From f97676611937f4550a60970acadeccbd5e6f124c Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 2 Sep 2021 19:15:26 +0300 Subject: fs/ntfs3: Change right headers to upcase.c There is no headers. They will be included through ntfs_fs.c, but that is not right thing to do. Let's include headers what this file need straight away. types.h is needed for __le16, u8 etc. kernel.h is needed for le16_to_cpu() Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/upcase.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/fs/ntfs3/upcase.c b/fs/ntfs3/upcase.c index bbeba778237e..b5e8256fd710 100644 --- a/fs/ntfs3/upcase.c +++ b/fs/ntfs3/upcase.c @@ -5,13 +5,9 @@ * */ -#include -#include -#include -#include +#include +#include -#include "debug.h" -#include "ntfs.h" #include "ntfs_fs.h" static inline u16 upcase_unicode_char(const u16 *upcase, u16 chr) -- cgit From 977d0558e310113767feed91fdcc618691dd2835 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 2 Sep 2021 19:15:27 +0300 Subject: fs/ntfs3: Change right headers to lznt.c There is lot of headers which we do not need in this file. Delete them and add what we really need. Here is list which identify why we need this header. // min() // kzalloc() // offsetof() // memcpy(), memset() // u8, size_t, etc. "debug.h" // PtrOffset() Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/lznt.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/ntfs3/lznt.c b/fs/ntfs3/lznt.c index f1f691a67cc4..12ba42518efe 100644 --- a/fs/ntfs3/lznt.c +++ b/fs/ntfs3/lznt.c @@ -5,13 +5,13 @@ * */ -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "debug.h" -#include "ntfs.h" #include "ntfs_fs.h" // clang-format off -- cgit From 9c2aadd0fdf88a7ebeebd1e97a9c66b07ad3e14a Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 2 Sep 2021 19:15:28 +0300 Subject: fs/ntfs3: Remove unneeded header files from c files We have lot of unnecessary headers in these files. Remove them so that we help compiler a little bit. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 5 ----- fs/ntfs3/attrlist.c | 3 --- fs/ntfs3/bitmap.c | 3 --- fs/ntfs3/dir.c | 3 --- fs/ntfs3/file.c | 1 - fs/ntfs3/frecord.c | 3 --- fs/ntfs3/fslog.c | 4 ---- fs/ntfs3/fsntfs.c | 1 - fs/ntfs3/index.c | 1 - fs/ntfs3/inode.c | 2 -- fs/ntfs3/namei.c | 4 ---- fs/ntfs3/record.c | 3 --- fs/ntfs3/run.c | 2 -- fs/ntfs3/super.c | 2 -- fs/ntfs3/xattr.c | 3 --- 15 files changed, 40 deletions(-) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index b1055b284c60..12cff28f3e71 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -6,12 +6,7 @@ * TODO: Merge attr_set_size/attr_data_get_block/attr_allocate_frame? */ -#include -#include #include -#include -#include -#include #include #include "debug.h" diff --git a/fs/ntfs3/attrlist.c b/fs/ntfs3/attrlist.c index fa32399eb517..b9da527b96aa 100644 --- a/fs/ntfs3/attrlist.c +++ b/fs/ntfs3/attrlist.c @@ -5,10 +5,7 @@ * */ -#include -#include #include -#include #include "debug.h" #include "ntfs.h" diff --git a/fs/ntfs3/bitmap.c b/fs/ntfs3/bitmap.c index 831501555009..a03584674fea 100644 --- a/fs/ntfs3/bitmap.c +++ b/fs/ntfs3/bitmap.c @@ -10,12 +10,9 @@ * */ -#include #include #include -#include -#include "debug.h" #include "ntfs.h" #include "ntfs_fs.h" diff --git a/fs/ntfs3/dir.c b/fs/ntfs3/dir.c index 40440df021ef..785e72d4392e 100644 --- a/fs/ntfs3/dir.c +++ b/fs/ntfs3/dir.c @@ -7,10 +7,7 @@ * */ -#include -#include #include -#include #include #include "debug.h" diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 0743d806c567..5fb3508e5422 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -12,7 +12,6 @@ #include #include #include -#include #include "debug.h" #include "ntfs.h" diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index 938b12d56ca6..080264ced909 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -5,11 +5,8 @@ * */ -#include -#include #include #include -#include #include #include "debug.h" diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c index b5853aed0e25..6e7f9b72792b 100644 --- a/fs/ntfs3/fslog.c +++ b/fs/ntfs3/fslog.c @@ -6,12 +6,8 @@ */ #include -#include #include -#include -#include #include -#include #include #include "debug.h" diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c index 91e3743e1442..9232a7f410c6 100644 --- a/fs/ntfs3/fsntfs.c +++ b/fs/ntfs3/fsntfs.c @@ -8,7 +8,6 @@ #include #include #include -#include #include "debug.h" #include "ntfs.h" diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c index b1175542d854..35b77c92e96d 100644 --- a/fs/ntfs3/index.c +++ b/fs/ntfs3/index.c @@ -8,7 +8,6 @@ #include #include #include -#include #include "debug.h" #include "ntfs.h" diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 9f740fd301b2..33f278a0947c 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -5,10 +5,8 @@ * */ -#include #include #include -#include #include #include #include diff --git a/fs/ntfs3/namei.c b/fs/ntfs3/namei.c index e58415d07132..1c475da4e19d 100644 --- a/fs/ntfs3/namei.c +++ b/fs/ntfs3/namei.c @@ -5,11 +5,7 @@ * */ -#include -#include #include -#include -#include #include #include "debug.h" diff --git a/fs/ntfs3/record.c b/fs/ntfs3/record.c index 103705c86772..861e35791506 100644 --- a/fs/ntfs3/record.c +++ b/fs/ntfs3/record.c @@ -5,10 +5,7 @@ * */ -#include -#include #include -#include #include "debug.h" #include "ntfs.h" diff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 26ed2b64345e..a8fec651f973 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -7,10 +7,8 @@ */ #include -#include #include #include -#include #include "debug.h" #include "ntfs.h" diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 3cba0b5e7ac7..acfa00acf4dd 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -23,14 +23,12 @@ * */ -#include #include #include #include #include #include #include -#include #include #include #include diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index 6f88cb77a17f..a8c5a899f0dd 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -5,10 +5,7 @@ * */ -#include -#include #include -#include #include #include #include -- cgit From 162333efa8dc4984d2ca0a2eb85528e13366f271 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 2 Sep 2021 18:40:48 +0300 Subject: fs/ntfs3: Limit binary search table size Current binary search allocates memory for table and fill whole table before we start actual binary search. This is quite inefficient because table fill will always be O(n). Also if table is huge we need to reallocate memory which is costly. This implementation use just stack memory and always when table is full we will check if last element is <= and if not start table fill again. The idea was that it would be same cost as table reallocation. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/index.c | 110 +++++++++++++++++++++---------------------------------- 1 file changed, 41 insertions(+), 69 deletions(-) diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c index 35b77c92e96d..a16256ab3e9f 100644 --- a/fs/ntfs3/index.c +++ b/fs/ntfs3/index.c @@ -677,98 +677,70 @@ static struct NTFS_DE *hdr_find_e(const struct ntfs_index *indx, u32 off = le32_to_cpu(hdr->de_off); #ifdef NTFS3_INDEX_BINARY_SEARCH - int max_idx = 0, fnd, min_idx; - int nslots = 64; - u16 *offs; + struct NTFS_DE *found = NULL; + int min_idx = 0, mid_idx, max_idx = 0; + int diff2; + u16 offs[64]; if (end > 0x10000) goto next; - offs = kmalloc(sizeof(u16) * nslots, GFP_NOFS); - if (!offs) - goto next; +fill_table: + if (off + sizeof(struct NTFS_DE) > end) + return NULL; - /* Use binary search algorithm. */ -next1: - if (off + sizeof(struct NTFS_DE) > end) { - e = NULL; - goto out1; - } e = Add2Ptr(hdr, off); e_size = le16_to_cpu(e->size); - if (e_size < sizeof(struct NTFS_DE) || off + e_size > end) { - e = NULL; - goto out1; - } - - if (max_idx >= nslots) { - u16 *ptr; - int new_slots = ALIGN(2 * nslots, 8); - - ptr = kmalloc(sizeof(u16) * new_slots, GFP_NOFS); - if (ptr) - memcpy(ptr, offs, sizeof(u16) * max_idx); - kfree(offs); - offs = ptr; - nslots = new_slots; - if (!ptr) - goto next; - } - - /* Store entry table. */ - offs[max_idx] = off; + if (e_size < sizeof(struct NTFS_DE) || off + e_size > end) + return NULL; if (!de_is_last(e)) { + offs[max_idx] = off; off += e_size; - max_idx += 1; - goto next1; - } - /* - * Table of pointers is created. - * Use binary search to find entry that is <= to the search value. - */ - fnd = -1; - min_idx = 0; + max_idx++; + if (max_idx < ARRAY_SIZE(offs)) + goto fill_table; - while (min_idx <= max_idx) { - int mid_idx = min_idx + ((max_idx - min_idx) >> 1); - int diff2; - - e = Add2Ptr(hdr, offs[mid_idx]); + max_idx--; + } - e_key_len = le16_to_cpu(e->key_size); +binary_search: + e_key_len = le16_to_cpu(e->key_size); - diff2 = (*cmp)(key, key_len, e + 1, e_key_len, ctx); + diff2 = (*cmp)(key, key_len, e + 1, e_key_len, ctx); + if (diff2 > 0) { + if (found) { + min_idx = mid_idx + 1; + } else { + if (de_is_last(e)) + return NULL; - if (!diff2) { - *diff = 0; - goto out1; + max_idx = 0; + goto fill_table; } - - if (diff2 < 0) { + } else if (diff2 < 0) { + if (found) max_idx = mid_idx - 1; - fnd = mid_idx; - if (!fnd) - break; - } else { - min_idx = mid_idx + 1; - } - } + else + max_idx--; - if (fnd == -1) { - e = NULL; - goto out1; + found = e; + } else { + *diff = 0; + return e; } - *diff = -1; - e = Add2Ptr(hdr, offs[fnd]); + if (min_idx > max_idx) { + *diff = -1; + return found; + } -out1: - kfree(offs); + mid_idx = (min_idx + max_idx) >> 1; + e = Add2Ptr(hdr, offs[mid_idx]); - return e; + goto binary_search; #endif next: -- cgit From ef9297007e9904588682699e618c56401f61d1c2 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 2 Sep 2021 18:40:49 +0300 Subject: fs/ntfs3: Make binary search to search smaller chunks in beginning We could try to optimize algorithm to first fill just small table and after that use bigger table all the way up to ARRAY_SIZE(offs). This way we can use bigger search array, but not lose benefits with entry count smaller < ARRAY_SIZE(offs). Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/index.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c index a16256ab3e9f..3ad1ee608e53 100644 --- a/fs/ntfs3/index.c +++ b/fs/ntfs3/index.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "debug.h" #include "ntfs.h" @@ -679,8 +680,9 @@ static struct NTFS_DE *hdr_find_e(const struct ntfs_index *indx, #ifdef NTFS3_INDEX_BINARY_SEARCH struct NTFS_DE *found = NULL; int min_idx = 0, mid_idx, max_idx = 0; + int table_size = 8; int diff2; - u16 offs[64]; + u16 offs[128]; if (end > 0x10000) goto next; @@ -700,7 +702,7 @@ fill_table: off += e_size; max_idx++; - if (max_idx < ARRAY_SIZE(offs)) + if (max_idx < table_size) goto fill_table; max_idx--; @@ -718,6 +720,7 @@ binary_search: return NULL; max_idx = 0; + table_size = min(table_size * 2, 128); goto fill_table; } } else if (diff2 < 0) { -- cgit From 8e69212253d320d4768071086b1111e6ab91d9bd Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 2 Sep 2021 18:40:50 +0300 Subject: fs/ntfs3: Always use binary search with entry search We do not have any reason to keep old linear search in. Before this was used for error path or if table was so big that it cannot be allocated. Current binary search implementation won't need error path. Remove old references to linear entry search. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/index.c | 50 ++++++-------------------------------------------- fs/ntfs3/ntfs.h | 3 --- 2 files changed, 6 insertions(+), 47 deletions(-) diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c index 3ad1ee608e53..4f71a91f07d9 100644 --- a/fs/ntfs3/index.c +++ b/fs/ntfs3/index.c @@ -671,22 +671,16 @@ static struct NTFS_DE *hdr_find_e(const struct ntfs_index *indx, const struct INDEX_HDR *hdr, const void *key, size_t key_len, const void *ctx, int *diff) { - struct NTFS_DE *e; + struct NTFS_DE *e, *found = NULL; NTFS_CMP_FUNC cmp = indx->cmp; + int min_idx = 0, mid_idx, max_idx = 0; + int diff2; + int table_size = 8; u32 e_size, e_key_len; u32 end = le32_to_cpu(hdr->used); u32 off = le32_to_cpu(hdr->de_off); - -#ifdef NTFS3_INDEX_BINARY_SEARCH - struct NTFS_DE *found = NULL; - int min_idx = 0, mid_idx, max_idx = 0; - int table_size = 8; - int diff2; u16 offs[128]; - if (end > 0x10000) - goto next; - fill_table: if (off + sizeof(struct NTFS_DE) > end) return NULL; @@ -720,7 +714,8 @@ binary_search: return NULL; max_idx = 0; - table_size = min(table_size * 2, 128); + table_size = min(table_size * 2, + (int)ARRAY_SIZE(offs)); goto fill_table; } } else if (diff2 < 0) { @@ -744,39 +739,6 @@ binary_search: e = Add2Ptr(hdr, offs[mid_idx]); goto binary_search; -#endif - -next: - /* - * Entries index are sorted. - * Enumerate all entries until we find entry - * that is <= to the search value. - */ - if (off + sizeof(struct NTFS_DE) > end) - return NULL; - - e = Add2Ptr(hdr, off); - e_size = le16_to_cpu(e->size); - - if (e_size < sizeof(struct NTFS_DE) || off + e_size > end) - return NULL; - - off += e_size; - - e_key_len = le16_to_cpu(e->key_size); - - *diff = (*cmp)(key, key_len, e + 1, e_key_len, ctx); - if (!*diff) - return e; - - if (*diff <= 0) - return e; - - if (de_is_last(e)) { - *diff = 1; - return e; - } - goto next; } /* diff --git a/fs/ntfs3/ntfs.h b/fs/ntfs3/ntfs.h index 695b684bce20..303a162c3158 100644 --- a/fs/ntfs3/ntfs.h +++ b/fs/ntfs3/ntfs.h @@ -21,9 +21,6 @@ /* TODO: Check 4K MFT record and 512 bytes cluster. */ -/* Activate this define to use binary search in indexes. */ -#define NTFS3_INDEX_BINARY_SEARCH - /* Check each run for marked clusters. */ #define NTFS3_CHECK_FREE_CLST -- cgit From 80f0a1f99983296be587325004acf72dd11eccd8 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Mon, 13 Sep 2021 12:02:56 +0200 Subject: workqueue: annotate alloc_workqueue() as printf This also enables checking of allows alloc_ordered_workqueue(). Signed-off-by: Rolf Eike Beer Signed-off-by: Tejun Heo --- include/linux/workqueue.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 2ebef6b1a3d6..74d3c1efd9bb 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -399,9 +399,8 @@ extern struct workqueue_struct *system_freezable_power_efficient_wq; * RETURNS: * Pointer to the allocated workqueue on success, %NULL on failure. */ -struct workqueue_struct *alloc_workqueue(const char *fmt, - unsigned int flags, - int max_active, ...); +__printf(1, 4) struct workqueue_struct * +alloc_workqueue(const char *fmt, unsigned int flags, int max_active, ...); /** * alloc_ordered_workqueue - allocate an ordered workqueue -- cgit From 22b1255792c033781dbe42b63e28501d38032b7e Mon Sep 17 00:00:00 2001 From: Chunguang Xu Date: Mon, 13 Sep 2021 13:09:14 +0800 Subject: docs/cgroup: remove some duplicate words When I tried to add some new entries to cgroup-v2.rst, I found that the description of memory.events had some repetitive words, so I tried to delete them. Signed-off-by: Chunguang Xu Signed-off-by: Tejun Heo --- Documentation/admin-guide/cgroup-v2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst index babbe04c8d37..fc53ae0e96b9 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst @@ -1226,7 +1226,7 @@ PAGE_SIZE multiple when read back. Note that all fields in this file are hierarchical and the file modified event can be generated due to an event down the - hierarchy. For for the local events at the cgroup level see + hierarchy. For the local events at the cgroup level see memory.events.local. low -- cgit From b94f9ac79a7395c2d6171cc753cc27942df0be73 Mon Sep 17 00:00:00 2001 From: Waiman Long Date: Thu, 9 Sep 2021 22:42:56 -0400 Subject: cgroup/cpuset: Change references of cpuset_mutex to cpuset_rwsem Since commit 1243dc518c9d ("cgroup/cpuset: Convert cpuset_mutex to percpu_rwsem"), cpuset_mutex has been replaced by cpuset_rwsem which is a percpu rwsem. However, the comments in kernel/cgroup/cpuset.c still reference cpuset_mutex which are now incorrect. Change all the references of cpuset_mutex to cpuset_rwsem. Fixes: 1243dc518c9d ("cgroup/cpuset: Convert cpuset_mutex to percpu_rwsem") Signed-off-by: Waiman Long Signed-off-by: Tejun Heo --- kernel/cgroup/cpuset.c | 56 ++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index df1ccf4558f8..2a9695ccb65f 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -311,17 +311,19 @@ static struct cpuset top_cpuset = { if (is_cpuset_online(((des_cs) = css_cs((pos_css))))) /* - * There are two global locks guarding cpuset structures - cpuset_mutex and + * There are two global locks guarding cpuset structures - cpuset_rwsem and * callback_lock. We also require taking task_lock() when dereferencing a * task's cpuset pointer. See "The task_lock() exception", at the end of this - * comment. + * comment. The cpuset code uses only cpuset_rwsem write lock. Other + * kernel subsystems can use cpuset_read_lock()/cpuset_read_unlock() to + * prevent change to cpuset structures. * * A task must hold both locks to modify cpusets. If a task holds - * cpuset_mutex, then it blocks others wanting that mutex, ensuring that it + * cpuset_rwsem, it blocks others wanting that rwsem, ensuring that it * is the only task able to also acquire callback_lock and be able to * modify cpusets. It can perform various checks on the cpuset structure * first, knowing nothing will change. It can also allocate memory while - * just holding cpuset_mutex. While it is performing these checks, various + * just holding cpuset_rwsem. While it is performing these checks, various * callback routines can briefly acquire callback_lock to query cpusets. * Once it is ready to make the changes, it takes callback_lock, blocking * everyone else. @@ -393,7 +395,7 @@ static inline bool is_in_v2_mode(void) * One way or another, we guarantee to return some non-empty subset * of cpu_online_mask. * - * Call with callback_lock or cpuset_mutex held. + * Call with callback_lock or cpuset_rwsem held. */ static void guarantee_online_cpus(struct task_struct *tsk, struct cpumask *pmask) @@ -435,7 +437,7 @@ out_unlock: * One way or another, we guarantee to return some non-empty subset * of node_states[N_MEMORY]. * - * Call with callback_lock or cpuset_mutex held. + * Call with callback_lock or cpuset_rwsem held. */ static void guarantee_online_mems(struct cpuset *cs, nodemask_t *pmask) { @@ -447,7 +449,7 @@ static void guarantee_online_mems(struct cpuset *cs, nodemask_t *pmask) /* * update task's spread flag if cpuset's page/slab spread flag is set * - * Call with callback_lock or cpuset_mutex held. + * Call with callback_lock or cpuset_rwsem held. */ static void cpuset_update_task_spread_flag(struct cpuset *cs, struct task_struct *tsk) @@ -468,7 +470,7 @@ static void cpuset_update_task_spread_flag(struct cpuset *cs, * * One cpuset is a subset of another if all its allowed CPUs and * Memory Nodes are a subset of the other, and its exclusive flags - * are only set if the other's are set. Call holding cpuset_mutex. + * are only set if the other's are set. Call holding cpuset_rwsem. */ static int is_cpuset_subset(const struct cpuset *p, const struct cpuset *q) @@ -577,7 +579,7 @@ static inline void free_cpuset(struct cpuset *cs) * If we replaced the flag and mask values of the current cpuset * (cur) with those values in the trial cpuset (trial), would * our various subset and exclusive rules still be valid? Presumes - * cpuset_mutex held. + * cpuset_rwsem held. * * 'cur' is the address of an actual, in-use cpuset. Operations * such as list traversal that depend on the actual address of the @@ -700,7 +702,7 @@ static void update_domain_attr_tree(struct sched_domain_attr *dattr, rcu_read_unlock(); } -/* Must be called with cpuset_mutex held. */ +/* Must be called with cpuset_rwsem held. */ static inline int nr_cpusets(void) { /* jump label reference count + the top-level cpuset */ @@ -726,7 +728,7 @@ static inline int nr_cpusets(void) * domains when operating in the severe memory shortage situations * that could cause allocation failures below. * - * Must be called with cpuset_mutex held. + * Must be called with cpuset_rwsem held. * * The three key local variables below are: * cp - cpuset pointer, used (together with pos_css) to perform a @@ -1005,7 +1007,7 @@ partition_and_rebuild_sched_domains(int ndoms_new, cpumask_var_t doms_new[], * 'cpus' is removed, then call this routine to rebuild the * scheduler's dynamic sched domains. * - * Call with cpuset_mutex held. Takes cpus_read_lock(). + * Call with cpuset_rwsem held. Takes cpus_read_lock(). */ static void rebuild_sched_domains_locked(void) { @@ -1078,7 +1080,7 @@ void rebuild_sched_domains(void) * @cs: the cpuset in which each task's cpus_allowed mask needs to be changed * * Iterate through each task of @cs updating its cpus_allowed to the - * effective cpuset's. As this function is called with cpuset_mutex held, + * effective cpuset's. As this function is called with cpuset_rwsem held, * cpuset membership stays stable. */ static void update_tasks_cpumask(struct cpuset *cs) @@ -1347,7 +1349,7 @@ static int update_parent_subparts_cpumask(struct cpuset *cpuset, int cmd, * * On legacy hierarchy, effective_cpus will be the same with cpu_allowed. * - * Called with cpuset_mutex held + * Called with cpuset_rwsem held */ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp) { @@ -1704,12 +1706,12 @@ static void *cpuset_being_rebound; * @cs: the cpuset in which each task's mems_allowed mask needs to be changed * * Iterate through each task of @cs updating its mems_allowed to the - * effective cpuset's. As this function is called with cpuset_mutex held, + * effective cpuset's. As this function is called with cpuset_rwsem held, * cpuset membership stays stable. */ static void update_tasks_nodemask(struct cpuset *cs) { - static nodemask_t newmems; /* protected by cpuset_mutex */ + static nodemask_t newmems; /* protected by cpuset_rwsem */ struct css_task_iter it; struct task_struct *task; @@ -1722,7 +1724,7 @@ static void update_tasks_nodemask(struct cpuset *cs) * take while holding tasklist_lock. Forks can happen - the * mpol_dup() cpuset_being_rebound check will catch such forks, * and rebind their vma mempolicies too. Because we still hold - * the global cpuset_mutex, we know that no other rebind effort + * the global cpuset_rwsem, we know that no other rebind effort * will be contending for the global variable cpuset_being_rebound. * It's ok if we rebind the same mm twice; mpol_rebind_mm() * is idempotent. Also migrate pages in each mm to new nodes. @@ -1768,7 +1770,7 @@ static void update_tasks_nodemask(struct cpuset *cs) * * On legacy hierarchy, effective_mems will be the same with mems_allowed. * - * Called with cpuset_mutex held + * Called with cpuset_rwsem held */ static void update_nodemasks_hier(struct cpuset *cs, nodemask_t *new_mems) { @@ -1821,7 +1823,7 @@ static void update_nodemasks_hier(struct cpuset *cs, nodemask_t *new_mems) * mempolicies and if the cpuset is marked 'memory_migrate', * migrate the tasks pages to the new memory. * - * Call with cpuset_mutex held. May take callback_lock during call. + * Call with cpuset_rwsem held. May take callback_lock during call. * Will take tasklist_lock, scan tasklist for tasks in cpuset cs, * lock each such tasks mm->mmap_lock, scan its vma's and rebind * their mempolicies to the cpusets new mems_allowed. @@ -1911,7 +1913,7 @@ static int update_relax_domain_level(struct cpuset *cs, s64 val) * @cs: the cpuset in which each task's spread flags needs to be changed * * Iterate through each task of @cs updating its spread flags. As this - * function is called with cpuset_mutex held, cpuset membership stays + * function is called with cpuset_rwsem held, cpuset membership stays * stable. */ static void update_tasks_flags(struct cpuset *cs) @@ -1931,7 +1933,7 @@ static void update_tasks_flags(struct cpuset *cs) * cs: the cpuset to update * turning_on: whether the flag is being set or cleared * - * Call with cpuset_mutex held. + * Call with cpuset_rwsem held. */ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, @@ -1980,7 +1982,7 @@ out: * cs: the cpuset to update * new_prs: new partition root state * - * Call with cpuset_mutex held. + * Call with cpuset_rwsem held. */ static int update_prstate(struct cpuset *cs, int new_prs) { @@ -2167,7 +2169,7 @@ static int fmeter_getrate(struct fmeter *fmp) static struct cpuset *cpuset_attach_old_cs; -/* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */ +/* Called by cgroups to determine if a cpuset is usable; cpuset_rwsem held */ static int cpuset_can_attach(struct cgroup_taskset *tset) { struct cgroup_subsys_state *css; @@ -2219,7 +2221,7 @@ static void cpuset_cancel_attach(struct cgroup_taskset *tset) } /* - * Protected by cpuset_mutex. cpus_attach is used only by cpuset_attach() + * Protected by cpuset_rwsem. cpus_attach is used only by cpuset_attach() * but we can't allocate it dynamically there. Define it global and * allocate from cpuset_init(). */ @@ -2227,7 +2229,7 @@ static cpumask_var_t cpus_attach; static void cpuset_attach(struct cgroup_taskset *tset) { - /* static buf protected by cpuset_mutex */ + /* static buf protected by cpuset_rwsem */ static nodemask_t cpuset_attach_nodemask_to; struct task_struct *task; struct task_struct *leader; @@ -2417,7 +2419,7 @@ static ssize_t cpuset_write_resmask(struct kernfs_open_file *of, * operation like this one can lead to a deadlock through kernfs * active_ref protection. Let's break the protection. Losing the * protection is okay as we check whether @cs is online after - * grabbing cpuset_mutex anyway. This only happens on the legacy + * grabbing cpuset_rwsem anyway. This only happens on the legacy * hierarchies. */ css_get(&cs->css); @@ -3672,7 +3674,7 @@ void __cpuset_memory_pressure_bump(void) * - Used for /proc//cpuset. * - No need to task_lock(tsk) on this tsk->cpuset reference, as it * doesn't really matter if tsk->cpuset changes after we read it, - * and we take cpuset_mutex, keeping cpuset_attach() from changing it + * and we take cpuset_rwsem, keeping cpuset_attach() from changing it * anyway. */ int proc_cpuset_show(struct seq_file *m, struct pid_namespace *ns, -- cgit From c0002d11d79900f8aa5c8375336434940d6afedf Mon Sep 17 00:00:00 2001 From: ArthurChiao Date: Wed, 8 Sep 2021 16:08:15 +0800 Subject: cgroupv2, docs: fix misinformation in "device controller" section Hotmail was rejected by the mailing list, switched to gmail to resend. 1. Clarify cgroup BPF program type and attach type; 2. Fix file path broken. Signed-off-by: ArthurChiao Signed-off-by: Tejun Heo --- Documentation/admin-guide/cgroup-v2.rst | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst index fc53ae0e96b9..4d8c27eca96b 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst @@ -2170,19 +2170,19 @@ existing device files. Cgroup v2 device controller has no interface files and is implemented on top of cgroup BPF. To control access to device files, a user may -create bpf programs of the BPF_CGROUP_DEVICE type and attach them -to cgroups. On an attempt to access a device file, corresponding -BPF programs will be executed, and depending on the return value -the attempt will succeed or fail with -EPERM. - -A BPF_CGROUP_DEVICE program takes a pointer to the bpf_cgroup_dev_ctx -structure, which describes the device access attempt: access type -(mknod/read/write) and device (type, major and minor numbers). -If the program returns 0, the attempt fails with -EPERM, otherwise -it succeeds. - -An example of BPF_CGROUP_DEVICE program may be found in the kernel -source tree in the tools/testing/selftests/bpf/progs/dev_cgroup.c file. +create bpf programs of type BPF_PROG_TYPE_CGROUP_DEVICE and attach +them to cgroups with BPF_CGROUP_DEVICE flag. On an attempt to access a +device file, corresponding BPF programs will be executed, and depending +on the return value the attempt will succeed or fail with -EPERM. + +A BPF_PROG_TYPE_CGROUP_DEVICE program takes a pointer to the +bpf_cgroup_dev_ctx structure, which describes the device access attempt: +access type (mknod/read/write) and device (type, major and minor numbers). +If the program returns 0, the attempt fails with -EPERM, otherwise it +succeeds. + +An example of BPF_PROG_TYPE_CGROUP_DEVICE program may be found in +tools/testing/selftests/bpf/progs/dev_cgroup.c in the kernel source tree. RDMA -- cgit From f7a28df7db84eb3410e9eca37832efa5aed93338 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 16 Aug 2021 21:39:54 +0300 Subject: iio: dac: ti-dac5571: fix an error code in probe() If we have an unexpected number of channels then return -EINVAL instead of returning success. Fixes: df38a4a72a3b ("iio: dac: add TI DAC5571 family support") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/20210816183954.GB2068@kili Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ti-dac5571.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/dac/ti-dac5571.c b/drivers/iio/dac/ti-dac5571.c index 2a5ba1b08a1d..546a4cf6c5ef 100644 --- a/drivers/iio/dac/ti-dac5571.c +++ b/drivers/iio/dac/ti-dac5571.c @@ -350,6 +350,7 @@ static int dac5571_probe(struct i2c_client *client, data->dac5571_pwrdwn = dac5571_pwrdwn_quad; break; default: + ret = -EINVAL; goto err; } -- cgit From 9033c7a357481fb5bcc1737bafa4aec572dca5c6 Mon Sep 17 00:00:00 2001 From: Sean Nyekjaer Date: Tue, 17 Aug 2021 14:43:36 +0200 Subject: iio: accel: fxls8962af: return IRQ_HANDLED when fifo is flushed fxls8962af_fifo_flush() will return the samples flushed. So return IRQ_NONE only if an error is returned. Fixes: 79e3a5bdd9ef ("iio: accel: fxls8962af: add hw buffered sampling") Signed-off-by: Sean Nyekjaer Link: https://lore.kernel.org/r/20210817124336.1672169-1-sean@geanix.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/accel/fxls8962af-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/accel/fxls8962af-core.c b/drivers/iio/accel/fxls8962af-core.c index 0019f1ea7df2..f41db9e0249a 100644 --- a/drivers/iio/accel/fxls8962af-core.c +++ b/drivers/iio/accel/fxls8962af-core.c @@ -738,7 +738,7 @@ static irqreturn_t fxls8962af_interrupt(int irq, void *p) if (reg & FXLS8962AF_INT_STATUS_SRC_BUF) { ret = fxls8962af_fifo_flush(indio_dev); - if (ret) + if (ret < 0) return IRQ_NONE; return IRQ_HANDLED; -- cgit From 9909a395e9807aa79145c9289d0c13d0133359a2 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 17 Aug 2021 18:21:11 +0100 Subject: iio: adc: rzg2l_adc: Fix -EBUSY timeout error return Currently when a timeout occurs in rzg2l_adc_hw_init the error -EBUSY is assigned to ret but the error code is used as the function is hard-coded to return 0. The variable ret is 0 before entering the while-loop hence the fix is just to return ret at the end of the function to return the success 0 or -EBUSY return code. Addresses-Coverity: ("Unused value") Fixes: d484c21bacfa ("iio: adc: Add driver for Renesas RZ/G2L A/D converter") Signed-off-by: Colin Ian King Reviewed-by: Lad Prabhakar Link: https://lore.kernel.org/r/20210817172111.495897-1-colin.king@canonical.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/rzg2l_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/rzg2l_adc.c b/drivers/iio/adc/rzg2l_adc.c index 9996d5eef289..868b183e75ea 100644 --- a/drivers/iio/adc/rzg2l_adc.c +++ b/drivers/iio/adc/rzg2l_adc.c @@ -401,7 +401,7 @@ static int rzg2l_adc_hw_init(struct rzg2l_adc *adc) exit_hw_init: clk_disable_unprepare(adc->pclk); - return 0; + return ret; } static void rzg2l_adc_pm_runtime_disable(void *data) -- cgit From bbcf40816b547b3c37af49168950491d20d81ce1 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 21 Aug 2021 12:37:24 +0200 Subject: iio: adc128s052: Fix the error handling path of 'adc128_probe()' A successful 'regulator_enable()' call should be balanced by a corresponding 'regulator_disable()' call in the error handling path of the probe, as already done in the remove function. Update the error handling path accordingly. Fixes: 913b86468674 ("iio: adc: Add TI ADC128S052") Signed-off-by: Christophe JAILLET Reviewed-by: Alexandru Ardelean Link: https://lore.kernel.org/r/85189f1cfcf6f5f7b42d8730966f2a074b07b5f5.1629542160.git.christophe.jaillet@wanadoo.fr Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti-adc128s052.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/iio/adc/ti-adc128s052.c b/drivers/iio/adc/ti-adc128s052.c index 3143f35a6509..83c1ae07b3e9 100644 --- a/drivers/iio/adc/ti-adc128s052.c +++ b/drivers/iio/adc/ti-adc128s052.c @@ -171,7 +171,13 @@ static int adc128_probe(struct spi_device *spi) mutex_init(&adc->lock); ret = iio_device_register(indio_dev); + if (ret) + goto err_disable_regulator; + return 0; + +err_disable_regulator: + regulator_disable(adc->reg); return ret; } -- cgit From 732ae19ee8f58ecaf30cbc1bbbda5cbee6a45043 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Wed, 18 Aug 2021 13:11:24 +0200 Subject: iio: adc: max1027: Fix wrong shift with 12-bit devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 10-bit devices must shift the value twice. This is not needed anymore on 12-bit devices. Fixes: ae47d009b508 ("iio: adc: max1027: Introduce 12-bit devices support") Cc: stable@vger.kernel.org Signed-off-by: Miquel Raynal Reviewed-by: Nuno Sá Link: https://lore.kernel.org/r/20210818111139.330636-2-miquel.raynal@bootlin.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/max1027.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c index 655ab02d03d8..4a42d140a4b0 100644 --- a/drivers/iio/adc/max1027.c +++ b/drivers/iio/adc/max1027.c @@ -103,7 +103,7 @@ MODULE_DEVICE_TABLE(of, max1027_adc_dt_ids); .sign = 'u', \ .realbits = depth, \ .storagebits = 16, \ - .shift = 2, \ + .shift = (depth == 10) ? 2 : 0, \ .endianness = IIO_BE, \ }, \ } -- cgit From f0cb5fed37ab37f6a6c5463c5fd39b58a45670c8 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Wed, 18 Aug 2021 13:11:25 +0200 Subject: iio: adc: max1027: Fix the number of max1X31 channels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The macro MAX1X29_CHANNELS() already calls MAX1X27_CHANNELS(). Calling MAX1X27_CHANNELS() before MAX1X29_CHANNELS() in the definition of MAX1X31_CHANNELS() declares the first 8 channels twice. So drop this extra call from the MAX1X31 channels list definition. Fixes: 7af5257d8427 ("iio: adc: max1027: Prepare the introduction of different resolutions") Cc: stable@vger.kernel.org Signed-off-by: Miquel Raynal Reviewed-by: Nuno Sá Link: https://lore.kernel.org/r/20210818111139.330636-3-miquel.raynal@bootlin.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/max1027.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c index 4a42d140a4b0..b753658bb41e 100644 --- a/drivers/iio/adc/max1027.c +++ b/drivers/iio/adc/max1027.c @@ -142,7 +142,6 @@ MODULE_DEVICE_TABLE(of, max1027_adc_dt_ids); MAX1027_V_CHAN(11, depth) #define MAX1X31_CHANNELS(depth) \ - MAX1X27_CHANNELS(depth), \ MAX1X29_CHANNELS(depth), \ MAX1027_V_CHAN(12, depth), \ MAX1027_V_CHAN(13, depth), \ -- cgit From fa002b364981b49d04e818abbc06fd47a5ec7b51 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Thu, 19 Aug 2021 21:24:16 +0800 Subject: iio: adc: rzg2l_adc: add missing clk_disable_unprepare() in rzg2l_adc_pm_runtime_resume() Add clk_disable_unprepare() on error path in rzg2l_adc_pm_runtime_resume(). Reported-by: Hulk Robot Signed-off-by: Yang Yingliang Reviewed-by: Lad Prabhakar Link: https://lore.kernel.org/r/20210819132416.175644-1-yangyingliang@huawei.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/rzg2l_adc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/rzg2l_adc.c b/drivers/iio/adc/rzg2l_adc.c index 868b183e75ea..32fbf57c362f 100644 --- a/drivers/iio/adc/rzg2l_adc.c +++ b/drivers/iio/adc/rzg2l_adc.c @@ -570,8 +570,10 @@ static int __maybe_unused rzg2l_adc_pm_runtime_resume(struct device *dev) return ret; ret = clk_prepare_enable(adc->adclk); - if (ret) + if (ret) { + clk_disable_unprepare(adc->pclk); return ret; + } rzg2l_adc_pwr(adc, true); -- cgit From eb795cd97365a3d3d9da3926d234a7bc32a3bb15 Mon Sep 17 00:00:00 2001 From: Billy Tsai Date: Tue, 31 Aug 2021 15:14:44 +0800 Subject: iio: adc: aspeed: set driver data when adc probe. Fix the issue when adc remove will get the null driver data. Fixed: commit 573803234e72 ("iio: Aspeed ADC") Signed-off-by: Billy Tsai Link: https://lore.kernel.org/r/20210831071458.2334-2-billy_tsai@aspeedtech.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/aspeed_adc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c index 19efaa41bc34..34ec0c28b2df 100644 --- a/drivers/iio/adc/aspeed_adc.c +++ b/drivers/iio/adc/aspeed_adc.c @@ -183,6 +183,7 @@ static int aspeed_adc_probe(struct platform_device *pdev) data = iio_priv(indio_dev); data->dev = &pdev->dev; + platform_set_drvdata(pdev, indio_dev); data->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(data->base)) -- cgit From 89a86da5cb8e0ee153111fb68a719d31582c206b Mon Sep 17 00:00:00 2001 From: Alexandru Tachici Date: Mon, 6 Sep 2021 09:56:28 +0300 Subject: iio: adc: ad7192: Add IRQ flag IRQ type in ad_sigma_delta_info struct was missing. In Sigma-Delta devices the SDO line is also used as an interrupt. Leaving IRQ on level instead of falling might trigger a sample read when the IRQ is enabled, as the SDO line is already low. Not sure if SDO line will always immediately go high in ad_sd_buffer_postenable before the IRQ is enabled. Also the datasheet seem to explicitly say the falling edge of the SDO should be used as an interrupt: >From the AD7192 datasheet: "The DOUT/RDY falling edge can be used as an interrupt to a processor," Fixes: da4d3d6bb9f6 ("iio: adc: ad-sigma-delta: Allow custom IRQ flags") Signed-off-by: Alexandru Tachici Cc: Link: https://lore.kernel.org/r/20210906065630.16325-2-alexandru.tachici@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7192.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c index ee8ed9481025..2121a812b0c3 100644 --- a/drivers/iio/adc/ad7192.c +++ b/drivers/iio/adc/ad7192.c @@ -293,6 +293,7 @@ static const struct ad_sigma_delta_info ad7192_sigma_delta_info = { .has_registers = true, .addr_shift = 3, .read_mask = BIT(6), + .irq_flags = IRQF_TRIGGER_FALLING, }; static const struct ad_sd_calib_data ad7192_calib_arr[8] = { -- cgit From e081102f3077aa716974ccebec97003c890d5641 Mon Sep 17 00:00:00 2001 From: Alexandru Tachici Date: Mon, 6 Sep 2021 09:56:29 +0300 Subject: iio: adc: ad7780: Fix IRQ flag Correct IRQ flag here is falling. In Sigma-Delta devices the SDO line is also used as an interrupt. Leaving IRQ on level instead of falling might trigger a sample read when the IRQ is enabled, as the SDO line is already low. Not sure if SDO line will always immediately go high in ad_sd_buffer_postenable before the IRQ is enabled. Also the datasheet seem to explicitly say the falling edge of the SDO should be used as an interrupt: >From the AD7780 datasheet: " The DOUT/Figure 22 RDY falling edge can be used as an interrupt to a processor" Fixes: da4d3d6bb9f6 ("iio: adc: ad-sigma-delta: Allow custom IRQ flags") Signed-off-by: Alexandru Tachici Cc: Link: https://lore.kernel.org/r/20210906065630.16325-3-alexandru.tachici@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7780.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad7780.c b/drivers/iio/adc/ad7780.c index 42bb952f4738..b6e8c8abf6f4 100644 --- a/drivers/iio/adc/ad7780.c +++ b/drivers/iio/adc/ad7780.c @@ -203,7 +203,7 @@ static const struct ad_sigma_delta_info ad7780_sigma_delta_info = { .set_mode = ad7780_set_mode, .postprocess_sample = ad7780_postprocess_sample, .has_registers = false, - .irq_flags = IRQF_TRIGGER_LOW, + .irq_flags = IRQF_TRIGGER_FALLING, }; #define _AD7780_CHANNEL(_bits, _wordsize, _mask_all) \ -- cgit From 1a913270e57a8e7f1e3789802f1f64e6d0654626 Mon Sep 17 00:00:00 2001 From: Alexandru Tachici Date: Mon, 6 Sep 2021 09:56:30 +0300 Subject: iio: adc: ad7793: Fix IRQ flag In Sigma-Delta devices the SDO line is also used as an interrupt. Leaving IRQ on level instead of falling might trigger a sample read when the IRQ is enabled, as the SDO line is already low. Not sure if SDO line will always immediately go high in ad_sd_buffer_postenable before the IRQ is enabled. Also the datasheet seem to explicitly say the falling edge of the SDO should be used as an interrupt: >From the AD7793 datasheet: " The DOUT/RDY falling edge can be used as an interrupt to a processor" Fixes: da4d3d6bb9f6 ("iio: adc: ad-sigma-delta: Allow custom IRQ flags") Signed-off-by: Alexandru Tachici Cc: Link: https://lore.kernel.org/r/20210906065630.16325-4-alexandru.tachici@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7793.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index ef3e2d3ecb0c..0e7ab3fb072a 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -206,7 +206,7 @@ static const struct ad_sigma_delta_info ad7793_sigma_delta_info = { .has_registers = true, .addr_shift = 3, .read_mask = BIT(6), - .irq_flags = IRQF_TRIGGER_LOW, + .irq_flags = IRQF_TRIGGER_FALLING, }; static const struct ad_sd_calib_data ad7793_calib_arr[6] = { -- cgit From f60f5741002b9fde748cff65fd09bd6222c5db0c Mon Sep 17 00:00:00 2001 From: Md Sadre Alam Date: Tue, 7 Sep 2021 12:35:57 +0530 Subject: mtd: rawnand: qcom: Update code word value for raw read From QPIC V2 onwards there is a separate register to read last code word "QPIC_NAND_READ_LOCATION_LAST_CW_n". qcom_nandc_read_cw_raw() is used to read only one code word at a time. If we will configure number of code words to 1 in in QPIC_NAND_DEV0_CFG0 register then QPIC controller thinks its reading the last code word, since from QPIC V2 onwards we are having separate register to read the last code word, we have to configure "QPIC_NAND_READ_LOCATION_LAST_CW_n" register to fetch data from controller buffer to system memory. Fixes: 503ee5aad430 ("mtd: rawnand: qcom: update last code word register") Cc: stable@kernel.org Signed-off-by: Md Sadre Alam Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/1630998357-1359-1-git-send-email-mdalam@codeaurora.org --- drivers/mtd/nand/raw/qcom_nandc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index ef0badea4f41..04e6f7b26706 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -1676,13 +1676,17 @@ qcom_nandc_read_cw_raw(struct mtd_info *mtd, struct nand_chip *chip, struct nand_ecc_ctrl *ecc = &chip->ecc; int data_size1, data_size2, oob_size1, oob_size2; int ret, reg_off = FLASH_BUF_ACC, read_loc = 0; + int raw_cw = cw; nand_read_page_op(chip, page, 0, NULL, 0); host->use_ecc = false; + if (nandc->props->qpic_v2) + raw_cw = ecc->steps - 1; + clear_bam_transaction(nandc); set_address(host, host->cw_size * cw, page); - update_rw_regs(host, 1, true, cw); + update_rw_regs(host, 1, true, raw_cw); config_nand_page_read(chip); data_size1 = mtd->writesize - host->cw_size * (ecc->steps - 1); @@ -1711,7 +1715,7 @@ qcom_nandc_read_cw_raw(struct mtd_info *mtd, struct nand_chip *chip, nandc_set_read_loc(chip, cw, 3, read_loc, oob_size2, 1); } - config_nand_cw_read(chip, false, cw); + config_nand_cw_read(chip, false, raw_cw); read_data_dma(nandc, reg_off, data_buf, data_size1, 0); reg_off += data_size1; -- cgit From 7d95995ab4de07ee642c925aa6dbf6d07069a751 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 11:34:38 +0300 Subject: fs/ntfs3: Remove '+' before constant in ni_insert_resident() No need for plus sign here. So remove it. Checkpatch will also be happy. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/frecord.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index 080264ced909..df41eae8f7e1 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -1448,7 +1448,7 @@ int ni_insert_resident(struct ntfs_inode *ni, u32 data_size, attr->res.flags = RESIDENT_FLAG_INDEXED; /* is_attr_indexed(attr)) == true */ - le16_add_cpu(&ni->mi.mrec->hard_links, +1); + le16_add_cpu(&ni->mi.mrec->hard_links, 1); ni->mi.dirty = true; } attr->res.res = 0; -- cgit From 4ca7fe57f21a25afc4a651db5145bfe090c6248f Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 11:34:39 +0300 Subject: fs/ntfs3: Place Comparisons constant right side of the test For better code readability place constant always right side of the test. This will also address checkpatch warning. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/frecord.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index df41eae8f7e1..2f8af53da219 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -1603,7 +1603,7 @@ struct ATTR_FILE_NAME *ni_fname_type(struct ntfs_inode *ni, u8 name_type, *le = NULL; - if (FILE_NAME_POSIX == name_type) + if (name_type == FILE_NAME_POSIX) return NULL; /* Enumerate all names. */ -- cgit From 2829e39e0e8add377508b3c6ef4cf48e6db324fb Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 11:34:40 +0300 Subject: fs/ntfs3: Remove braces from single statment block Remove braces from single statment block as they are not needed. Also Linux kernel coding style guide recommend this and checkpatch warn about this. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/frecord.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index 2f8af53da219..1e1a09034f65 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -2903,9 +2903,8 @@ bool ni_remove_name_undo(struct ntfs_inode *dir_ni, struct ntfs_inode *ni, memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), de + 1, de_key_size); mi_get_ref(&ni->mi, &de->ref); - if (indx_insert_entry(&dir_ni->dir, dir_ni, de, sbi, NULL, 1)) { + if (indx_insert_entry(&dir_ni->dir, dir_ni, de, sbi, NULL, 1)) return false; - } } return true; -- cgit From cffb5152eea82de890dd418a90612aede96068d6 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 11:34:41 +0300 Subject: fs/ntfs3: Remove tabs before spaces from comment Remove tabs before spaces from comment as recommended by kernel coding style. Checkpatch also warn about these. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/lznt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ntfs3/lznt.c b/fs/ntfs3/lznt.c index 12ba42518efe..28f654561f27 100644 --- a/fs/ntfs3/lznt.c +++ b/fs/ntfs3/lznt.c @@ -292,7 +292,7 @@ next: /* * get_lznt_ctx * @level: 0 - Standard compression. - * !0 - Best compression, requires a lot of cpu. + * !0 - Best compression, requires a lot of cpu. */ struct lznt *get_lznt_ctx(int level) { -- cgit From edb853ff3dc01c22577ea5d0383d067b68a6d663 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 17:28:39 +0300 Subject: fs/ntfs3: Fix ntfs_look_for_free_space() does only report -ENOSPC If ntfs_refresh_zone() returns error it will be changed to -ENOSPC. It is not right. Also caller of this functions also check other errors. Fixes: 78ab59fee07f ("fs/ntfs3: Rework file operations") Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/fsntfs.c | 51 +++++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c index 9232a7f410c6..e77fad89eaed 100644 --- a/fs/ntfs3/fsntfs.c +++ b/fs/ntfs3/fsntfs.c @@ -357,7 +357,7 @@ int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len, enum ALLOCATE_OPT opt) { int err; - CLST alen = 0; + CLST alen; struct super_block *sb = sbi->sb; size_t alcn, zlen, zeroes, zlcn, zlen2, ztrim, new_zlen; struct wnd_bitmap *wnd = &sbi->used.bitmap; @@ -369,13 +369,15 @@ int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len, if (!zlen) { err = ntfs_refresh_zone(sbi); if (err) - goto out; + goto up_write; + zlen = wnd_zone_len(wnd); } if (!zlen) { ntfs_err(sbi->sb, "no free space to extend mft"); - goto out; + err = -ENOSPC; + goto up_write; } lcn = wnd_zone_bit(wnd); @@ -384,12 +386,11 @@ int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len, wnd_zone_set(wnd, lcn + alen, zlen - alen); err = wnd_set_used(wnd, lcn, alen); - if (err) { - up_write(&wnd->rw_lock); - return err; - } + if (err) + goto up_write; + alcn = lcn; - goto out; + goto space_found; } /* * 'Cause cluster 0 is always used this value means that we should use @@ -403,15 +404,17 @@ int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len, alen = wnd_find(wnd, len, lcn, BITMAP_FIND_MARK_AS_USED, &alcn); if (alen) - goto out; + goto space_found; /* Try to use clusters from MftZone. */ zlen = wnd_zone_len(wnd); zeroes = wnd_zeroes(wnd); /* Check too big request */ - if (len > zeroes + zlen || zlen <= NTFS_MIN_MFT_ZONE) - goto out; + if (len > zeroes + zlen || zlen <= NTFS_MIN_MFT_ZONE) { + err = -ENOSPC; + goto up_write; + } /* How many clusters to cat from zone. */ zlcn = wnd_zone_bit(wnd); @@ -430,22 +433,22 @@ int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len, /* Allocate continues clusters. */ alen = wnd_find(wnd, len, 0, BITMAP_FIND_MARK_AS_USED | BITMAP_FIND_FULL, &alcn); - -out: - if (alen) { - err = 0; - *new_len = alen; - *new_lcn = alcn; - - ntfs_unmap_meta(sb, alcn, alen); - - /* Set hint for next requests. */ - if (!(opt & ALLOCATE_MFT)) - sbi->used.next_free_lcn = alcn + alen; - } else { + if (!alen) { err = -ENOSPC; + goto up_write; } +space_found: + err = 0; + *new_len = alen; + *new_lcn = alcn; + + ntfs_unmap_meta(sb, alcn, alen); + + /* Set hint for next requests. */ + if (!(opt & ALLOCATE_MFT)) + sbi->used.next_free_lcn = alcn + alen; +up_write: up_write(&wnd->rw_lock); return err; } -- cgit From f162f7b8dbc29742896f8a7e678bb31192716ae0 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 17:28:40 +0300 Subject: fs/ntfs3: Remove always false condition check We do not need this check as this is same thing as NTFS_MIN_MFT_ZONE > zlen. We already check NTFS_MIN_MFT_ZONE <= zlen and exit because is too big request. Remove it so code is cleaner. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/fsntfs.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c index e77fad89eaed..4cd24e4e58ff 100644 --- a/fs/ntfs3/fsntfs.c +++ b/fs/ntfs3/fsntfs.c @@ -422,11 +422,8 @@ int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len, ztrim = len > zlen ? zlen : (len > zlen2 ? len : zlen2); new_zlen = zlen - ztrim; - if (new_zlen < NTFS_MIN_MFT_ZONE) { + if (new_zlen < NTFS_MIN_MFT_ZONE) new_zlen = NTFS_MIN_MFT_ZONE; - if (new_zlen > zlen) - new_zlen = zlen; - } wnd_zone_set(wnd, zlcn, new_zlen); -- cgit From b5322eb1ae94572f5a52e804857e641b846059f4 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 17:28:41 +0300 Subject: fs/ntfs3: Use clamp/max macros instead of comparisons We can make code little more readable by using kernel macros clamp/max. This were found with kernel included Coccinelle minmax script. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/fsntfs.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c index 4cd24e4e58ff..c964d3996aab 100644 --- a/fs/ntfs3/fsntfs.c +++ b/fs/ntfs3/fsntfs.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "debug.h" #include "ntfs.h" @@ -419,11 +420,8 @@ int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len, /* How many clusters to cat from zone. */ zlcn = wnd_zone_bit(wnd); zlen2 = zlen >> 1; - ztrim = len > zlen ? zlen : (len > zlen2 ? len : zlen2); - new_zlen = zlen - ztrim; - - if (new_zlen < NTFS_MIN_MFT_ZONE) - new_zlen = NTFS_MIN_MFT_ZONE; + ztrim = clamp_val(len, zlen2, zlen); + new_zlen = max_t(size_t, zlen - ztrim, NTFS_MIN_MFT_ZONE); wnd_zone_set(wnd, zlcn, new_zlen); -- cgit From 6e3331ee34461be37f50912295a2e924a673dbc6 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 7 Sep 2021 17:28:42 +0300 Subject: fs/ntfs3: Use min/max macros instated of ternary operators We can make code little bit more readable by using min/max macros. These were found with Coccinelle. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 3 ++- fs/ntfs3/bitmap.c | 11 ++++++----- fs/ntfs3/fsntfs.c | 6 +++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 12cff28f3e71..c15cc17e3cd9 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -8,6 +8,7 @@ #include #include +#include #include "debug.h" #include "ntfs.h" @@ -1961,7 +1962,7 @@ int attr_punch_hole(struct ntfs_inode *ni, u64 vbo, u64 bytes, u32 *frame_size) return 0; from = vbo; - to = (vbo + bytes) < data_size ? (vbo + bytes) : data_size; + to = min_t(u64, vbo + bytes, data_size); memset(Add2Ptr(resident_data(attr_b), from), 0, to - from); return 0; } diff --git a/fs/ntfs3/bitmap.c b/fs/ntfs3/bitmap.c index a03584674fea..aa184407520f 100644 --- a/fs/ntfs3/bitmap.c +++ b/fs/ntfs3/bitmap.c @@ -12,6 +12,7 @@ #include #include +#include #include "ntfs.h" #include "ntfs_fs.h" @@ -432,7 +433,7 @@ static void wnd_remove_free_ext(struct wnd_bitmap *wnd, size_t bit, size_t len) ; } else { n3 = rb_next(&e->count.node); - max_new_len = len > new_len ? len : new_len; + max_new_len = max(len, new_len); if (!n3) { wnd->extent_max = max_new_len; } else { @@ -728,7 +729,7 @@ int wnd_set_free(struct wnd_bitmap *wnd, size_t bit, size_t bits) wbits = wnd->bits_last; tail = wbits - wbit; - op = tail < bits ? tail : bits; + op = min_t(u32, tail, bits); bh = wnd_map(wnd, iw); if (IS_ERR(bh)) { @@ -781,7 +782,7 @@ int wnd_set_used(struct wnd_bitmap *wnd, size_t bit, size_t bits) wbits = wnd->bits_last; tail = wbits - wbit; - op = tail < bits ? tail : bits; + op = min_t(u32, tail, bits); bh = wnd_map(wnd, iw); if (IS_ERR(bh)) { @@ -831,7 +832,7 @@ static bool wnd_is_free_hlp(struct wnd_bitmap *wnd, size_t bit, size_t bits) wbits = wnd->bits_last; tail = wbits - wbit; - op = tail < bits ? tail : bits; + op = min_t(u32, tail, bits); if (wbits != wnd->free_bits[iw]) { bool ret; @@ -923,7 +924,7 @@ use_wnd: wbits = wnd->bits_last; tail = wbits - wbit; - op = tail < bits ? tail : bits; + op = min_t(u32, tail, bits); if (wnd->free_bits[iw]) { bool ret; diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c index c964d3996aab..77d2e56d5b4f 100644 --- a/fs/ntfs3/fsntfs.c +++ b/fs/ntfs3/fsntfs.c @@ -382,7 +382,7 @@ int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len, } lcn = wnd_zone_bit(wnd); - alen = zlen > len ? len : zlen; + alen = min_t(CLST, len, zlen); wnd_zone_set(wnd, lcn + alen, zlen - alen); @@ -1096,7 +1096,7 @@ int ntfs_sb_write_run(struct ntfs_sb_info *sbi, const struct runs_tree *run, len = ((u64)clen << cluster_bits) - off; for (;;) { - u32 op = len < bytes ? len : bytes; + u32 op = min_t(u64, len, bytes); int err = ntfs_sb_write(sb, lbo, op, buf, 0); if (err) @@ -1297,7 +1297,7 @@ int ntfs_get_bh(struct ntfs_sb_info *sbi, const struct runs_tree *run, u64 vbo, nb->off = off = lbo & (blocksize - 1); for (;;) { - u32 len32 = len < bytes ? len : bytes; + u32 len32 = min_t(u64, len, bytes); sector_t block = lbo >> sb->s_blocksize_bits; do { -- cgit From 4170d3dd1467e9d78cb9af374b19357dc324b328 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 14 Sep 2021 13:53:33 +0300 Subject: iio: ssp_sensors: fix error code in ssp_print_mcu_debug() The ssp_print_mcu_debug() function should return negative error codes on error. Returning "length" is meaningless. This change does not affect runtime because the callers only care about zero/non-zero. Reported-by: Jonathan Cameron Fixes: 50dd64d57eee ("iio: common: ssp_sensors: Add sensorhub driver") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/20210914105333.GA11657@kili Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/common/ssp_sensors/ssp_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/common/ssp_sensors/ssp_spi.c b/drivers/iio/common/ssp_sensors/ssp_spi.c index 4864c38b8d1c..77449b4f3df5 100644 --- a/drivers/iio/common/ssp_sensors/ssp_spi.c +++ b/drivers/iio/common/ssp_sensors/ssp_spi.c @@ -137,7 +137,7 @@ static int ssp_print_mcu_debug(char *data_frame, int *data_index, if (length > received_len - *data_index || length <= 0) { ssp_dbg("[SSP]: MSG From MCU-invalid debug length(%d/%d)\n", length, received_len); - return length ? length : -EPROTO; + return -EPROTO; } ssp_dbg("[SSP]: MSG From MCU - %s\n", &data_frame[*data_index]); -- cgit From 8167c9a375ccceed19048ad9d68cb2d02ed276e0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 9 Sep 2021 12:13:36 +0300 Subject: iio: ssp_sensors: add more range checking in ssp_parse_dataframe() The "idx" is validated at the start of the loop but it gets incremented during the iteration so it needs to be checked again. Fixes: 50dd64d57eee ("iio: common: ssp_sensors: Add sensorhub driver") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/20210909091336.GA26312@kili Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/common/ssp_sensors/ssp_spi.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/iio/common/ssp_sensors/ssp_spi.c b/drivers/iio/common/ssp_sensors/ssp_spi.c index 77449b4f3df5..769bd9280524 100644 --- a/drivers/iio/common/ssp_sensors/ssp_spi.c +++ b/drivers/iio/common/ssp_sensors/ssp_spi.c @@ -273,6 +273,8 @@ static int ssp_parse_dataframe(struct ssp_data *data, char *dataframe, int len) for (idx = 0; idx < len;) { switch (dataframe[idx++]) { case SSP_MSG2AP_INST_BYPASS_DATA: + if (idx >= len) + return -EPROTO; sd = dataframe[idx++]; if (sd < 0 || sd >= SSP_SENSOR_MAX) { dev_err(SSP_DEV, @@ -282,10 +284,13 @@ static int ssp_parse_dataframe(struct ssp_data *data, char *dataframe, int len) if (indio_devs[sd]) { spd = iio_priv(indio_devs[sd]); - if (spd->process_data) + if (spd->process_data) { + if (idx >= len) + return -EPROTO; spd->process_data(indio_devs[sd], &dataframe[idx], data->timestamp); + } } else { dev_err(SSP_DEV, "no client for frame\n"); } @@ -293,6 +298,8 @@ static int ssp_parse_dataframe(struct ssp_data *data, char *dataframe, int len) idx += ssp_offset_map[sd]; break; case SSP_MSG2AP_INST_DEBUG_DATA: + if (idx >= len) + return -EPROTO; sd = ssp_print_mcu_debug(dataframe, &idx, len); if (sd) { dev_err(SSP_DEV, -- cgit From 0412016e48076f5f9dbdcc6613436e3c6db89523 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 9 Sep 2021 21:09:32 +0300 Subject: fs/ntfs3: Fix wrong error message $Logfile -> $UpCase Fix wrong error message $Logfile -> $UpCase. Probably copy paste. Fixes: 203c2b3a406a ("fs/ntfs3: Add initialization of super block") Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index acfa00acf4dd..1e01184f4ee2 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -1201,7 +1201,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) inode = ntfs_iget5(sb, &ref, &NAME_UPCASE); if (IS_ERR(inode)) { err = PTR_ERR(inode); - ntfs_err(sb, "Failed to load \x24LogFile."); + ntfs_err(sb, "Failed to load $UpCase."); inode = NULL; goto out; } -- cgit From 7ea04817866a5ac369f1a33d1b86d06a695aaedb Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 9 Sep 2021 21:09:33 +0300 Subject: fs/ntfs3: Change EINVAL to ENOMEM when d_make_root fails Change EINVAL to ENOMEM when d_make_root fails because that is right errno. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 1e01184f4ee2..642bd63932d0 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -1284,7 +1284,7 @@ load_root: sb->s_root = d_make_root(inode); if (!sb->s_root) { - err = -EINVAL; + err = -ENOMEM; goto out; } -- cgit From 5d7d6b16bc1dbe0f84997e639c49b5ed98a562f7 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 9 Sep 2021 21:09:34 +0300 Subject: fs/ntfs3: Remove impossible fault condition in fill_super Remove root drop when we fault out. This can never happened because when we allocate root we eather fault when no root or success. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 642bd63932d0..ad185c723c0e 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -1295,12 +1295,6 @@ load_root: out: iput(inode); - - if (sb->s_root) { - d_drop(sb->s_root); - sb->s_root = NULL; - } - return err; } -- cgit From bce1828f6d82ad0ffa3b7259d6f1769ffbcec30c Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 9 Sep 2021 21:09:35 +0300 Subject: fs/ntfs3: Return straight without goto in fill_super In many places it is not needed to use goto out. We can just return right away. This will make code little bit more cleaner as we won't need to check error path. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 56 ++++++++++++++++---------------------------------------- 1 file changed, 16 insertions(+), 40 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index ad185c723c0e..31a9a0d16261 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -921,7 +921,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) err = ntfs_init_from_boot(sb, rq ? queue_logical_block_size(rq) : 512, bd_inode->i_size); if (err) - goto out; + return err; #ifdef CONFIG_NTFS3_64BIT_CLUSTER sb->s_maxbytes = MAX_LFS_FILESIZE; @@ -937,10 +937,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) ref.seq = cpu_to_le16(MFT_REC_VOL); inode = ntfs_iget5(sb, &ref, &NAME_VOLUME); if (IS_ERR(inode)) { - err = PTR_ERR(inode); ntfs_err(sb, "Failed to load $Volume."); - inode = NULL; - goto out; + return PTR_ERR(inode); } ni = ntfs_i(inode); @@ -988,10 +986,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) ref.seq = cpu_to_le16(MFT_REC_MIRR); inode = ntfs_iget5(sb, &ref, &NAME_MIRROR); if (IS_ERR(inode)) { - err = PTR_ERR(inode); ntfs_err(sb, "Failed to load $MFTMirr."); - inode = NULL; - goto out; + return PTR_ERR(inode); } sbi->mft.recs_mirr = @@ -1004,10 +1000,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) ref.seq = cpu_to_le16(MFT_REC_LOG); inode = ntfs_iget5(sb, &ref, &NAME_LOGFILE); if (IS_ERR(inode)) { - err = PTR_ERR(inode); ntfs_err(sb, "Failed to load \x24LogFile."); - inode = NULL; - goto out; + return PTR_ERR(inode); } ni = ntfs_i(inode); @@ -1025,16 +1019,14 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) if (!is_ro) { ntfs_warn(sb, "failed to replay log file. Can't mount rw!"); - err = -EINVAL; - goto out; + return -EINVAL; } } else if (sbi->volume.flags & VOLUME_FLAG_DIRTY) { if (!is_ro && !sbi->options->force) { ntfs_warn( sb, "volume is dirty and \"force\" flag is not set!"); - err = -EINVAL; - goto out; + return -EINVAL; } } @@ -1044,10 +1036,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) inode = ntfs_iget5(sb, &ref, &NAME_MFT); if (IS_ERR(inode)) { - err = PTR_ERR(inode); ntfs_err(sb, "Failed to load $MFT."); - inode = NULL; - goto out; + return PTR_ERR(inode); } ni = ntfs_i(inode); @@ -1071,10 +1061,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) ref.seq = cpu_to_le16(MFT_REC_BADCLUST); inode = ntfs_iget5(sb, &ref, &NAME_BADCLUS); if (IS_ERR(inode)) { - err = PTR_ERR(inode); ntfs_err(sb, "Failed to load $BadClus."); - inode = NULL; - goto out; + return PTR_ERR(inode); } ni = ntfs_i(inode); @@ -1096,10 +1084,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) ref.seq = cpu_to_le16(MFT_REC_BITMAP); inode = ntfs_iget5(sb, &ref, &NAME_BITMAP); if (IS_ERR(inode)) { - err = PTR_ERR(inode); ntfs_err(sb, "Failed to load $Bitmap."); - inode = NULL; - goto out; + return PTR_ERR(inode); } ni = ntfs_i(inode); @@ -1129,17 +1115,15 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) /* Compute the MFT zone. */ err = ntfs_refresh_zone(sbi); if (err) - goto out; + return err; /* Load $AttrDef. */ ref.low = cpu_to_le32(MFT_REC_ATTR); ref.seq = cpu_to_le16(MFT_REC_ATTR); inode = ntfs_iget5(sbi->sb, &ref, &NAME_ATTRDEF); if (IS_ERR(inode)) { - err = PTR_ERR(inode); ntfs_err(sb, "Failed to load $AttrDef -> %d", err); - inode = NULL; - goto out; + return PTR_ERR(inode); } if (inode->i_size < sizeof(struct ATTR_DEF_ENTRY)) { @@ -1200,10 +1184,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) ref.seq = cpu_to_le16(MFT_REC_UPCASE); inode = ntfs_iget5(sb, &ref, &NAME_UPCASE); if (IS_ERR(inode)) { - err = PTR_ERR(inode); ntfs_err(sb, "Failed to load $UpCase."); - inode = NULL; - goto out; + return PTR_ERR(inode); } ni = ntfs_i(inode); @@ -1249,7 +1231,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) /* Load $Secure. */ err = ntfs_security_init(sbi); if (err) - goto out; + return err; /* Load $Extend. */ err = ntfs_extend_init(sbi); @@ -1273,26 +1255,20 @@ load_root: ref.seq = cpu_to_le16(MFT_REC_ROOT); inode = ntfs_iget5(sb, &ref, &NAME_ROOT); if (IS_ERR(inode)) { - err = PTR_ERR(inode); ntfs_err(sb, "Failed to load root."); - inode = NULL; - goto out; + return PTR_ERR(inode); } ni = ntfs_i(inode); sb->s_root = d_make_root(inode); - - if (!sb->s_root) { - err = -ENOMEM; - goto out; - } + if (!sb->s_root) + return -ENOMEM; fc->fs_private = NULL; fc->s_fs_info = NULL; return 0; - out: iput(inode); return err; -- cgit From 10b4f12c7028399007aaebc25810b18d8f7731a7 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 9 Sep 2021 21:09:36 +0300 Subject: fs/ntfs3: Remove unnecessary variable loading in fill_super Remove some unnecessary variable loading. These look like copy paste work and they are not used to anything. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 31a9a0d16261..4ff61534682c 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -877,7 +877,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) struct block_device *bdev = sb->s_bdev; struct inode *bd_inode = bdev->bd_inode; struct request_queue *rq = bdev_get_queue(bdev); - struct inode *inode = NULL; + struct inode *inode; struct ntfs_inode *ni; size_t i, tt; CLST vcn, lcn, len; @@ -977,9 +977,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) sbi->volume.major_ver = info->major_ver; sbi->volume.minor_ver = info->minor_ver; sbi->volume.flags = info->flags; - sbi->volume.ni = ni; - inode = NULL; /* Load $MFTMirr to estimate recs_mirr. */ ref.low = cpu_to_le32(MFT_REC_MIRR); @@ -1011,7 +1009,6 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) goto out; iput(inode); - inode = NULL; is_ro = sb_rdonly(sbi->sb); @@ -1088,8 +1085,6 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) return PTR_ERR(inode); } - ni = ntfs_i(inode); - #ifndef CONFIG_NTFS3_64BIT_CLUSTER if (inode->i_size >> 32) { err = -EINVAL; @@ -1188,8 +1183,6 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) return PTR_ERR(inode); } - ni = ntfs_i(inode); - if (inode->i_size != 0x10000 * sizeof(short)) { err = -EINVAL; goto out; @@ -1225,7 +1218,6 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) } iput(inode); - inode = NULL; if (is_ntfs3(sbi)) { /* Load $Secure. */ @@ -1259,8 +1251,6 @@ load_root: return PTR_ERR(inode); } - ni = ntfs_i(inode); - sb->s_root = d_make_root(inode); if (!sb->s_root) return -ENOMEM; -- cgit From b4f110d65e21bf937fc5d3d894ec1cd540c85a71 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 9 Sep 2021 21:09:37 +0300 Subject: fs/ntfs3: Use sb instead of sbi->sb in fill_super Use sb instead of sbi->sb in fill_super. We have sb so why not use it. Also makes code more readable. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 4ff61534682c..c18705bf857f 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -1010,7 +1010,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) iput(inode); - is_ro = sb_rdonly(sbi->sb); + is_ro = sb_rdonly(sb); if (sbi->flags & NTFS_FLAGS_NEED_REPLAY) { if (!is_ro) { @@ -1101,7 +1101,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) /* Not necessary. */ sbi->used.bitmap.set_tail = true; - err = wnd_init(&sbi->used.bitmap, sbi->sb, tt); + err = wnd_init(&sbi->used.bitmap, sb, tt); if (err) goto out; @@ -1115,7 +1115,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) /* Load $AttrDef. */ ref.low = cpu_to_le32(MFT_REC_ATTR); ref.seq = cpu_to_le16(MFT_REC_ATTR); - inode = ntfs_iget5(sbi->sb, &ref, &NAME_ATTRDEF); + inode = ntfs_iget5(sb, &ref, &NAME_ATTRDEF); if (IS_ERR(inode)) { ntfs_err(sb, "Failed to load $AttrDef -> %d", err); return PTR_ERR(inode); -- cgit From 0cde7e81cd448a5df01a3960f6608b15dc3f12a3 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 9 Sep 2021 21:09:38 +0300 Subject: fs/ntfs3: Remove tmp var is_ro in ntfs_fill_super We only use this in two places so we do not really need it. Also wrapper sb_rdonly() is pretty self explanatory. This will make little bit easier to read this super long variable list in the beginning of ntfs_fill_super(). Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index c18705bf857f..93b8a1f4d748 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -887,7 +887,6 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) struct ATTR_DEF_ENTRY *t; u16 *upcase; u16 *shared; - bool is_ro; struct MFT_REF ref; ref.high = 0; @@ -1010,16 +1009,14 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) iput(inode); - is_ro = sb_rdonly(sb); - if (sbi->flags & NTFS_FLAGS_NEED_REPLAY) { - if (!is_ro) { + if (!sb_rdonly(sb)) { ntfs_warn(sb, "failed to replay log file. Can't mount rw!"); return -EINVAL; } } else if (sbi->volume.flags & VOLUME_FLAG_DIRTY) { - if (!is_ro && !sbi->options->force) { + if (!sb_rdonly(sb) && !sbi->options->force) { ntfs_warn( sb, "volume is dirty and \"force\" flag is not set!"); -- cgit From 4ea41b3eb5fd51b47742c6fa2ac1851a51ab0c69 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 9 Sep 2021 21:09:39 +0300 Subject: fs/ntfs3: Remove tmp pointer bd_inode in fill_super Drop tmp pointer bd_inode because this is only used ones in fill_super. Also we have so many initializing happening at the beginning that it is already way too much to follow. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 93b8a1f4d748..e5ec808bd052 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -875,7 +875,6 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) int err; struct ntfs_sb_info *sbi = sb->s_fs_info; struct block_device *bdev = sb->s_bdev; - struct inode *bd_inode = bdev->bd_inode; struct request_queue *rq = bdev_get_queue(bdev); struct inode *inode; struct ntfs_inode *ni; @@ -918,7 +917,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) /* Parse boot. */ err = ntfs_init_from_boot(sb, rq ? queue_logical_block_size(rq) : 512, - bd_inode->i_size); + bdev->bd_inode->i_size); if (err) return err; -- cgit From 0056b273757b3057a5aff73f96a7fa134641caf4 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 9 Sep 2021 21:09:40 +0300 Subject: fs/ntfs3: Remove tmp pointer upcase in fill_super We can survive without this tmp point upcase. So remove it we don't have so many tmp pointer in this function. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index e5ec808bd052..8ce0d4f439a1 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -884,7 +884,6 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) const struct VOLUME_INFO *info; u32 idx, done, bytes; struct ATTR_DEF_ENTRY *t; - u16 *upcase; u16 *shared; struct MFT_REF ref; @@ -1184,11 +1183,9 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) goto out; } - upcase = sbi->upcase; - for (idx = 0; idx < (0x10000 * sizeof(short) >> PAGE_SHIFT); idx++) { const __le16 *src; - u16 *dst = Add2Ptr(upcase, idx << PAGE_SHIFT); + u16 *dst = Add2Ptr(sbi->upcase, idx << PAGE_SHIFT); struct page *page = ntfs_map_page(inode->i_mapping, idx); if (IS_ERR(page)) { @@ -1207,10 +1204,10 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) ntfs_unmap_page(page); } - shared = ntfs_set_shared(upcase, 0x10000 * sizeof(short)); - if (shared && upcase != shared) { + shared = ntfs_set_shared(sbi->upcase, 0x10000 * sizeof(short)); + if (shared && sbi->upcase != shared) { + kvfree(sbi->upcase); sbi->upcase = shared; - kvfree(upcase); } iput(inode); -- cgit From 0e59a87ee619915c2eb189eb232a972c276681fb Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 9 Sep 2021 21:09:41 +0300 Subject: fs/ntfs3: Initialize pointer before use place in fill_super Initializing should be as close as possible when we use it so that we do not need to scroll up to see what is happening. Also bdev_get_queue() can never return NULL so we do not need to check for !rq. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 8ce0d4f439a1..3d034eac2bd1 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -875,7 +875,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) int err; struct ntfs_sb_info *sbi = sb->s_fs_info; struct block_device *bdev = sb->s_bdev; - struct request_queue *rq = bdev_get_queue(bdev); + struct request_queue *rq; struct inode *inode; struct ntfs_inode *ni; size_t i, tt; @@ -904,9 +904,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) return -EINVAL; } - if (!rq || !blk_queue_discard(rq) || !rq->limits.discard_granularity) { - ; - } else { + rq = bdev_get_queue(bdev); + if (blk_queue_discard(rq) && rq->limits.discard_granularity) { sbi->discard_granularity = rq->limits.discard_granularity; sbi->discard_granularity_mask_inv = ~(u64)(sbi->discard_granularity - 1); -- cgit From 28861e3bbd9e7ac4cd9c811aad71b4d116e27930 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Thu, 9 Sep 2021 21:09:42 +0300 Subject: fs/ntfs3: Initiliaze sb blocksize only in one place + refactor Right now sb blocksize first get initiliazed in fill_super but in can be changed in helper function. It makes more sense to that this happened only in one place. Because we move this to helper function it makes more sense that s_maxbytes will also be there. I rather have every sb releted thing in fill_super, but because there is already sb releted stuff in this helper. This will have to do for now. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 3d034eac2bd1..cefb9ddaf4db 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -840,8 +840,7 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size, rec->total = cpu_to_le32(sbi->record_size); ((struct ATTRIB *)Add2Ptr(rec, ao))->type = ATTR_END; - if (sbi->cluster_size < PAGE_SIZE) - sb_set_blocksize(sb, sbi->cluster_size); + sb_set_blocksize(sb, min_t(u32, sbi->cluster_size, PAGE_SIZE)); sbi->block_mask = sb->s_blocksize - 1; sbi->blocks_per_cluster = sbi->cluster_size >> sb->s_blocksize_bits; @@ -854,9 +853,11 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size, if (clusters >= (1ull << (64 - sbi->cluster_bits))) sbi->maxbytes = -1; sbi->maxbytes_sparse = -1; + sb->s_maxbytes = MAX_LFS_FILESIZE; #else /* Maximum size for sparse file. */ sbi->maxbytes_sparse = (1ull << (sbi->cluster_bits + 32)) - 1; + sb->s_maxbytes = 0xFFFFFFFFull << sbi->cluster_bits; #endif err = 0; @@ -911,20 +912,12 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) ~(u64)(sbi->discard_granularity - 1); } - sb_set_blocksize(sb, PAGE_SIZE); - /* Parse boot. */ err = ntfs_init_from_boot(sb, rq ? queue_logical_block_size(rq) : 512, bdev->bd_inode->i_size); if (err) return err; -#ifdef CONFIG_NTFS3_64BIT_CLUSTER - sb->s_maxbytes = MAX_LFS_FILESIZE; -#else - sb->s_maxbytes = 0xFFFFFFFFull << sbi->cluster_bits; -#endif - /* * Load $Volume. This should be done before $LogFile * 'cause 'sbi->volume.ni' is used 'ntfs_set_state'. -- cgit From a0fc05a37cae9e61aa29f7e283662ce70f7df342 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Fri, 10 Sep 2021 00:57:53 +0300 Subject: Doc/fs/ntfs3: Fix rst format and make it cleaner Current ntfs3 rst documentation is broken. I turn table to list table as this is current Linux documentation quide line. Simple table also did not quite work in our situation as we need to span rows together. It still look quite good as text so we did not loss anything. This will also make diffing quite bit more pleasure. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- Documentation/filesystems/ntfs3.rst | 139 ++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 63 deletions(-) diff --git a/Documentation/filesystems/ntfs3.rst b/Documentation/filesystems/ntfs3.rst index 7b6afe452197..d67ccd22c63b 100644 --- a/Documentation/filesystems/ntfs3.rst +++ b/Documentation/filesystems/ntfs3.rst @@ -4,99 +4,112 @@ NTFS3 ===== - Summary and Features ==================== -NTFS3 is fully functional NTFS Read-Write driver. The driver works with -NTFS versions up to 3.1, normal/compressed/sparse files -and journal replaying. File system type to use on mount is 'ntfs3'. +NTFS3 is fully functional NTFS Read-Write driver. The driver works with NTFS +versions up to 3.1. File system type to use on mount is *ntfs3*. - This driver implements NTFS read/write support for normal, sparse and compressed files. -- Supports native journal replaying; -- Supports extended attributes - Predefined extended attributes: - - 'system.ntfs_security' gets/sets security - descriptor (SECURITY_DESCRIPTOR_RELATIVE) - - 'system.ntfs_attrib' gets/sets ntfs file/dir attributes. - Note: applied to empty files, this allows to switch type between - sparse(0x200), compressed(0x800) and normal; +- Supports native journal replaying. - Supports NFS export of mounted NTFS volumes. +- Supports extended attributes. Predefined extended attributes: + + - *system.ntfs_security* gets/sets security + + Descriptor: SECURITY_DESCRIPTOR_RELATIVE + + - *system.ntfs_attrib* gets/sets ntfs file/dir attributes. + + Note: Applied to empty files, this allows to switch type between + sparse(0x200), compressed(0x800) and normal. Mount Options ============= The list below describes mount options supported by NTFS3 driver in addition to -generic ones. +generic ones. You can use every mount option with **no** option. If it is in +this table marked with no it means default is without **no**. -=============================================================================== +.. flat-table:: + :widths: 1 5 + :fill-cells: -iocharset=name This option informs the driver how to interpret path - strings and translate them to Unicode and back. If - this option is not set, the default codepage will be - used (CONFIG_NLS_DEFAULT). - Examples: - 'iocharset=utf8' + * - iocharset=name + - This option informs the driver how to interpret path strings and + translate them to Unicode and back. If this option is not set, the + default codepage will be used (CONFIG_NLS_DEFAULT). -uid= -gid= -umask= Controls the default permissions for files/directories created - after the NTFS volume is mounted. + Example: iocharset=utf8 -fmask= -dmask= Instead of specifying umask which applies both to - files and directories, fmask applies only to files and - dmask only to directories. + * - uid= + - :rspan:`1` + * - gid= -nohidden Files with the Windows-specific HIDDEN (FILE_ATTRIBUTE_HIDDEN) - attribute will not be shown under Linux. + * - umask= + - Controls the default permissions for files/directories created after + the NTFS volume is mounted. -sys_immutable Files with the Windows-specific SYSTEM - (FILE_ATTRIBUTE_SYSTEM) attribute will be marked as system - immutable files. + * - dmask= + - :rspan:`1` Instead of specifying umask which applies both to files and + directories, fmask applies only to files and dmask only to directories. + * - fmask= -discard Enable support of the TRIM command for improved performance - on delete operations, which is recommended for use with the - solid-state drives (SSD). + * - noacsrules + - "No access rules" mount option sets access rights for files/folders to + 777 and owner/group to root. This mount option absorbs all other + permissions. -force Forces the driver to mount partitions even if 'dirty' flag - (volume dirty) is set. Not recommended for use. + - Permissions change for files/folders will be reported as successful, + but they will remain 777. -sparse Create new files as "sparse". + - Owner/group change will be reported as successful, butthey will stay + as root. -showmeta Use this parameter to show all meta-files (System Files) on - a mounted NTFS partition. - By default, all meta-files are hidden. + * - nohidden + - Files with the Windows-specific HIDDEN (FILE_ATTRIBUTE_HIDDEN) attribute + will not be shown under Linux. -prealloc Preallocate space for files excessively when file size is - increasing on writes. Decreases fragmentation in case of - parallel write operations to different files. + * - sys_immutable + - Files with the Windows-specific SYSTEM (FILE_ATTRIBUTE_SYSTEM) attribute + will be marked as system immutable files. -noacsrules "No access rules" mount option sets access rights for - files/folders to 777 and owner/group to root. This mount - option absorbs all other permissions: - - permissions change for files/folders will be reported - as successful, but they will remain 777; - - owner/group change will be reported as successful, but - they will stay as root + * - discard + - Enable support of the TRIM command for improved performance on delete + operations, which is recommended for use with the solid-state drives + (SSD). -acl Support POSIX ACLs (Access Control Lists). Effective if - supported by Kernel. Not to be confused with NTFS ACLs. - The option specified as acl enables support for POSIX ACLs. + * - force + - Forces the driver to mount partitions even if volume is marked dirty. + Not recommended for use. -=============================================================================== + * - sparse + - Create new files as sparse. -ToDo list -========= + * - showmeta + - Use this parameter to show all meta-files (System Files) on a mounted + NTFS partition. By default, all meta-files are hidden. -- Full journaling support (currently journal replaying is supported) over JBD. + * - prealloc + - Preallocate space for files excessively when file size is increasing on + writes. Decreases fragmentation in case of parallel write operations to + different files. + * - acl + - Support POSIX ACLs (Access Control Lists). Effective if supported by + Kernel. Not to be confused with NTFS ACLs. The option specified as acl + enables support for POSIX ACLs. + +Todo list +========= +- Full journaling support over JBD. Currently journal replaying is supported + which is not necessarily as effectice as JBD would be. References ========== -https://www.paragon-software.com/home/ntfs-linux-professional/ - - Commercial version of the NTFS driver for Linux. +- Commercial version of the NTFS driver for Linux. + https://www.paragon-software.com/home/ntfs-linux-professional/ -almaz.alexandrovich@paragon-software.com - - Direct e-mail address for feedback and requests on the NTFS3 implementation. +- Direct e-mail address for feedback and requests on the NTFS3 implementation. + almaz.alexandrovich@paragon-software.com -- cgit From 880301bb313295a65523e79bc5666f5cf49eb3ed Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 10 Sep 2021 11:02:02 +0100 Subject: fs/ntfs3: Fix a memory leak on object opts Currently a failed allocation on sbi->upcase will cause an exit via the label free_sbi causing a memory leak on object opts. Fix this by re-ordering the exit paths free_opts and free_sbi so that kfree's occur in the reverse allocation order. Addresses-Coverity: ("Resource leak") Fixes: 27fac77707a1 ("fs/ntfs3: Init spi more in init_fs_context than fill_super") Signed-off-by: Colin Ian King Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index cefb9ddaf4db..6a535b144ff9 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -1393,10 +1393,10 @@ ok: fc->ops = &ntfs_context_ops; return 0; -free_opts: - kfree(opts); free_sbi: kfree(sbi); +free_opts: + kfree(opts); return -ENOMEM; } -- cgit From d7a48e27b38a94bf73c973c236461234610256d5 Mon Sep 17 00:00:00 2001 From: Apurva Nandan Date: Mon, 20 Sep 2021 19:57:13 +0530 Subject: spi: Use 'flash' node name instead of 'spi-flash' in example Change the nodename in the example with spi-nand from 'spi-flash@1' to 'flash@1' to make the schema uniform with both spi-nand and spi-nor flashes. jedec,spi-nor.yaml uses 'flash@' nodename for spi-nor flashes, so make the spi-nand examples in dt-bindings use it too for uniformity. Signed-off-by: Apurva Nandan Reviewed-by: Serge Semin Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210920142713.129295-3-a-nandan@ti.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml index ca91201a9926..d7e08b03e204 100644 --- a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml +++ b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml @@ -171,7 +171,7 @@ examples: cs-gpios = <&gpio0 13 0>, <&gpio0 14 0>; rx-sample-delay-ns = <3>; - spi-flash@1 { + flash@1 { compatible = "spi-nand"; reg = <1>; rx-sample-delay-ns = <7>; -- cgit From ee9d4810aab95208541d2807f9d114f1d5edcee0 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Wed, 8 Sep 2021 18:39:53 +0300 Subject: fs/ntfs3: Fix insertion of attr in ni_ins_attr_ext Do not try to insert attribute if there is no room in record. Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/frecord.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index 1e1a09034f65..0d00b2301a2f 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -953,6 +953,13 @@ static int ni_ins_attr_ext(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le, continue; } + /* + * Do not try to insert this attribute + * if there is no room in record. + */ + if (le32_to_cpu(mi->mrec->used) + asize > sbi->record_size) + continue; + /* Try to insert attribute into this subrecord. */ attr = ni_ins_new_attr(ni, mi, le, type, name, name_len, asize, name_off, svcn, ins_le); -- cgit From 56eaeb10e2619081cc383febf6740a4c3e806777 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 9 Sep 2021 13:12:41 +0300 Subject: fs/ntfs3: Change max hardlinks limit to 4000 xfstest generic/041 works with 3003 hardlinks. Because of this we raise hardlinks limit to 4000. There are no drawbacks or regressions. Theoretically we can raise all the way up to ffff, but there is no practical use for this. Signed-off-by: Konstantin Komarov --- fs/ntfs3/ntfs.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/ntfs3/ntfs.h b/fs/ntfs3/ntfs.h index 303a162c3158..9cc396b117bf 100644 --- a/fs/ntfs3/ntfs.h +++ b/fs/ntfs3/ntfs.h @@ -26,9 +26,11 @@ #define NTFS_NAME_LEN 255 -/* ntfs.sys used 500 maximum links on-disk struct allows up to 0xffff. */ -#define NTFS_LINK_MAX 0x400 -//#define NTFS_LINK_MAX 0xffff +/* + * ntfs.sys used 500 maximum links on-disk struct allows up to 0xffff. + * xfstest generic/041 creates 3003 hardlinks. + */ +#define NTFS_LINK_MAX 4000 /* * Activate to use 64 bit clusters instead of 32 bits in ntfs.sys. -- cgit From 6354467245ff8dd04b54e39790f2ee4d21d5419e Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 9 Sep 2021 13:15:20 +0300 Subject: fs/ntfs3: Add sync flag to ntfs_sb_write_run and al_update This allows to wait only when it's requested. It speeds up creation of hardlinks. Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 2 +- fs/ntfs3/attrlist.c | 6 +++--- fs/ntfs3/frecord.c | 2 +- fs/ntfs3/fslog.c | 8 ++++---- fs/ntfs3/fsntfs.c | 8 ++++---- fs/ntfs3/inode.c | 2 +- fs/ntfs3/ntfs_fs.h | 4 ++-- fs/ntfs3/xattr.c | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index c15cc17e3cd9..8a00fa978f5f 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -287,7 +287,7 @@ int attr_make_nonresident(struct ntfs_inode *ni, struct ATTRIB *attr, if (!rsize) { /* Empty resident -> Non empty nonresident. */ } else if (!is_data) { - err = ntfs_sb_write_run(sbi, run, 0, data, rsize); + err = ntfs_sb_write_run(sbi, run, 0, data, rsize, 0); if (err) goto out2; } else if (!page) { diff --git a/fs/ntfs3/attrlist.c b/fs/ntfs3/attrlist.c index b9da527b96aa..bad6d8a849a2 100644 --- a/fs/ntfs3/attrlist.c +++ b/fs/ntfs3/attrlist.c @@ -333,7 +333,7 @@ int al_add_le(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name, if (attr && attr->non_res) { err = ntfs_sb_write_run(ni->mi.sbi, &al->run, 0, al->le, - al->size); + al->size, 0); if (err) return err; al->dirty = false; @@ -420,7 +420,7 @@ next: return true; } -int al_update(struct ntfs_inode *ni) +int al_update(struct ntfs_inode *ni, int sync) { int err; struct ATTRIB *attr; @@ -442,7 +442,7 @@ int al_update(struct ntfs_inode *ni) memcpy(resident_data(attr), al->le, al->size); } else { err = ntfs_sb_write_run(ni->mi.sbi, &al->run, 0, al->le, - al->size); + al->size, sync); if (err) goto out; diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index 0d00b2301a2f..9a53f809576d 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -3208,7 +3208,7 @@ int ni_write_inode(struct inode *inode, int sync, const char *hint) goto out; } - err = al_update(ni); + err = al_update(ni, sync); if (err) goto out; } diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c index 6e7f9b72792b..06492f088d60 100644 --- a/fs/ntfs3/fslog.c +++ b/fs/ntfs3/fslog.c @@ -2215,7 +2215,7 @@ file_is_valid: err = ntfs_sb_write_run(log->ni->mi.sbi, &log->ni->file.run, off, page, - log->page_size); + log->page_size, 0); if (err) goto out; @@ -3706,7 +3706,7 @@ move_data: if (a_dirty) { attr = oa->attr; - err = ntfs_sb_write_run(sbi, oa->run1, vbo, buffer_le, bytes); + err = ntfs_sb_write_run(sbi, oa->run1, vbo, buffer_le, bytes, 0); if (err) goto out; } @@ -5148,10 +5148,10 @@ end_reply: ntfs_fix_pre_write(&rh->rhdr, log->page_size); - err = ntfs_sb_write_run(sbi, &ni->file.run, 0, rh, log->page_size); + err = ntfs_sb_write_run(sbi, &ni->file.run, 0, rh, log->page_size, 0); if (!err) err = ntfs_sb_write_run(sbi, &log->ni->file.run, log->page_size, - rh, log->page_size); + rh, log->page_size, 0); kfree(rh); if (err) diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c index 77d2e56d5b4f..4de9acb16968 100644 --- a/fs/ntfs3/fsntfs.c +++ b/fs/ntfs3/fsntfs.c @@ -1077,7 +1077,7 @@ int ntfs_sb_write(struct super_block *sb, u64 lbo, size_t bytes, } int ntfs_sb_write_run(struct ntfs_sb_info *sbi, const struct runs_tree *run, - u64 vbo, const void *buf, size_t bytes) + u64 vbo, const void *buf, size_t bytes, int sync) { struct super_block *sb = sbi->sb; u8 cluster_bits = sbi->cluster_bits; @@ -1097,7 +1097,7 @@ int ntfs_sb_write_run(struct ntfs_sb_info *sbi, const struct runs_tree *run, for (;;) { u32 op = min_t(u64, len, bytes); - int err = ntfs_sb_write(sb, lbo, op, buf, 0); + int err = ntfs_sb_write(sb, lbo, op, buf, sync); if (err) return err; @@ -2172,7 +2172,7 @@ int ntfs_insert_security(struct ntfs_sb_info *sbi, /* Write main SDS bucket. */ err = ntfs_sb_write_run(sbi, &ni->file.run, sbi->security.next_off, - d_security, aligned_sec_size); + d_security, aligned_sec_size, 0); if (err) goto out; @@ -2190,7 +2190,7 @@ int ntfs_insert_security(struct ntfs_sb_info *sbi, /* Write copy SDS bucket. */ err = ntfs_sb_write_run(sbi, &ni->file.run, mirr_off, d_security, - aligned_sec_size); + aligned_sec_size, 0); if (err) goto out; diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 33f278a0947c..d583b71bec50 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -1584,7 +1584,7 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns, /* Write non resident data. */ if (nsize) { - err = ntfs_sb_write_run(sbi, &ni->file.run, 0, rp, nsize); + err = ntfs_sb_write_run(sbi, &ni->file.run, 0, rp, nsize, 0); if (err) goto out7; } diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index dae6dd4ac619..6731b5d9e2d8 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -465,7 +465,7 @@ bool al_remove_le(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le); bool al_delete_le(struct ntfs_inode *ni, enum ATTR_TYPE type, CLST vcn, const __le16 *name, size_t name_len, const struct MFT_REF *ref); -int al_update(struct ntfs_inode *ni); +int al_update(struct ntfs_inode *ni, int sync); static inline size_t al_aligned(size_t size) { return (size + 1023) & ~(size_t)1023; @@ -606,7 +606,7 @@ int ntfs_sb_read(struct super_block *sb, u64 lbo, size_t bytes, void *buffer); int ntfs_sb_write(struct super_block *sb, u64 lbo, size_t bytes, const void *buffer, int wait); int ntfs_sb_write_run(struct ntfs_sb_info *sbi, const struct runs_tree *run, - u64 vbo, const void *buf, size_t bytes); + u64 vbo, const void *buf, size_t bytes, int sync); struct buffer_head *ntfs_bread_run(struct ntfs_sb_info *sbi, const struct runs_tree *run, u64 vbo); int ntfs_read_run_nb(struct ntfs_sb_info *sbi, const struct runs_tree *run, diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index a8c5a899f0dd..5c7c5c7a5ec1 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -441,7 +441,7 @@ update_ea: /* Delete xattr, ATTR_EA */ ni_remove_attr_le(ni, attr, mi, le); } else if (attr->non_res) { - err = ntfs_sb_write_run(sbi, &ea_run, 0, ea_all, size); + err = ntfs_sb_write_run(sbi, &ea_run, 0, ea_all, size, 0); if (err) goto out; } else { -- cgit From d2846bf33c1423ff872c7a7c2afde292ad502c04 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 18 Sep 2021 21:56:19 +0200 Subject: fs/ntfs3: Remove a useless test in 'indx_find()' 'fnd' has been dereferenced several time before, so testing it here is pointless. Moreover, all callers of 'indx_find()' already have some error handling code that makes sure that no NULL 'fnd' is passed. So, remove the useless test. Signed-off-by: Christophe JAILLET Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/index.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c index 4f71a91f07d9..6f81e3a49abf 100644 --- a/fs/ntfs3/index.c +++ b/fs/ntfs3/index.c @@ -1072,9 +1072,7 @@ int indx_find(struct ntfs_index *indx, struct ntfs_inode *ni, if (!e) return -EINVAL; - if (fnd) - fnd->root_de = e; - + fnd->root_de = e; err = 0; for (;;) { -- cgit From 808bc0a82bcd2cbe32a139613325b1a3e03f35f1 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 18 Sep 2021 21:56:28 +0200 Subject: fs/ntfs3: Remove a useless shadowing variable There is already a 'u8 mask' defined at the top of the function. There is no need to define a new one here. Remove the useless and shadowing new 'mask' variable. Signed-off-by: Christophe JAILLET Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/bitfunc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/ntfs3/bitfunc.c b/fs/ntfs3/bitfunc.c index bf10e2da5c6e..50d838093790 100644 --- a/fs/ntfs3/bitfunc.c +++ b/fs/ntfs3/bitfunc.c @@ -119,8 +119,7 @@ bool are_bits_set(const ulong *lmap, size_t bit, size_t nbits) pos = nbits & 7; if (pos) { - u8 mask = fill_mask[pos]; - + mask = fill_mask[pos]; if ((*map & mask) != mask) return false; } -- cgit From 82cb875313188ccbd3ac174b471c86dcb97b8626 Mon Sep 17 00:00:00 2001 From: Kari Argillander Date: Tue, 21 Sep 2021 20:19:01 +0300 Subject: fs/ntfs3: Remove deprecated mount options nls Some discussion has been spoken that this deprecated mount options should be removed before 5.15 lands. This driver is not never seen day light so it was decided that nls mount option has to be removed. We have always possibility to add this if needed. One possible need is example if current ntfs driver will be taken out of kernel and ntfs3 needs to support mount options what it has. Signed-off-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 6a535b144ff9..800897777eb0 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -246,10 +246,6 @@ static const struct fs_parameter_spec ntfs_fs_parameters[] = { fsparam_flag_no("prealloc", Opt_prealloc), fsparam_flag_no("acsrules", Opt_noacsrules), fsparam_string("iocharset", Opt_iocharset), - - __fsparam(fs_param_is_string, - "nls", Opt_iocharset, - fs_param_deprecated, NULL), {} }; -- cgit From 664bb2e45b89cd8213e3c9772713323f75e21892 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Wed, 22 Sep 2021 12:24:04 +0100 Subject: clk: renesas: r9a07g044: Mark IA55_CLK and DMAC_ACLK critical Add IA55_CLK and DMAC_ACLK as critical clocks. Previously it worked ok, because of a bug in clock status function and the following patch in this series fixes the original bug. Fixes: c3e67ad6f5a2 ("dt-bindings: clock: r9a07g044-cpg: Update clock/reset definitions") Fixes: eb829e549ba6 ("clk: renesas: r9a07g044: Add DMAC clocks/resets") Signed-off-by: Biju Das Link: https://lore.kernel.org/r/20210922112405.26413-1-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a07g044-cpg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c index 4c94b94c4125..1490446985e2 100644 --- a/drivers/clk/renesas/r9a07g044-cpg.c +++ b/drivers/clk/renesas/r9a07g044-cpg.c @@ -186,6 +186,8 @@ static struct rzg2l_reset r9a07g044_resets[] = { static const unsigned int r9a07g044_crit_mod_clks[] __initconst = { MOD_CLK_BASE + R9A07G044_GIC600_GICCLK, + MOD_CLK_BASE + R9A07G044_IA55_CLK, + MOD_CLK_BASE + R9A07G044_DMAC_ACLK, }; const struct rzg2l_cpg_info r9a07g044_cpg_info = { -- cgit From fa2a30f8e0aa9304919750b116a9e9e322465299 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Wed, 22 Sep 2021 12:24:05 +0100 Subject: clk: renesas: rzg2l: Fix clk status function As per RZ/G2L HW(Rev.0.50) manual, clock monitor register value 0 means clock is not supplied and 1 means clock is supplied. This patch fixes the issue by removing the inverted logic. Fixing the above, triggered following 2 issues 1) GIC interrupts don't work if we disable IA55_CLK and DMAC_ACLK. Fixed this issue by adding these clocks as critical clocks. 2) DMA is not working, since the DMA driver is not turning on DMAC_PCLK. So will provide a fix in the DMA driver to turn on DMA_PCLK. Fixes: ef3c613ccd68 ("clk: renesas: Add CPG core wrapper for RZ/G2L SoC") Signed-off-by: Biju Das Link: https://lore.kernel.org/r/20210922112405.26413-2-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzg2l-cpg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 3b3b2c3347f3..761922ea5db7 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -391,7 +391,7 @@ static int rzg2l_mod_clock_is_enabled(struct clk_hw *hw) value = readl(priv->base + CLK_MON_R(clock->off)); - return !(value & bitmask); + return value & bitmask; } static const struct clk_ops rzg2l_mod_clock_ops = { -- cgit From 6c1ee4d304983d2f68bf7639d5912f781398d5ac Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 23 Sep 2021 18:05:36 +0300 Subject: fs/ntfs3: Fix logical error in ntfs_create_inode We need to always call indx_delete_entry after indx_insert_entry if error occurred. Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index d583b71bec50..d51bf4018835 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -1575,7 +1575,7 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns, if (!S_ISLNK(mode) && (sb->s_flags & SB_POSIXACL)) { err = ntfs_init_acl(mnt_userns, inode, dir); if (err) - goto out6; + goto out7; } else #endif { -- cgit From d562e901f25d275b55b0496fe01935beeff0ed37 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Thu, 23 Sep 2021 18:04:26 +0300 Subject: fs/ntfs3: Move ni_lock_dir and ni_unlock into ntfs_create_inode Now ntfs3 locks mutex for smaller time. Theoretically in successful cases those locks aren't needed at all. But proving the same for error cases is difficult. So instead of removing them we just move them. Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/inode.c | 17 ++++++++++++++--- fs/ntfs3/namei.c | 20 -------------------- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index d51bf4018835..7dd162f6a7e2 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -1198,9 +1198,13 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns, struct REPARSE_DATA_BUFFER *rp = NULL; bool rp_inserted = false; + ni_lock_dir(dir_ni); + dir_root = indx_get_root(&dir_ni->dir, dir_ni, NULL, NULL); - if (!dir_root) - return ERR_PTR(-EINVAL); + if (!dir_root) { + err = -EINVAL; + goto out1; + } if (S_ISDIR(mode)) { /* Use parent's directory attributes. */ @@ -1549,6 +1553,9 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns, if (err) goto out6; + /* Unlock parent directory before ntfs_init_acl. */ + ni_unlock(dir_ni); + inode->i_generation = le16_to_cpu(rec->seq); dir->i_mtime = dir->i_ctime = inode->i_atime; @@ -1605,8 +1612,10 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns, out7: /* Undo 'indx_insert_entry'. */ + ni_lock_dir(dir_ni); indx_delete_entry(&dir_ni->dir, dir_ni, new_de + 1, le16_to_cpu(new_de->key_size), sbi); + /* ni_unlock(dir_ni); will be called later. */ out6: if (rp_inserted) ntfs_remove_reparse(sbi, IO_REPARSE_TAG_SYMLINK, &new_de->ref); @@ -1630,8 +1639,10 @@ out2: kfree(rp); out1: - if (err) + if (err) { + ni_unlock(dir_ni); return ERR_PTR(err); + } unlock_new_inode(inode); diff --git a/fs/ntfs3/namei.c b/fs/ntfs3/namei.c index 1c475da4e19d..bc741213ad84 100644 --- a/fs/ntfs3/namei.c +++ b/fs/ntfs3/namei.c @@ -95,16 +95,11 @@ static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *dentry, static int ntfs_create(struct user_namespace *mnt_userns, struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) { - struct ntfs_inode *ni = ntfs_i(dir); struct inode *inode; - ni_lock_dir(ni); - inode = ntfs_create_inode(mnt_userns, dir, dentry, NULL, S_IFREG | mode, 0, NULL, 0, NULL); - ni_unlock(ni); - return IS_ERR(inode) ? PTR_ERR(inode) : 0; } @@ -116,16 +111,11 @@ static int ntfs_create(struct user_namespace *mnt_userns, struct inode *dir, static int ntfs_mknod(struct user_namespace *mnt_userns, struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev) { - struct ntfs_inode *ni = ntfs_i(dir); struct inode *inode; - ni_lock_dir(ni); - inode = ntfs_create_inode(mnt_userns, dir, dentry, NULL, mode, rdev, NULL, 0, NULL); - ni_unlock(ni); - return IS_ERR(inode) ? PTR_ERR(inode) : 0; } @@ -196,15 +186,10 @@ static int ntfs_symlink(struct user_namespace *mnt_userns, struct inode *dir, { u32 size = strlen(symname); struct inode *inode; - struct ntfs_inode *ni = ntfs_i(dir); - - ni_lock_dir(ni); inode = ntfs_create_inode(mnt_userns, dir, dentry, NULL, S_IFLNK | 0777, 0, symname, size, NULL); - ni_unlock(ni); - return IS_ERR(inode) ? PTR_ERR(inode) : 0; } @@ -215,15 +200,10 @@ static int ntfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir, struct dentry *dentry, umode_t mode) { struct inode *inode; - struct ntfs_inode *ni = ntfs_i(dir); - - ni_lock_dir(ni); inode = ntfs_create_inode(mnt_userns, dir, dentry, NULL, S_IFDIR | mode, 0, NULL, 0, NULL); - ni_unlock(ni); - return IS_ERR(inode) ? PTR_ERR(inode) : 0; } -- cgit From 0bd5fdb811b0449fcef948a100099cc3197f1b73 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Wed, 22 Sep 2021 18:28:36 +0300 Subject: fs/ntfs3: Refactor ntfs_get_acl_ex for better readability We can safely move set_cached_acl because it works with NULL acl too. Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/xattr.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index 5c7c5c7a5ec1..3795943efc8e 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -518,12 +518,15 @@ static struct posix_acl *ntfs_get_acl_ex(struct user_namespace *mnt_userns, /* Translate extended attribute to acl. */ if (err >= 0) { acl = posix_acl_from_xattr(mnt_userns, buf, err); - if (!IS_ERR(acl)) - set_cached_acl(inode, type, acl); + } else if (err == -ENODATA) { + acl = NULL; } else { - acl = err == -ENODATA ? NULL : ERR_PTR(err); + acl = ERR_PTR(err); } + if (!IS_ERR(acl)) + set_cached_acl(inode, type, acl); + __putname(buf); return acl; -- cgit From 398c35f4d78410725e154c2fc0a51ecac05a3f1f Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Wed, 22 Sep 2021 18:33:38 +0300 Subject: fs/ntfs3: Pass flags to ntfs_set_ea in ntfs_set_acl_ex In case of removing of xattr there must be XATTR_REPLACE flag and zero length. We already check XATTR_REPLACE in ntfs_set_ea, so now we pass XATTR_REPLACE to ntfs_set_ea. Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/xattr.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index 3795943efc8e..70f2f9eb6b1e 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -549,6 +549,7 @@ static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns, size_t size, name_len; void *value = NULL; int err = 0; + int flags; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; @@ -591,20 +592,24 @@ static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns, } if (!acl) { + /* Remove xattr if it can be presented via mode. */ size = 0; value = NULL; + flags = XATTR_REPLACE; } else { size = posix_acl_xattr_size(acl->a_count); value = kmalloc(size, GFP_NOFS); if (!value) return -ENOMEM; - err = posix_acl_to_xattr(mnt_userns, acl, value, size); if (err < 0) goto out; + flags = 0; } - err = ntfs_set_ea(inode, name, name_len, value, size, 0, locked); + err = ntfs_set_ea(inode, name, name_len, value, size, flags, locked); + if (err == -ENODATA && !size) + err = 0; /* Removing non existed xattr. */ if (!err) set_cached_acl(inode, type, acl); -- cgit From ba77237ef880320105e681b93d596b2fb13860f9 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Wed, 22 Sep 2021 18:46:14 +0300 Subject: fs/ntfs3: Change posix_acl_equiv_mode to posix_acl_update_mode Right now ntfs3 uses posix_acl_equiv_mode instead of posix_acl_update_mode like all other fs. Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/xattr.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index 70f2f9eb6b1e..59ec5e61a239 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -559,22 +559,15 @@ static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns, if (acl) { umode_t mode = inode->i_mode; - err = posix_acl_equiv_mode(acl, &mode); - if (err < 0) - return err; + 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); } - - if (!err) { - /* - * ACL can be exactly represented in the - * traditional file mode permission bits. - */ - acl = NULL; - } } name = XATTR_NAME_POSIX_ACL_ACCESS; name_len = sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1; -- cgit From 66019837a5563e1f80a4228b7d110d8c52bfdd8b Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Wed, 22 Sep 2021 18:50:58 +0300 Subject: fs/ntfs3: Refactoring lock in ntfs_init_acl This is possible because of moving lock into ntfs_create_inode. Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/xattr.c | 55 ++++++++++++++----------------------------------------- 1 file changed, 14 insertions(+), 41 deletions(-) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index 59ec5e61a239..83bbee277e12 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -693,54 +693,27 @@ int ntfs_init_acl(struct user_namespace *mnt_userns, struct inode *inode, struct posix_acl *default_acl, *acl; int err; - /* - * TODO: Refactoring lock. - * ni_lock(dir) ... -> posix_acl_create(dir,...) -> ntfs_get_acl -> ni_lock(dir) - */ - inode->i_default_acl = NULL; - - default_acl = ntfs_get_acl_ex(mnt_userns, dir, ACL_TYPE_DEFAULT, 1); - - if (!default_acl || default_acl == ERR_PTR(-EOPNOTSUPP)) { - inode->i_mode &= ~current_umask(); - err = 0; - goto out; - } - - if (IS_ERR(default_acl)) { - err = PTR_ERR(default_acl); - goto out; - } - - acl = default_acl; - err = __posix_acl_create(&acl, GFP_NOFS, &inode->i_mode); - if (err < 0) - goto out1; - if (!err) { - posix_acl_release(acl); - acl = NULL; - } - - if (!S_ISDIR(inode->i_mode)) { - posix_acl_release(default_acl); - default_acl = NULL; - } + err = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl); + if (err) + return err; - if (default_acl) + if (default_acl) { err = ntfs_set_acl_ex(mnt_userns, inode, default_acl, ACL_TYPE_DEFAULT, 1); + posix_acl_release(default_acl); + } else { + inode->i_default_acl = NULL; + } if (!acl) inode->i_acl = NULL; - else if (!err) - err = ntfs_set_acl_ex(mnt_userns, inode, acl, ACL_TYPE_ACCESS, - 1); - - posix_acl_release(acl); -out1: - posix_acl_release(default_acl); + else { + if (!err) + err = ntfs_set_acl_ex(mnt_userns, inode, acl, + ACL_TYPE_ACCESS, 1); + posix_acl_release(acl); + } -out: return err; } #endif -- cgit From 09540fa337196be20e9f0241652364f09275d374 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Thu, 16 Sep 2021 17:51:26 -0500 Subject: clk: socfpga: agilex: fix duplicate s2f_user0_clk Remove the duplicate s2f_user0_clk and the unused s2f_usr0_mux define. Fixes: f817c132db67 ("clk: socfpga: agilex: fix up s2f_user0_clk representation") Cc: stable@vger.kernel.org Signed-off-by: Dinh Nguyen Link: https://lore.kernel.org/r/20210916225126.1427700-1-dinguyen@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/socfpga/clk-agilex.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/clk/socfpga/clk-agilex.c b/drivers/clk/socfpga/clk-agilex.c index 242e94c0cf8a..bf8cd928c228 100644 --- a/drivers/clk/socfpga/clk-agilex.c +++ b/drivers/clk/socfpga/clk-agilex.c @@ -165,13 +165,6 @@ static const struct clk_parent_data mpu_mux[] = { .name = "boot_clk", }, }; -static const struct clk_parent_data s2f_usr0_mux[] = { - { .fw_name = "f2s-free-clk", - .name = "f2s-free-clk", }, - { .fw_name = "boot_clk", - .name = "boot_clk", }, -}; - static const struct clk_parent_data emac_mux[] = { { .fw_name = "emaca_free_clk", .name = "emaca_free_clk", }, @@ -312,8 +305,6 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = { 4, 0x44, 28, 1, 0, 0, 0}, { AGILEX_CS_TIMER_CLK, "cs_timer_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, 5, 0, 0, 0, 0x30, 1, 0}, - { AGILEX_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x24, - 6, 0, 0, 0, 0, 0, 0}, { AGILEX_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C, 0, 0, 0, 0, 0x94, 26, 0}, { AGILEX_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C, -- cgit From 9da1b86865ab4376408c58cd9fec332c8bdb5c73 Mon Sep 17 00:00:00 2001 From: Nuno Sá Date: Mon, 20 Sep 2021 11:00:47 +0200 Subject: iio: adis16475: fix deadlock on frequency set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With commit 39c024b51b560 ("iio: adis16475: improve sync scale mode handling"), two deadlocks were introduced: 1) The call to 'adis_write_reg_16()' was not changed to it's unlocked version. 2) The lock was not being released on the success path of the function. This change fixes both these issues. Fixes: 39c024b51b560 ("iio: adis16475: improve sync scale mode handling") Signed-off-by: Nuno Sá Reviewed-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20210920090047.74903-1-nuno.sa@analog.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis16475.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c index eb48102f9424..287fff39a927 100644 --- a/drivers/iio/imu/adis16475.c +++ b/drivers/iio/imu/adis16475.c @@ -353,10 +353,11 @@ static int adis16475_set_freq(struct adis16475 *st, const u32 freq) if (dec > st->info->max_dec) dec = st->info->max_dec; - ret = adis_write_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, dec); + ret = __adis_write_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, dec); if (ret) goto error; + adis_dev_unlock(&st->adis); /* * If decimation is used, then gyro and accel data will have meaningful * bits on the LSB registers. This info is used on the trigger handler. -- cgit From c2980c64c7fd4585d684574c92d1624d44961edd Mon Sep 17 00:00:00 2001 From: Hui Liu Date: Sun, 26 Sep 2021 15:30:28 +0800 Subject: iio: mtk-auxadc: fix case IIO_CHAN_INFO_PROCESSED The previous driver does't apply the necessary scaling to take the voltage range into account. We change readback value from raw data to input voltage to fix case IIO_CHAN_INFO_PROCESSED. Fixes: ace4cdfe67be ("iio: adc: mt2701: Add Mediatek auxadc driver for mt2701.") Signed-off-by: Hui Liu Link: https://lore.kernel.org/r/20210926073028.11045-2-hui.liu@mediatek.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mt6577_auxadc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c index 79c1dd68b909..d4fccd52ef08 100644 --- a/drivers/iio/adc/mt6577_auxadc.c +++ b/drivers/iio/adc/mt6577_auxadc.c @@ -82,6 +82,10 @@ static const struct iio_chan_spec mt6577_auxadc_iio_channels[] = { MT6577_AUXADC_CHANNEL(15), }; +/* For Voltage calculation */ +#define VOLTAGE_FULL_RANGE 1500 /* VA voltage */ +#define AUXADC_PRECISE 4096 /* 12 bits */ + static int mt_auxadc_get_cali_data(int rawdata, bool enable_cali) { return rawdata; @@ -191,6 +195,10 @@ static int mt6577_auxadc_read_raw(struct iio_dev *indio_dev, } if (adc_dev->dev_comp->sample_data_cali) *val = mt_auxadc_get_cali_data(*val, true); + + /* Convert adc raw data to voltage: 0 - 1500 mV */ + *val = *val * VOLTAGE_FULL_RANGE / AUXADC_PRECISE; + return IIO_VAL_INT; default: -- cgit From ea1945c2f72d7bd253e2ebaa97cdd8d9ffcde076 Mon Sep 17 00:00:00 2001 From: Nuno Sá Date: Fri, 3 Sep 2021 16:14:23 +0200 Subject: iio: adis16480: fix devices that do not support sleep mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not all devices supported by this driver support being put to sleep mode. For those devices, when calling 'adis16480_stop_device()' on the unbind path, we where actually writing in the SYNC_SCALE register. Fixes: 80cbc848c4fa0 ("iio: imu: adis16480: Add support for ADIS16490") Fixes: 82e7a1b250170 ("iio: imu: adis16480: Add support for ADIS1649x family of devices") Signed-off-by: Nuno Sá Link: https://lore.kernel.org/r/20210903141423.517028-6-nuno.sa@analog.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis16480.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index a869a6e52a16..ed129321a14d 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -144,6 +144,7 @@ struct adis16480_chip_info { unsigned int max_dec_rate; const unsigned int *filter_freqs; bool has_pps_clk_mode; + bool has_sleep_cnt; const struct adis_data adis_data; }; @@ -939,6 +940,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .temp_scale = 5650, /* 5.65 milli degree Celsius */ .int_clk = 2460000, .max_dec_rate = 2048, + .has_sleep_cnt = true, .filter_freqs = adis16480_def_filter_freqs, .adis_data = ADIS16480_DATA(16375, &adis16485_timeouts, 0), }, @@ -952,6 +954,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .temp_scale = 5650, /* 5.65 milli degree Celsius */ .int_clk = 2460000, .max_dec_rate = 2048, + .has_sleep_cnt = true, .filter_freqs = adis16480_def_filter_freqs, .adis_data = ADIS16480_DATA(16480, &adis16480_timeouts, 0), }, @@ -965,6 +968,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .temp_scale = 5650, /* 5.65 milli degree Celsius */ .int_clk = 2460000, .max_dec_rate = 2048, + .has_sleep_cnt = true, .filter_freqs = adis16480_def_filter_freqs, .adis_data = ADIS16480_DATA(16485, &adis16485_timeouts, 0), }, @@ -978,6 +982,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .temp_scale = 5650, /* 5.65 milli degree Celsius */ .int_clk = 2460000, .max_dec_rate = 2048, + .has_sleep_cnt = true, .filter_freqs = adis16480_def_filter_freqs, .adis_data = ADIS16480_DATA(16488, &adis16485_timeouts, 0), }, @@ -1425,9 +1430,12 @@ static int adis16480_probe(struct spi_device *spi) if (ret) return ret; - ret = devm_add_action_or_reset(&spi->dev, adis16480_stop, indio_dev); - if (ret) - return ret; + if (st->chip_info->has_sleep_cnt) { + ret = devm_add_action_or_reset(&spi->dev, adis16480_stop, + indio_dev); + if (ret) + return ret; + } ret = adis16480_config_irq_pin(spi->dev.of_node, st); if (ret) -- cgit From 6840615f85f6046039ebc4989870ddb12892b7fc Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Sep 2021 18:00:23 +0100 Subject: spi: spidev: Add SPI ID table Currently autoloading for SPI devices does not use the DT ID table, it uses SPI modalises. Supporting OF modalises is going to be difficult if not impractical, an attempt was made but has been reverted, so ensure that module autoloading works for this driver by adding an id_table listing the SPI IDs for everything. Fixes: 96c8395e2166 ("spi: Revert modalias changes") Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20210923170023.1683-1-broonie@kernel.org Signed-off-by: Mark Brown --- drivers/spi/spidev.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 6dc29ce3b4bf..1bd73e322b7b 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -673,6 +673,19 @@ static const struct file_operations spidev_fops = { static struct class *spidev_class; +static const struct spi_device_id spidev_spi_ids[] = { + { .name = "dh2228fv" }, + { .name = "ltc2488" }, + { .name = "sx1301" }, + { .name = "bk4" }, + { .name = "dhcom-board" }, + { .name = "m53cpld" }, + { .name = "spi-petra" }, + { .name = "spi-authenta" }, + {}, +}; +MODULE_DEVICE_TABLE(spi, spidev_spi_ids); + #ifdef CONFIG_OF static const struct of_device_id spidev_dt_ids[] = { { .compatible = "rohm,dh2228fv" }, @@ -818,6 +831,7 @@ static struct spi_driver spidev_spi_driver = { }, .probe = spidev_probe, .remove = spidev_remove, + .id_table = spidev_spi_ids, /* NOTE: suspend/resume methods are not necessary here. * We don't do anything except pass the requests to/from -- cgit From 2a2a79577ddae7d5314b2f57ca86b44d794403d5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 27 Sep 2021 14:44:03 +0100 Subject: fpga: ice40-spi: Add SPI device ID table Currently autoloading for SPI devices does not use the DT ID table, it uses SPI modalises. Supporting OF modalises is going to be difficult if not impractical, an attempt was made but has been reverted, so ensure that module autoloading works for this driver by adding a SPI ID table. Fixes: 96c8395e2166 ("spi: Revert modalias changes") Signed-off-by: Mark Brown Signed-off-by: Moritz Fischer --- drivers/fpga/ice40-spi.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/fpga/ice40-spi.c b/drivers/fpga/ice40-spi.c index 69dec5af23c3..029d3cdb918d 100644 --- a/drivers/fpga/ice40-spi.c +++ b/drivers/fpga/ice40-spi.c @@ -192,12 +192,19 @@ static const struct of_device_id ice40_fpga_of_match[] = { }; MODULE_DEVICE_TABLE(of, ice40_fpga_of_match); +static const struct spi_device_id ice40_fpga_spi_ids[] = { + { .name = "ice40-fpga-mgr", }, + {}, +}; +MODULE_DEVICE_TABLE(spi, ice40_fpga_spi_ids); + static struct spi_driver ice40_fpga_driver = { .probe = ice40_fpga_probe, .driver = { .name = "ice40spi", .of_match_table = of_match_ptr(ice40_fpga_of_match), }, + .id_table = ice40_fpga_spi_ids, }; module_spi_driver(ice40_fpga_driver); -- cgit From 0d67e332e6df72f43eaa21228daa3a79e23093f3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 27 Sep 2021 14:15:10 +0200 Subject: module: fix clang CFI with MODULE_UNLOAD=n When CONFIG_MODULE_UNLOAD is disabled, the module->exit member is not defined, causing a build failure: kernel/module.c:4493:8: error: no member named 'exit' in 'struct module' mod->exit = *exit; add an #ifdef block around this. Fixes: cf68fffb66d6 ("add support for Clang CFI") Acked-by: Kees Cook Reviewed-by: Sami Tolvanen Reviewed-by: Miroslav Benes Signed-off-by: Arnd Bergmann Signed-off-by: Jessica Yu --- kernel/module.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/module.c b/kernel/module.c index 40ec9a030eec..5c26a76e800b 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -4489,8 +4489,10 @@ static void cfi_init(struct module *mod) /* Fix init/exit functions to point to the CFI jump table */ if (init) mod->init = *init; +#ifdef CONFIG_MODULE_UNLOAD if (exit) mod->exit = *exit; +#endif cfi_module_add(mod, module_addr_min); #endif -- cgit From 4ca57d5139a0be3cf76c1667a4c0afb16d4a3b02 Mon Sep 17 00:00:00 2001 From: Rajaravi Krishna Katta Date: Tue, 14 Sep 2021 18:28:48 +0300 Subject: habanalabs: fix resetting args in wait for CS IOCTL In wait for CS IOCTL code, the driver resets the incoming args structure before returning to the user, regardless of the return value of the IOCTL. In case the IOCTL returns EINTR, resetting the args will result in error in case the userspace will repeat the ioctl call immediately (which is the behavior in the hl-thunk userspace library). The solution is to reset the args only if the driver returns success (0) as a return value for the IOCTL. Signed-off-by: Rajaravi Krishna Katta Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- .../misc/habanalabs/common/command_submission.c | 33 +++++++++++++--------- include/uapi/misc/habanalabs.h | 6 ++-- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/drivers/misc/habanalabs/common/command_submission.c b/drivers/misc/habanalabs/common/command_submission.c index 91b57544f7c6..6dafff375f1c 100644 --- a/drivers/misc/habanalabs/common/command_submission.c +++ b/drivers/misc/habanalabs/common/command_submission.c @@ -2649,11 +2649,18 @@ put_ctx: free_seq_arr: kfree(cs_seq_arr); - /* update output args */ - memset(args, 0, sizeof(*args)); if (rc) return rc; + if (mcs_data.wait_status == -ERESTARTSYS) { + dev_err_ratelimited(hdev->dev, + "user process got signal while waiting for Multi-CS\n"); + return -EINTR; + } + + /* update output args */ + memset(args, 0, sizeof(*args)); + if (mcs_data.completion_bitmap) { args->out.status = HL_WAIT_CS_STATUS_COMPLETED; args->out.cs_completion_map = mcs_data.completion_bitmap; @@ -2667,8 +2674,6 @@ free_seq_arr: /* update if some CS was gone */ if (mcs_data.timestamp) args->out.flags |= HL_WAIT_CS_STATUS_FLAG_GONE; - } else if (mcs_data.wait_status == -ERESTARTSYS) { - args->out.status = HL_WAIT_CS_STATUS_INTERRUPTED; } else { args->out.status = HL_WAIT_CS_STATUS_BUSY; } @@ -2688,16 +2693,17 @@ static int hl_cs_wait_ioctl(struct hl_fpriv *hpriv, void *data) rc = _hl_cs_wait_ioctl(hdev, hpriv->ctx, args->in.timeout_us, seq, &status, ×tamp); + if (rc == -ERESTARTSYS) { + dev_err_ratelimited(hdev->dev, + "user process got signal while waiting for CS handle %llu\n", + seq); + return -EINTR; + } + memset(args, 0, sizeof(*args)); if (rc) { - if (rc == -ERESTARTSYS) { - dev_err_ratelimited(hdev->dev, - "user process got signal while waiting for CS handle %llu\n", - seq); - args->out.status = HL_WAIT_CS_STATUS_INTERRUPTED; - rc = -EINTR; - } else if (rc == -ETIMEDOUT) { + if (rc == -ETIMEDOUT) { dev_err_ratelimited(hdev->dev, "CS %llu has timed-out while user process is waiting for it\n", seq); @@ -2823,7 +2829,6 @@ wait_again: dev_err_ratelimited(hdev->dev, "user process got signal while waiting for interrupt ID %d\n", interrupt->interrupt_id); - *status = HL_WAIT_CS_STATUS_INTERRUPTED; rc = -EINTR; } else { *status = CS_WAIT_STATUS_BUSY; @@ -2878,8 +2883,6 @@ static int hl_interrupt_wait_ioctl(struct hl_fpriv *hpriv, void *data) args->in.interrupt_timeout_us, args->in.addr, args->in.target, interrupt_offset, &status); - memset(args, 0, sizeof(*args)); - if (rc) { if (rc != -EINTR) dev_err_ratelimited(hdev->dev, @@ -2888,6 +2891,8 @@ static int hl_interrupt_wait_ioctl(struct hl_fpriv *hpriv, void *data) return rc; } + memset(args, 0, sizeof(*args)); + switch (status) { case CS_WAIT_STATUS_COMPLETED: args->out.status = HL_WAIT_CS_STATUS_COMPLETED; diff --git a/include/uapi/misc/habanalabs.h b/include/uapi/misc/habanalabs.h index 7cc2a0f3f2f5..d13bb8c1b450 100644 --- a/include/uapi/misc/habanalabs.h +++ b/include/uapi/misc/habanalabs.h @@ -917,7 +917,6 @@ struct hl_wait_cs_in { #define HL_WAIT_CS_STATUS_BUSY 1 #define HL_WAIT_CS_STATUS_TIMEDOUT 2 #define HL_WAIT_CS_STATUS_ABORTED 3 -#define HL_WAIT_CS_STATUS_INTERRUPTED 4 #define HL_WAIT_CS_STATUS_FLAG_GONE 0x1 #define HL_WAIT_CS_STATUS_FLAG_TIMESTAMP_VLD 0x2 @@ -1286,7 +1285,8 @@ struct hl_debug_args { * EIO - The CS was aborted (usually because the device was reset) * ENODEV - The device wants to do hard-reset (so user need to close FD) * - * The driver also returns a custom define inside the IOCTL which can be: + * The driver also returns a custom define in case the IOCTL call returned 0. + * The define can be one of the following: * * HL_WAIT_CS_STATUS_COMPLETED - The CS has been completed successfully (0) * HL_WAIT_CS_STATUS_BUSY - The CS is still executing (0) @@ -1294,8 +1294,6 @@ struct hl_debug_args { * (ETIMEDOUT) * HL_WAIT_CS_STATUS_ABORTED - The CS was aborted, usually because the * device was reset (EIO) - * HL_WAIT_CS_STATUS_INTERRUPTED - Waiting for the CS was interrupted (EINTR) - * */ #define HL_IOCTL_WAIT_CS \ -- cgit From 8ec59ac3ad29891c0afef627640df36f2daa0349 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 29 Sep 2021 09:35:40 +0200 Subject: ALSA: usb-audio: Fix a missing error check in scarlett gen2 mixer The check of the returned error code is missing in scarlett2_update_monitor_other(). Let's fix it. Fixes: d5bda7e03982 ("ALSA: usb-audio: scarlett2: Add support for the talkback feature") Reported-by: kernel test robot Cc: Link: https://lore.kernel.org/r/202109131831.9IodEzRx-lkp@intel.com Link: https://lore.kernel.org/r/20210929073540.9611-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/mixer_scarlett_gen2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 3d5848d5481b..53ebabf42472 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -2450,6 +2450,8 @@ static int scarlett2_update_monitor_other(struct usb_mixer_interface *mixer) err = scarlett2_usb_get_config(mixer, SCARLETT2_CONFIG_TALKBACK_MAP, 1, &bitmap); + if (err < 0) + return err; for (i = 0; i < num_mixes; i++, bitmap >>= 1) private->talkback_map[i] = bitmap & 1; } -- cgit From eb676622846b34a751e2ff9b5910a5322a4e0000 Mon Sep 17 00:00:00 2001 From: John Liu Date: Thu, 30 Sep 2021 13:53:16 +0200 Subject: ALSA: hda/realtek: Enable 4-speaker output for Dell Precision 5560 laptop The Dell Precision 5560 laptop appears to use the 4-speakers-on-ALC289 audio just like its sibling product XPS 9510, so it requires the same quirk to enable woofer output. Tested on my Dell Precision 5560. Signed-off-by: John Liu Cc: Link: https://lore.kernel.org/r/20210930115316.659-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 4407f7da57c4..f17bfc6007d3 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -8452,6 +8452,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0a30, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC), SND_PCI_QUIRK(0x1028, 0x0a58, "Dell", ALC255_FIXUP_DELL_HEADSET_MIC), SND_PCI_QUIRK(0x1028, 0x0a61, "Dell XPS 15 9510", ALC289_FIXUP_DUAL_SPK), + SND_PCI_QUIRK(0x1028, 0x0a62, "Dell Precision 5560", ALC289_FIXUP_DUAL_SPK), SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), -- cgit From 1f8763c59c4ec6254d629fe77c0a52220bd907aa Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 30 Sep 2021 13:41:14 +0200 Subject: ALSA: seq: Fix a potential UAF by wrong private_free call order John Keeping reported and posted a patch for a potential UAF in rawmidi sequencer destruction: the snd_rawmidi_dev_seq_free() may be called after the associated rawmidi object got already freed. After a deeper look, it turned out that the bug is rather the incorrect private_free call order for a snd_seq_device. The snd_seq_device private_free gets called at the release callback of the sequencer device object, while this was rather expected to be executed at the snd_device call chains that runs at the beginning of the whole card-free procedure. It's been broken since the rewrite of sequencer-device binding (although it hasn't surfaced because the sequencer device release happens usually right along with the card device release). This patch corrects the private_free call to be done in the right place, at snd_seq_device_dev_free(). Fixes: 7c37ae5c625a ("ALSA: seq: Rewrite sequencer device binding with standard bus") Reported-and-tested-by: John Keeping Cc: Link: https://lore.kernel.org/r/20210930114114.8645-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/seq_device.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sound/core/seq_device.c b/sound/core/seq_device.c index 382275c5b193..7f3fd8eb016f 100644 --- a/sound/core/seq_device.c +++ b/sound/core/seq_device.c @@ -156,6 +156,8 @@ static int snd_seq_device_dev_free(struct snd_device *device) struct snd_seq_device *dev = device->device_data; cancel_autoload_drivers(); + if (dev->private_free) + dev->private_free(dev); put_device(&dev->dev); return 0; } @@ -183,11 +185,7 @@ static int snd_seq_device_dev_disconnect(struct snd_device *device) static void snd_seq_dev_release(struct device *dev) { - struct snd_seq_device *sdev = to_seq_dev(dev); - - if (sdev->private_free) - sdev->private_free(sdev); - kfree(sdev); + kfree(to_seq_dev(dev)); } /* -- cgit From 09f7c338da7818fd33af401d855b895550e7c170 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Tue, 28 Sep 2021 19:19:17 +0300 Subject: fs/ntfs3: Reject mount if boot's cluster size < media sector size If we continue to work in this case, then we can corrupt fs. Fixes: 82cae269cfa9 ("fs/ntfs3: Add initialization of super block"). Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 800897777eb0..e9b6a3734576 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -763,9 +763,20 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size, sbi->mft.lbo = mlcn << sbi->cluster_bits; sbi->mft.lbo2 = mlcn2 << sbi->cluster_bits; - if (sbi->cluster_size < sbi->sector_size) + /* Compare boot's cluster and sector. */ + if (sbi->cluster_size < boot_sector_size) goto out; + /* Compare boot's cluster and media sector. */ + if (sbi->cluster_size < sector_size) { + /* No way to use ntfs_get_block in this case. */ + ntfs_err( + sb, + "Failed to mount 'cause NTFS's cluster size (%u) is less than media sector size (%u)", + sbi->cluster_size, sector_size); + goto out; + } + sbi->cluster_mask = sbi->cluster_size - 1; sbi->cluster_mask_inv = ~(u64)sbi->cluster_mask; sbi->record_size = record_size = boot->record_size < 0 -- cgit From dbf59e2a33d2cb5ae0534523fd3d6d8bda808be8 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Tue, 28 Sep 2021 19:19:49 +0300 Subject: fs/ntfs3: Refactoring of ntfs_init_from_boot Remove ntfs_sb_info members sector_size and sector_bits. Print details why mount failed. Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/ntfs_fs.h | 2 -- fs/ntfs3/super.c | 19 +++++++++---------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 6731b5d9e2d8..38b7c1a9dc52 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -211,10 +211,8 @@ struct ntfs_sb_info { u32 blocks_per_cluster; // cluster_size / sb->s_blocksize u32 record_size; - u32 sector_size; u32 index_size; - u8 sector_bits; u8 cluster_bits; u8 record_bits; diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index e9b6a3734576..705d8b4f4894 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -682,7 +682,7 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size, struct ntfs_sb_info *sbi = sb->s_fs_info; int err; u32 mb, gb, boot_sector_size, sct_per_clst, record_size; - u64 sectors, clusters, fs_size, mlcn, mlcn2; + u64 sectors, clusters, mlcn, mlcn2; struct NTFS_BOOT *boot; struct buffer_head *bh; struct MFT_REC *rec; @@ -740,20 +740,20 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size, goto out; } - sbi->sector_size = boot_sector_size; - sbi->sector_bits = blksize_bits(boot_sector_size); - fs_size = (sectors + 1) << sbi->sector_bits; + sbi->volume.size = sectors * boot_sector_size; - gb = format_size_gb(fs_size, &mb); + gb = format_size_gb(sbi->volume.size + boot_sector_size, &mb); /* * - Volume formatted and mounted with the same sector size. * - Volume formatted 4K and mounted as 512. * - Volume formatted 512 and mounted as 4K. */ - if (sbi->sector_size != sector_size) { - ntfs_warn(sb, - "Different NTFS' sector size and media sector size"); + if (boot_sector_size != sector_size) { + ntfs_warn( + sb, + "Different NTFS' sector size (%u) and media sector size (%u)", + boot_sector_size, sector_size); dev_size += sector_size - 1; } @@ -800,10 +800,9 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size, : (u32)boot->index_size << sbi->cluster_bits; sbi->volume.ser_num = le64_to_cpu(boot->serial_num); - sbi->volume.size = sectors << sbi->sector_bits; /* Warning if RAW volume. */ - if (dev_size < fs_size) { + if (dev_size < sbi->volume.size + boot_sector_size) { u32 mb0, gb0; gb0 = format_size_gb(dev_size, &mb0); -- cgit From 35afb70dcfe4eb445060dd955e5b67d962869ce5 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Wed, 29 Sep 2021 19:29:52 +0300 Subject: fs/ntfs3: Check for NULL if ATTR_EA_INFO is incorrect This can be reason for reported panic https://lore.kernel.org/ntfs3/f9de5807-2311-7374-afb0-bc5dffb522c0@gmail.com/ Fixes: 4342306f0f0d ("fs/ntfs3: Add file operations and implementation") Reported-by: Mohammad Rasim Signed-off-by: Konstantin Komarov --- fs/ntfs3/frecord.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index 9a53f809576d..007602badd90 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -3080,7 +3080,9 @@ static bool ni_update_parent(struct ntfs_inode *ni, struct NTFS_DUP_INFO *dup, const struct EA_INFO *info; info = resident_data_ex(attr, sizeof(struct EA_INFO)); - dup->ea_size = info->size_pack; + /* If ATTR_EA_INFO exists 'info' can't be NULL. */ + if (info) + dup->ea_size = info->size_pack; } } -- cgit From 8001f21fcd03253ba0eeac6f91f79239ac03ee60 Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Mon, 27 Sep 2021 21:27:24 -0700 Subject: MAINTAINERS: Add Hao and Yilun as maintainers Hao and Yilun have agreed to help out with maintenance. Both have been active in the Linux FPGA community for a long time and we need backups for vacation and load-balancing. Cc: Xu Yilun Cc: Wu Hao Cc: Greg Kroah-Hartman Acked-by: Xu Yilun Acked-by: Wu Hao Signed-off-by: Moritz Fischer --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index eeb4c70b3d5b..2ec4c2a2458a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7337,6 +7337,8 @@ F: include/uapi/linux/fpga-dfl.h FPGA MANAGER FRAMEWORK M: Moritz Fischer +M: Wu Hao +M: Xu Yilun R: Tom Rix L: linux-fpga@vger.kernel.org S: Maintained -- cgit From 2b987fe84429361c7f189568c476d1bd00d2ff7e Mon Sep 17 00:00:00 2001 From: Chris Chiu Date: Fri, 1 Oct 2021 14:28:56 +0800 Subject: ALSA: hda - Enable headphone mic on Dell Latitude laptops with ALC3254 The headphone mic is not working on Dell Latitude laptops with ALC3254. The codec vendor id is 0x10ec0295 and share the same pincfg as defined in ALC295_STANDARD_PINS. So the ALC269_FIXUP_DELL1_MIC_NO_PRESENCE will be applied per alc269_pin_fixup_tbl[] but actually the headphone mic is using NID 0x1b instead of 0x1a. The ALC269_FIXUP_DELL4_MIC_NO_PRESENCE need to be applied instead. Use ALC269_FIXUP_DELL4_MIC_NO_PRESENCE for particular models before a generic fixup comes out. Signed-off-by: Chris Chiu Cc: Link: https://lore.kernel.org/r/20211001062856.1037901-1-chris.chiu@canonical.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 f17bfc6007d3..6bf6151347d8 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -8453,6 +8453,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0a58, "Dell", ALC255_FIXUP_DELL_HEADSET_MIC), SND_PCI_QUIRK(0x1028, 0x0a61, "Dell XPS 15 9510", ALC289_FIXUP_DUAL_SPK), SND_PCI_QUIRK(0x1028, 0x0a62, "Dell Precision 5560", ALC289_FIXUP_DUAL_SPK), + SND_PCI_QUIRK(0x1028, 0x0a9d, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x0a9e, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), -- cgit From 75e33c55ae8fb4a177fe07c284665e1d61b02560 Mon Sep 17 00:00:00 2001 From: Ville Baillie Date: Tue, 21 Sep 2021 07:21:32 +0000 Subject: spi: atmel: Fix PDC transfer setup bug atmel_spi_dma_map_xfer to never be called in PDC mode. This causes the driver to silently fail. This patch changes the conditional to match the behaviour of the previous commit before the refactor. Fixes: 5fa5e6dec762 ("spi: atmel: Switch to transfer_one transfer method") Signed-off-by: Ville Baillie Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210921072132.21831-1-villeb@bytesnap.co.uk Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 788dcdf25f00..f872cf196c2f 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1301,7 +1301,7 @@ static int atmel_spi_one_transfer(struct spi_master *master, * DMA map early, for performance (empties dcache ASAP) and * better fault reporting. */ - if ((!master->cur_msg_mapped) + if ((!master->cur_msg->is_dma_mapped) && as->use_pdc) { if (atmel_spi_dma_map_xfer(as, xfer) < 0) return -ENOMEM; @@ -1381,7 +1381,7 @@ static int atmel_spi_one_transfer(struct spi_master *master, } } - if (!master->cur_msg_mapped + if (!master->cur_msg->is_dma_mapped && as->use_pdc) atmel_spi_dma_unmap_xfer(master, xfer); -- cgit From 3672bb820f3292b6f035469f863c020317a3dd28 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Fri, 1 Oct 2021 17:21:53 +0200 Subject: spi: mediatek: skip delays if they are 0 In the function 'mtk_spi_set_hw_cs_timing' the 'setup', 'hold' and 'inactive' delays are configured. In case those values are 0 it causes errors on mt8173: cros-ec-i2c-tunnel 1100a000.spi:ec@0:i2c-tunnel0: Error transferring EC i2c message -71 cros-ec-spi spi0.0: EC failed to respond in time. This patch fixes that issues by setting only the values that are not 0. Fixes: 04e6bb0d6bb1 ("spi: modify set_cs_timing parameter") Signed-off-by: Dafna Hirschfeld Link: https://lore.kernel.org/r/20211001152153.4604-1-dafna.hirschfeld@collabora.com Signed-off-by: Mark Brown --- drivers/spi/spi-mt65xx.c | 64 +++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 386e8c84be0a..a15de10ee286 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -233,36 +233,44 @@ static int mtk_spi_set_hw_cs_timing(struct spi_device *spi) return delay; inactive = (delay * DIV_ROUND_UP(mdata->spi_clk_hz, 1000000)) / 1000; - setup = setup ? setup : 1; - hold = hold ? hold : 1; - inactive = inactive ? inactive : 1; - - reg_val = readl(mdata->base + SPI_CFG0_REG); - if (mdata->dev_comp->enhance_timing) { - hold = min_t(u32, hold, 0x10000); - setup = min_t(u32, setup, 0x10000); - reg_val &= ~(0xffff << SPI_ADJUST_CFG0_CS_HOLD_OFFSET); - reg_val |= (((hold - 1) & 0xffff) - << SPI_ADJUST_CFG0_CS_HOLD_OFFSET); - reg_val &= ~(0xffff << SPI_ADJUST_CFG0_CS_SETUP_OFFSET); - reg_val |= (((setup - 1) & 0xffff) - << SPI_ADJUST_CFG0_CS_SETUP_OFFSET); - } else { - hold = min_t(u32, hold, 0x100); - setup = min_t(u32, setup, 0x100); - reg_val &= ~(0xff << SPI_CFG0_CS_HOLD_OFFSET); - reg_val |= (((hold - 1) & 0xff) << SPI_CFG0_CS_HOLD_OFFSET); - reg_val &= ~(0xff << SPI_CFG0_CS_SETUP_OFFSET); - reg_val |= (((setup - 1) & 0xff) - << SPI_CFG0_CS_SETUP_OFFSET); + if (hold || setup) { + reg_val = readl(mdata->base + SPI_CFG0_REG); + if (mdata->dev_comp->enhance_timing) { + if (hold) { + hold = min_t(u32, hold, 0x10000); + reg_val &= ~(0xffff << SPI_ADJUST_CFG0_CS_HOLD_OFFSET); + reg_val |= (((hold - 1) & 0xffff) + << SPI_ADJUST_CFG0_CS_HOLD_OFFSET); + } + if (setup) { + setup = min_t(u32, setup, 0x10000); + reg_val &= ~(0xffff << SPI_ADJUST_CFG0_CS_SETUP_OFFSET); + reg_val |= (((setup - 1) & 0xffff) + << SPI_ADJUST_CFG0_CS_SETUP_OFFSET); + } + } else { + if (hold) { + hold = min_t(u32, hold, 0x100); + reg_val &= ~(0xff << SPI_CFG0_CS_HOLD_OFFSET); + reg_val |= (((hold - 1) & 0xff) << SPI_CFG0_CS_HOLD_OFFSET); + } + if (setup) { + setup = min_t(u32, setup, 0x100); + reg_val &= ~(0xff << SPI_CFG0_CS_SETUP_OFFSET); + reg_val |= (((setup - 1) & 0xff) + << SPI_CFG0_CS_SETUP_OFFSET); + } + } + writel(reg_val, mdata->base + SPI_CFG0_REG); } - writel(reg_val, mdata->base + SPI_CFG0_REG); - inactive = min_t(u32, inactive, 0x100); - reg_val = readl(mdata->base + SPI_CFG1_REG); - reg_val &= ~SPI_CFG1_CS_IDLE_MASK; - reg_val |= (((inactive - 1) & 0xff) << SPI_CFG1_CS_IDLE_OFFSET); - writel(reg_val, mdata->base + SPI_CFG1_REG); + if (inactive) { + inactive = min_t(u32, inactive, 0x100); + reg_val = readl(mdata->base + SPI_CFG1_REG); + reg_val &= ~SPI_CFG1_CS_IDLE_MASK; + reg_val |= (((inactive - 1) & 0xff) << SPI_CFG1_CS_IDLE_OFFSET); + writel(reg_val, mdata->base + SPI_CFG1_REG); + } return 0; } -- cgit From d8c23ead708b40a16413163f5f93e07fbd4f077d Mon Sep 17 00:00:00 2001 From: Daniel Latypov Date: Wed, 22 Sep 2021 09:39:21 -0700 Subject: kunit: tool: better handling of quasi-bool args (--json, --raw_output) Problem: What does this do? $ kunit.py run --json Well, it runs all the tests and prints test results out as JSON. And next is $ kunit.py run my-test-suite --json This runs just `my-test-suite` and prints results out as JSON. But what about? $ kunit.py run --json my-test-suite This runs all the tests and stores the json results in a "my-test-suite" file. Why: --json, and now --raw_output are actually string flags. They just have a default value. --json in particular takes the name of an output file. It was intended that you'd do $ kunit.py run --json=my_output_file my-test-suite if you ever wanted to specify the value. Workaround: It doesn't seem like there's a way to make https://docs.python.org/3/library/argparse.html only accept arg values after a '='. I believe that `--json` should "just work" regardless of where it is. So this patch automatically rewrites a bare `--json` to `--json=stdout`. That makes the examples above work the same way. Add a regression test that can catch this for --raw_output. Fixes: 6a499c9c42d0 ("kunit: tool: make --raw_output support only showing kunit output") Signed-off-by: Daniel Latypov Tested-by: David Gow Reviewed-by: Brendan Higgins Signed-off-by: Shuah Khan --- tools/testing/kunit/kunit.py | 24 ++++++++++++++++++++++-- tools/testing/kunit/kunit_tool_test.py | 8 ++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/tools/testing/kunit/kunit.py b/tools/testing/kunit/kunit.py index 5a931456e718..ac35c61f65f5 100755 --- a/tools/testing/kunit/kunit.py +++ b/tools/testing/kunit/kunit.py @@ -16,7 +16,7 @@ assert sys.version_info >= (3, 7), "Python version is too old" from collections import namedtuple from enum import Enum, auto -from typing import Iterable +from typing import Iterable, Sequence import kunit_config import kunit_json @@ -186,6 +186,26 @@ def run_tests(linux: kunit_kernel.LinuxSourceTree, exec_result.elapsed_time)) return parse_result +# Problem: +# $ kunit.py run --json +# works as one would expect and prints the parsed test results as JSON. +# $ kunit.py run --json suite_name +# would *not* pass suite_name as the filter_glob and print as json. +# argparse will consider it to be another way of writing +# $ kunit.py run --json=suite_name +# i.e. it would run all tests, and dump the json to a `suite_name` file. +# So we hackily automatically rewrite --json => --json=stdout +pseudo_bool_flag_defaults = { + '--json': 'stdout', + '--raw_output': 'kunit', +} +def massage_argv(argv: Sequence[str]) -> Sequence[str]: + def massage_arg(arg: str) -> str: + if arg not in pseudo_bool_flag_defaults: + return arg + return f'{arg}={pseudo_bool_flag_defaults[arg]}' + return list(map(massage_arg, argv)) + def add_common_opts(parser) -> None: parser.add_argument('--build_dir', help='As in the make command, it specifies the build ' @@ -303,7 +323,7 @@ def main(argv, linux=None): help='Specifies the file to read results from.', type=str, nargs='?', metavar='input_file') - cli_args = parser.parse_args(argv) + cli_args = parser.parse_args(massage_argv(argv)) if get_kernel_root_path(): os.chdir(get_kernel_root_path()) diff --git a/tools/testing/kunit/kunit_tool_test.py b/tools/testing/kunit/kunit_tool_test.py index 619c4554cbff..1edcc8373b4e 100755 --- a/tools/testing/kunit/kunit_tool_test.py +++ b/tools/testing/kunit/kunit_tool_test.py @@ -408,6 +408,14 @@ class KUnitMainTest(unittest.TestCase): self.assertNotEqual(call, mock.call(StrContains('Testing complete.'))) self.assertNotEqual(call, mock.call(StrContains(' 0 tests run'))) + def test_run_raw_output_does_not_take_positional_args(self): + # --raw_output is a string flag, but we don't want it to consume + # any positional arguments, only ones after an '=' + self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) + kunit.main(['run', '--raw_output', 'filter_glob'], self.linux_source_mock) + self.linux_source_mock.run_kernel.assert_called_once_with( + args=None, build_dir='.kunit', filter_glob='filter_glob', timeout=300) + def test_exec_timeout(self): timeout = 3453 kunit.main(['exec', '--timeout', str(timeout)], self.linux_source_mock) -- cgit From f62314b1ced25c58b86e044fc951cd6a1ea234cf Mon Sep 17 00:00:00 2001 From: Xiyu Yang Date: Thu, 9 Sep 2021 15:24:36 +0800 Subject: kunit: fix reference count leak in kfree_at_end The reference counting issue happens in the normal path of kfree_at_end(). When kunit_alloc_and_get_resource() is invoked, the function forgets to handle the returned resource object, whose refcount increased inside, causing a refcount leak. Fix this issue by calling kunit_alloc_resource() instead of kunit_alloc_and_get_resource(). Fixed the following when applying: Shuah Khan CHECK: Alignment should match open parenthesis + kunit_alloc_resource(test, NULL, kfree_res_free, GFP_KERNEL, (void *)to_free); Signed-off-by: Xiyu Yang Signed-off-by: Xin Tan Reviewed-by: Daniel Latypov Reviewed-by: Brendan Higgins Signed-off-by: Shuah Khan --- lib/kunit/executor_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/kunit/executor_test.c b/lib/kunit/executor_test.c index cdbe54b16501..e14a18af573d 100644 --- a/lib/kunit/executor_test.c +++ b/lib/kunit/executor_test.c @@ -116,8 +116,8 @@ static void kfree_at_end(struct kunit *test, const void *to_free) /* kfree() handles NULL already, but avoid allocating a no-op cleanup. */ if (IS_ERR_OR_NULL(to_free)) return; - kunit_alloc_and_get_resource(test, NULL, kfree_res_free, GFP_KERNEL, - (void *)to_free); + kunit_alloc_resource(test, NULL, kfree_res_free, GFP_KERNEL, + (void *)to_free); } static struct kunit_suite *alloc_fake_suite(struct kunit *test, -- cgit From 654e9c18dfab02c8e5f9c5877c7a2f3264fa520a Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sun, 26 Sep 2021 11:56:58 -0700 Subject: drm/msm: Fix crash on dev file close If the device file was opened prior to fw being available (such as from initrd before rootfs is mounted, when the initrd does not contain GPU fw), that would cause a later crash when the dev file is closed due to unitialized submitqueues list: CPU: 4 PID: 263 Comm: plymouthd Tainted: G W 5.15.0-rc2-next-20210924 #2 Hardware name: LENOVO 81JL/LNVNB161216, BIOS 9UCN33WW(V2.06) 06/ 4/2019 pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : msm_submitqueue_close+0x30/0x190 [msm] lr : msm_postclose+0x54/0xf0 [msm] sp : ffff80001074bb80 x29: ffff80001074bb80 x28: ffff03ad80c4db80 x27: ffff03ad80dc5ab0 x26: 0000000000000000 x25: ffff03ad80dc5af8 x24: ffff03ad81e90800 x23: 0000000000000000 x22: ffff03ad81e90800 x21: ffff03ad8b35e788 x20: ffff03ad81e90878 x19: 0000000000000000 x18: 0000000000000000 x17: 0000000000000000 x16: ffffda15f14f7940 x15: 0000000000000000 x14: 0000000000000000 x13: 0000000000000001 x12: 0000000000000040 x11: 0000000000000000 x10: 0000000000000000 x9 : ffffda15cd18ff88 x8 : ffff03ad80c4db80 x7 : 0000000000000228 x6 : 0000000000000000 x5 : 1793a4e807e636bd x4 : ffff03ad80c4db80 x3 : ffff03ad81e90878 x2 : 0000000000000000 x1 : ffff03ad80c4db80 x0 : 0000000000000000 Call trace: msm_submitqueue_close+0x30/0x190 [msm] msm_postclose+0x54/0xf0 [msm] drm_file_free.part.0+0x1cc/0x2e0 [drm] drm_close_helper.isra.0+0x74/0x84 [drm] drm_release+0x78/0x120 [drm] __fput+0x78/0x23c ____fput+0x1c/0x30 task_work_run+0xcc/0x22c do_exit+0x304/0x9f4 do_group_exit+0x44/0xb0 __wake_up_parent+0x0/0x3c invoke_syscall+0x50/0x120 el0_svc_common.constprop.0+0x4c/0xf4 do_el0_svc+0x30/0x9c el0_svc+0x20/0x60 el0t_64_sync_handler+0xe8/0xf0 el0t_64_sync+0x1a0/0x1a4 Code: aa0003f5 a90153f3 f8408eb3 aa1303e0 (f85e8674) ---[ end trace 39b2fa37509a2be2 ]--- Fixing recursive fault but reboot is needed! Fixes: 86c2a0f000c1 drm/msm: ("Small submitqueue creation cleanup") Reported-by: Steev Klimaszewski Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_drv.c | 3 +++ drivers/gpu/drm/msm/msm_submitqueue.c | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 2e6fc185e54d..6176519d8bb0 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -689,6 +689,9 @@ static int context_init(struct drm_device *dev, struct drm_file *file) if (!ctx) return -ENOMEM; + INIT_LIST_HEAD(&ctx->submitqueues); + rwlock_init(&ctx->queuelock); + kref_init(&ctx->ref); msm_submitqueue_init(dev, ctx); diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c index 32a55d81b58b..7ce0771b5582 100644 --- a/drivers/gpu/drm/msm/msm_submitqueue.c +++ b/drivers/gpu/drm/msm/msm_submitqueue.c @@ -140,10 +140,6 @@ int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx) */ default_prio = DIV_ROUND_UP(max_priority, 2); - INIT_LIST_HEAD(&ctx->submitqueues); - - rwlock_init(&ctx->queuelock); - return msm_submitqueue_create(drm, ctx, default_prio, 0, NULL); } -- cgit From f6f59072e821901d96c791864a07d57d8ec8d312 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 27 Sep 2021 11:00:04 -0700 Subject: drm/msm/a6xx: Serialize GMU communication I've seen some crashes in our crash reporting that *look* like multiple threads stomping on each other while communicating with GMU. So wrap all those paths in a lock. Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 6 ++++++ drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 3 +++ drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 40 +++++++++++++++++++++++++++++------ 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index a7c58018959f..8b73f70766a4 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -296,6 +296,8 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) u32 val; int request, ack; + WARN_ON_ONCE(!mutex_is_locked(&gmu->lock)); + if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits)) return -EINVAL; @@ -337,6 +339,8 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) { int bit; + WARN_ON_ONCE(!mutex_is_locked(&gmu->lock)); + if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits)) return; @@ -1482,6 +1486,8 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) if (!pdev) return -ENODEV; + mutex_init(&gmu->lock); + gmu->dev = &pdev->dev; of_dma_configure(gmu->dev, node, true); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h index 3c74f64e3126..84bd516f01e8 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h @@ -44,6 +44,9 @@ struct a6xx_gmu_bo { struct a6xx_gmu { struct device *dev; + /* For serializing communication with the GMU: */ + struct mutex lock; + struct msm_gem_address_space *aspace; void * __iomem mmio; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 40c9fef457a4..cd68cfb08446 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -881,7 +881,7 @@ static int a6xx_zap_shader_init(struct msm_gpu *gpu) A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \ A6XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR) -static int a6xx_hw_init(struct msm_gpu *gpu) +static int hw_init(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); @@ -1135,6 +1135,19 @@ out: return ret; } +static int a6xx_hw_init(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + int ret; + + mutex_lock(&a6xx_gpu->gmu.lock); + ret = hw_init(gpu); + mutex_unlock(&a6xx_gpu->gmu.lock); + + return ret; +} + static void a6xx_dump(struct msm_gpu *gpu) { DRM_DEV_INFO(&gpu->pdev->dev, "status: %08x\n", @@ -1509,7 +1522,9 @@ static int a6xx_pm_resume(struct msm_gpu *gpu) trace_msm_gpu_resume(0); + mutex_lock(&a6xx_gpu->gmu.lock); ret = a6xx_gmu_resume(a6xx_gpu); + mutex_unlock(&a6xx_gpu->gmu.lock); if (ret) return ret; @@ -1532,7 +1547,9 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu) msm_devfreq_suspend(gpu); + mutex_lock(&a6xx_gpu->gmu.lock); ret = a6xx_gmu_stop(a6xx_gpu); + mutex_unlock(&a6xx_gpu->gmu.lock); if (ret) return ret; @@ -1547,18 +1564,19 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); - static DEFINE_MUTEX(perfcounter_oob); - mutex_lock(&perfcounter_oob); + mutex_lock(&a6xx_gpu->gmu.lock); /* Force the GPU power on so we can read this register */ a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); *value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER_LO, - REG_A6XX_CP_ALWAYS_ON_COUNTER_HI); + REG_A6XX_CP_ALWAYS_ON_COUNTER_HI); a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); - mutex_unlock(&perfcounter_oob); + + mutex_unlock(&a6xx_gpu->gmu.lock); + return 0; } @@ -1622,6 +1640,16 @@ static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu) return (unsigned long)busy_time; } +void a6xx_gpu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + + mutex_lock(&a6xx_gpu->gmu.lock); + a6xx_gmu_set_freq(gpu, opp); + mutex_unlock(&a6xx_gpu->gmu.lock); +} + static struct msm_gem_address_space * a6xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev) { @@ -1766,7 +1794,7 @@ static const struct adreno_gpu_funcs funcs = { #endif .gpu_busy = a6xx_gpu_busy, .gpu_get_freq = a6xx_gmu_get_freq, - .gpu_set_freq = a6xx_gmu_set_freq, + .gpu_set_freq = a6xx_gpu_set_freq, #if defined(CONFIG_DRM_MSM_GPU_STATE) .gpu_state_get = a6xx_gpu_state_get, .gpu_state_put = a6xx_gpu_state_put, -- cgit From 14eb0cb4e9a7323c8735cf6c681ed8423ce6ae06 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 30 Sep 2021 10:43:20 -0700 Subject: drm/msm/a6xx: Track current ctx by seqno In theory a context can be destroyed and a new one allocated at the same address, making the pointer comparision to detect when we don't need to update the current pagetables invalid. Instead assign a sequence number to each context on creation, and use this for the check. Fixes: 84c31ee16f90 ("drm/msm/a6xx: Add support for per-instance pagetables") Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 6 +++--- drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 11 ++++++++++- drivers/gpu/drm/msm/msm_drv.c | 3 +++ drivers/gpu/drm/msm/msm_drv.h | 1 + 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index cd68cfb08446..33da25b81615 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -106,7 +106,7 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, u32 asid; u64 memptr = rbmemptr(ring, ttbr0); - if (ctx == a6xx_gpu->cur_ctx) + if (ctx->seqno == a6xx_gpu->cur_ctx_seqno) return; if (msm_iommu_pagetable_params(ctx->aspace->mmu, &ttbr, &asid)) @@ -139,7 +139,7 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, OUT_PKT7(ring, CP_EVENT_WRITE, 1); OUT_RING(ring, 0x31); - a6xx_gpu->cur_ctx = ctx; + a6xx_gpu->cur_ctx_seqno = ctx->seqno; } static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) @@ -1081,7 +1081,7 @@ static int hw_init(struct msm_gpu *gpu) /* Always come up on rb 0 */ a6xx_gpu->cur_ring = gpu->rb[0]; - a6xx_gpu->cur_ctx = NULL; + a6xx_gpu->cur_ctx_seqno = 0; /* Enable the SQE_to start the CP engine */ gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 1); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h index 0bc2d062f54a..8e5527c881b1 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h @@ -19,7 +19,16 @@ struct a6xx_gpu { uint64_t sqe_iova; struct msm_ringbuffer *cur_ring; - struct msm_file_private *cur_ctx; + + /** + * cur_ctx_seqno: + * + * The ctx->seqno value of the context with current pgtables + * installed. Tracked by seqno rather than pointer value to + * avoid dangling pointers, and cases where a ctx can be freed + * and a new one created with the same address. + */ + int cur_ctx_seqno; struct a6xx_gmu gmu; diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 6176519d8bb0..4443d7b48618 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -682,6 +682,7 @@ static void load_gpu(struct drm_device *dev) static int context_init(struct drm_device *dev, struct drm_file *file) { + static atomic_t ident = ATOMIC_INIT(0); struct msm_drm_private *priv = dev->dev_private; struct msm_file_private *ctx; @@ -698,6 +699,8 @@ static int context_init(struct drm_device *dev, struct drm_file *file) ctx->aspace = msm_gpu_create_private_address_space(priv->gpu, current); file->driver_priv = ctx; + ctx->seqno = atomic_inc_return(&ident); + return 0; } diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 8b005d1ac899..a0340607984a 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -59,6 +59,7 @@ struct msm_file_private { int queueid; struct msm_gem_address_space *aspace; struct kref ref; + int seqno; }; enum msm_mdp_plane_property { -- cgit From 4cd82aa39bda20a9237b8f42676796d0a5ee9bfc Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 1 Oct 2021 08:58:15 -0700 Subject: drm/msm: A bit more docs + cleanup msm_file_private is more gpu related, and in the next commit it will need access to other GPU specific #defines. While we're at it, add some comments. Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_drv.h | 44 -------------------------------- drivers/gpu/drm/msm/msm_gpu.h | 58 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index a0340607984a..e99242164076 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -53,15 +53,6 @@ struct msm_disp_state; #define FRAC_16_16(mult, div) (((mult) << 16) / (div)) -struct msm_file_private { - rwlock_t queuelock; - struct list_head submitqueues; - int queueid; - struct msm_gem_address_space *aspace; - struct kref ref; - int seqno; -}; - enum msm_mdp_plane_property { PLANE_PROP_ZPOS, PLANE_PROP_ALPHA, @@ -489,41 +480,6 @@ void msm_writel(u32 data, void __iomem *addr); u32 msm_readl(const void __iomem *addr); void msm_rmw(void __iomem *addr, u32 mask, u32 or); -struct msm_gpu_submitqueue; -int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx); -struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx, - u32 id); -int msm_submitqueue_create(struct drm_device *drm, - struct msm_file_private *ctx, - u32 prio, u32 flags, u32 *id); -int msm_submitqueue_query(struct drm_device *drm, struct msm_file_private *ctx, - struct drm_msm_submitqueue_query *args); -int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id); -void msm_submitqueue_close(struct msm_file_private *ctx); - -void msm_submitqueue_destroy(struct kref *kref); - -static inline void __msm_file_private_destroy(struct kref *kref) -{ - struct msm_file_private *ctx = container_of(kref, - struct msm_file_private, ref); - - msm_gem_address_space_put(ctx->aspace); - kfree(ctx); -} - -static inline void msm_file_private_put(struct msm_file_private *ctx) -{ - kref_put(&ctx->ref, __msm_file_private_destroy); -} - -static inline struct msm_file_private *msm_file_private_get( - struct msm_file_private *ctx) -{ - kref_get(&ctx->ref); - return ctx; -} - #define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) #define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 0e4b45bff2e6..42f85c523cfe 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -257,6 +257,26 @@ struct msm_gpu_perfcntr { */ #define NR_SCHED_PRIORITIES (1 + DRM_SCHED_PRIORITY_HIGH - DRM_SCHED_PRIORITY_MIN) +/** + * struct msm_file_private - per-drm_file context + * + * @queuelock: synchronizes access to submitqueues list + * @submitqueues: list of &msm_gpu_submitqueue created by userspace + * @queueid: counter incremented each time a submitqueue is created, + * used to assign &msm_gpu_submitqueue.id + * @aspace: the per-process GPU address-space + * @ref: reference count + * @seqno: unique per process seqno + */ +struct msm_file_private { + rwlock_t queuelock; + struct list_head submitqueues; + int queueid; + struct msm_gem_address_space *aspace; + struct kref ref; + int seqno; +}; + /** * msm_gpu_convert_priority - Map userspace priority to ring # and sched priority * @@ -304,6 +324,8 @@ static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio, } /** + * struct msm_gpu_submitqueues - Userspace created context. + * * A submitqueue is associated with a gl context or vk queue (or equiv) * in userspace. * @@ -321,7 +343,7 @@ static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio, * seqno, protected by submitqueue lock * @lock: submitqueue lock * @ref: reference count - * @entity: the submit job-queue + * @entity: the submit job-queue */ struct msm_gpu_submitqueue { int id; @@ -421,6 +443,40 @@ static inline void gpu_write64(struct msm_gpu *gpu, u32 lo, u32 hi, u64 val) int msm_gpu_pm_suspend(struct msm_gpu *gpu); int msm_gpu_pm_resume(struct msm_gpu *gpu); +int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx); +struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx, + u32 id); +int msm_submitqueue_create(struct drm_device *drm, + struct msm_file_private *ctx, + u32 prio, u32 flags, u32 *id); +int msm_submitqueue_query(struct drm_device *drm, struct msm_file_private *ctx, + struct drm_msm_submitqueue_query *args); +int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id); +void msm_submitqueue_close(struct msm_file_private *ctx); + +void msm_submitqueue_destroy(struct kref *kref); + +static inline void __msm_file_private_destroy(struct kref *kref) +{ + struct msm_file_private *ctx = container_of(kref, + struct msm_file_private, ref); + + msm_gem_address_space_put(ctx->aspace); + kfree(ctx); +} + +static inline void msm_file_private_put(struct msm_file_private *ctx) +{ + kref_put(&ctx->ref, __msm_file_private_destroy); +} + +static inline struct msm_file_private *msm_file_private_get( + struct msm_file_private *ctx) +{ + kref_get(&ctx->ref); + return ctx; +} + void msm_devfreq_init(struct msm_gpu *gpu); void msm_devfreq_cleanup(struct msm_gpu *gpu); void msm_devfreq_resume(struct msm_gpu *gpu); -- cgit From 68002469e571ae3db095e4ade1cfef64903f8fa1 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 1 Oct 2021 09:42:05 -0700 Subject: drm/msm: One sched entity per process per priority Some userspace apps make assumptions that rendering against multiple contexts within the same process (from the same thread, with appropriate MakeCurrent() calls) provides sufficient synchronization without any external synchronization (ie. glFenceSync()/glWaitSync()). Since a submitqueue maps to a gl/vk context, having multiple sched entities of the same priority only works with implicit sync enabled. To fix this, limit things to a single sched entity per priority level per process. An alternative would be sharing submitqueues between contexts in userspace, but tracking of per-context faults (ie. GL_EXT_robustness) is already done at the submitqueue level, so this is not an option. Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gem_submit.c | 4 +-- drivers/gpu/drm/msm/msm_gpu.h | 24 ++++++++----- drivers/gpu/drm/msm/msm_submitqueue.c | 68 +++++++++++++++++++++++++++++------ 3 files changed, 75 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index fdc5367aecaa..7e0f6571cbca 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -46,7 +46,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, if (!submit) return ERR_PTR(-ENOMEM); - ret = drm_sched_job_init(&submit->base, &queue->entity, queue); + ret = drm_sched_job_init(&submit->base, queue->entity, queue); if (ret) { kfree(submit); return ERR_PTR(ret); @@ -907,7 +907,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, /* The scheduler owns a ref now: */ msm_gem_submit_get(submit); - drm_sched_entity_push_job(&submit->base, &queue->entity); + drm_sched_entity_push_job(&submit->base, queue->entity); args->fence = submit->fence_id; diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 42f85c523cfe..030f82f149c2 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -275,6 +275,19 @@ struct msm_file_private { struct msm_gem_address_space *aspace; struct kref ref; int seqno; + + /** + * entities: + * + * Table of per-priority-level sched entities used by submitqueues + * associated with this &drm_file. Because some userspace apps + * make assumptions about rendering from multiple gl contexts + * (of the same priority) within the process happening in FIFO + * order without requiring any fencing beyond MakeCurrent(), we + * create at most one &drm_sched_entity per-process per-priority- + * level. + */ + struct drm_sched_entity *entities[NR_SCHED_PRIORITIES * MSM_GPU_MAX_RINGS]; }; /** @@ -355,7 +368,7 @@ struct msm_gpu_submitqueue { struct idr fence_idr; struct mutex lock; struct kref ref; - struct drm_sched_entity entity; + struct drm_sched_entity *entity; }; struct msm_gpu_state_bo { @@ -456,14 +469,7 @@ void msm_submitqueue_close(struct msm_file_private *ctx); void msm_submitqueue_destroy(struct kref *kref); -static inline void __msm_file_private_destroy(struct kref *kref) -{ - struct msm_file_private *ctx = container_of(kref, - struct msm_file_private, ref); - - msm_gem_address_space_put(ctx->aspace); - kfree(ctx); -} +void __msm_file_private_destroy(struct kref *kref); static inline void msm_file_private_put(struct msm_file_private *ctx) { diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c index 7ce0771b5582..b8621c6e0554 100644 --- a/drivers/gpu/drm/msm/msm_submitqueue.c +++ b/drivers/gpu/drm/msm/msm_submitqueue.c @@ -7,6 +7,24 @@ #include "msm_gpu.h" +void __msm_file_private_destroy(struct kref *kref) +{ + struct msm_file_private *ctx = container_of(kref, + struct msm_file_private, ref); + int i; + + for (i = 0; i < ARRAY_SIZE(ctx->entities); i++) { + if (!ctx->entities[i]) + continue; + + drm_sched_entity_destroy(ctx->entities[i]); + kfree(ctx->entities[i]); + } + + msm_gem_address_space_put(ctx->aspace); + kfree(ctx); +} + void msm_submitqueue_destroy(struct kref *kref) { struct msm_gpu_submitqueue *queue = container_of(kref, @@ -14,8 +32,6 @@ void msm_submitqueue_destroy(struct kref *kref) idr_destroy(&queue->fence_idr); - drm_sched_entity_destroy(&queue->entity); - msm_file_private_put(queue->ctx); kfree(queue); @@ -61,13 +77,47 @@ void msm_submitqueue_close(struct msm_file_private *ctx) } } +static struct drm_sched_entity * +get_sched_entity(struct msm_file_private *ctx, struct msm_ringbuffer *ring, + unsigned ring_nr, enum drm_sched_priority sched_prio) +{ + static DEFINE_MUTEX(entity_lock); + unsigned idx = (ring_nr * NR_SCHED_PRIORITIES) + sched_prio; + + /* We should have already validated that the requested priority is + * valid by the time we get here. + */ + if (WARN_ON(idx >= ARRAY_SIZE(ctx->entities))) + return ERR_PTR(-EINVAL); + + mutex_lock(&entity_lock); + + if (!ctx->entities[idx]) { + struct drm_sched_entity *entity; + struct drm_gpu_scheduler *sched = &ring->sched; + int ret; + + entity = kzalloc(sizeof(*ctx->entities[idx]), GFP_KERNEL); + + ret = drm_sched_entity_init(entity, sched_prio, &sched, 1, NULL); + if (ret) { + kfree(entity); + return ERR_PTR(ret); + } + + ctx->entities[idx] = entity; + } + + mutex_unlock(&entity_lock); + + return ctx->entities[idx]; +} + int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx, u32 prio, u32 flags, u32 *id) { struct msm_drm_private *priv = drm->dev_private; struct msm_gpu_submitqueue *queue; - struct msm_ringbuffer *ring; - struct drm_gpu_scheduler *sched; enum drm_sched_priority sched_prio; unsigned ring_nr; int ret; @@ -91,12 +141,10 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx, queue->flags = flags; queue->ring_nr = ring_nr; - ring = priv->gpu->rb[ring_nr]; - sched = &ring->sched; - - ret = drm_sched_entity_init(&queue->entity, - sched_prio, &sched, 1, NULL); - if (ret) { + queue->entity = get_sched_entity(ctx, priv->gpu->rb[ring_nr], + ring_nr, sched_prio); + if (IS_ERR(queue->entity)) { + ret = PTR_ERR(queue->entity); kfree(queue); return ret; } -- cgit From 95c58291ee709424557996891926a05a32c5b13a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 27 Sep 2021 13:36:23 +0200 Subject: drm/msm/submit: fix overflow check on 64-bit architectures The overflow check does causes a warning from clang-14 when 'sz' is a type that is smaller than size_t: drivers/gpu/drm/msm/msm_gem_submit.c:217:10: error: result of comparison of constant 18446744073709551615 with expression of type 'unsigned int' is always false [-Werror,-Wtautological-constant-out-of-range-compare] if (sz == SIZE_MAX) { Change the type accordingly. Fixes: 20224d715a88 ("drm/msm/submit: Move copy_from_user ahead of locking bos") Signed-off-by: Arnd Bergmann Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20210927113632.3849987-1-arnd@kernel.org Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gem_submit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 7e0f6571cbca..151d19e4453c 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -171,7 +171,8 @@ out: static int submit_lookup_cmds(struct msm_gem_submit *submit, struct drm_msm_gem_submit *args, struct drm_file *file) { - unsigned i, sz; + unsigned i; + size_t sz; int ret = 0; for (i = 0; i < args->nr_cmds; i++) { -- cgit From 67a12ae52599c9f2f24ef14adb43fc3b164792b5 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Fri, 1 Oct 2021 23:27:26 +0200 Subject: spi: spi-nxp-fspi: don't depend on a specific node name erratum workaround In commit 7e71b85473f8 ("arm64: dts: ls1028a: fix node name for the sysclk") the sysclk node name was renamed and broke the erratum workaround because it tries to fetch a device tree node by its name, which is very fragile in general. We don't even need the sysclk node because the only possible sysclk frequency input is 100MHz. In fact, the erratum says it applies if SYS_PLL_RAT is 3, not that the platform clock is 300 MHz. Make the workaround more reliable and just drop the unneeded sysclk lookup. For reference, the error during the bootup is the following: [ 4.898400] nxp-fspi 20c0000.spi: Errata cannot be executed. Read via IP bus may not work Fixes: 82ce7d0e74b6 ("spi: spi-nxp-fspi: Implement errata workaround for LS1028A") Cc: Vladimir Oltean Signed-off-by: Michael Walle Link: https://lore.kernel.org/r/20211001212726.159437-1-michael@walle.cc Signed-off-by: Mark Brown --- drivers/spi/spi-nxp-fspi.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index a66fa97046ee..2b0301fc971c 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -315,6 +316,7 @@ #define NXP_FSPI_MIN_IOMAP SZ_4M #define DCFG_RCWSR1 0x100 +#define SYS_PLL_RAT GENMASK(6, 2) /* Access flash memory using IP bus only */ #define FSPI_QUIRK_USE_IP_ONLY BIT(0) @@ -926,9 +928,8 @@ static void erratum_err050568(struct nxp_fspi *f) { .family = "QorIQ LS1028A" }, { /* sentinel */ } }; - struct device_node *np; struct regmap *map; - u32 val = 0, sysclk = 0; + u32 val, sys_pll_ratio; int ret; /* Check for LS1028A family */ @@ -937,7 +938,6 @@ static void erratum_err050568(struct nxp_fspi *f) return; } - /* Compute system clock frequency multiplier ratio */ map = syscon_regmap_lookup_by_compatible("fsl,ls1028a-dcfg"); if (IS_ERR(map)) { dev_err(f->dev, "No syscon regmap\n"); @@ -948,23 +948,11 @@ static void erratum_err050568(struct nxp_fspi *f) if (ret < 0) goto err; - /* Strap bits 6:2 define SYS_PLL_RAT i.e frequency multiplier ratio */ - val = (val >> 2) & 0x1F; - WARN(val == 0, "Strapping is zero: Cannot determine ratio"); + sys_pll_ratio = FIELD_GET(SYS_PLL_RAT, val); + dev_dbg(f->dev, "val: 0x%08x, sys_pll_ratio: %d\n", val, sys_pll_ratio); - /* Compute system clock frequency */ - np = of_find_node_by_name(NULL, "clock-sysclk"); - if (!np) - goto err; - - if (of_property_read_u32(np, "clock-frequency", &sysclk)) - goto err; - - sysclk = (sysclk * val) / 1000000; /* Convert sysclk to Mhz */ - dev_dbg(f->dev, "val: 0x%08x, sysclk: %dMhz\n", val, sysclk); - - /* Use IP bus only if PLL is 300MHz */ - if (sysclk == 300) + /* Use IP bus only if platform clock is 300MHz */ + if (sys_pll_ratio == 3) f->devtype_data->quirks |= FSPI_QUIRK_USE_IP_ONLY; return; -- cgit From 57b44817a8d63e75394bc21849f585ded53de8bb Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Tue, 28 Sep 2021 07:57:53 -0700 Subject: MAINTAINERS: Drop outdated FPGA Manager website The rocketboards website no longer really reflects a good landing place for people interested in FPGA Manager. Cc: Xu Yilun Cc: Wu Hao Acked-by: Xu Yilun Signed-off-by: Moritz Fischer --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 2ec4c2a2458a..c4eaac287edb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7342,7 +7342,6 @@ M: Xu Yilun R: Tom Rix L: linux-fpga@vger.kernel.org S: Maintained -W: http://www.rocketboards.org Q: http://patchwork.kernel.org/project/linux-fpga/list/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/mdf/linux-fpga.git F: Documentation/devicetree/bindings/fpga/ -- cgit From 26d90b5590579def54382a2fc34cfbe8518a9851 Mon Sep 17 00:00:00 2001 From: Jiri Valek - 2N Date: Mon, 20 Sep 2021 14:53:48 +0200 Subject: iio: light: opt3001: Fixed timeout error when 0 lux Reading from sensor returned timeout error under zero light conditions. Signed-off-by: Jiri Valek - 2N Fixes: ac663db3678a ("iio: light: opt3001: enable operation w/o IRQ") Link: https://lore.kernel.org/r/20210920125351.6569-1-valek@2n.cz Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/light/opt3001.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index 52963da401a7..1880bd5bb258 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -276,6 +276,8 @@ static int opt3001_get_lux(struct opt3001 *opt, int *val, int *val2) ret = wait_event_timeout(opt->result_ready_queue, opt->result_ready, msecs_to_jiffies(OPT3001_RESULT_READY_LONG)); + if (ret == 0) + return -ETIMEDOUT; } else { /* Sleep for result ready time */ timeout = (opt->int_time == OPT3001_INT_TIME_SHORT) ? @@ -312,9 +314,7 @@ err: /* Disallow IRQ to access the device while lock is active */ opt->ok_to_ignore_lock = false; - if (ret == 0) - return -ETIMEDOUT; - else if (ret < 0) + if (ret < 0) return ret; if (opt->use_irq) { -- cgit From 1f8d398e1cd8813f8ec16d55c086e8270a9c18ab Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Fri, 1 Oct 2021 15:31:10 +0200 Subject: ALSA: hda/realtek: Complete partial device name to avoid ambiguity The string "Clevo X170" is not enough to unambiguously identify the correct device. Fixing it so another Clevo barebone name starting with "X170" can be added without causing confusion. Signed-off-by: Werner Sembach Cc: Link: https://lore.kernel.org/r/20211001133111.428249-2-wse@tuxedocomputers.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6bf6151347d8..45e1f570f1e6 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2537,7 +2537,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x67e5, "Clevo PC70D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), - SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170", ALC1220_FIXUP_CLEVO_PB51ED_PINS), + SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170SM", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1558, 0x9506, "Clevo P955HQ", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1558, 0x950a, "Clevo P955H[PR]", ALC1220_FIXUP_CLEVO_P950), -- cgit From cc03069a397005da24f6783835c274d5aedf6043 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Fri, 1 Oct 2021 15:31:11 +0200 Subject: ALSA: hda/realtek: Add quirk for Clevo X170KM-G This applies a SND_PCI_QUIRK(...) to the Clevo X170KM-G barebone. This fixes the issue of the devices internal Speaker not working. Signed-off-by: Werner Sembach Cc: Link: https://lore.kernel.org/r/20211001133111.428249-3-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 45e1f570f1e6..0331fae5525e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2538,6 +2538,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x1558, 0x67e5, "Clevo PC70D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170SM", ALC1220_FIXUP_CLEVO_PB51ED_PINS), + SND_PCI_QUIRK(0x1558, 0x7715, "Clevo X170KM-G", ALC1220_FIXUP_CLEVO_PB51ED), SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1558, 0x9506, "Clevo P955HQ", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1558, 0x950a, "Clevo P955H[PR]", ALC1220_FIXUP_CLEVO_P950), -- cgit From 410d591a19543f1347bc2b4b4ec3399cb548ba47 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Mon, 4 Oct 2021 09:03:53 +0800 Subject: kernfs: don't create a negative dentry if inactive node exists It's been reported that doing stress test for module insertion and removal can result in an ENOENT from libkmod for a valid module. In kernfs_iop_lookup() a negative dentry is created if there's no kernfs node associated with the dentry or the node is inactive. But inactive kernfs nodes are meant to be invisible to the VFS and creating a negative dentry for these can have unexpected side effects when the node transitions to an active state. The point of creating negative dentries is to avoid the expensive alloc/free cycle that occurs if there are frequent lookups for kernfs attributes that don't exist. So kernfs nodes that are not yet active should not result in a negative dentry being created so when they transition to an active state VFS lookups can create an associated dentry is a natural way. It's also been reported that https://github.com/osandov/blktests.git test block/001 hangs during the test. It was suggested that recent changes to blktests might have caused it but applying this patch resolved the problem without change to blktests. Fixes: c7e7c04274b1 ("kernfs: use VFS negative dentry caching") Tested-by: Yi Zhang ACKed-by: Al Viro Signed-off-by: Ian Kent Link: https://lore.kernel.org/r/163330943316.19450.15056895533949392922.stgit@mickey.themaw.net Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/dir.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index cfc3ce8b815a..8e0a1378a4b1 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -1111,7 +1111,14 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir, kn = kernfs_find_ns(parent, dentry->d_name.name, ns); /* attach dentry and inode */ - if (kn && kernfs_active(kn)) { + if (kn) { + /* Inactive nodes are invisible to the VFS so don't + * create a negative. + */ + if (!kernfs_active(kn)) { + up_read(&kernfs_rwsem); + return NULL; + } inode = kernfs_get_inode(dir->i_sb, kn); if (!inode) inode = ERR_PTR(-ENOMEM); -- cgit From 5963e5262180129f1be7556bd96994b6e52f3178 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 4 Oct 2021 09:40:50 +0200 Subject: ALSA: usb-audio: Enable rate validation for Scarlett devices The Scarlett device series from Focusrite Novation seem requiring the sample rate validations as we've done for MOTU devices; otherwise the driver probes invalid audioformat entries that contain the sample rates that actually don't work, and this may result in an incomplete setup as reported recently. This patch adds the needed quirk flag for enabling the sample rate validation for Focusrite Novation devices. Fixes: fe773b8711e3 ("ALSA: usb-audio: workaround for iface reset issue") BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=214493 Link: https://lore.kernel.org/r/20211004074050.28241-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/quirks.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 6ee6d24c847f..889c855addfc 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1900,6 +1900,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_IFACE_DELAY), VENDOR_FLG(0x07fd, /* MOTU */ QUIRK_FLAG_VALIDATE_RATES), + VENDOR_FLG(0x1235, /* Focusrite Novation */ + QUIRK_FLAG_VALIDATE_RATES), VENDOR_FLG(0x152a, /* Thesycon devices */ QUIRK_FLAG_DSD_RAW), VENDOR_FLG(0x1de7, /* Phoenix Audio */ -- cgit From 5aec98913095ed3b4424ed6c5fdeb6964e9734da Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Tue, 5 Oct 2021 14:35:14 +0800 Subject: ALSA: hda/realtek - ALC236 headset MIC recording issue In power save mode, the recording voice from headset mic will 2s more delay. Add this patch will solve this issue. [ minor coding style fix by tiwai ] Signed-off-by: Kailang Yang Tested-by: Kai-Heng Feng Cc: Link: https://lore.kernel.org/r/ccb0cdd5bbd7486eabbd8d987d384cb0@realtek.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0331fae5525e..0689f43fc7af 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -526,6 +526,8 @@ static void alc_shutup_pins(struct hda_codec *codec) struct alc_spec *spec = codec->spec; switch (codec->core.vendor_id) { + case 0x10ec0236: + case 0x10ec0256: case 0x10ec0283: case 0x10ec0286: case 0x10ec0288: @@ -3529,7 +3531,8 @@ static void alc256_shutup(struct hda_codec *codec) /* If disable 3k pulldown control for alc257, the Mic detection will not work correctly * when booting with headset plugged. So skip setting it for the codec alc257 */ - if (codec->core.vendor_id != 0x10ec0257) + if (spec->codec_variant != ALC269_TYPE_ALC257 && + spec->codec_variant != ALC269_TYPE_ALC256) alc_update_coef_idx(codec, 0x46, 0, 3 << 12); if (!spec->no_shutup_pins) -- cgit From 244f5d597e1ea519c2085fbd9819458688775e42 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Fri, 24 Sep 2021 10:28:58 +0100 Subject: firmware: arm_ffa: Add missing remove callback to ffa_bus_type Currently the arm_ffa firmware driver can be built as module and hence all the users of FFA driver. If any driver on the ffa bus is removed or unregistered, the remove callback on all the device bound to the driver being removed should be callback. For that to happen, we must register a remove callback on the ffa_bus which is currently missing. This results in the probe getting called again without the previous remove callback on a device which may result in kernel crash. Fix the issue by registering the remove callback on the FFA bus. Link: https://lore.kernel.org/r/20210924092859.3057562-1-sudeep.holla@arm.com Fixes: e781858488b9 ("firmware: arm_ffa: Add initial FFA bus support for device enumeration") Reported-by: Jens Wiklander Tested-by: Jens Wiklander Signed-off-by: Sudeep Holla --- drivers/firmware/arm_ffa/bus.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c index 00fe595a5bc8..f01348e6cf1c 100644 --- a/drivers/firmware/arm_ffa/bus.c +++ b/drivers/firmware/arm_ffa/bus.c @@ -49,6 +49,13 @@ static int ffa_device_probe(struct device *dev) return ffa_drv->probe(ffa_dev); } +static void ffa_device_remove(struct device *dev) +{ + struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver); + + ffa_drv->remove(to_ffa_dev(dev)); +} + static int ffa_device_uevent(struct device *dev, struct kobj_uevent_env *env) { struct ffa_device *ffa_dev = to_ffa_dev(dev); @@ -86,6 +93,7 @@ struct bus_type ffa_bus_type = { .name = "arm_ffa", .match = ffa_device_match, .probe = ffa_device_probe, + .remove = ffa_device_remove, .uevent = ffa_device_uevent, .dev_groups = ffa_device_attributes_groups, }; -- cgit From eb7b52e6db7c21400b9b2d539f9343fb6e94bd94 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Fri, 24 Sep 2021 10:28:59 +0100 Subject: firmware: arm_ffa: Fix __ffa_devices_unregister When arm_ffa firmware driver module is unloaded or removed we call __ffa_devices_unregister on all the devices on the ffa bus. It must unregister all the devices instead it is currently just releasing the devices without unregistering. That is pure wrong as when we try to load the module back again, it will result in the kernel crash something like below. -->8 CPU: 2 PID: 232 Comm: modprobe Not tainted 5.15.0-rc2+ #169 Hardware name: FVP Base RevC (DT) Call trace: dump_backtrace+0x0/0x1cc show_stack+0x18/0x64 dump_stack_lvl+0x64/0x7c dump_stack+0x18/0x38 sysfs_create_dir_ns+0xe4/0x140 kobject_add_internal+0x170/0x358 kobject_add+0x94/0x100 device_add+0x178/0x5f0 device_register+0x20/0x30 ffa_device_register+0x80/0xcc [ffa_module] ffa_setup_partitions+0x7c/0x108 [ffa_module] init_module+0x290/0x2dc [ffa_module] do_one_initcall+0xbc/0x230 do_init_module+0x58/0x304 load_module+0x15e0/0x1f68 __arm64_sys_finit_module+0xb8/0xf4 invoke_syscall+0x44/0x140 el0_svc_common+0xb4/0xf0 do_el0_svc+0x24/0x80 el0_svc+0x20/0x50 el0t_64_sync_handler+0x84/0xe4 el0t_64_sync+0x1a0/0x1a4 kobject_add_internal failed for arm-ffa-8001 with -EEXIST, don't try to register things with the same name in the same directory. ---- Fix the issue by calling device_unregister in __ffa_devices_unregister which will also take care of calling device_release(which is mapped to ffa_release_device) Link: https://lore.kernel.org/r/20210924092859.3057562-2-sudeep.holla@arm.com Fixes: e781858488b9 ("firmware: arm_ffa: Add initial FFA bus support for device enumeration") Tested-by: Jens Wiklander Signed-off-by: Sudeep Holla --- drivers/firmware/arm_ffa/bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c index f01348e6cf1c..641a91819088 100644 --- a/drivers/firmware/arm_ffa/bus.c +++ b/drivers/firmware/arm_ffa/bus.c @@ -135,7 +135,7 @@ static void ffa_release_device(struct device *dev) static int __ffa_devices_unregister(struct device *dev, void *data) { - ffa_release_device(dev); + device_unregister(dev); return 0; } -- cgit From 7ff4034e910fe00a90d985f0d05bacf60c162f02 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 27 Sep 2021 13:36:56 +0200 Subject: staging: vc04_services: shut up out-of-range warning The comparison against SIZE_MAX produces a harmless warning on 64-bit architectures: drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c:185:16: error: result of comparison of constant 419244183493398898 with expression of type 'unsigned int' is always false [-Werror,-Wtautological-constant-out-of-range-compare] if (num_pages > (SIZE_MAX - sizeof(struct pagelist) - ~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Shut up that warning by adding a cast to a longer type. Fixes: ca641bae6da9 ("staging: vc04_services: prevent integer overflow in create_pagelist()") Cc: stable Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20210927113702.3866843-1-arnd@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index b25369a13452..967f10b9582a 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -182,7 +182,7 @@ create_pagelist(char *buf, char __user *ubuf, offset = (uintptr_t)ubuf & (PAGE_SIZE - 1); num_pages = DIV_ROUND_UP(count + offset, PAGE_SIZE); - if (num_pages > (SIZE_MAX - sizeof(struct pagelist) - + if ((size_t)num_pages > (SIZE_MAX - sizeof(struct pagelist) - sizeof(struct vchiq_pagelist_info)) / (sizeof(u32) + sizeof(pages[0]) + sizeof(struct scatterlist))) -- cgit From 37f12202c5d28291ba5f83ce229771447ce9148f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 30 Sep 2021 15:26:04 +0300 Subject: staging: r8188eu: prevent array underflow in rtw_hal_update_ra_mask() The problem is that "mac_id" is a u32 so this check for underflow does not work when "mac_id" is zero. In that situation, "mac_id - 1" is UINT_MAX instead of -1 so the condition is true. It leads to an array underflow on the next line. Fixes: 8cd574e6af54 ("staging: r8188eu: introduce new hal dir for RTL8188eu driver") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/20210930122604.GB10068@kili Signed-off-by: Greg Kroah-Hartman --- drivers/staging/r8188eu/hal/hal_intf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/r8188eu/hal/hal_intf.c b/drivers/staging/r8188eu/hal/hal_intf.c index a6d589e89aeb..f27eba72d646 100644 --- a/drivers/staging/r8188eu/hal/hal_intf.c +++ b/drivers/staging/r8188eu/hal/hal_intf.c @@ -248,7 +248,7 @@ void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level) #ifdef CONFIG_88EU_AP_MODE struct sta_info *psta = NULL; struct sta_priv *pstapriv = &adapt->stapriv; - if ((mac_id - 1) > 0) + if (mac_id >= 2) psta = pstapriv->sta_aid[(mac_id - 1) - 1]; if (psta) add_RATid(adapt, psta, 0);/* todo: based on rssi_level*/ -- cgit From 68c9cdf37a0456b7ba25a50b1ea8794f305da17f Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 29 Aug 2021 15:23:10 +0200 Subject: efi/libstub: Simplify "Exiting bootservices" message The message "Exiting boot services and installing virtual address map...\n" is even shown if we have efi=novamap on the command line or the firmware does not provide EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP. To avoid confusion just print "Exiting boot services...\n" Signed-off-by: Heinrich Schuchardt Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/libstub/fdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index 365c3a43a198..fe567be0f118 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c @@ -271,7 +271,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle, return status; } - efi_info("Exiting boot services and installing virtual address map...\n"); + efi_info("Exiting boot services...\n"); map.map = &memory_map; status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, ULONG_MAX); -- cgit From b3a72ca80351917cc23f9e24c35f3c3979d3c121 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 1 Sep 2021 08:33:19 +0200 Subject: efi/cper: use stack buffer for error record decoding Joe reports that using a statically allocated buffer for converting CPER error records into human readable text is probably a bad idea. Even though we are not aware of any actual issues, a stack buffer is clearly a better choice here anyway, so let's move the buffer into the stack frames of the two functions that refer to it. Cc: Reported-by: Joe Perches Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/cper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c index 73bdbd207e7a..6ec8edec6329 100644 --- a/drivers/firmware/efi/cper.c +++ b/drivers/firmware/efi/cper.c @@ -25,8 +25,6 @@ #include #include -static char rcd_decode_str[CPER_REC_LEN]; - /* * CPER record ID need to be unique even after reboot, because record * ID is used as index for ERST storage, while CPER records from @@ -312,6 +310,7 @@ const char *cper_mem_err_unpack(struct trace_seq *p, struct cper_mem_err_compact *cmem) { const char *ret = trace_seq_buffer_ptr(p); + char rcd_decode_str[CPER_REC_LEN]; if (cper_mem_err_location(cmem, rcd_decode_str)) trace_seq_printf(p, "%s", rcd_decode_str); @@ -326,6 +325,7 @@ static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem, int len) { struct cper_mem_err_compact cmem; + char rcd_decode_str[CPER_REC_LEN]; /* Don't trust UEFI 2.1/2.2 structure with bad validation bits */ if (len == sizeof(struct cper_sec_mem_err_old) && -- cgit From 38fa3206bf441911258e5001ac8b6738693f8d82 Mon Sep 17 00:00:00 2001 From: Zhang Jianhua Date: Thu, 23 Sep 2021 10:53:40 +0800 Subject: efi: Change down_interruptible() in virt_efi_reset_system() to down_trylock() While reboot the system by sysrq, the following bug will be occur. BUG: sleeping function called from invalid context at kernel/locking/semaphore.c:90 in_atomic(): 0, irqs_disabled(): 128, non_block: 0, pid: 10052, name: rc.shutdown CPU: 3 PID: 10052 Comm: rc.shutdown Tainted: G W O 5.10.0 #1 Call trace: dump_backtrace+0x0/0x1c8 show_stack+0x18/0x28 dump_stack+0xd0/0x110 ___might_sleep+0x14c/0x160 __might_sleep+0x74/0x88 down_interruptible+0x40/0x118 virt_efi_reset_system+0x3c/0xd0 efi_reboot+0xd4/0x11c machine_restart+0x60/0x9c emergency_restart+0x1c/0x2c sysrq_handle_reboot+0x1c/0x2c __handle_sysrq+0xd0/0x194 write_sysrq_trigger+0xbc/0xe4 proc_reg_write+0xd4/0xf0 vfs_write+0xa8/0x148 ksys_write+0x6c/0xd8 __arm64_sys_write+0x18/0x28 el0_svc_common.constprop.3+0xe4/0x16c do_el0_svc+0x1c/0x2c el0_svc+0x20/0x30 el0_sync_handler+0x80/0x17c el0_sync+0x158/0x180 The reason for this problem is that irq has been disabled in machine_restart() and then it calls down_interruptible() in virt_efi_reset_system(), which would occur sleep in irq context, it is dangerous! Commit 99409b935c9a("locking/semaphore: Add might_sleep() to down_*() family") add might_sleep() in down_interruptible(), so the bug info is here. down_trylock() can solve this problem, cause there is no might_sleep. -------- Cc: Signed-off-by: Zhang Jianhua Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/runtime-wrappers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index 1410beaef5c3..f3e54f6616f0 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c @@ -414,7 +414,7 @@ static void virt_efi_reset_system(int reset_type, unsigned long data_size, efi_char16_t *data) { - if (down_interruptible(&efi_runtime_lock)) { + if (down_trylock(&efi_runtime_lock)) { pr_warn("failed to invoke the reset_system() runtime service:\n" "could not get exclusive access to the firmware\n"); return; -- cgit From beb76cb4eebf9ac4ff15312e33f97db621b46da7 Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Tue, 5 Oct 2021 09:54:50 +0200 Subject: MAINTAINERS: rectify entry for SY8106A REGULATOR DRIVER Commit b1c36aae51c9 ("regulator: Convert SY8106A binding to a schema") converts sy8106a-regulator.txt to silergy,sy8106a.yaml, but missed to adjust its reference in MAINTAINERS. Hence, ./scripts/get_maintainer.pl --self-test=patterns complains about a broken reference. Repair this file reference in SY8106A REGULATOR DRIVER. Signed-off-by: Lukas Bulwahn Link: https://lore.kernel.org/r/20211005075451.29691-11-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 a61f4f3b78a9..5004a2bcbc9d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17780,7 +17780,7 @@ F: net/switchdev/ SY8106A REGULATOR DRIVER M: Icenowy Zheng S: Maintained -F: Documentation/devicetree/bindings/regulator/sy8106a-regulator.txt +F: Documentation/devicetree/bindings/regulator/silergy,sy8106a.yaml F: drivers/regulator/sy8106a-regulator.c SYNC FILE FRAMEWORK -- cgit From cb2282213e84f04ab7e93fd4537815da5db2f010 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 24 Sep 2021 16:12:32 +0200 Subject: serial: 8250: allow disabling of Freescale 16550 compile test The SERIAL_8250_FSL option is used to enable a workaround for a break-detection erratum for Freescale 16550 UARTs in the 8250 driver and is currently also used to enable support for ACPI enumeration. It is enabled on PPC, ARM and ARM64 whenever 8250 console support is enabled (since the quirk is needed for sysrq handling). Commit b1442c55ce89 ("serial: 8250: extend compile-test coverage") enabled compile testing of the code in question but did not provide a means to disable the option when COMPILE_TEST is enabled. Add a conditional input prompt instead so that SERIAL_8250_FSL is no longer enabled by default when compile testing while continuing to always enable the quirk for platforms that may need it. Fixes: b1442c55ce89 ("serial: 8250: extend compile-test coverage") Reported-by: Geert Uytterhoeven Signed-off-by: Johan Hovold Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20210924141232.4419-1-johan@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/Kconfig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 71ae16de0f90..39fc96dc2531 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -361,9 +361,13 @@ config SERIAL_8250_BCM2835AUX If unsure, say N. config SERIAL_8250_FSL - bool + bool "Freescale 16550 UART support" if COMPILE_TEST && !(PPC || ARM || ARM64) depends on SERIAL_8250_CONSOLE - default PPC || ARM || ARM64 || COMPILE_TEST + default PPC || ARM || ARM64 + help + Selecting this option enables a workaround for a break-detection + erratum for Freescale 16550 UARTs in the 8250 driver. It also + enables support for ACPI enumeration. config SERIAL_8250_DW tristate "Support for Synopsys DesignWare 8250 quirks" -- cgit From b1e0c55a409955aba2d5a151f3f3a8bda8e45193 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Fri, 24 Sep 2021 17:47:04 +0300 Subject: fs/ntfs3: Use available posix_acl_release instead of ntfs_posix_acl_release We don't need to maintain ntfs_posix_acl_release. Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/xattr.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index 83bbee277e12..253a07d9aa7b 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -475,12 +475,6 @@ out: } #ifdef CONFIG_NTFS3_FS_POSIX_ACL -static inline void ntfs_posix_acl_release(struct posix_acl *acl) -{ - if (acl && refcount_dec_and_test(&acl->a_refcount)) - kfree(acl); -} - static struct posix_acl *ntfs_get_acl_ex(struct user_namespace *mnt_userns, struct inode *inode, int type, int locked) @@ -641,7 +635,7 @@ static int ntfs_xattr_get_acl(struct user_namespace *mnt_userns, return -ENODATA; err = posix_acl_to_xattr(mnt_userns, acl, buffer, size); - ntfs_posix_acl_release(acl); + posix_acl_release(acl); return err; } @@ -678,7 +672,7 @@ static int ntfs_xattr_set_acl(struct user_namespace *mnt_userns, err = ntfs_set_acl(mnt_userns, inode, acl, type); release_and_out: - ntfs_posix_acl_release(acl); + posix_acl_release(acl); return err; } -- cgit From d81e06be921f90d5f1bada59d4549ca6f1bedc61 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Fri, 24 Sep 2021 17:50:22 +0300 Subject: fs/ntfs3: Remove locked argument in ntfs_set_ea We always need to lock now, because locks became smaller (see d562e901f25d "fs/ntfs3: Move ni_lock_dir and ni_unlock into ntfs_create_inode"). Signed-off-by: Konstantin Komarov --- fs/ntfs3/xattr.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index 253a07d9aa7b..29f571b53083 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -257,7 +257,7 @@ out: static noinline int ntfs_set_ea(struct inode *inode, const char *name, size_t name_len, const void *value, - size_t val_size, int flags, int locked) + size_t val_size, int flags) { struct ntfs_inode *ni = ntfs_i(inode); struct ntfs_sb_info *sbi = ni->mi.sbi; @@ -276,8 +276,7 @@ static noinline int ntfs_set_ea(struct inode *inode, const char *name, u64 new_sz; void *p; - if (!locked) - ni_lock(ni); + ni_lock(ni); run_init(&ea_run); @@ -465,8 +464,7 @@ update_ea: mark_inode_dirty(&ni->vfs_inode); out: - if (!locked) - ni_unlock(ni); + ni_unlock(ni); run_close(&ea_run); kfree(ea_all); @@ -537,7 +535,7 @@ struct posix_acl *ntfs_get_acl(struct inode *inode, int type) static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns, struct inode *inode, struct posix_acl *acl, - int type, int locked) + int type) { const char *name; size_t size, name_len; @@ -594,7 +592,7 @@ static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns, flags = 0; } - err = ntfs_set_ea(inode, name, name_len, value, size, flags, locked); + err = ntfs_set_ea(inode, name, name_len, value, size, flags); if (err == -ENODATA && !size) err = 0; /* Removing non existed xattr. */ if (!err) @@ -612,7 +610,7 @@ out: int ntfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode, struct posix_acl *acl, int type) { - return ntfs_set_acl_ex(mnt_userns, inode, acl, type, 0); + return ntfs_set_acl_ex(mnt_userns, inode, acl, type); } static int ntfs_xattr_get_acl(struct user_namespace *mnt_userns, @@ -693,7 +691,7 @@ int ntfs_init_acl(struct user_namespace *mnt_userns, struct inode *inode, if (default_acl) { err = ntfs_set_acl_ex(mnt_userns, inode, default_acl, - ACL_TYPE_DEFAULT, 1); + ACL_TYPE_DEFAULT); posix_acl_release(default_acl); } else { inode->i_default_acl = NULL; @@ -704,7 +702,7 @@ int ntfs_init_acl(struct user_namespace *mnt_userns, struct inode *inode, else { if (!err) err = ntfs_set_acl_ex(mnt_userns, inode, acl, - ACL_TYPE_ACCESS, 1); + ACL_TYPE_ACCESS); posix_acl_release(acl); } @@ -988,7 +986,7 @@ set_new_fa: } #endif /* Deal with NTFS extended attribute. */ - err = ntfs_set_ea(inode, name, name_len, value, size, flags, 0); + err = ntfs_set_ea(inode, name, name_len, value, size, flags); out: return err; @@ -1004,28 +1002,29 @@ int ntfs_save_wsl_perm(struct inode *inode) int err; __le32 value; + /* TODO: refactor this, so we don't lock 4 times in ntfs_set_ea */ value = cpu_to_le32(i_uid_read(inode)); err = ntfs_set_ea(inode, "$LXUID", sizeof("$LXUID") - 1, &value, - sizeof(value), 0, 0); + sizeof(value), 0); if (err) goto out; value = cpu_to_le32(i_gid_read(inode)); err = ntfs_set_ea(inode, "$LXGID", sizeof("$LXGID") - 1, &value, - sizeof(value), 0, 0); + sizeof(value), 0); if (err) goto out; value = cpu_to_le32(inode->i_mode); err = ntfs_set_ea(inode, "$LXMOD", sizeof("$LXMOD") - 1, &value, - sizeof(value), 0, 0); + sizeof(value), 0); if (err) goto out; if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { value = cpu_to_le32(inode->i_rdev); err = ntfs_set_ea(inode, "$LXDEV", sizeof("$LXDEV") - 1, &value, - sizeof(value), 0, 0); + sizeof(value), 0); if (err) goto out; } -- cgit From cff32466bf851bf29cd491d8a3cbeb4dc4a36ab6 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Fri, 24 Sep 2021 17:53:56 +0300 Subject: fs/ntfs3: Refactoring of ntfs_set_ea Make code more readable. Don't try to read zero bytes. Add warning when size of exteneded attribute exceeds limit. Signed-off-by: Konstantin Komarov --- fs/ntfs3/xattr.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index 29f571b53083..cdc01877227a 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -75,6 +75,7 @@ static int ntfs_read_ea(struct ntfs_inode *ni, struct EA_FULL **ea, size_t add_bytes, const struct EA_INFO **info) { int err; + struct ntfs_sb_info *sbi = ni->mi.sbi; struct ATTR_LIST_ENTRY *le = NULL; struct ATTRIB *attr_info, *attr_ea; void *ea_p; @@ -99,10 +100,10 @@ static int ntfs_read_ea(struct ntfs_inode *ni, struct EA_FULL **ea, /* Check Ea limit. */ size = le32_to_cpu((*info)->size); - if (size > ni->mi.sbi->ea_max_size) + if (size > sbi->ea_max_size) return -EFBIG; - if (attr_size(attr_ea) > ni->mi.sbi->ea_max_size) + if (attr_size(attr_ea) > sbi->ea_max_size) return -EFBIG; /* Allocate memory for packed Ea. */ @@ -110,15 +111,16 @@ static int ntfs_read_ea(struct ntfs_inode *ni, struct EA_FULL **ea, if (!ea_p) return -ENOMEM; - if (attr_ea->non_res) { + if (!size) { + ; + } else if (attr_ea->non_res) { struct runs_tree run; run_init(&run); err = attr_load_runs(attr_ea, ni, &run, NULL); if (!err) - err = ntfs_read_run_nb(ni->mi.sbi, &run, 0, ea_p, size, - NULL); + err = ntfs_read_run_nb(sbi, &run, 0, ea_p, size, NULL); run_close(&run); if (err) @@ -366,21 +368,22 @@ static noinline int ntfs_set_ea(struct inode *inode, const char *name, new_ea->name[name_len] = 0; memcpy(new_ea->name + name_len + 1, value, val_size); new_pack = le16_to_cpu(ea_info.size_pack) + packed_ea_size(new_ea); - - /* Should fit into 16 bits. */ - if (new_pack > 0xffff) { - err = -EFBIG; // -EINVAL? - goto out; - } ea_info.size_pack = cpu_to_le16(new_pack); - /* New size of ATTR_EA. */ size += add; - if (size > sbi->ea_max_size) { + ea_info.size = cpu_to_le32(size); + + /* + * 1. Check ea_info.size_pack for overflow. + * 2. New attibute size must fit value from $AttrDef + */ + if (new_pack > 0xffff || size > sbi->ea_max_size) { + ntfs_inode_warn( + inode, + "The size of extended attributes must not exceed 64KiB"); err = -EFBIG; // -EINVAL? goto out; } - ea_info.size = cpu_to_le32(size); update_ea: -- cgit From a3e16937319aea285c64ab5bf8464470afac8dd3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Sep 2021 20:46:09 +0100 Subject: misc: gehc: Add SPI ID table Currently autoloading for SPI devices does not use the DT ID table, it uses SPI modalises. Supporting OF modalises is going to be difficult if not impractical, an attempt was made but has been reverted, so ensure that module autoloading works for this driver by adding a SPI ID table entry for the device name part of the compatible - currently only the full compatible is listed which isn't very idiomatic and won't match the modalias that is generated. Fixes: 96c8395e2166 ("spi: Revert modalias changes") Cc: stable Tested-by: Martyn Welch Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20210923194609.52647-1-broonie@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/gehc-achc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/misc/gehc-achc.c b/drivers/misc/gehc-achc.c index 02f33bc60c56..4c9c5394da6f 100644 --- a/drivers/misc/gehc-achc.c +++ b/drivers/misc/gehc-achc.c @@ -539,6 +539,7 @@ static int gehc_achc_probe(struct spi_device *spi) static const struct spi_device_id gehc_achc_id[] = { { "ge,achc", 0 }, + { "achc", 0 }, { } }; MODULE_DEVICE_TABLE(spi, gehc_achc_id); -- cgit From 42641042c10c757fe10cc09088cf3f436cec5007 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 27 Sep 2021 14:13:57 +0200 Subject: cb710: avoid NULL pointer subtraction clang-14 complains about an unusual way of converting a pointer to an integer: drivers/misc/cb710/sgbuf2.c:50:15: error: performing pointer subtraction with a null pointer has undefined behavior [-Werror,-Wnull-pointer-subtraction] return ((ptr - NULL) & 3) != 0; Replace this with a normal cast to uintptr_t. Fixes: 5f5bac8272be ("mmc: Driver for CB710/720 memory card reader (MMC part)") Cc: stable Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20210927121408.939246-1-arnd@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/cb710/sgbuf2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/cb710/sgbuf2.c b/drivers/misc/cb710/sgbuf2.c index e5a4ed3701eb..a798fad5f03c 100644 --- a/drivers/misc/cb710/sgbuf2.c +++ b/drivers/misc/cb710/sgbuf2.c @@ -47,7 +47,7 @@ static inline bool needs_unaligned_copy(const void *ptr) #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS return false; #else - return ((ptr - NULL) & 3) != 0; + return ((uintptr_t)ptr & 3) != 0; #endif } -- cgit From f9a470db2736b01538ad193c316eb3f26be37d58 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Wed, 22 Sep 2021 16:43:26 +0100 Subject: misc: fastrpc: Add missing lock before accessing find_vma() fastrpc driver is using find_vma() without any protection, as a result we see below warning due to recent patch 5b78ed24e8ec ("mm/pagemap: add mmap_assert_locked() annotations to find_vma*()") which added mmap_assert_locked() in find_vma() function. This bug went un-noticed in previous versions. Fix this issue by adding required protection while calling find_vma(). CPU: 0 PID: 209746 Comm: benchmark_model Not tainted 5.15.0-rc2-00445-ge14fe2bf817a-dirty #969 Hardware name: Qualcomm Technologies, Inc. Robotics RB5 (DT) pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : find_vma+0x64/0xd0 lr : find_vma+0x60/0xd0 sp : ffff8000158ebc40 ... Call trace: find_vma+0x64/0xd0 fastrpc_internal_invoke+0x570/0xda8 fastrpc_device_ioctl+0x3e0/0x928 __arm64_sys_ioctl+0xac/0xf0 invoke_syscall+0x44/0x100 el0_svc_common.constprop.3+0x70/0xf8 do_el0_svc+0x24/0x88 el0_svc+0x3c/0x138 el0t_64_sync_handler+0x90/0xb8 el0t_64_sync+0x180/0x184 Fixes: 80f3afd72bd4 ("misc: fastrpc: consider address offset before sending to DSP") Cc: stable@vger.kernel.org Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210922154326.8927-1-srinivas.kandagatla@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/fastrpc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index beda610e6b30..ad6ced454655 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -814,10 +814,12 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx) rpra[i].pv = (u64) ctx->args[i].ptr; pages[i].addr = ctx->maps[i]->phys; + mmap_read_lock(current->mm); vma = find_vma(current->mm, ctx->args[i].ptr); if (vma) pages[i].addr += ctx->args[i].ptr - vma->vm_start; + mmap_read_unlock(current->mm); pg_start = (ctx->args[i].ptr & PAGE_MASK) >> PAGE_SHIFT; pg_end = ((ctx->args[i].ptr + len - 1) & PAGE_MASK) >> -- cgit From 8241fffae7c8bab5cec5fc8bcaceccd03079e3aa Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Tue, 28 Sep 2021 20:04:10 +0300 Subject: fs/ntfs3: Forbid FALLOC_FL_PUNCH_HOLE for normal files FALLOC_FL_PUNCH_HOLE isn't allowed with normal files. Filesystem must remember info about hole, but for normal file we can only zero it and forget. Fixes: 4342306f0f0d ("fs/ntfs3: Add file operations and implementation") Now xfstests generic/016 generic/021 generic/022 pass. Signed-off-by: Konstantin Komarov --- fs/ntfs3/file.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 5fb3508e5422..43b1451bff53 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -587,8 +587,11 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) truncate_pagecache(inode, vbo_down); if (!is_sparsed(ni) && !is_compressed(ni)) { - /* Normal file. */ - err = ntfs_zero_range(inode, vbo, end); + /* + * Normal file, can't make hole. + * TODO: Try to find way to save info about hole. + */ + err = -EOPNOTSUPP; goto out; } -- cgit From 97d8ebead87b7457ba5c4f4e7860b8fc8cf013fd Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 3 Oct 2021 17:16:41 -0700 Subject: misc: HI6421V600_IRQ should depend on HAS_IOMEM MFD_CORE depends on HAS_IOMEM so anything that selects MFD_CORE should also depend on HAS_IOMEM since 'select' does not check any dependencies of the symbol that is being selected. Prevents this kconfig warning: WARNING: unmet direct dependencies detected for MFD_CORE Depends on [n]: HAS_IOMEM [=n] Selected by [m]: - HI6421V600_IRQ [=m] && OF [=y] && SPMI [=m] Fixes: bb3b6552a5b0 ("staging: hikey9xx: split hi6421v600 irq into a separate driver") Cc: Mauro Carvalho Chehab Cc: Greg Kroah-Hartman Cc: Arnd Bergmann Signed-off-by: Randy Dunlap Link: https://lore.kernel.org/r/20211004001641.23180-1-rdunlap@infradead.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 85ba901bc11b..0f5a49fc7c9e 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -224,6 +224,7 @@ config HI6421V600_IRQ tristate "HiSilicon Hi6421v600 IRQ and powerkey" depends on OF depends on SPMI + depends on HAS_IOMEM select MFD_CORE select REGMAP_SPMI help -- cgit From 9e2cd444909b3c93f5cc83463d12291e3e0f990b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Sep 2021 18:24:53 +0100 Subject: eeprom: at25: Add SPI ID table Currently autoloading for SPI devices does not use the DT ID table, it uses SPI modalises. Supporting OF modalises is going to be difficult if not impractical, an attempt was made but has been reverted, so ensure that module autoloading works for this driver by adding an id_table listing the SPI IDs for everything. Fixes: 96c8395e2166 ("spi: Revert modalias changes") Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20210923172453.4921-1-broonie@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/eeprom/at25.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c index 4d09b672ac3c..632325474233 100644 --- a/drivers/misc/eeprom/at25.c +++ b/drivers/misc/eeprom/at25.c @@ -366,6 +366,13 @@ static const struct of_device_id at25_of_match[] = { }; MODULE_DEVICE_TABLE(of, at25_of_match); +static const struct spi_device_id at25_spi_ids[] = { + { .name = "at25",}, + { .name = "fm25",}, + { } +}; +MODULE_DEVICE_TABLE(spi, at25_spi_ids); + static int at25_probe(struct spi_device *spi) { struct at25_data *at25 = NULL; @@ -491,6 +498,7 @@ static struct spi_driver at25_driver = { .dev_groups = sernum_groups, }, .probe = at25_probe, + .id_table = at25_spi_ids, }; module_spi_driver(at25_driver); -- cgit From 137879f7ff23c635d2c6b2e43f4b39e2d305c3e2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 22 Sep 2021 19:40:48 +0100 Subject: eeprom: 93xx46: Add SPI device ID table Currently autoloading for SPI devices does not use the DT ID table, it uses SPI modalises. Supporting OF modalises is going to be difficult if not impractical, an attempt was made but has been reverted, so ensure that module autoloading works for this driver by adding a SPI device ID table. Fixes: 96c8395e2166 ("spi: Revert modalias changes") Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20210922184048.34770-1-broonie@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/eeprom/eeprom_93xx46.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index 29d8971ec558..660ee924f8b1 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -406,6 +406,23 @@ static const struct of_device_id eeprom_93xx46_of_table[] = { }; MODULE_DEVICE_TABLE(of, eeprom_93xx46_of_table); +static const struct spi_device_id eeprom_93xx46_spi_ids[] = { + { .name = "eeprom-93xx46", + .driver_data = (kernel_ulong_t)&at93c46_data, }, + { .name = "at93c46", + .driver_data = (kernel_ulong_t)&at93c46_data, }, + { .name = "at93c46d", + .driver_data = (kernel_ulong_t)&atmel_at93c46d_data, }, + { .name = "at93c56", + .driver_data = (kernel_ulong_t)&at93c56_data, }, + { .name = "at93c66", + .driver_data = (kernel_ulong_t)&at93c66_data, }, + { .name = "93lc46b", + .driver_data = (kernel_ulong_t)µchip_93lc46b_data, }, + {} +}; +MODULE_DEVICE_TABLE(of, eeprom_93xx46_of_table); + static int eeprom_93xx46_probe_dt(struct spi_device *spi) { const struct of_device_id *of_id = @@ -555,6 +572,7 @@ static struct spi_driver eeprom_93xx46_driver = { }, .probe = eeprom_93xx46_probe, .remove = eeprom_93xx46_remove, + .id_table = eeprom_93xx46_spi_ids, }; module_spi_driver(eeprom_93xx46_driver); -- cgit From 75c10c5e7a715550afdd51ef8cfd1d975f48f9e1 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 1 Oct 2021 20:36:44 +0300 Subject: mei: me: add Ice Lake-N device id. Add Ice Lake-N device ID. The device can be found on MacBookPro16,2 [1]. [1]: https://linux-hardware.org/?probe=f1c5cf0c43 Signed-off-by: Andy Shevchenko Cc: stable Link: https://lore.kernel.org/r/20211001173644.16068-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me-regs.h | 1 + drivers/misc/mei/pci-me.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h index cb34925e10f1..67bb6a25fd0a 100644 --- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h @@ -92,6 +92,7 @@ #define MEI_DEV_ID_CDF 0x18D3 /* Cedar Fork */ #define MEI_DEV_ID_ICP_LP 0x34E0 /* Ice Lake Point LP */ +#define MEI_DEV_ID_ICP_N 0x38E0 /* Ice Lake Point N */ #define MEI_DEV_ID_JSP_N 0x4DE0 /* Jasper Lake Point N */ diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index c3393b383e59..3a45aaf002ac 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -96,6 +96,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = { {MEI_PCI_DEVICE(MEI_DEV_ID_CMP_H_3, MEI_ME_PCH8_ITOUCH_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICP_N, MEI_ME_PCH12_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_TGP_LP, MEI_ME_PCH15_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_TGP_H, MEI_ME_PCH15_SPS_CFG)}, -- cgit From 95dd8b2c1ed00c76aaf41b552041c90724749a53 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Tue, 5 Oct 2021 17:22:29 +0300 Subject: fs/ntfs3: Remove unnecessary functions We don't need ntfs_xattr_get_acl and ntfs_xattr_set_acl. There are ntfs_get_acl_ex and ntfs_set_acl_ex. Signed-off-by: Konstantin Komarov --- fs/ntfs3/xattr.c | 94 -------------------------------------------------------- 1 file changed, 94 deletions(-) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index cdc01877227a..2143099cffdf 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -616,67 +616,6 @@ int ntfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode, return ntfs_set_acl_ex(mnt_userns, inode, acl, type); } -static int ntfs_xattr_get_acl(struct user_namespace *mnt_userns, - struct inode *inode, int type, void *buffer, - size_t size) -{ - struct posix_acl *acl; - int err; - - if (!(inode->i_sb->s_flags & SB_POSIXACL)) { - ntfs_inode_warn(inode, "add mount option \"acl\" to use acl"); - return -EOPNOTSUPP; - } - - acl = ntfs_get_acl(inode, type); - if (IS_ERR(acl)) - return PTR_ERR(acl); - - if (!acl) - return -ENODATA; - - err = posix_acl_to_xattr(mnt_userns, acl, buffer, size); - posix_acl_release(acl); - - return err; -} - -static int ntfs_xattr_set_acl(struct user_namespace *mnt_userns, - struct inode *inode, int type, const void *value, - size_t size) -{ - struct posix_acl *acl; - int err; - - if (!(inode->i_sb->s_flags & SB_POSIXACL)) { - ntfs_inode_warn(inode, "add mount option \"acl\" to use acl"); - return -EOPNOTSUPP; - } - - if (!inode_owner_or_capable(mnt_userns, inode)) - return -EPERM; - - if (!value) { - acl = NULL; - } else { - acl = posix_acl_from_xattr(mnt_userns, value, size); - if (IS_ERR(acl)) - return PTR_ERR(acl); - - if (acl) { - err = posix_acl_valid(mnt_userns, acl); - if (err) - goto release_and_out; - } - } - - err = ntfs_set_acl(mnt_userns, inode, acl, type); - -release_and_out: - posix_acl_release(acl); - return err; -} - /* * ntfs_init_acl - Initialize the ACLs of a new inode. * @@ -843,23 +782,6 @@ static int ntfs_getxattr(const struct xattr_handler *handler, struct dentry *de, goto out; } -#ifdef CONFIG_NTFS3_FS_POSIX_ACL - if ((name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 && - !memcmp(name, XATTR_NAME_POSIX_ACL_ACCESS, - sizeof(XATTR_NAME_POSIX_ACL_ACCESS))) || - (name_len == sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1 && - !memcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT, - sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)))) { - /* TODO: init_user_ns? */ - err = ntfs_xattr_get_acl( - &init_user_ns, inode, - name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 - ? ACL_TYPE_ACCESS - : ACL_TYPE_DEFAULT, - buffer, size); - goto out; - } -#endif /* Deal with NTFS extended attribute. */ err = ntfs_get_ea(inode, name, name_len, buffer, size, NULL); @@ -972,22 +894,6 @@ set_new_fa: goto out; } -#ifdef CONFIG_NTFS3_FS_POSIX_ACL - if ((name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 && - !memcmp(name, XATTR_NAME_POSIX_ACL_ACCESS, - sizeof(XATTR_NAME_POSIX_ACL_ACCESS))) || - (name_len == sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1 && - !memcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT, - sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)))) { - err = ntfs_xattr_set_acl( - mnt_userns, inode, - name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 - ? ACL_TYPE_ACCESS - : ACL_TYPE_DEFAULT, - value, size); - goto out; - } -#endif /* Deal with NTFS extended attribute. */ err = ntfs_set_ea(inode, name, name_len, value, size, flags); -- cgit From f729a592adb6760013c3e48622a5bf256b992452 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Wed, 29 Sep 2021 12:05:49 -0700 Subject: driver core: Reject pointless SYNC_STATE_ONLY device links SYNC_STATE_ONLY device links intentionally allow cycles because cyclic sync_state() dependencies are valid and necessary. However a SYNC_STATE_ONLY device link where the consumer and the supplier are the same device is pointless because the device link would be deleted as soon as the device probes (because it's also the consumer) and won't affect when the sync_state() callback is called. It's a waste of CPU cycles and memory to create this device link. So reject any attempts to create such a device link. Fixes: 05ef983e0d65 ("driver core: Add device link support for SYNC_STATE_ONLY flag") Cc: stable Reported-by: Ulf Hansson Reviewed-by: Rafael J. Wysocki Reviewed-by: Ulf Hansson Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20210929190549.860541-1-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 15986cc2fe5e..249da496581a 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -687,7 +687,8 @@ struct device_link *device_link_add(struct device *consumer, { struct device_link *link; - if (!consumer || !supplier || flags & ~DL_ADD_VALID_FLAGS || + if (!consumer || !supplier || consumer == supplier || + flags & ~DL_ADD_VALID_FLAGS || (flags & DL_FLAG_STATELESS && flags & DL_MANAGED_LINK_FLAGS) || (flags & DL_FLAG_SYNC_STATE_ONLY && (flags & ~DL_FLAG_INFERRED) != DL_FLAG_SYNC_STATE_ONLY) || -- cgit From 98e96cf80045a383fcc47c58dd4e87b3ae587b3e Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Tue, 28 Sep 2021 17:07:33 -0700 Subject: drivers: bus: simple-pm-bus: Add support for probing simple bus only devices fw_devlink could end up creating device links for bus only devices. However, bus only devices don't get probed and can block probe() or sync_state() [1] call backs of other devices. To avoid this, probe these devices using the simple-pm-bus driver. However, there are instances of devices that are not simple buses (they get probed by their specific drivers) that also list the "simple-bus" (or other bus only compatible strings) in their compatible property to automatically populate their child devices. We still want these devices to get probed by their specific drivers. So, we make sure this driver only probes devices that are only buses. [1] - https://lore.kernel.org/lkml/CAPDyKFo9Bxremkb1dDrr4OcXSpE0keVze94Cm=zrkOVxHHxBmQ@mail.gmail.com/ Fixes: c442a0d18744 ("driver core: Set fw_devlink to "permissive" behavior by default") Cc: stable Cc: Rob Herring Tested-by: Saravana Kannan Tested-by: Ulf Hansson Tested-by: Geert Uytterhoeven Tested-by: Damien Le Moal Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20210929000735.585237-2-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/bus/simple-pm-bus.c | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/drivers/bus/simple-pm-bus.c b/drivers/bus/simple-pm-bus.c index 01a3d0cd08ed..6b8d6257ed8a 100644 --- a/drivers/bus/simple-pm-bus.c +++ b/drivers/bus/simple-pm-bus.c @@ -13,11 +13,36 @@ #include #include - static int simple_pm_bus_probe(struct platform_device *pdev) { - const struct of_dev_auxdata *lookup = dev_get_platdata(&pdev->dev); - struct device_node *np = pdev->dev.of_node; + const struct device *dev = &pdev->dev; + const struct of_dev_auxdata *lookup = dev_get_platdata(dev); + struct device_node *np = dev->of_node; + const struct of_device_id *match; + + /* + * Allow user to use driver_override to bind this driver to a + * transparent bus device which has a different compatible string + * that's not listed in simple_pm_bus_of_match. We don't want to do any + * of the simple-pm-bus tasks for these devices, so return early. + */ + if (pdev->driver_override) + return 0; + + match = of_match_device(dev->driver->of_match_table, dev); + /* + * These are transparent bus devices (not simple-pm-bus matches) that + * have their child nodes populated automatically. So, don't need to + * do anything more. We only match with the device if this driver is + * the most specific match because we don't want to incorrectly bind to + * a device that has a more specific driver. + */ + if (match && match->data) { + if (of_property_match_string(np, "compatible", match->compatible) == 0) + return 0; + else + return -ENODEV; + } dev_dbg(&pdev->dev, "%s\n", __func__); @@ -31,14 +56,25 @@ static int simple_pm_bus_probe(struct platform_device *pdev) static int simple_pm_bus_remove(struct platform_device *pdev) { + const void *data = of_device_get_match_data(&pdev->dev); + + if (pdev->driver_override || data) + return 0; + dev_dbg(&pdev->dev, "%s\n", __func__); pm_runtime_disable(&pdev->dev); return 0; } +#define ONLY_BUS ((void *) 1) /* Match if the device is only a bus. */ + static const struct of_device_id simple_pm_bus_of_match[] = { { .compatible = "simple-pm-bus", }, + { .compatible = "simple-bus", .data = ONLY_BUS }, + { .compatible = "simple-mfd", .data = ONLY_BUS }, + { .compatible = "isa", .data = ONLY_BUS }, + { .compatible = "arm,amba-bus", .data = ONLY_BUS }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, simple_pm_bus_of_match); -- cgit From 81967efb5f3966e8692f9173c7fa2964034ece5d Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Tue, 28 Sep 2021 17:07:34 -0700 Subject: drivers: bus: Delete CONFIG_SIMPLE_PM_BUS The simple-pm-bus driver is mandatory for CONFIG_OF based platforms to work with fw_devlink. So, always compile it in for CONFIG_OF and delete the config since it's no longer necessary. Tested-by: Ulf Hansson Tested-by: Geert Uytterhoeven Tested-by: Damien Le Moal Cc: Rob Herring Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20210929000735.585237-3-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- arch/arm/configs/multi_v7_defconfig | 1 - arch/arm/configs/oxnas_v6_defconfig | 1 - arch/arm/configs/shmobile_defconfig | 1 - arch/arm/mach-omap2/Kconfig | 1 - arch/arm64/configs/defconfig | 1 - drivers/bus/Kconfig | 12 ------------ drivers/bus/Makefile | 2 +- drivers/soc/canaan/Kconfig | 1 - 8 files changed, 1 insertion(+), 19 deletions(-) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index ba67c4717dcc..1f72c67438f9 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -197,7 +197,6 @@ CONFIG_PCI_EPF_TEST=m CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_OMAP_OCP2SCP=y -CONFIG_SIMPLE_PM_BUS=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_BLOCK=y diff --git a/arch/arm/configs/oxnas_v6_defconfig b/arch/arm/configs/oxnas_v6_defconfig index cae0db6b4eaf..de37f7e90999 100644 --- a/arch/arm/configs/oxnas_v6_defconfig +++ b/arch/arm/configs/oxnas_v6_defconfig @@ -46,7 +46,6 @@ CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_DMA_CMA=y CONFIG_CMA_SIZE_MBYTES=64 -CONFIG_SIMPLE_PM_BUS=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_BLOCK=y diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index d9a27e4e0914..18d2a960b2d2 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -40,7 +40,6 @@ CONFIG_PCI_RCAR_GEN2=y CONFIG_PCIE_RCAR_HOST=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y -CONFIG_SIMPLE_PM_BUS=y CONFIG_MTD=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 7f13adf26e61..02c253de9b6e 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -112,7 +112,6 @@ config ARCH_OMAP2PLUS select PM_GENERIC_DOMAINS select PM_GENERIC_DOMAINS_OF select RESET_CONTROLLER - select SIMPLE_PM_BUS select SOC_BUS select TI_SYSC select OMAP_IRQCHIP diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 156d96afbbfc..545197bc0501 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -245,7 +245,6 @@ CONFIG_DEVTMPFS_MOUNT=y CONFIG_FW_LOADER_USER_HELPER=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y CONFIG_HISILICON_LPC=y -CONFIG_SIMPLE_PM_BUS=y CONFIG_FSL_MC_BUS=y CONFIG_TEGRA_ACONNECT=m CONFIG_GNSS=m diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index a5b96f3aad67..a4cf3d692dc3 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -152,18 +152,6 @@ config QCOM_EBI2 Interface 2, which can be used to connect things like NAND Flash, SRAM, ethernet adapters, FPGAs and LCD displays. -config SIMPLE_PM_BUS - tristate "Simple Power-Managed Bus Driver" - depends on OF && PM - help - Driver for transparent busses that don't need a real driver, but - where the bus controller is part of a PM domain, or under the control - of a functional clock, and thus relies on runtime PM for managing - this PM domain and/or clock. - An example of such a bus controller is the Renesas Bus State - Controller (BSC, sometimes called "LBSC within Bus Bridge", or - "External Bus Interface") as found on several Renesas ARM SoCs. - config SUN50I_DE2_BUS bool "Allwinner A64 DE2 Bus Driver" default ARM64 diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile index 1c29c5e8ffb8..52c2f35a26a9 100644 --- a/drivers/bus/Makefile +++ b/drivers/bus/Makefile @@ -27,7 +27,7 @@ obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o obj-$(CONFIG_QCOM_EBI2) += qcom-ebi2.o obj-$(CONFIG_SUN50I_DE2_BUS) += sun50i-de2.o obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o -obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o +obj-$(CONFIG_OF) += simple-pm-bus.o obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o obj-$(CONFIG_TEGRA_GMI) += tegra-gmi.o obj-$(CONFIG_TI_PWMSS) += ti-pwmss.o diff --git a/drivers/soc/canaan/Kconfig b/drivers/soc/canaan/Kconfig index 8179b69518b4..853096b7e84c 100644 --- a/drivers/soc/canaan/Kconfig +++ b/drivers/soc/canaan/Kconfig @@ -5,7 +5,6 @@ config SOC_K210_SYSCTL depends on RISCV && SOC_CANAAN && OF default SOC_CANAAN select PM - select SIMPLE_PM_BUS select SYSCON select MFD_SYSCON help -- cgit From 9287e91e9019d4bc1018adb55ab791ae672e0b14 Mon Sep 17 00:00:00 2001 From: Mateusz Kwiatkowski Date: Thu, 22 Jul 2021 21:02:08 +0200 Subject: ARM: dts: bcm283x: Fix VEC address for BCM2711 The VEC has a different address (0x7ec13000) on the BCM2711 (used in e.g. Raspberry Pi 4) compared to BCM283x (e.g. Pi 3 and earlier). This was erroneously not taken account for. Definition of the VEC in the devicetrees had to be moved from bcm283x.dtsi to bcm2711.dtsi and bcm2835-common.dtsi to allow for this differentiation. Fixes: 7894bdc6228f ("ARM: boot: dts: bcm2711: Add BCM2711 VEC compatible") Signed-off-by: Mateusz Kwiatkowski Signed-off-by: Stefan Wahren Link: https://lore.kernel.org/r/1626980528-3835-1-git-send-email-stefan.wahren@i2se.com Signed-off-by: Nicolas Saenz Julienne --- arch/arm/boot/dts/bcm2711.dtsi | 8 ++++++++ arch/arm/boot/dts/bcm2835-common.dtsi | 8 ++++++++ arch/arm/boot/dts/bcm283x.dtsi | 8 -------- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi index b8a4096192aa..734342c6bb15 100644 --- a/arch/arm/boot/dts/bcm2711.dtsi +++ b/arch/arm/boot/dts/bcm2711.dtsi @@ -300,6 +300,14 @@ status = "disabled"; }; + vec: vec@7ec13000 { + compatible = "brcm,bcm2711-vec"; + reg = <0x7ec13000 0x1000>; + clocks = <&clocks BCM2835_CLOCK_VEC>; + interrupts = ; + status = "disabled"; + }; + dvp: clock@7ef00000 { compatible = "brcm,brcm2711-dvp"; reg = <0x7ef00000 0x10>; diff --git a/arch/arm/boot/dts/bcm2835-common.dtsi b/arch/arm/boot/dts/bcm2835-common.dtsi index 4119271c979d..c25e797b9060 100644 --- a/arch/arm/boot/dts/bcm2835-common.dtsi +++ b/arch/arm/boot/dts/bcm2835-common.dtsi @@ -106,6 +106,14 @@ status = "okay"; }; + vec: vec@7e806000 { + compatible = "brcm,bcm2835-vec"; + reg = <0x7e806000 0x1000>; + clocks = <&clocks BCM2835_CLOCK_VEC>; + interrupts = <2 27>; + status = "disabled"; + }; + pixelvalve@7e807000 { compatible = "brcm,bcm2835-pixelvalve2"; reg = <0x7e807000 0x100>; diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi index 0f3be55201a5..a3e06b680947 100644 --- a/arch/arm/boot/dts/bcm283x.dtsi +++ b/arch/arm/boot/dts/bcm283x.dtsi @@ -464,14 +464,6 @@ status = "disabled"; }; - vec: vec@7e806000 { - compatible = "brcm,bcm2835-vec"; - reg = <0x7e806000 0x1000>; - clocks = <&clocks BCM2835_CLOCK_VEC>; - interrupts = <2 27>; - status = "disabled"; - }; - usb: usb@7e980000 { compatible = "brcm,bcm2835-usb"; reg = <0x7e980000 0x10000>; -- cgit From 2faff6737a8a684b077264f0aed131526c99eec4 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sat, 7 Aug 2021 13:06:32 +0200 Subject: ARM: dts: bcm2711: fix MDIO #address- and #size-cells The values of #address-cells and #size-cells are swapped. Fix this and avoid the following DT schema warnings for mdio@e14: #address-cells:0:0: 1 was expected #size-cells:0:0: 0 was expected Fixes: be8af7a9e3cc ("ARM: dts: bcm2711-rpi-4: Enable GENET support") Signed-off-by: Stefan Wahren Link: https://lore.kernel.org/r/1628334401-6577-2-git-send-email-stefan.wahren@i2se.com Signed-off-by: Nicolas Saenz Julienne --- arch/arm/boot/dts/bcm2711.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi index 734342c6bb15..3b60297af7f6 100644 --- a/arch/arm/boot/dts/bcm2711.dtsi +++ b/arch/arm/boot/dts/bcm2711.dtsi @@ -540,8 +540,8 @@ compatible = "brcm,genet-mdio-v5"; reg = <0xe14 0x8>; reg-names = "mdio"; - #address-cells = <0x0>; - #size-cells = <0x1>; + #address-cells = <0x1>; + #size-cells = <0x0>; }; }; }; -- cgit From b55ec7528879a822a4d350248daa04bbb27f25fd Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sat, 7 Aug 2021 13:06:33 +0200 Subject: ARM: dts: bcm2711-rpi-4-b: fix sd_io_1v8_reg regulator states DT schema check complains at sd_io_1v8_reg about the following: [1800000, 1, 3300000, 0] is too long Additional items are not allowed (3300000, 0 were unexpected) So fix the states definition. Fixes: 7dbe8c62ceeb ("ARM: dts: Add minimal Raspberry Pi 4 support") Signed-off-by: Stefan Wahren Link: https://lore.kernel.org/r/1628334401-6577-3-git-send-email-stefan.wahren@i2se.com Signed-off-by: Nicolas Saenz Julienne --- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts index f24bdd0870a5..abf8298610a7 100644 --- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts +++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts @@ -40,8 +40,8 @@ regulator-always-on; regulator-settling-time-us = <5000>; gpios = <&expgpio 4 GPIO_ACTIVE_HIGH>; - states = <1800000 0x1 - 3300000 0x0>; + states = <1800000 0x1>, + <3300000 0x0>; status = "okay"; }; -- cgit From be4491838359e78e42e88db4ac479e21c5eda1e0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 22 Sep 2021 17:17:36 +0100 Subject: gpio: 74x164: Add SPI device ID table Currently autoloading for SPI devices does not use the DT ID table, it uses SPI modalises. Supporting OF modalises is going to be difficult if not impractical, an attempt was made but has been reverted, so ensure that module autoloading works for this driver by adding a SPI device ID table. Fixes: 96c8395e2166 ("spi: Revert modalias changes") Signed-off-by: Mark Brown Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-74x164.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index 05637d585152..4a55cdf089d6 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -174,6 +174,13 @@ static int gen_74x164_remove(struct spi_device *spi) return 0; } +static const struct spi_device_id gen_74x164_spi_ids[] = { + { .name = "74hc595" }, + { .name = "74lvc594" }, + {}, +}; +MODULE_DEVICE_TABLE(spi, gen_74x164_spi_ids); + static const struct of_device_id gen_74x164_dt_ids[] = { { .compatible = "fairchild,74hc595" }, { .compatible = "nxp,74lvc594" }, @@ -188,6 +195,7 @@ static struct spi_driver gen_74x164_driver = { }, .probe = gen_74x164_probe, .remove = gen_74x164_remove, + .id_table = gen_74x164_spi_ids, }; module_spi_driver(gen_74x164_driver); -- cgit From 55a9968c7e139209a9e93d4ca4321731bea5fc95 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 24 Sep 2021 01:46:40 +0300 Subject: gpio: pca953x: Improve bias setting The commit 15add06841a3 ("gpio: pca953x: add ->set_config implementation") introduced support for bias setting. However this, due to being half-baked, brought potential issues: - the turning bias via disabling makes the pin floating for a while; - once enabled, bias can't be disabled. Fix all these by adding support for bias disabling and move the disabling part under the corresponding conditional. While at it, add support for default setting, since it's cheap to add. Fixes: 15add06841a3 ("gpio: pca953x: add ->set_config implementation") Cc: Thomas Petazzoni Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pca953x.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 8ebf369b3ba0..d2fe76f3f34f 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -559,21 +559,21 @@ static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip, mutex_lock(&chip->i2c_lock); - /* Disable pull-up/pull-down */ - ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, 0); - if (ret) - goto exit; - /* Configure pull-up/pull-down */ if (config == PIN_CONFIG_BIAS_PULL_UP) ret = regmap_write_bits(chip->regmap, pull_sel_reg, bit, bit); else if (config == PIN_CONFIG_BIAS_PULL_DOWN) ret = regmap_write_bits(chip->regmap, pull_sel_reg, bit, 0); + else + ret = 0; if (ret) goto exit; - /* Enable pull-up/pull-down */ - ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, bit); + /* Disable/Enable pull-up/pull-down */ + if (config == PIN_CONFIG_BIAS_DISABLE) + ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, 0); + else + ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, bit); exit: mutex_unlock(&chip->i2c_lock); @@ -587,7 +587,9 @@ static int pca953x_gpio_set_config(struct gpio_chip *gc, unsigned int offset, switch (pinconf_to_config_param(config)) { case PIN_CONFIG_BIAS_PULL_UP: + case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_DISABLE: return pca953x_gpio_set_pull_up_down(chip, offset, config); default: return -ENOTSUPP; -- cgit From 6fda593f3082ef1aa783ac13e89f673fd69a2cb6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 5 Oct 2021 15:24:49 +0300 Subject: gpio: mockup: Convert to use software nodes The gpio-mockup driver creates the properties that are shared between platform and GPIO devices. Because of that, the properties may not be removed at the proper point of time without provoking a use-after-free as shown in the following backtrace: refcount_t: underflow; use-after-free. WARNING: CPU: 0 PID: 103 at lib/refcount.c:28 refcount_warn_saturate+0xd1/0x120 ... Call Trace: kobject_put+0xdc/0xf0 software_node_notify_remove+0xa8/0xc0 device_del+0x15a/0x3e0 That's why the driver has to manage the lifetime of the software nodes by itself. The problem originates from the old device_add_properties() API, but has been only revealed after the commit bd1e336aa853 ("driver core: platform: Remove platform_device_add_properties()"). Hence, it's used as a landmark for backporting. Fixes: bd1e336aa853 ("driver core: platform: Remove platform_device_add_properties()") Reported-by: Kent Gibson Tested-by: Kent Gibson Signed-off-by: Andy Shevchenko [Bartosz: tweaked local variable placement] Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-mockup.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index 0a9d746a0fe0..d26bff29157b 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -476,10 +476,19 @@ static struct platform_device *gpio_mockup_pdevs[GPIO_MOCKUP_MAX_GC]; static void gpio_mockup_unregister_pdevs(void) { + struct platform_device *pdev; + struct fwnode_handle *fwnode; int i; - for (i = 0; i < GPIO_MOCKUP_MAX_GC; i++) - platform_device_unregister(gpio_mockup_pdevs[i]); + for (i = 0; i < GPIO_MOCKUP_MAX_GC; i++) { + pdev = gpio_mockup_pdevs[i]; + if (!pdev) + continue; + + fwnode = dev_fwnode(&pdev->dev); + platform_device_unregister(pdev); + fwnode_remove_software_node(fwnode); + } } static __init char **gpio_mockup_make_line_names(const char *label, @@ -508,6 +517,7 @@ static int __init gpio_mockup_register_chip(int idx) struct property_entry properties[GPIO_MOCKUP_MAX_PROP]; struct platform_device_info pdevinfo; struct platform_device *pdev; + struct fwnode_handle *fwnode; char **line_names = NULL; char chip_label[32]; int prop = 0, base; @@ -536,13 +546,18 @@ static int __init gpio_mockup_register_chip(int idx) "gpio-line-names", line_names, ngpio); } + fwnode = fwnode_create_software_node(properties, NULL); + if (IS_ERR(fwnode)) + return PTR_ERR(fwnode); + pdevinfo.name = "gpio-mockup"; pdevinfo.id = idx; - pdevinfo.properties = properties; + pdevinfo.fwnode = fwnode; pdev = platform_device_register_full(&pdevinfo); kfree_strarray(line_names, ngpio); if (IS_ERR(pdev)) { + fwnode_remove_software_node(fwnode); pr_err("error registering device"); return PTR_ERR(pdev); } -- cgit From dd6dd6e3c791db7fdbc5433ec7e450717aa3a0ce Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Wed, 6 Oct 2021 15:04:15 +0200 Subject: ALSA: hda/realtek: Add quirk for TongFang PHxTxX1 This applies a SND_PCI_QUIRK(...) to the TongFang PHxTxX1 barebone. This fixes the issue of the internal Microphone not working after booting another OS. When booting a certain another OS this barebone keeps some coeff settings even after a cold shutdown. These coeffs prevent the microphone detection from working in Linux, making the Laptop think that there is always an external microphone plugged-in and therefore preventing the use of the internal one. The relevant indexes and values where gathered by naively diff-ing and reading a working and a non-working coeff dump. Signed-off-by: Werner Sembach Cc: Link: https://lore.kernel.org/r/20211006130415.538243-1-wse@tuxedocomputers.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0689f43fc7af..73e7a92c3728 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6453,6 +6453,24 @@ static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec, /* for alc285_fixup_ideapad_s740_coef() */ #include "ideapad_s740_helper.c" +static void alc256_fixup_tongfang_reset_persistent_settings(struct hda_codec *codec, + const struct hda_fixup *fix, + int action) +{ + /* + * A certain other OS sets these coeffs to different values. On at least one TongFang + * barebone these settings might survive even a cold reboot. So to restore a clean slate the + * values are explicitly reset to default here. Without this, the external microphone is + * always in a plugged-in state, while the internal microphone is always in an unplugged + * state, breaking the ability to use the internal microphone. + */ + alc_write_coef_idx(codec, 0x24, 0x0000); + alc_write_coef_idx(codec, 0x26, 0x0000); + alc_write_coef_idx(codec, 0x29, 0x3000); + alc_write_coef_idx(codec, 0x37, 0xfe05); + alc_write_coef_idx(codec, 0x45, 0x5089); +} + enum { ALC269_FIXUP_GPIO2, ALC269_FIXUP_SONY_VAIO, @@ -6667,7 +6685,8 @@ enum { ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS, ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE, ALC287_FIXUP_YOGA7_14ITL_SPEAKERS, - ALC287_FIXUP_13S_GEN2_SPEAKERS + ALC287_FIXUP_13S_GEN2_SPEAKERS, + ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS, }; static const struct hda_fixup alc269_fixups[] = { @@ -8365,6 +8384,10 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC269_FIXUP_HEADSET_MODE, }, + [ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc256_fixup_tongfang_reset_persistent_settings, + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -8796,6 +8819,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */ SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802), SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X), + SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS), SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC), SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC), -- cgit From 554afc3b9797511e3245864e32aebeb6abbab1e3 Mon Sep 17 00:00:00 2001 From: Brendan Higgins Date: Wed, 29 Sep 2021 14:27:09 -0700 Subject: gcc-plugins/structleak: add makefile var for disabling structleak KUnit and structleak don't play nice, so add a makefile variable for enabling structleak when it complains. Co-developed-by: Kees Cook Signed-off-by: Kees Cook Signed-off-by: Brendan Higgins Reviewed-by: David Gow Signed-off-by: Shuah Khan --- scripts/Makefile.gcc-plugins | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins index 952e46876329..4aad28480035 100644 --- a/scripts/Makefile.gcc-plugins +++ b/scripts/Makefile.gcc-plugins @@ -19,6 +19,10 @@ gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF) \ += -fplugin-arg-structleak_plugin-byref gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL) \ += -fplugin-arg-structleak_plugin-byref-all +ifdef CONFIG_GCC_PLUGIN_STRUCTLEAK + DISABLE_STRUCTLEAK_PLUGIN += -fplugin-arg-structleak_plugin-disable +endif +export DISABLE_STRUCTLEAK_PLUGIN gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) \ += -DSTRUCTLEAK_PLUGIN -- cgit From 2326f3cdba1d105b68cc1295e78f17ae8faa5a76 Mon Sep 17 00:00:00 2001 From: Brendan Higgins Date: Wed, 29 Sep 2021 14:27:10 -0700 Subject: iio/test-format: build kunit tests without structleak plugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The structleak plugin causes the stack frame size to grow immensely when used with KUnit: ../drivers/iio/test/iio-test-format.c: In function ‘iio_test_iio_format_value_fixedpoint’: ../drivers/iio/test/iio-test-format.c:98:1: warning: the frame size of 2336 bytes is larger than 2048 bytes [-Wframe-larger-than=] Turn it off in this file. Signed-off-by: Brendan Higgins Suggested-by: Arnd Bergmann Reviewed-by: Kees Cook Acked-by: Jonathan Cameron Signed-off-by: Shuah Khan --- drivers/iio/test/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/test/Makefile b/drivers/iio/test/Makefile index f1099b495301..467519a2027e 100644 --- a/drivers/iio/test/Makefile +++ b/drivers/iio/test/Makefile @@ -5,3 +5,4 @@ # Keep in alphabetical order obj-$(CONFIG_IIO_TEST_FORMAT) += iio-test-format.o +CFLAGS_iio-test-format.o += $(DISABLE_STRUCTLEAK_PLUGIN) -- cgit From 6a1e2d93d55b000962b82b9a080006446150b022 Mon Sep 17 00:00:00 2001 From: Brendan Higgins Date: Wed, 29 Sep 2021 14:27:11 -0700 Subject: device property: build kunit tests without structleak plugin The structleak plugin causes the stack frame size to grow immensely when used with KUnit: ../drivers/base/test/property-entry-test.c:492:1: warning: the frame size of 2832 bytes is larger than 2048 bytes [-Wframe-larger-than=] ../drivers/base/test/property-entry-test.c:322:1: warning: the frame size of 2080 bytes is larger than 2048 bytes [-Wframe-larger-than=] ../drivers/base/test/property-entry-test.c:250:1: warning: the frame size of 4976 bytes is larger than 2048 bytes [-Wframe-larger-than=] ../drivers/base/test/property-entry-test.c:115:1: warning: the frame size of 3280 bytes is larger than 2048 bytes [-Wframe-larger-than=] Turn it off in this file. Signed-off-by: Brendan Higgins Suggested-by: Arnd Bergmann Reviewed-by: Kees Cook Signed-off-by: Shuah Khan --- drivers/base/test/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/test/Makefile b/drivers/base/test/Makefile index 64b2f3d744d5..7f76fee6f989 100644 --- a/drivers/base/test/Makefile +++ b/drivers/base/test/Makefile @@ -2,4 +2,4 @@ obj-$(CONFIG_TEST_ASYNC_DRIVER_PROBE) += test_async_driver_probe.o obj-$(CONFIG_DRIVER_PE_KUNIT_TEST) += property-entry-test.o -CFLAGS_REMOVE_property-entry-test.o += -fplugin-arg-structleak_plugin-byref -fplugin-arg-structleak_plugin-byref-all +CFLAGS_property-entry-test.o += $(DISABLE_STRUCTLEAK_PLUGIN) -- cgit From 33d4951e021bb67ebd6bdb01f3d437c0f45b3c0c Mon Sep 17 00:00:00 2001 From: Brendan Higgins Date: Wed, 29 Sep 2021 14:27:12 -0700 Subject: thunderbolt: build kunit tests without structleak plugin The structleak plugin causes the stack frame size to grow immensely when used with KUnit: drivers/thunderbolt/test.c:1529:1: error: the frame size of 1176 bytes is larger than 1024 bytes [-Werror=frame-larger-than=] Turn it off in this file. Linus already split up tests in this file, so this change *should* be redundant now. Signed-off-by: Brendan Higgins Suggested-by: Arnd Bergmann Acked-by: Mika Westerberg Reviewed-by: Kees Cook Signed-off-by: Shuah Khan --- drivers/thunderbolt/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index da19d7987d00..78fd365893c1 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -7,6 +7,7 @@ thunderbolt-objs += usb4_port.o nvm.o retimer.o quirks.o thunderbolt-${CONFIG_ACPI} += acpi.o thunderbolt-$(CONFIG_DEBUG_FS) += debugfs.o thunderbolt-${CONFIG_USB4_KUNIT_TEST} += test.o +CFLAGS_test.o += $(DISABLE_STRUCTLEAK_PLUGIN) thunderbolt_dma_test-${CONFIG_USB4_DMA_TEST} += dma_test.o obj-$(CONFIG_USB4_DMA_TEST) += thunderbolt_dma_test.o -- cgit From a8cf90332ae3e2b53813a146a99261b6a5e16a73 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 29 Sep 2021 14:27:13 -0700 Subject: bitfield: build kunit tests without structleak plugin The structleak plugin causes the stack frame size to grow immensely: lib/bitfield_kunit.c: In function 'test_bitfields_constants': lib/bitfield_kunit.c:93:1: error: the frame size of 7440 bytes is larger than 2048 bytes [-Werror=frame-larger-than=] Turn it off in this file. Signed-off-by: Arnd Bergmann Signed-off-by: Brendan Higgins Reviewed-by: Kees Cook Signed-off-by: Shuah Khan --- lib/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Makefile b/lib/Makefile index 5efd1b435a37..a841be5244ac 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -351,7 +351,7 @@ obj-$(CONFIG_OBJAGG) += objagg.o obj-$(CONFIG_PLDMFW) += pldmfw/ # KUnit tests -CFLAGS_bitfield_kunit.o := $(call cc-option,-Wframe-larger-than=10240) +CFLAGS_bitfield_kunit.o := $(DISABLE_STRUCTLEAK_PLUGIN) obj-$(CONFIG_BITFIELD_KUNIT) += bitfield_kunit.o obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o -- cgit From 361b57df62de249dc0b2acbf48823662a5001bcd Mon Sep 17 00:00:00 2001 From: Daniel Latypov Date: Tue, 5 Oct 2021 13:46:32 -0700 Subject: kunit: fix kernel-doc warnings due to mismatched arg names Commit 7122debb4367 ("kunit: introduce kunit_kmalloc_array/kunit_kcalloc() helpers") added new functions but called last arg `flags`, unlike the existing code that used `gfp`. This only is an issue in test.h, test.c still used `gfp`. But the documentation was copy-pasted with the old names, leading to kernel-doc warnings. Do s/flags/gfp to make the names consistent and fix the warnings. Fixes: 7122debb4367 ("kunit: introduce kunit_kmalloc_array/kunit_kcalloc() helpers") Reported-by: Randy Dunlap Signed-off-by: Daniel Latypov Reviewed-by: Randy Dunlap Reviewed-by: Brendan Higgins Signed-off-by: Shuah Khan --- include/kunit/test.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/kunit/test.h b/include/kunit/test.h index 24b40e5c160b..018e776a34b9 100644 --- a/include/kunit/test.h +++ b/include/kunit/test.h @@ -613,7 +613,7 @@ void kunit_remove_resource(struct kunit *test, struct kunit_resource *res); * and is automatically cleaned up after the test case concludes. See &struct * kunit_resource for more information. */ -void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t flags); +void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t gfp); /** * kunit_kmalloc() - Like kmalloc() except the allocation is *test managed*. @@ -657,9 +657,9 @@ static inline void *kunit_kzalloc(struct kunit *test, size_t size, gfp_t gfp) * * See kcalloc() and kunit_kmalloc_array() for more information. */ -static inline void *kunit_kcalloc(struct kunit *test, size_t n, size_t size, gfp_t flags) +static inline void *kunit_kcalloc(struct kunit *test, size_t n, size_t size, gfp_t gfp) { - return kunit_kmalloc_array(test, n, size, flags | __GFP_ZERO); + return kunit_kmalloc_array(test, n, size, gfp | __GFP_ZERO); } void kunit_cleanup(struct kunit *test); -- cgit From b46179d6bb3182c020f2bf9bb4df6ba5463b0495 Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Sat, 8 May 2021 17:01:02 -0700 Subject: objtool: Check for gelf_update_rel[a] failures Otherwise, if these fail we end up with garbage data in the .rela.orc_unwind_ip section, leading to errors like ld: fs/squashfs/namei.o: bad reloc symbol index (0x7f16 >= 0x12) for offset 0x7f16d5c82cc8 in section `.orc_unwind_ip' Signed-off-by: Michael Forney Reviewed-by: Miroslav Benes Signed-off-by: Josh Poimboeuf Link: https://lore.kernel.org/r/20210509000103.11008-1-mforney@mforney.org --- tools/objtool/elf.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c index b18f0055b50b..d1d4491e9cf5 100644 --- a/tools/objtool/elf.c +++ b/tools/objtool/elf.c @@ -1001,7 +1001,10 @@ static int elf_rebuild_rel_reloc_section(struct section *sec, int nr) list_for_each_entry(reloc, &sec->reloc_list, list) { reloc->rel.r_offset = reloc->offset; reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type); - gelf_update_rel(sec->data, idx, &reloc->rel); + if (!gelf_update_rel(sec->data, idx, &reloc->rel)) { + WARN_ELF("gelf_update_rel"); + return -1; + } idx++; } @@ -1033,7 +1036,10 @@ static int elf_rebuild_rela_reloc_section(struct section *sec, int nr) reloc->rela.r_offset = reloc->offset; reloc->rela.r_addend = reloc->addend; reloc->rela.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type); - gelf_update_rela(sec->data, idx, &reloc->rela); + if (!gelf_update_rela(sec->data, idx, &reloc->rela)) { + WARN_ELF("gelf_update_rela"); + return -1; + } idx++; } -- cgit From 86e1e054e0d2105cf32b0266cf1a64e6c26424f7 Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Sat, 8 May 2021 17:01:03 -0700 Subject: objtool: Update section header before relocations The libelf implementation from elftoolchain has a safety check in gelf_update_rel[a] to check that the data corresponds to a section that has type SHT_REL[A] [0]. If the relocation is updated before the section header is updated with the proper type, this check fails. To fix this, update the section header first, before the relocations. Previously, the section size was calculated in elf_rebuild_reloc_section by counting the number of entries in the reloc_list. However, we now need the size during elf_write so instead keep a running total and add to it for every new relocation. [0] https://sourceforge.net/p/elftoolchain/mailman/elftoolchain-developers/thread/CAGw6cBtkZro-8wZMD2ULkwJ39J+tHtTtAWXufMjnd3cQ7XG54g@mail.gmail.com/ Signed-off-by: Michael Forney Reviewed-by: Miroslav Benes Signed-off-by: Josh Poimboeuf Link: https://lore.kernel.org/r/20210509000103.11008-2-mforney@mforney.org --- tools/objtool/elf.c | 46 +++++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c index d1d4491e9cf5..fee03b744a6e 100644 --- a/tools/objtool/elf.c +++ b/tools/objtool/elf.c @@ -508,6 +508,7 @@ int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset, list_add_tail(&reloc->list, &sec->reloc->reloc_list); elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc)); + sec->reloc->sh.sh_size += sec->reloc->sh.sh_entsize; sec->reloc->changed = true; return 0; @@ -977,26 +978,23 @@ static struct section *elf_create_reloc_section(struct elf *elf, } } -static int elf_rebuild_rel_reloc_section(struct section *sec, int nr) +static int elf_rebuild_rel_reloc_section(struct section *sec) { struct reloc *reloc; - int idx = 0, size; + int idx = 0; void *buf; /* Allocate a buffer for relocations */ - size = nr * sizeof(GElf_Rel); - buf = malloc(size); + buf = malloc(sec->sh.sh_size); if (!buf) { perror("malloc"); return -1; } sec->data->d_buf = buf; - sec->data->d_size = size; + sec->data->d_size = sec->sh.sh_size; sec->data->d_type = ELF_T_REL; - sec->sh.sh_size = size; - idx = 0; list_for_each_entry(reloc, &sec->reloc_list, list) { reloc->rel.r_offset = reloc->offset; @@ -1011,26 +1009,23 @@ static int elf_rebuild_rel_reloc_section(struct section *sec, int nr) return 0; } -static int elf_rebuild_rela_reloc_section(struct section *sec, int nr) +static int elf_rebuild_rela_reloc_section(struct section *sec) { struct reloc *reloc; - int idx = 0, size; + int idx = 0; void *buf; /* Allocate a buffer for relocations with addends */ - size = nr * sizeof(GElf_Rela); - buf = malloc(size); + buf = malloc(sec->sh.sh_size); if (!buf) { perror("malloc"); return -1; } sec->data->d_buf = buf; - sec->data->d_size = size; + sec->data->d_size = sec->sh.sh_size; sec->data->d_type = ELF_T_RELA; - sec->sh.sh_size = size; - idx = 0; list_for_each_entry(reloc, &sec->reloc_list, list) { reloc->rela.r_offset = reloc->offset; @@ -1048,16 +1043,9 @@ static int elf_rebuild_rela_reloc_section(struct section *sec, int nr) static int elf_rebuild_reloc_section(struct elf *elf, struct section *sec) { - struct reloc *reloc; - int nr; - - nr = 0; - list_for_each_entry(reloc, &sec->reloc_list, list) - nr++; - switch (sec->sh.sh_type) { - case SHT_REL: return elf_rebuild_rel_reloc_section(sec, nr); - case SHT_RELA: return elf_rebuild_rela_reloc_section(sec, nr); + case SHT_REL: return elf_rebuild_rel_reloc_section(sec); + case SHT_RELA: return elf_rebuild_rela_reloc_section(sec); default: return -1; } } @@ -1117,12 +1105,6 @@ int elf_write(struct elf *elf) /* Update changed relocation sections and section headers: */ list_for_each_entry(sec, &elf->sections, list) { if (sec->changed) { - if (sec->base && - elf_rebuild_reloc_section(elf, sec)) { - WARN("elf_rebuild_reloc_section"); - return -1; - } - s = elf_getscn(elf->elf, sec->idx); if (!s) { WARN_ELF("elf_getscn"); @@ -1133,6 +1115,12 @@ int elf_write(struct elf *elf) return -1; } + if (sec->base && + elf_rebuild_reloc_section(elf, sec)) { + WARN("elf_rebuild_reloc_section"); + return -1; + } + sec->changed = false; elf->changed = true; } -- cgit From c0f1886de7e173865f1a0fa7680a1c07954a987f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 6 Oct 2021 16:19:40 +0200 Subject: ALSA: hda: intel: Allow repeatedly probing on codec configuration errors It seems that a few recent AMD systems show the codec configuration errors at the early boot, while loading the driver at a later stage works magically. Although the root cause of the error isn't clear, it's certainly not bad to allow retrying the codec probe in such a case if that helps. This patch adds the capability for retrying the probe upon codec probe errors on the certain AMD platforms. The probe_work is changed to a delayed work, and at the secondary call, it'll jump to the codec probing. Note that, not only adding the re-probing, this includes the behavior changes in the codec configuration function. Namely, snd_hda_codec_configure() won't unregister the codec at errors any longer. Instead, its caller, azx_codec_configure() unregisters the codecs with the probe failures *if* any codec has been successfully configured. If all codec probe failed, it doesn't unregister but let it re-probed -- which is the most case we're seeing and this patch tries to improve. Even if the driver doesn't re-probe or give up, it will go to the "free-all" error path, hence the leftover codecs shall be disabled / deleted in anyway. BugLink: https://bugzilla.suse.com/show_bug.cgi?id=1190801 Link: https://lore.kernel.org/r/20211006141940.2897-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- include/sound/hda_codec.h | 1 + sound/pci/hda/hda_bind.c | 20 +++++++++++--------- sound/pci/hda/hda_codec.c | 1 + sound/pci/hda/hda_controller.c | 24 ++++++++++++++++-------- sound/pci/hda/hda_controller.h | 2 +- sound/pci/hda/hda_intel.c | 29 +++++++++++++++++++++++------ sound/pci/hda/hda_intel.h | 4 +++- 7 files changed, 56 insertions(+), 25 deletions(-) diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h index 01570dbda503..0e45963bb767 100644 --- a/include/sound/hda_codec.h +++ b/include/sound/hda_codec.h @@ -224,6 +224,7 @@ struct hda_codec { #endif /* misc flags */ + unsigned int configured:1; /* codec was configured */ unsigned int in_freeing:1; /* being released */ unsigned int registered:1; /* codec was registered */ unsigned int display_power_control:1; /* needs display power */ diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c index 2523b23389e9..1c8bffc3eec6 100644 --- a/sound/pci/hda/hda_bind.c +++ b/sound/pci/hda/hda_bind.c @@ -298,29 +298,31 @@ int snd_hda_codec_configure(struct hda_codec *codec) { int err; + if (codec->configured) + return 0; + if (is_generic_config(codec)) codec->probe_id = HDA_CODEC_ID_GENERIC; else codec->probe_id = 0; - err = snd_hdac_device_register(&codec->core); - if (err < 0) - return err; + if (!device_is_registered(&codec->core.dev)) { + err = snd_hdac_device_register(&codec->core); + if (err < 0) + return err; + } if (!codec->preset) codec_bind_module(codec); if (!codec->preset) { err = codec_bind_generic(codec); if (err < 0) { - codec_err(codec, "Unable to bind the codec\n"); - goto error; + codec_dbg(codec, "Unable to bind the codec\n"); + return err; } } + codec->configured = 1; return 0; - - error: - snd_hdac_device_unregister(&codec->core); - return err; } EXPORT_SYMBOL_GPL(snd_hda_codec_configure); diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index a9ebefd60cf6..0c4a337c9fc0 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -791,6 +791,7 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec) snd_array_free(&codec->nids); remove_conn_list(codec); snd_hdac_regmap_exit(&codec->core); + codec->configured = 0; } EXPORT_SYMBOL_GPL(snd_hda_codec_cleanup_for_unbind); diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 7cd452831fd3..930ae4002a81 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -25,6 +25,7 @@ #include #include #include "hda_controller.h" +#include "hda_local.h" #define CREATE_TRACE_POINTS #include "hda_controller_trace.h" @@ -1248,17 +1249,24 @@ EXPORT_SYMBOL_GPL(azx_probe_codecs); int azx_codec_configure(struct azx *chip) { struct hda_codec *codec, *next; + int success = 0; - /* use _safe version here since snd_hda_codec_configure() deregisters - * the device upon error and deletes itself from the bus list. - */ - list_for_each_codec_safe(codec, next, &chip->bus) { - snd_hda_codec_configure(codec); + list_for_each_codec(codec, &chip->bus) { + if (!snd_hda_codec_configure(codec)) + success++; } - if (!azx_bus(chip)->num_codecs) - return -ENODEV; - return 0; + if (success) { + /* unregister failed codecs if any codec has been probed */ + list_for_each_codec_safe(codec, next, &chip->bus) { + if (!codec->configured) { + codec_err(codec, "Unable to configure, disabling\n"); + snd_hdac_device_unregister(&codec->core); + } + } + } + + return success ? 0 : -ENODEV; } EXPORT_SYMBOL_GPL(azx_codec_configure); diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index 3062f87380b1..f5bf295eb830 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h @@ -41,7 +41,7 @@ /* 24 unused */ #define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */ #define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */ -/* 27 unused */ +#define AZX_DCAPS_RETRY_PROBE (1 << 27) /* retry probe if no codec is configured */ #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */ #define AZX_DCAPS_NO_MSI64 (1 << 29) /* Stick to 32-bit MSIs */ #define AZX_DCAPS_SEPARATE_STREAM_TAG (1 << 30) /* capture and playback use separate stream tag */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 47777439961c..4d22e7adeee8 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -307,7 +307,8 @@ enum { /* quirks for AMD SB */ #define AZX_DCAPS_PRESET_AMD_SB \ (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_AMD_WORKAROUND |\ - AZX_DCAPS_SNOOP_TYPE(ATI) | AZX_DCAPS_PM_RUNTIME) + AZX_DCAPS_SNOOP_TYPE(ATI) | AZX_DCAPS_PM_RUNTIME |\ + AZX_DCAPS_RETRY_PROBE) /* quirks for Nvidia */ #define AZX_DCAPS_PRESET_NVIDIA \ @@ -1723,7 +1724,7 @@ static void azx_check_snoop_available(struct azx *chip) static void azx_probe_work(struct work_struct *work) { - struct hda_intel *hda = container_of(work, struct hda_intel, probe_work); + struct hda_intel *hda = container_of(work, struct hda_intel, probe_work.work); azx_probe_continue(&hda->chip); } @@ -1828,7 +1829,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, } /* continue probing in work context as may trigger request module */ - INIT_WORK(&hda->probe_work, azx_probe_work); + INIT_DELAYED_WORK(&hda->probe_work, azx_probe_work); *rchip = chip; @@ -2142,7 +2143,7 @@ static int azx_probe(struct pci_dev *pci, #endif if (schedule_probe) - schedule_work(&hda->probe_work); + schedule_delayed_work(&hda->probe_work, 0); dev++; if (chip->disabled) @@ -2228,6 +2229,11 @@ static int azx_probe_continue(struct azx *chip) int dev = chip->dev_index; int err; + if (chip->disabled || hda->init_failed) + return -EIO; + if (hda->probe_retry) + goto probe_retry; + to_hda_bus(bus)->bus_probing = 1; hda->probe_continued = 1; @@ -2289,10 +2295,20 @@ static int azx_probe_continue(struct azx *chip) #endif } #endif + + probe_retry: if (bus->codec_mask && !(probe_only[dev] & 1)) { err = azx_codec_configure(chip); - if (err < 0) + if (err) { + if ((chip->driver_caps & AZX_DCAPS_RETRY_PROBE) && + ++hda->probe_retry < 60) { + schedule_delayed_work(&hda->probe_work, + msecs_to_jiffies(1000)); + return 0; /* keep things up */ + } + dev_err(chip->card->dev, "Cannot probe codecs, giving up\n"); goto out_free; + } } err = snd_card_register(chip->card); @@ -2322,6 +2338,7 @@ out_free: display_power(chip, false); complete_all(&hda->probe_wait); to_hda_bus(bus)->bus_probing = 0; + hda->probe_retry = 0; return 0; } @@ -2347,7 +2364,7 @@ static void azx_remove(struct pci_dev *pci) * device during cancel_work_sync() call. */ device_unlock(&pci->dev); - cancel_work_sync(&hda->probe_work); + cancel_delayed_work_sync(&hda->probe_work); device_lock(&pci->dev); snd_card_free(card); diff --git a/sound/pci/hda/hda_intel.h b/sound/pci/hda/hda_intel.h index 3fb119f09040..0f39418f9328 100644 --- a/sound/pci/hda/hda_intel.h +++ b/sound/pci/hda/hda_intel.h @@ -14,7 +14,7 @@ struct hda_intel { /* sync probing */ struct completion probe_wait; - struct work_struct probe_work; + struct delayed_work probe_work; /* card list (for power_save trigger) */ struct list_head list; @@ -30,6 +30,8 @@ struct hda_intel { unsigned int freed:1; /* resources already released */ bool need_i915_power:1; /* the hda controller needs i915 power */ + + int probe_retry; /* being probe-retry */ }; #endif -- cgit From f5a8a07edafed8bede17a95ef8940fe3a57a77d5 Mon Sep 17 00:00:00 2001 From: Daniele Palmas Date: Mon, 4 Oct 2021 12:56:55 +0200 Subject: USB: serial: option: add Telit LE910Cx composition 0x1204 Add the following Telit LE910Cx composition: 0x1204: tty, adb, mbim, tty, tty, tty, tty Signed-off-by: Daniele Palmas Link: https://lore.kernel.org/r/20211004105655.8515-1-dnlplm@gmail.com Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 6cfb5d33609f..15e47bb40658 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1227,6 +1227,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1203, 0xff), /* Telit LE910Cx (RNDIS) */ .driver_info = NCTRL(2) | RSVD(3) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1204, 0xff), /* Telit LE910Cx (MBIM) */ + .driver_info = NCTRL(0) | RSVD(1) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4), .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) | RSVD(3) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), -- cgit From c184accc4a42c7872dc8e8d0fc97a740dc61fe24 Mon Sep 17 00:00:00 2001 From: Tomaz Solc Date: Wed, 6 Oct 2021 14:57:50 +0200 Subject: USB: serial: option: add prod. id for Quectel EG91 Adding support for Quectel EG91 LTE module. The interface layout is same as for EG95. usb-devices output: T: Bus=01 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=2c7c ProdID=0191 Rev=03.18 S: Manufacturer=Android S: Product=Android C: #Ifs= 5 Cfg#= 1 Atr=a0 MxPwr=500mA I: If#=0x0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#=0x1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none) I: If#=0x2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none) I: If#=0x3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none) I: If#=0x4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan Interfaces: 0: Diag 1: GNSS 2: AT-command interface/modem 3: Modem 4: QMI Signed-off-by: Tomaz Solc Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 15e47bb40658..ac3b0bd82bb9 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -246,6 +246,7 @@ static void option_instat_callback(struct urb *urb); /* These Quectel products use Quectel's vendor ID */ #define QUECTEL_PRODUCT_EC21 0x0121 #define QUECTEL_PRODUCT_EC25 0x0125 +#define QUECTEL_PRODUCT_EG91 0x0191 #define QUECTEL_PRODUCT_EG95 0x0195 #define QUECTEL_PRODUCT_BG96 0x0296 #define QUECTEL_PRODUCT_EP06 0x0306 @@ -1111,6 +1112,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25, 0xff, 0xff, 0xff), .driver_info = NUMEP2 }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG91, 0xff, 0xff, 0xff), + .driver_info = NUMEP2 }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG91, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0xff, 0xff), .driver_info = NUMEP2 }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0, 0) }, -- cgit From 2263eb7370060bdb0013bc14e1a7c9bf33617a55 Mon Sep 17 00:00:00 2001 From: Yu-Tung Chang Date: Thu, 30 Sep 2021 10:11:12 +0800 Subject: USB: serial: option: add Quectel EC200S-CN module support Add usb product id of the Quectel EC200S-CN module. usb-devices output for 0x6002: T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 3 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=2c7c ProdID=6002 Rev=03.18 S: Manufacturer=Android S: Product=Android S: SerialNumber=0000 C: #Ifs= 5 Cfg#= 1 Atr=e0 MxPwr=500mA I: If#=0x0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=06 Prot=00 Driver=cdc_ether I: If#=0x1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=cdc_ether I: If#=0x2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none) I: If#=0x3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none) I: If#=0x4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none) Signed-off-by: Yu-Tung Chang Link: https://lore.kernel.org/r/20210930021112.330396-1-mtwget@gmail.com Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ac3b0bd82bb9..a484ff5e4ebf 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -252,6 +252,7 @@ static void option_instat_callback(struct urb *urb); #define QUECTEL_PRODUCT_EP06 0x0306 #define QUECTEL_PRODUCT_EM12 0x0512 #define QUECTEL_PRODUCT_RM500Q 0x0800 +#define QUECTEL_PRODUCT_EC200S_CN 0x6002 #define QUECTEL_PRODUCT_EC200T 0x6026 #define CMOTECH_VENDOR_ID 0x16d8 @@ -1132,6 +1133,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x10), .driver_info = ZLP }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) }, -- cgit From 11c52d250b34a0862edc29db03fbec23b30db6da Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Thu, 7 Oct 2021 14:25:01 +0200 Subject: USB: serial: qcserial: add EM9191 QDL support When the module boots into QDL download mode it exposes the 1199:90d2 ids, which can be mapped to the qcserial driver, and used to run firmware upgrades (e.g. with the qmi-firmware-update program). T: Bus=01 Lev=03 Prnt=08 Port=03 Cnt=01 Dev#= 10 Spd=480 MxCh= 0 D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1199 ProdID=90d2 Rev=00.00 S: Manufacturer=Sierra Wireless, Incorporated S: Product=Sierra Wireless EM9191 S: SerialNumber=8W0382004102A109 C: #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=2mA I: If#=0x0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=10 Driver=qcserial Signed-off-by: Aleksander Morgado Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/qcserial.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 83da8236e3c8..c18bf8164bc2 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -165,6 +165,7 @@ static const struct usb_device_id id_table[] = { {DEVICE_SWI(0x1199, 0x907b)}, /* Sierra Wireless EM74xx */ {DEVICE_SWI(0x1199, 0x9090)}, /* Sierra Wireless EM7565 QDL */ {DEVICE_SWI(0x1199, 0x9091)}, /* Sierra Wireless EM7565 */ + {DEVICE_SWI(0x1199, 0x90d2)}, /* Sierra Wireless EM9191 QDL */ {DEVICE_SWI(0x413c, 0x81a2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81a3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ -- cgit From 424b650f35c77defbb3cbd6e5221d3697af42250 Mon Sep 17 00:00:00 2001 From: Jackie Liu Date: Wed, 22 Sep 2021 10:51:22 +0800 Subject: tracing: Fix missing osnoise tracer on max_latency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The compiler warns when the data are actually unused: kernel/trace/trace.c:1712:13: error: ‘trace_create_maxlat_file’ defined but not used [-Werror=unused-function] 1712 | static void trace_create_maxlat_file(struct trace_array *tr, | ^~~~~~~~~~~~~~~~~~~~~~~~ [Why] CONFIG_HWLAT_TRACER=n, CONFIG_TRACER_MAX_TRACE=n, CONFIG_OSNOISE_TRACER=y gcc report warns. [How] Now trace_create_maxlat_file will only take effect when CONFIG_HWLAT_TRACER=y or CONFIG_TRACER_MAX_TRACE=y. In fact, after adding osnoise trace, it also needs to take effect. Link: https://lore.kernel.org/all/c1d9e328-ad7c-920b-6c24-9e1598a6421c@infradead.org/ Link: https://lkml.kernel.org/r/20210922025122.3268022-1-liu.yun@linux.dev Fixes: bce29ac9ce0b ("trace: Add osnoise tracer") Cc: Daniel Bristot de Oliveira Suggested-by: Steven Rostedt Reviewed-by: Daniel Bristot de Oliveira Tested-by: Randy Dunlap # build-tested Signed-off-by: Jackie Liu Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 7896d30d90f7..bc677cd64224 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1744,16 +1744,15 @@ void latency_fsnotify(struct trace_array *tr) irq_work_queue(&tr->fsnotify_irqwork); } -/* - * (defined(CONFIG_TRACER_MAX_TRACE) || defined(CONFIG_HWLAT_TRACER)) && \ - * defined(CONFIG_FSNOTIFY) - */ -#else +#elif defined(CONFIG_TRACER_MAX_TRACE) || defined(CONFIG_HWLAT_TRACER) \ + || defined(CONFIG_OSNOISE_TRACER) #define trace_create_maxlat_file(tr, d_tracer) \ trace_create_file("tracing_max_latency", 0644, d_tracer, \ &tr->max_latency, &tracing_max_lat_fops) +#else +#define trace_create_maxlat_file(tr, d_tracer) do { } while (0) #endif #ifdef CONFIG_TRACER_MAX_TRACE @@ -9473,9 +9472,7 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer) create_trace_options_dir(tr); -#if defined(CONFIG_TRACER_MAX_TRACE) || defined(CONFIG_HWLAT_TRACER) trace_create_maxlat_file(tr, d_tracer); -#endif if (ftrace_create_function_files(tr, d_tracer)) MEM_FAIL(1, "Could not allocate function filter files"); -- cgit From 85f74acf097a63a07f5a7c215db6883e5c35e3ff Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Wed, 6 Oct 2021 23:50:31 -0700 Subject: nvme-pci: Fix abort command id The request tag is no longer the only component of the command id. Fixes: e7006de6c2380 ("nvme: code command_id with a genctr for use-after-free validation") Reviewed-by: Sagi Grimberg Signed-off-by: Keith Busch --- drivers/nvme/host/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index b82492cd7503..7fc992a99624 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1330,7 +1330,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved) iod->aborted = 1; cmd.abort.opcode = nvme_admin_abort_cmd; - cmd.abort.cid = req->tag; + cmd.abort.cid = nvme_cid(req); cmd.abort.sqid = cpu_to_le16(nvmeq->qid); dev_warn(nvmeq->dev->ctrl.device, -- cgit From 19ea40dddf1833db868533958ca066f368862211 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Tue, 14 Sep 2021 14:57:59 +0800 Subject: btrfs: unlock newly allocated extent buffer after error [BUG] There is a bug report that injected ENOMEM error could leave a tree block locked while we return to user-space: BTRFS info (device loop0): enabling ssd optimizations FAULT_INJECTION: forcing a failure. name failslab, interval 1, probability 0, space 0, times 0 CPU: 0 PID: 7579 Comm: syz-executor Not tainted 5.15.0-rc1 #16 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0x8d/0xcf lib/dump_stack.c:106 fail_dump lib/fault-inject.c:52 [inline] should_fail+0x13c/0x160 lib/fault-inject.c:146 should_failslab+0x5/0x10 mm/slab_common.c:1328 slab_pre_alloc_hook.constprop.99+0x4e/0xc0 mm/slab.h:494 slab_alloc_node mm/slub.c:3120 [inline] slab_alloc mm/slub.c:3214 [inline] kmem_cache_alloc+0x44/0x280 mm/slub.c:3219 btrfs_alloc_delayed_extent_op fs/btrfs/delayed-ref.h:299 [inline] btrfs_alloc_tree_block+0x38c/0x670 fs/btrfs/extent-tree.c:4833 __btrfs_cow_block+0x16f/0x7d0 fs/btrfs/ctree.c:415 btrfs_cow_block+0x12a/0x300 fs/btrfs/ctree.c:570 btrfs_search_slot+0x6b0/0xee0 fs/btrfs/ctree.c:1768 btrfs_insert_empty_items+0x80/0xf0 fs/btrfs/ctree.c:3905 btrfs_new_inode+0x311/0xa60 fs/btrfs/inode.c:6530 btrfs_create+0x12b/0x270 fs/btrfs/inode.c:6783 lookup_open+0x660/0x780 fs/namei.c:3282 open_last_lookups fs/namei.c:3352 [inline] path_openat+0x465/0xe20 fs/namei.c:3557 do_filp_open+0xe3/0x170 fs/namei.c:3588 do_sys_openat2+0x357/0x4a0 fs/open.c:1200 do_sys_open+0x87/0xd0 fs/open.c:1216 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x34/0xb0 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x44/0xae RIP: 0033:0x46ae99 Code: f7 d8 64 89 02 b8 ff ff ff ff c3 66 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 c7 c1 bc ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f46711b9c48 EFLAGS: 00000246 ORIG_RAX: 0000000000000055 RAX: ffffffffffffffda RBX: 000000000078c0a0 RCX: 000000000046ae99 RDX: 0000000000000000 RSI: 00000000000000a1 RDI: 0000000020005800 RBP: 00007f46711b9c80 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000017 R13: 0000000000000000 R14: 000000000078c0a0 R15: 00007ffc129da6e0 ================================================ WARNING: lock held when returning to user space! 5.15.0-rc1 #16 Not tainted ------------------------------------------------ syz-executor/7579 is leaving the kernel with locks still held! 1 lock held by syz-executor/7579: #0: ffff888104b73da8 (btrfs-tree-01/1){+.+.}-{3:3}, at: __btrfs_tree_lock+0x2e/0x1a0 fs/btrfs/locking.c:112 [CAUSE] In btrfs_alloc_tree_block(), after btrfs_init_new_buffer(), the new extent buffer @buf is locked, but if later operations like adding delayed tree ref fail, we just free @buf without unlocking it, resulting above warning. [FIX] Unlock @buf in out_free_buf: label. Reported-by: Hao Sun Link: https://lore.kernel.org/linux-btrfs/CACkBjsZ9O6Zr0KK1yGn=1rQi6Crh1yeCRdTSBxx9R99L4xdn-Q@mail.gmail.com/ CC: stable@vger.kernel.org # 5.4+ Signed-off-by: Qu Wenruo Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/extent-tree.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index fc3da7585fb7..0ab456cb4bf8 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -4859,6 +4859,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, out_free_delayed: btrfs_free_delayed_extent_op(extent_op); out_free_buf: + btrfs_tree_unlock(buf); free_extent_buffer(buf); out_free_reserved: btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, 0); -- cgit From d175209be04d7d263fa1a54cde7608c706c9d0d7 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 1 Oct 2021 13:57:18 -0400 Subject: btrfs: update refs for any root except tree log roots I hit a stuck relocation on btrfs/061 during my overnight testing. This turned out to be because we had left over extent entries in our extent root for a data reloc inode that no longer existed. This happened because in btrfs_drop_extents() we only update refs if we have SHAREABLE set or we are the tree_root. This regression was introduced by aeb935a45581 ("btrfs: don't set SHAREABLE flag for data reloc tree") where we stopped setting SHAREABLE for the data reloc tree. The problem here is we actually do want to update extent references for data extents in the data reloc tree, in fact we only don't want to update extent references if the file extents are in the log tree. Update this check to only skip updating references in the case of the log tree. This is relatively rare, because you have to be running scrub at the same time, which is what btrfs/061 does. The data reloc inode has its extents pre-allocated, and then we copy the extent into the pre-allocated chunks. We theoretically should never be calling btrfs_drop_extents() on a data reloc inode. The exception of course is with scrub, if our pre-allocated extent falls inside of the block group we are scrubbing, then the block group will be marked read only and we will be forced to cow that extent. This means we will call btrfs_drop_extents() on that range when we COW that file extent. This isn't really problematic if we do this, the data reloc inode requires that our extent lengths match exactly with the extent we are copying, thankfully we validate the extent is correct with get_new_location(), so if we happen to COW only part of the extent we won't link it in when we do the relocation, so we are safe from any other shenanigans that arise because of this interaction with scrub. Fixes: aeb935a45581 ("btrfs: don't set SHAREABLE flag for data reloc tree") CC: stable@vger.kernel.org # 5.8+ Reviewed-by: Qu Wenruo Signed-off-by: Josef Bacik Signed-off-by: David Sterba --- fs/btrfs/file.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 7ff577005d0f..a949cb2894f4 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -734,8 +734,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, if (args->start >= inode->disk_i_size && !args->replace_extent) modify_tree = 0; - update_refs = (test_bit(BTRFS_ROOT_SHAREABLE, &root->state) || - root == fs_info->tree_root); + update_refs = (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID); while (1) { recow = 0; ret = btrfs_lookup_file_extent(trans, root, path, ino, -- cgit From 77a5b9e3d14cbce49ceed2766b2003c034c066dc Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Fri, 1 Oct 2021 13:52:30 +0100 Subject: btrfs: deal with errors when checking if a dir entry exists during log replay Currently inode_in_dir() ignores errors returned from btrfs_lookup_dir_index_item() and from btrfs_lookup_dir_item(), treating any errors as if the directory entry does not exists in the fs/subvolume tree, which is obviously not correct, as we can get errors such as -EIO when reading extent buffers while searching the fs/subvolume's tree. Fix that by making inode_in_dir() return the errors and making its only caller, add_inode_ref(), deal with returned errors as well. Signed-off-by: Filipe Manana Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/tree-log.c | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index f7efc26aa82a..491d4ba22cfc 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -939,9 +939,11 @@ out: } /* - * helper function to see if a given name and sequence number found - * in an inode back reference are already in a directory and correctly - * point to this inode + * See if a given name and sequence number found in an inode back reference are + * already in a directory and correctly point to this inode. + * + * Returns: < 0 on error, 0 if the directory entry does not exists and 1 if it + * exists. */ static noinline int inode_in_dir(struct btrfs_root *root, struct btrfs_path *path, @@ -950,29 +952,35 @@ static noinline int inode_in_dir(struct btrfs_root *root, { struct btrfs_dir_item *di; struct btrfs_key location; - int match = 0; + int ret = 0; di = btrfs_lookup_dir_index_item(NULL, root, path, dirid, index, name, name_len, 0); - if (di && !IS_ERR(di)) { + if (IS_ERR(di)) { + if (PTR_ERR(di) != -ENOENT) + ret = PTR_ERR(di); + goto out; + } else if (di) { btrfs_dir_item_key_to_cpu(path->nodes[0], di, &location); if (location.objectid != objectid) goto out; - } else + } else { goto out; - btrfs_release_path(path); + } + btrfs_release_path(path); di = btrfs_lookup_dir_item(NULL, root, path, dirid, name, name_len, 0); - if (di && !IS_ERR(di)) { - btrfs_dir_item_key_to_cpu(path->nodes[0], di, &location); - if (location.objectid != objectid) - goto out; - } else + if (IS_ERR(di)) { + ret = PTR_ERR(di); goto out; - match = 1; + } else if (di) { + btrfs_dir_item_key_to_cpu(path->nodes[0], di, &location); + if (location.objectid == objectid) + ret = 1; + } out: btrfs_release_path(path); - return match; + return ret; } /* @@ -1517,10 +1525,12 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, if (ret) goto out; - /* if we already have a perfect match, we're done */ - if (!inode_in_dir(root, path, btrfs_ino(BTRFS_I(dir)), - btrfs_ino(BTRFS_I(inode)), ref_index, - name, namelen)) { + ret = inode_in_dir(root, path, btrfs_ino(BTRFS_I(dir)), + btrfs_ino(BTRFS_I(inode)), ref_index, + name, namelen); + if (ret < 0) { + goto out; + } else if (ret == 0) { /* * look for a conflicting back reference in the * metadata. if we find one we have to unlink that name @@ -1580,6 +1590,7 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, if (ret) goto out; } + /* Else, ret == 1, we already have a perfect match, we're done. */ ref_ptr = (unsigned long)(ref_ptr + ref_struct_size) + namelen; kfree(name); -- cgit From e15ac6413745e3def00e663de00aea5a717311c1 Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Fri, 1 Oct 2021 13:52:31 +0100 Subject: btrfs: deal with errors when replaying dir entry during log replay At replay_one_one(), we are treating any error returned from btrfs_lookup_dir_item() or from btrfs_lookup_dir_index_item() as meaning that there is no existing directory entry in the fs/subvolume tree. This is not correct since we can get errors such as, for example, -EIO when reading extent buffers while searching the fs/subvolume's btree. So fix that and return the error to the caller when it is not -ENOENT. CC: stable@vger.kernel.org # 4.14+ Signed-off-by: Filipe Manana Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/tree-log.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 491d4ba22cfc..007b5051b2f1 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -1988,7 +1988,14 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, ret = -EINVAL; goto out; } - if (IS_ERR_OR_NULL(dst_di)) { + + if (dst_di == ERR_PTR(-ENOENT)) + dst_di = NULL; + + if (IS_ERR(dst_di)) { + ret = PTR_ERR(dst_di); + goto out; + } else if (!dst_di) { /* we need a sequence number to insert, so we only * do inserts for the BTRFS_DIR_INDEX_KEY types */ -- cgit From 52db77791fe24538c8aa2a183248399715f6b380 Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Fri, 1 Oct 2021 13:52:32 +0100 Subject: btrfs: deal with errors when adding inode reference during log replay At __inode_add_ref(), we treating any error returned from btrfs_lookup_dir_item() or from btrfs_lookup_dir_index_item() as meaning that there is no existing directory entry in the fs/subvolume tree. This is not correct since we can get errors such as, for example, -EIO when reading extent buffers while searching the fs/subvolume's btree. So fix that and return the error to the caller when it is not -ENOENT. CC: stable@vger.kernel.org # 4.14+ Signed-off-by: Filipe Manana Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/tree-log.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 007b5051b2f1..1b6008240ec6 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -1190,7 +1190,10 @@ next: /* look for a conflicting sequence number */ di = btrfs_lookup_dir_index_item(trans, root, path, btrfs_ino(dir), ref_index, name, namelen, 0); - if (di && !IS_ERR(di)) { + if (IS_ERR(di)) { + if (PTR_ERR(di) != -ENOENT) + return PTR_ERR(di); + } else if (di) { ret = drop_one_dir_item(trans, root, path, dir, di); if (ret) return ret; @@ -1200,7 +1203,9 @@ next: /* look for a conflicting name */ di = btrfs_lookup_dir_item(trans, root, path, btrfs_ino(dir), name, namelen, 0); - if (di && !IS_ERR(di)) { + if (IS_ERR(di)) { + return PTR_ERR(di); + } else if (di) { ret = drop_one_dir_item(trans, root, path, dir, di); if (ret) return ret; -- cgit From 8dcbc26194eb872cc3430550fb70bb461424d267 Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Fri, 1 Oct 2021 13:52:33 +0100 Subject: btrfs: unify lookup return value when dir entry is missing btrfs_lookup_dir_index_item() and btrfs_lookup_dir_item() lookup for dir entries and both are used during log replay or when updating a log tree during an unlink. However when the dir item does not exists, btrfs_lookup_dir_item() returns NULL while btrfs_lookup_dir_index_item() returns PTR_ERR(-ENOENT), and if the dir item exists but there is no matching entry for a given name or index, both return NULL. This makes the call sites during log replay to be more verbose than necessary and it makes it easy to miss this slight difference. Since we don't need to distinguish between those two cases, make btrfs_lookup_dir_index_item() always return NULL when there is no matching directory entry - either because there isn't any dir entry or because there is one but it does not match the given name and index. Also rename the argument 'objectid' of btrfs_lookup_dir_index_item() to 'index' since it is supposed to match an index number, and the name 'objectid' is not very good because it can easily be confused with an inode number (like the inode number a dir entry points to). CC: stable@vger.kernel.org # 4.14+ Signed-off-by: Filipe Manana Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/ctree.h | 2 +- fs/btrfs/dir-item.c | 48 +++++++++++++++++++++++++++++++++++++----------- fs/btrfs/tree-log.c | 14 ++++---------- 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index f07c82fafa04..852a49dcc22b 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -3030,7 +3030,7 @@ struct btrfs_dir_item * btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, u64 dir, - u64 objectid, const char *name, int name_len, + u64 index, const char *name, int name_len, int mod); struct btrfs_dir_item * btrfs_search_dir_index_item(struct btrfs_root *root, diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index f1274d5c3805..7721ce0c0604 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c @@ -190,9 +190,20 @@ static struct btrfs_dir_item *btrfs_lookup_match_dir( } /* - * lookup a directory item based on name. 'dir' is the objectid - * we're searching in, and 'mod' tells us if you plan on deleting the - * item (use mod < 0) or changing the options (use mod > 0) + * Lookup for a directory item by name. + * + * @trans: The transaction handle to use. Can be NULL if @mod is 0. + * @root: The root of the target tree. + * @path: Path to use for the search. + * @dir: The inode number (objectid) of the directory. + * @name: The name associated to the directory entry we are looking for. + * @name_len: The length of the name. + * @mod: Used to indicate if the tree search is meant for a read only + * lookup, for a modification lookup or for a deletion lookup, so + * its value should be 0, 1 or -1, respectively. + * + * Returns: NULL if the dir item does not exists, an error pointer if an error + * happened, or a pointer to a dir item if a dir item exists for the given name. */ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, @@ -273,27 +284,42 @@ out: } /* - * lookup a directory item based on index. 'dir' is the objectid - * we're searching in, and 'mod' tells us if you plan on deleting the - * item (use mod < 0) or changing the options (use mod > 0) + * Lookup for a directory index item by name and index number. * - * The name is used to make sure the index really points to the name you were - * looking for. + * @trans: The transaction handle to use. Can be NULL if @mod is 0. + * @root: The root of the target tree. + * @path: Path to use for the search. + * @dir: The inode number (objectid) of the directory. + * @index: The index number. + * @name: The name associated to the directory entry we are looking for. + * @name_len: The length of the name. + * @mod: Used to indicate if the tree search is meant for a read only + * lookup, for a modification lookup or for a deletion lookup, so + * its value should be 0, 1 or -1, respectively. + * + * Returns: NULL if the dir index item does not exists, an error pointer if an + * error happened, or a pointer to a dir item if the dir index item exists and + * matches the criteria (name and index number). */ struct btrfs_dir_item * btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, u64 dir, - u64 objectid, const char *name, int name_len, + u64 index, const char *name, int name_len, int mod) { + struct btrfs_dir_item *di; struct btrfs_key key; key.objectid = dir; key.type = BTRFS_DIR_INDEX_KEY; - key.offset = objectid; + key.offset = index; - return btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod); + di = btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod); + if (di == ERR_PTR(-ENOENT)) + return NULL; + + return di; } struct btrfs_dir_item * diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 1b6008240ec6..1bb5ebf13383 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -957,8 +957,7 @@ static noinline int inode_in_dir(struct btrfs_root *root, di = btrfs_lookup_dir_index_item(NULL, root, path, dirid, index, name, name_len, 0); if (IS_ERR(di)) { - if (PTR_ERR(di) != -ENOENT) - ret = PTR_ERR(di); + ret = PTR_ERR(di); goto out; } else if (di) { btrfs_dir_item_key_to_cpu(path->nodes[0], di, &location); @@ -1191,8 +1190,7 @@ next: di = btrfs_lookup_dir_index_item(trans, root, path, btrfs_ino(dir), ref_index, name, namelen, 0); if (IS_ERR(di)) { - if (PTR_ERR(di) != -ENOENT) - return PTR_ERR(di); + return PTR_ERR(di); } else if (di) { ret = drop_one_dir_item(trans, root, path, dir, di); if (ret) @@ -1994,9 +1992,6 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, goto out; } - if (dst_di == ERR_PTR(-ENOENT)) - dst_di = NULL; - if (IS_ERR(dst_di)) { ret = PTR_ERR(dst_di); goto out; @@ -2304,7 +2299,7 @@ again: dir_key->offset, name, name_len, 0); } - if (!log_di || log_di == ERR_PTR(-ENOENT)) { + if (!log_di) { btrfs_dir_item_key_to_cpu(eb, di, &location); btrfs_release_path(path); btrfs_release_path(log_path); @@ -3563,8 +3558,7 @@ out_unlock: if (err == -ENOSPC) { btrfs_set_log_full_commit(trans); err = 0; - } else if (err < 0 && err != -ENOENT) { - /* ENOENT can be returned if the entry hasn't been fsynced yet */ + } else if (err < 0) { btrfs_abort_transaction(trans, err); } -- cgit From cfd312695b71df04c3a2597859ff12c470d1e2e4 Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Fri, 1 Oct 2021 13:48:18 +0100 Subject: btrfs: check for error when looking up inode during dir entry replay At replay_one_name(), we are treating any error from btrfs_lookup_inode() as if the inode does not exists. Fix this by checking for an error and returning it to the caller. CC: stable@vger.kernel.org # 4.14+ Signed-off-by: Filipe Manana Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/tree-log.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 1bb5ebf13383..b415c5ec03ea 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -1950,8 +1950,8 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, struct btrfs_key log_key; struct inode *dir; u8 log_type; - int exists; - int ret = 0; + bool exists; + int ret; bool update_size = (key->type == BTRFS_DIR_INDEX_KEY); bool name_added = false; @@ -1971,12 +1971,12 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, name_len); btrfs_dir_item_key_to_cpu(eb, di, &log_key); - exists = btrfs_lookup_inode(trans, root, path, &log_key, 0); - if (exists == 0) - exists = 1; - else - exists = 0; + ret = btrfs_lookup_inode(trans, root, path, &log_key, 0); btrfs_release_path(path); + if (ret < 0) + goto out; + exists = (ret == 0); + ret = 0; if (key->type == BTRFS_DIR_ITEM_KEY) { dst_di = btrfs_lookup_dir_item(trans, root, path, key->objectid, -- cgit From 4afb912f439c4bc4e6a4f3e7547f2e69e354108f Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 5 Oct 2021 16:35:27 -0400 Subject: btrfs: fix abort logic in btrfs_replace_file_extents Error injection testing uncovered a case where we'd end up with a corrupt file system with a missing extent in the middle of a file. This occurs because the if statement to decide if we should abort is wrong. The only way we would abort in this case is if we got a ret != -EOPNOTSUPP and we called from the file clone code. However the prealloc code uses this path too. Instead we need to abort if there is an error, and the only error we _don't_ abort on is -EOPNOTSUPP and only if we came from the clone file code. CC: stable@vger.kernel.org # 5.10+ Reviewed-by: Nikolay Borisov Reviewed-by: Filipe Manana Signed-off-by: Josef Bacik Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/file.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index a949cb2894f4..a1762363f61f 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -2703,14 +2703,16 @@ int btrfs_replace_file_extents(struct btrfs_inode *inode, drop_args.bytes_found); if (ret != -ENOSPC) { /* - * When cloning we want to avoid transaction aborts when - * nothing was done and we are attempting to clone parts - * of inline extents, in such cases -EOPNOTSUPP is - * returned by __btrfs_drop_extents() without having - * changed anything in the file. + * The only time we don't want to abort is if we are + * attempting to clone a partial inline extent, in which + * case we'll get EOPNOTSUPP. However if we aren't + * clone we need to abort no matter what, because if we + * got EOPNOTSUPP via prealloc then we messed up and + * need to abort. */ - if (extent_info && !extent_info->is_new_extent && - ret && ret != -EOPNOTSUPP) + if (ret && + (ret != -EOPNOTSUPP || + (extent_info && extent_info->is_new_extent))) btrfs_abort_transaction(trans, ret); break; } -- cgit From 612f71d7328c14369924384ad2170aae2a6abd92 Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Thu, 7 Oct 2021 15:05:00 -0700 Subject: mptcp: fix possible stall on recvmsg() recvmsg() can enter an infinite loop if the caller provides the MSG_WAITALL, the data present in the receive queue is not sufficient to fulfill the request, and no more data is received by the peer. When the above happens, mptcp_wait_data() will always return with no wait, as the MPTCP_DATA_READY flag checked by such function is set and never cleared in such code path. Leveraging the above syzbot was able to trigger an RCU stall: rcu: INFO: rcu_preempt self-detected stall on CPU rcu: 0-...!: (10499 ticks this GP) idle=0af/1/0x4000000000000000 softirq=10678/10678 fqs=1 (t=10500 jiffies g=13089 q=109) rcu: rcu_preempt kthread starved for 10497 jiffies! g13089 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x0 ->cpu=1 rcu: Unless rcu_preempt kthread gets sufficient CPU time, OOM is now expected behavior. rcu: RCU grace-period kthread stack dump: task:rcu_preempt state:R running task stack:28696 pid: 14 ppid: 2 flags:0x00004000 Call Trace: context_switch kernel/sched/core.c:4955 [inline] __schedule+0x940/0x26f0 kernel/sched/core.c:6236 schedule+0xd3/0x270 kernel/sched/core.c:6315 schedule_timeout+0x14a/0x2a0 kernel/time/timer.c:1881 rcu_gp_fqs_loop+0x186/0x810 kernel/rcu/tree.c:1955 rcu_gp_kthread+0x1de/0x320 kernel/rcu/tree.c:2128 kthread+0x405/0x4f0 kernel/kthread.c:327 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:295 rcu: Stack dump where RCU GP kthread last ran: Sending NMI from CPU 0 to CPUs 1: NMI backtrace for cpu 1 CPU: 1 PID: 8510 Comm: syz-executor827 Not tainted 5.15.0-rc2-next-20210920-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:bytes_is_nonzero mm/kasan/generic.c:84 [inline] RIP: 0010:memory_is_nonzero mm/kasan/generic.c:102 [inline] RIP: 0010:memory_is_poisoned_n mm/kasan/generic.c:128 [inline] RIP: 0010:memory_is_poisoned mm/kasan/generic.c:159 [inline] RIP: 0010:check_region_inline mm/kasan/generic.c:180 [inline] RIP: 0010:kasan_check_range+0xc8/0x180 mm/kasan/generic.c:189 Code: 38 00 74 ed 48 8d 50 08 eb 09 48 83 c0 01 48 39 d0 74 7a 80 38 00 74 f2 48 89 c2 b8 01 00 00 00 48 85 d2 75 56 5b 5d 41 5c c3 <48> 85 d2 74 5e 48 01 ea eb 09 48 83 c0 01 48 39 d0 74 50 80 38 00 RSP: 0018:ffffc9000cd676c8 EFLAGS: 00000283 RAX: ffffed100e9a110e RBX: ffffed100e9a110f RCX: ffffffff88ea062a RDX: 0000000000000001 RSI: 0000000000000008 RDI: ffff888074d08870 RBP: ffffed100e9a110e R08: 0000000000000001 R09: ffff888074d08877 R10: ffffed100e9a110e R11: 0000000000000000 R12: ffff888074d08000 R13: ffff888074d08000 R14: ffff888074d08088 R15: ffff888074d08000 FS: 0000555556d8e300(0000) GS:ffff8880b9d00000(0000) knlGS:0000000000000000 S: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000020000180 CR3: 0000000068909000 CR4: 00000000001506e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: instrument_atomic_read_write include/linux/instrumented.h:101 [inline] test_and_clear_bit include/asm-generic/bitops/instrumented-atomic.h:83 [inline] mptcp_release_cb+0x14a/0x210 net/mptcp/protocol.c:3016 release_sock+0xb4/0x1b0 net/core/sock.c:3204 mptcp_wait_data net/mptcp/protocol.c:1770 [inline] mptcp_recvmsg+0xfd1/0x27b0 net/mptcp/protocol.c:2080 inet6_recvmsg+0x11b/0x5e0 net/ipv6/af_inet6.c:659 sock_recvmsg_nosec net/socket.c:944 [inline] ____sys_recvmsg+0x527/0x600 net/socket.c:2626 ___sys_recvmsg+0x127/0x200 net/socket.c:2670 do_recvmmsg+0x24d/0x6d0 net/socket.c:2764 __sys_recvmmsg net/socket.c:2843 [inline] __do_sys_recvmmsg net/socket.c:2866 [inline] __se_sys_recvmmsg net/socket.c:2859 [inline] __x64_sys_recvmmsg+0x20b/0x260 net/socket.c:2859 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x44/0xae RIP: 0033:0x7fc200d2dc39 Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 41 15 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 c0 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007ffc5758e5a8 EFLAGS: 00000246 ORIG_RAX: 000000000000012b RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007fc200d2dc39 RDX: 0000000000000002 RSI: 00000000200017c0 RDI: 0000000000000003 RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000f0b5ff R10: 0000000000000100 R11: 0000000000000246 R12: 0000000000000003 R13: 00007ffc5758e5d0 R14: 00007ffc5758e5c0 R15: 0000000000000003 Fix the issue by replacing the MPTCP_DATA_READY bit with direct inspection of the msk receive queue. Reported-and-tested-by: syzbot+3360da629681aa0d22fe@syzkaller.appspotmail.com Fixes: 7a6a6cbc3e59 ("mptcp: recvmsg() can drain data from multiple subflow") Signed-off-by: Paolo Abeni Signed-off-by: Mat Martineau Signed-off-by: David S. Miller --- net/mptcp/protocol.c | 55 ++++++++++++++-------------------------------------- 1 file changed, 15 insertions(+), 40 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index e5df0b5971c8..d073b2111382 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -528,7 +528,6 @@ static bool mptcp_check_data_fin(struct sock *sk) sk->sk_shutdown |= RCV_SHUTDOWN; smp_mb__before_atomic(); /* SHUTDOWN must be visible first */ - set_bit(MPTCP_DATA_READY, &msk->flags); switch (sk->sk_state) { case TCP_ESTABLISHED: @@ -742,10 +741,9 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk) /* Wake-up the reader only for in-sequence data */ mptcp_data_lock(sk); - if (move_skbs_to_msk(msk, ssk)) { - set_bit(MPTCP_DATA_READY, &msk->flags); + if (move_skbs_to_msk(msk, ssk)) sk->sk_data_ready(sk); - } + mptcp_data_unlock(sk); } @@ -847,7 +845,6 @@ static void mptcp_check_for_eof(struct mptcp_sock *msk) sk->sk_shutdown |= RCV_SHUTDOWN; smp_mb__before_atomic(); /* SHUTDOWN must be visible first */ - set_bit(MPTCP_DATA_READY, &msk->flags); sk->sk_data_ready(sk); } @@ -1759,21 +1756,6 @@ out: return copied ? : ret; } -static void mptcp_wait_data(struct sock *sk, long *timeo) -{ - DEFINE_WAIT_FUNC(wait, woken_wake_function); - struct mptcp_sock *msk = mptcp_sk(sk); - - add_wait_queue(sk_sleep(sk), &wait); - sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); - - sk_wait_event(sk, timeo, - test_bit(MPTCP_DATA_READY, &msk->flags), &wait); - - sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk); - remove_wait_queue(sk_sleep(sk), &wait); -} - static int __mptcp_recvmsg_mskq(struct mptcp_sock *msk, struct msghdr *msg, size_t len, int flags, @@ -2077,19 +2059,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, } pr_debug("block timeout %ld", timeo); - mptcp_wait_data(sk, &timeo); - } - - if (skb_queue_empty_lockless(&sk->sk_receive_queue) && - skb_queue_empty(&msk->receive_queue)) { - /* entire backlog drained, clear DATA_READY. */ - clear_bit(MPTCP_DATA_READY, &msk->flags); - - /* .. race-breaker: ssk might have gotten new data - * after last __mptcp_move_skbs() returned false. - */ - if (unlikely(__mptcp_move_skbs(msk))) - set_bit(MPTCP_DATA_READY, &msk->flags); + sk_wait_data(sk, &timeo, NULL); } out_err: @@ -2098,9 +2068,9 @@ out_err: tcp_recv_timestamp(msg, sk, &tss); } - pr_debug("msk=%p data_ready=%d rx queue empty=%d copied=%d", - msk, test_bit(MPTCP_DATA_READY, &msk->flags), - skb_queue_empty_lockless(&sk->sk_receive_queue), copied); + pr_debug("msk=%p rx queue empty=%d:%d copied=%d", + msk, skb_queue_empty_lockless(&sk->sk_receive_queue), + skb_queue_empty(&msk->receive_queue), copied); if (!(flags & MSG_PEEK)) mptcp_rcv_space_adjust(msk, copied); @@ -2368,7 +2338,6 @@ static void mptcp_check_fastclose(struct mptcp_sock *msk) inet_sk_state_store(sk, TCP_CLOSE); sk->sk_shutdown = SHUTDOWN_MASK; smp_mb__before_atomic(); /* SHUTDOWN must be visible first */ - set_bit(MPTCP_DATA_READY, &msk->flags); set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags); mptcp_close_wake_up(sk); @@ -3385,8 +3354,14 @@ unlock_fail: static __poll_t mptcp_check_readable(struct mptcp_sock *msk) { - return test_bit(MPTCP_DATA_READY, &msk->flags) ? EPOLLIN | EPOLLRDNORM : - 0; + /* Concurrent splices from sk_receive_queue into receive_queue will + * always show at least one non-empty queue when checked in this order. + */ + if (skb_queue_empty_lockless(&((struct sock *)msk)->sk_receive_queue) && + skb_queue_empty_lockless(&msk->receive_queue)) + return 0; + + return EPOLLIN | EPOLLRDNORM; } static __poll_t mptcp_check_writeable(struct mptcp_sock *msk) @@ -3421,7 +3396,7 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock, state = inet_sk_state_load(sk); pr_debug("msk=%p state=%d flags=%lx", msk, state, msk->flags); if (state == TCP_LISTEN) - return mptcp_check_readable(msk); + return test_bit(MPTCP_DATA_READY, &msk->flags) ? EPOLLIN | EPOLLRDNORM : 0; if (state != TCP_SYN_SENT && state != TCP_SYN_RECV) { mask |= mptcp_check_readable(msk); -- cgit From 075da584bae2da6a37428d59a477b6bdad430ac3 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Fri, 8 Oct 2021 12:34:37 +0200 Subject: net: stmmac: fix get_hw_feature() on old hardware Some old IPs do not provide the hardware feature register. On these IPs, this register is read 0x00000000. In old driver version, this feature was handled but a regression came with the commit f10a6a3541b4 ("stmmac: rework get_hw_feature function"). Indeed, this commit removes the return value in dma->get_hw_feature(). This return value was used to indicate the validity of retrieved information and used later on in stmmac_hw_init() to override priv->plat data if this hardware feature were valid. This patch restores the return code in ->get_hw_feature() in order to indicate the hardware feature validity and override priv->plat data only if this hardware feature is valid. Fixes: f10a6a3541b4 ("stmmac: rework get_hw_feature function") Signed-off-by: Herve Codina Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 13 +++++++++++-- drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c | 6 ++++-- drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 6 ++++-- drivers/net/ethernet/stmicro/stmmac/hwif.h | 6 +++--- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index 90383abafa66..f5581db0ba9b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c @@ -218,11 +218,18 @@ static void dwmac1000_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space) readl(ioaddr + DMA_BUS_MODE + i * 4); } -static void dwmac1000_get_hw_feature(void __iomem *ioaddr, - struct dma_features *dma_cap) +static int dwmac1000_get_hw_feature(void __iomem *ioaddr, + struct dma_features *dma_cap) { u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE); + if (!hw_cap) { + /* 0x00000000 is the value read on old hardware that does not + * implement this register + */ + return -EOPNOTSUPP; + } + dma_cap->mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL); dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1; dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2; @@ -252,6 +259,8 @@ static void dwmac1000_get_hw_feature(void __iomem *ioaddr, dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22; /* Alternate (enhanced) DESC mode */ dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24; + + return 0; } static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c index 5be8e6a631d9..d99fa028c646 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c @@ -347,8 +347,8 @@ static void dwmac4_dma_tx_chan_op_mode(void __iomem *ioaddr, int mode, writel(mtl_tx_op, ioaddr + MTL_CHAN_TX_OP_MODE(channel)); } -static void dwmac4_get_hw_feature(void __iomem *ioaddr, - struct dma_features *dma_cap) +static int dwmac4_get_hw_feature(void __iomem *ioaddr, + struct dma_features *dma_cap) { u32 hw_cap = readl(ioaddr + GMAC_HW_FEATURE0); @@ -437,6 +437,8 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr, dma_cap->frpbs = (hw_cap & GMAC_HW_FEAT_FRPBS) >> 11; dma_cap->frpsel = (hw_cap & GMAC_HW_FEAT_FRPSEL) >> 10; dma_cap->dvlan = (hw_cap & GMAC_HW_FEAT_DVLAN) >> 5; + + return 0; } /* Enable/disable TSO feature and set MSS */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index 906e985441a9..5e98355f422b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -371,8 +371,8 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr, return ret; } -static void dwxgmac2_get_hw_feature(void __iomem *ioaddr, - struct dma_features *dma_cap) +static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, + struct dma_features *dma_cap) { u32 hw_cap; @@ -445,6 +445,8 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr, dma_cap->frpes = (hw_cap & XGMAC_HWFEAT_FRPES) >> 11; dma_cap->frpbs = (hw_cap & XGMAC_HWFEAT_FRPPB) >> 9; dma_cap->frpsel = (hw_cap & XGMAC_HWFEAT_FRPSEL) >> 3; + + return 0; } static void dwxgmac2_rx_watchdog(void __iomem *ioaddr, u32 riwt, u32 queue) diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 6dc1c98ebec8..fe2660d5694d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -203,8 +203,8 @@ struct stmmac_dma_ops { int (*dma_interrupt) (void __iomem *ioaddr, struct stmmac_extra_stats *x, u32 chan, u32 dir); /* If supported then get the optional core features */ - void (*get_hw_feature)(void __iomem *ioaddr, - struct dma_features *dma_cap); + int (*get_hw_feature)(void __iomem *ioaddr, + struct dma_features *dma_cap); /* Program the HW RX Watchdog */ void (*rx_watchdog)(void __iomem *ioaddr, u32 riwt, u32 queue); void (*set_tx_ring_len)(void __iomem *ioaddr, u32 len, u32 chan); @@ -255,7 +255,7 @@ struct stmmac_dma_ops { #define stmmac_dma_interrupt_status(__priv, __args...) \ stmmac_do_callback(__priv, dma, dma_interrupt, __args) #define stmmac_get_hw_feature(__priv, __args...) \ - stmmac_do_void_callback(__priv, dma, get_hw_feature, __args) + stmmac_do_callback(__priv, dma, get_hw_feature, __args) #define stmmac_rx_watchdog(__priv, __args...) \ stmmac_do_void_callback(__priv, dma, rx_watchdog, __args) #define stmmac_set_tx_ring_len(__priv, __args...) \ -- cgit From 3781b6ad2ee1b1c3cf8b6523ac22a58f44c2c337 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Fri, 8 Oct 2021 12:34:38 +0200 Subject: dt-bindings: net: snps,dwmac: add dwmac 3.40a IP version dwmac 3.40a is an old ip version that can be found on SPEAr3xx soc. Signed-off-by: Herve Codina Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/net/snps,dwmac.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml index 42689b7d03a2..c115c95ee584 100644 --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml @@ -21,6 +21,7 @@ select: contains: enum: - snps,dwmac + - snps,dwmac-3.40a - snps,dwmac-3.50a - snps,dwmac-3.610 - snps,dwmac-3.70a @@ -76,6 +77,7 @@ properties: - rockchip,rk3399-gmac - rockchip,rv1108-gmac - snps,dwmac + - snps,dwmac-3.40a - snps,dwmac-3.50a - snps,dwmac-3.610 - snps,dwmac-3.70a -- cgit From 9cb1d19f47fafad7dcf7c8564e633440c946cfd7 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Fri, 8 Oct 2021 12:34:39 +0200 Subject: net: stmmac: add support for dwmac 3.40a dwmac 3.40a is an old ip version that can be found on SPEAr3xx soc. Signed-off-by: Herve Codina Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c | 1 + drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c index fbfda55b4c52..5e731a72cce8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c @@ -71,6 +71,7 @@ err_remove_config_dt: static const struct of_device_id dwmac_generic_match[] = { { .compatible = "st,spear600-gmac"}, + { .compatible = "snps,dwmac-3.40a"}, { .compatible = "snps,dwmac-3.50a"}, { .compatible = "snps,dwmac-3.610"}, { .compatible = "snps,dwmac-3.70a"}, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 62cec9bfcd33..232ac98943cd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -508,6 +508,14 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) plat->pmt = 1; } + if (of_device_is_compatible(np, "snps,dwmac-3.40a")) { + plat->has_gmac = 1; + plat->enh_desc = 1; + plat->tx_coe = 1; + plat->bugged_jumbo = 1; + plat->pmt = 1; + } + if (of_device_is_compatible(np, "snps,dwmac-4.00") || of_device_is_compatible(np, "snps,dwmac-4.10a") || of_device_is_compatible(np, "snps,dwmac-4.20a") || -- cgit From 6636fec29cdf6665bd219564609e8651f6ddc142 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Fri, 8 Oct 2021 12:34:40 +0200 Subject: ARM: dts: spear3xx: Fix gmac node On SPEAr3xx, ethernet driver is not compatible with the SPEAr600 one. Indeed, SPEAr3xx uses an earlier version of this IP (v3.40) and needs some driver tuning compare to SPEAr600. The v3.40 IP support was added to stmmac driver and this patch fixes this issue and use the correct compatible string for SPEAr3xx Signed-off-by: Herve Codina Signed-off-by: David S. Miller --- arch/arm/boot/dts/spear3xx.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/spear3xx.dtsi b/arch/arm/boot/dts/spear3xx.dtsi index f266b7b03482..cc88ebe7a60c 100644 --- a/arch/arm/boot/dts/spear3xx.dtsi +++ b/arch/arm/boot/dts/spear3xx.dtsi @@ -47,7 +47,7 @@ }; gmac: eth@e0800000 { - compatible = "st,spear600-gmac"; + compatible = "snps,dwmac-3.40a"; reg = <0xe0800000 0x8000>; interrupts = <23 22>; interrupt-names = "macirq", "eth_wake_irq"; -- cgit From 95f7f3e7dc6bd2e735cb5de11734ea2222b1e05a Mon Sep 17 00:00:00 2001 From: Karsten Graul Date: Thu, 7 Oct 2021 16:14:40 +0200 Subject: net/smc: improved fix wait on already cleared link Commit 8f3d65c16679 ("net/smc: fix wait on already cleared link") introduced link refcounting to avoid waits on already cleared links. This patch extents and improves the refcounting to cover all remaining possible cases for this kind of error situation. Fixes: 15e1b99aadfb ("net/smc: no WR buffer wait for terminating link group") Signed-off-by: Karsten Graul Signed-off-by: David S. Miller --- net/smc/smc_cdc.c | 7 +++++- net/smc/smc_core.c | 20 +++++++++-------- net/smc/smc_llc.c | 63 ++++++++++++++++++++++++++++++++++++++++++------------ net/smc/smc_tx.c | 22 +++++-------------- net/smc/smc_wr.h | 14 ++++++++++++ 5 files changed, 85 insertions(+), 41 deletions(-) diff --git a/net/smc/smc_cdc.c b/net/smc/smc_cdc.c index f23f558054a7..99acd337ba90 100644 --- a/net/smc/smc_cdc.c +++ b/net/smc/smc_cdc.c @@ -150,9 +150,11 @@ static int smcr_cdc_get_slot_and_msg_send(struct smc_connection *conn) again: link = conn->lnk; + if (!smc_wr_tx_link_hold(link)) + return -ENOLINK; rc = smc_cdc_get_free_slot(conn, link, &wr_buf, NULL, &pend); if (rc) - return rc; + goto put_out; spin_lock_bh(&conn->send_lock); if (link != conn->lnk) { @@ -160,6 +162,7 @@ again: spin_unlock_bh(&conn->send_lock); smc_wr_tx_put_slot(link, (struct smc_wr_tx_pend_priv *)pend); + smc_wr_tx_link_put(link); if (again) return -ENOLINK; again = true; @@ -167,6 +170,8 @@ again: } rc = smc_cdc_msg_send(conn, wr_buf, pend); spin_unlock_bh(&conn->send_lock); +put_out: + smc_wr_tx_link_put(link); return rc; } diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c index 8280c938be80..d2206743dc71 100644 --- a/net/smc/smc_core.c +++ b/net/smc/smc_core.c @@ -949,7 +949,7 @@ struct smc_link *smc_switch_conns(struct smc_link_group *lgr, to_lnk = &lgr->lnk[i]; break; } - if (!to_lnk) { + if (!to_lnk || !smc_wr_tx_link_hold(to_lnk)) { smc_lgr_terminate_sched(lgr); return NULL; } @@ -981,24 +981,26 @@ again: read_unlock_bh(&lgr->conns_lock); /* pre-fetch buffer outside of send_lock, might sleep */ rc = smc_cdc_get_free_slot(conn, to_lnk, &wr_buf, NULL, &pend); - if (rc) { - smcr_link_down_cond_sched(to_lnk); - return NULL; - } + if (rc) + goto err_out; /* avoid race with smcr_tx_sndbuf_nonempty() */ spin_lock_bh(&conn->send_lock); smc_switch_link_and_count(conn, to_lnk); rc = smc_switch_cursor(smc, pend, wr_buf); spin_unlock_bh(&conn->send_lock); sock_put(&smc->sk); - if (rc) { - smcr_link_down_cond_sched(to_lnk); - return NULL; - } + if (rc) + goto err_out; goto again; } read_unlock_bh(&lgr->conns_lock); + smc_wr_tx_link_put(to_lnk); return to_lnk; + +err_out: + smcr_link_down_cond_sched(to_lnk); + smc_wr_tx_link_put(to_lnk); + return NULL; } static void smcr_buf_unuse(struct smc_buf_desc *rmb_desc, diff --git a/net/smc/smc_llc.c b/net/smc/smc_llc.c index 2e7560eba981..72f4b72eb175 100644 --- a/net/smc/smc_llc.c +++ b/net/smc/smc_llc.c @@ -383,9 +383,11 @@ int smc_llc_send_confirm_link(struct smc_link *link, struct smc_wr_buf *wr_buf; int rc; + if (!smc_wr_tx_link_hold(link)) + return -ENOLINK; rc = smc_llc_add_pending_send(link, &wr_buf, &pend); if (rc) - return rc; + goto put_out; confllc = (struct smc_llc_msg_confirm_link *)wr_buf; memset(confllc, 0, sizeof(*confllc)); confllc->hd.common.type = SMC_LLC_CONFIRM_LINK; @@ -402,6 +404,8 @@ int smc_llc_send_confirm_link(struct smc_link *link, confllc->max_links = SMC_LLC_ADD_LNK_MAX_LINKS; /* send llc message */ rc = smc_wr_tx_send(link, pend); +put_out: + smc_wr_tx_link_put(link); return rc; } @@ -415,9 +419,11 @@ static int smc_llc_send_confirm_rkey(struct smc_link *send_link, struct smc_link *link; int i, rc, rtok_ix; + if (!smc_wr_tx_link_hold(send_link)) + return -ENOLINK; rc = smc_llc_add_pending_send(send_link, &wr_buf, &pend); if (rc) - return rc; + goto put_out; rkeyllc = (struct smc_llc_msg_confirm_rkey *)wr_buf; memset(rkeyllc, 0, sizeof(*rkeyllc)); rkeyllc->hd.common.type = SMC_LLC_CONFIRM_RKEY; @@ -444,6 +450,8 @@ static int smc_llc_send_confirm_rkey(struct smc_link *send_link, (u64)sg_dma_address(rmb_desc->sgt[send_link->link_idx].sgl)); /* send llc message */ rc = smc_wr_tx_send(send_link, pend); +put_out: + smc_wr_tx_link_put(send_link); return rc; } @@ -456,9 +464,11 @@ static int smc_llc_send_delete_rkey(struct smc_link *link, struct smc_wr_buf *wr_buf; int rc; + if (!smc_wr_tx_link_hold(link)) + return -ENOLINK; rc = smc_llc_add_pending_send(link, &wr_buf, &pend); if (rc) - return rc; + goto put_out; rkeyllc = (struct smc_llc_msg_delete_rkey *)wr_buf; memset(rkeyllc, 0, sizeof(*rkeyllc)); rkeyllc->hd.common.type = SMC_LLC_DELETE_RKEY; @@ -467,6 +477,8 @@ static int smc_llc_send_delete_rkey(struct smc_link *link, rkeyllc->rkey[0] = htonl(rmb_desc->mr_rx[link->link_idx]->rkey); /* send llc message */ rc = smc_wr_tx_send(link, pend); +put_out: + smc_wr_tx_link_put(link); return rc; } @@ -480,9 +492,11 @@ int smc_llc_send_add_link(struct smc_link *link, u8 mac[], u8 gid[], struct smc_wr_buf *wr_buf; int rc; + if (!smc_wr_tx_link_hold(link)) + return -ENOLINK; rc = smc_llc_add_pending_send(link, &wr_buf, &pend); if (rc) - return rc; + goto put_out; addllc = (struct smc_llc_msg_add_link *)wr_buf; memset(addllc, 0, sizeof(*addllc)); @@ -504,6 +518,8 @@ int smc_llc_send_add_link(struct smc_link *link, u8 mac[], u8 gid[], } /* send llc message */ rc = smc_wr_tx_send(link, pend); +put_out: + smc_wr_tx_link_put(link); return rc; } @@ -517,9 +533,11 @@ int smc_llc_send_delete_link(struct smc_link *link, u8 link_del_id, struct smc_wr_buf *wr_buf; int rc; + if (!smc_wr_tx_link_hold(link)) + return -ENOLINK; rc = smc_llc_add_pending_send(link, &wr_buf, &pend); if (rc) - return rc; + goto put_out; delllc = (struct smc_llc_msg_del_link *)wr_buf; memset(delllc, 0, sizeof(*delllc)); @@ -536,6 +554,8 @@ int smc_llc_send_delete_link(struct smc_link *link, u8 link_del_id, delllc->reason = htonl(reason); /* send llc message */ rc = smc_wr_tx_send(link, pend); +put_out: + smc_wr_tx_link_put(link); return rc; } @@ -547,9 +567,11 @@ static int smc_llc_send_test_link(struct smc_link *link, u8 user_data[16]) struct smc_wr_buf *wr_buf; int rc; + if (!smc_wr_tx_link_hold(link)) + return -ENOLINK; rc = smc_llc_add_pending_send(link, &wr_buf, &pend); if (rc) - return rc; + goto put_out; testllc = (struct smc_llc_msg_test_link *)wr_buf; memset(testllc, 0, sizeof(*testllc)); testllc->hd.common.type = SMC_LLC_TEST_LINK; @@ -557,6 +579,8 @@ static int smc_llc_send_test_link(struct smc_link *link, u8 user_data[16]) memcpy(testllc->user_data, user_data, sizeof(testllc->user_data)); /* send llc message */ rc = smc_wr_tx_send(link, pend); +put_out: + smc_wr_tx_link_put(link); return rc; } @@ -567,13 +591,16 @@ static int smc_llc_send_message(struct smc_link *link, void *llcbuf) struct smc_wr_buf *wr_buf; int rc; - if (!smc_link_usable(link)) + if (!smc_wr_tx_link_hold(link)) return -ENOLINK; rc = smc_llc_add_pending_send(link, &wr_buf, &pend); if (rc) - return rc; + goto put_out; memcpy(wr_buf, llcbuf, sizeof(union smc_llc_msg)); - return smc_wr_tx_send(link, pend); + rc = smc_wr_tx_send(link, pend); +put_out: + smc_wr_tx_link_put(link); + return rc; } /* schedule an llc send on link, may wait for buffers, @@ -586,13 +613,16 @@ static int smc_llc_send_message_wait(struct smc_link *link, void *llcbuf) struct smc_wr_buf *wr_buf; int rc; - if (!smc_link_usable(link)) + if (!smc_wr_tx_link_hold(link)) return -ENOLINK; rc = smc_llc_add_pending_send(link, &wr_buf, &pend); if (rc) - return rc; + goto put_out; memcpy(wr_buf, llcbuf, sizeof(union smc_llc_msg)); - return smc_wr_tx_send_wait(link, pend, SMC_LLC_WAIT_TIME); + rc = smc_wr_tx_send_wait(link, pend, SMC_LLC_WAIT_TIME); +put_out: + smc_wr_tx_link_put(link); + return rc; } /********************************* receive ***********************************/ @@ -672,9 +702,11 @@ static int smc_llc_add_link_cont(struct smc_link *link, struct smc_buf_desc *rmb; u8 n; + if (!smc_wr_tx_link_hold(link)) + return -ENOLINK; rc = smc_llc_add_pending_send(link, &wr_buf, &pend); if (rc) - return rc; + goto put_out; addc_llc = (struct smc_llc_msg_add_link_cont *)wr_buf; memset(addc_llc, 0, sizeof(*addc_llc)); @@ -706,7 +738,10 @@ static int smc_llc_add_link_cont(struct smc_link *link, addc_llc->hd.length = sizeof(struct smc_llc_msg_add_link_cont); if (lgr->role == SMC_CLNT) addc_llc->hd.flags |= SMC_LLC_FLAG_RESP; - return smc_wr_tx_send(link, pend); + rc = smc_wr_tx_send(link, pend); +put_out: + smc_wr_tx_link_put(link); + return rc; } static int smc_llc_cli_rkey_exchange(struct smc_link *link, diff --git a/net/smc/smc_tx.c b/net/smc/smc_tx.c index c79361dfcdfb..738a4a99c827 100644 --- a/net/smc/smc_tx.c +++ b/net/smc/smc_tx.c @@ -496,7 +496,7 @@ static int smc_tx_rdma_writes(struct smc_connection *conn, /* Wakeup sndbuf consumers from any context (IRQ or process) * since there is more data to transmit; usable snd_wnd as max transmit */ -static int _smcr_tx_sndbuf_nonempty(struct smc_connection *conn) +static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn) { struct smc_cdc_producer_flags *pflags = &conn->local_tx_ctrl.prod_flags; struct smc_link *link = conn->lnk; @@ -505,8 +505,11 @@ static int _smcr_tx_sndbuf_nonempty(struct smc_connection *conn) struct smc_wr_buf *wr_buf; int rc; + if (!link || !smc_wr_tx_link_hold(link)) + return -ENOLINK; rc = smc_cdc_get_free_slot(conn, link, &wr_buf, &wr_rdma_buf, &pend); if (rc < 0) { + smc_wr_tx_link_put(link); if (rc == -EBUSY) { struct smc_sock *smc = container_of(conn, struct smc_sock, conn); @@ -547,22 +550,7 @@ static int _smcr_tx_sndbuf_nonempty(struct smc_connection *conn) out_unlock: spin_unlock_bh(&conn->send_lock); - return rc; -} - -static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn) -{ - struct smc_link *link = conn->lnk; - int rc = -ENOLINK; - - if (!link) - return rc; - - atomic_inc(&link->wr_tx_refcnt); - if (smc_link_usable(link)) - rc = _smcr_tx_sndbuf_nonempty(conn); - if (atomic_dec_and_test(&link->wr_tx_refcnt)) - wake_up_all(&link->wr_tx_wait); + smc_wr_tx_link_put(link); return rc; } diff --git a/net/smc/smc_wr.h b/net/smc/smc_wr.h index 423b8709f1c9..2bc626f230a5 100644 --- a/net/smc/smc_wr.h +++ b/net/smc/smc_wr.h @@ -60,6 +60,20 @@ static inline void smc_wr_tx_set_wr_id(atomic_long_t *wr_tx_id, long val) atomic_long_set(wr_tx_id, val); } +static inline bool smc_wr_tx_link_hold(struct smc_link *link) +{ + if (!smc_link_usable(link)) + return false; + atomic_inc(&link->wr_tx_refcnt); + return true; +} + +static inline void smc_wr_tx_link_put(struct smc_link *link) +{ + if (atomic_dec_and_test(&link->wr_tx_refcnt)) + wake_up_all(&link->wr_tx_wait); +} + static inline void smc_wr_wakeup_tx_wait(struct smc_link *lnk) { wake_up_all(&lnk->wr_tx_wait); -- cgit From 1b1499a817c90fd1ce9453a2c98d2a01cca0e775 Mon Sep 17 00:00:00 2001 From: Lin Ma Date: Thu, 7 Oct 2021 19:44:30 +0200 Subject: nfc: nci: fix the UAF of rf_conn_info object The nci_core_conn_close_rsp_packet() function will release the conn_info with given conn_id. However, it needs to set the rf_conn_info to NULL to prevent other routines like nci_rf_intf_activated_ntf_packet() to trigger the UAF. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lin Ma Signed-off-by: Krzysztof Kozlowski Signed-off-by: David S. Miller --- net/nfc/nci/rsp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c index a2e72c003805..b911ab78bed9 100644 --- a/net/nfc/nci/rsp.c +++ b/net/nfc/nci/rsp.c @@ -334,6 +334,8 @@ static void nci_core_conn_close_rsp_packet(struct nci_dev *ndev, ndev->cur_conn_id); if (conn_info) { list_del(&conn_info->list); + if (conn_info == ndev->rf_conn_info) + ndev->rf_conn_info = NULL; devm_kfree(&ndev->nfc_dev->dev, conn_info); } } -- cgit From 1bec0f05062cf21e78093b1c4a2ae744e2873b8a Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Thu, 7 Oct 2021 19:47:08 +0300 Subject: net: dsa: fix bridge_num not getting cleared after ports leaving the bridge The dp->bridge_num is zero-based, with -1 being the encoding for an invalid value. But dsa_bridge_num_put used to check for an invalid value by comparing bridge_num with 0, which is of course incorrect. The result is that the bridge_num will never get cleared by dsa_bridge_num_put, and further port joins to other bridges will get a bridge_num larger than the previous one, and once all the available bridges with TX forwarding offload supported by the hardware get exhausted, the TX forwarding offload feature is simply disabled. In the case of sja1105, 7 iterations of the loop below are enough to exhaust the TX forwarding offload bits, and further bridge joins operate without that feature. ip link add br0 type bridge vlan_filtering 1 while :; do ip link set sw0p2 master br0 && sleep 1 ip link set sw0p2 nomaster && sleep 1 done This issue is enough of an indication that having the dp->bridge_num invalid encoding be a negative number is prone to bugs, so this will be changed to a one-based value, with the dp->bridge_num of zero being the indication of no bridge. However, that is material for net-next. Fixes: f5e165e72b29 ("net: dsa: track unique bridge numbers across all DSA switch trees") Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- net/dsa/dsa2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index b29262eee00b..6d5cc0217133 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -170,7 +170,7 @@ void dsa_bridge_num_put(const struct net_device *bridge_dev, int bridge_num) /* Check if the bridge is still in use, otherwise it is time * to clean it up so we can reuse this bridge_num later. */ - if (!dsa_bridge_num_find(bridge_dev)) + if (dsa_bridge_num_find(bridge_dev) < 0) clear_bit(bridge_num, &dsa_fwd_offloading_bridges); } -- cgit From c7709a02c18aabebc3b2988d24661763a0449443 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Thu, 7 Oct 2021 19:47:09 +0300 Subject: net: dsa: tag_dsa: send packets with TX fwd offload from VLAN-unaware bridges using VID 0 The present code is structured this way due to an incomplete thought process. In Documentation/networking/switchdev.rst we document that if a bridge is VLAN-unaware, then the presence or lack of a pvid on a bridge port (or on the bridge itself, for that matter) should not affect the ability to receive and transmit tagged or untagged packets. If the bridge on behalf of which we are sending this packet is VLAN-aware, then the TX forwarding offload API ensures that the skb will be VLAN-tagged (if the packet was sent by user space as untagged, it will get transmitted town to the driver as tagged with the bridge device's pvid). But if the bridge is VLAN-unaware, it may or may not be VLAN-tagged. In fact the logic to insert the bridge's PVID came from the idea that we should emulate what is being done in the VLAN-aware case. But we shouldn't. It appears that injecting packets using a VLAN ID of 0 serves the purpose of forwarding the packets to the egress port with no VLAN tag added or stripped by the hardware, and no filtering being performed. So we can simply remove the superfluous logic. One reason why this logic is broken is that when CONFIG_BRIDGE_VLAN_FILTERING=n, we call br_vlan_get_pvid_rcu() but that returns an error and we do error out, dropping all packets on xmit. Not really smart. This is also an issue when the user deletes the bridge pvid: $ bridge vlan del dev br0 vid 1 self As mentioned, in both cases, packets should still flow freely, and they do just that on any net device where the bridge is not offloaded, but on mv88e6xxx they don't. Fixes: d82f8ab0d874 ("net: dsa: tag_dsa: offload the bridge forwarding process") Reported-by: Andrew Lunn Link: https://patchwork.kernel.org/project/netdevbpf/patch/20211003155141.2241314-1-andrew@lunn.ch/ Link: https://patchwork.kernel.org/project/netdevbpf/patch/20210928233708.1246774-1-vladimir.oltean@nxp.com/ Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- net/dsa/tag_dsa.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c index e5127b7d1c6a..68d5ddc3ef35 100644 --- a/net/dsa/tag_dsa.c +++ b/net/dsa/tag_dsa.c @@ -129,12 +129,9 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev, u8 tag_dev, tag_port; enum dsa_cmd cmd; u8 *dsa_header; - u16 pvid = 0; - int err; if (skb->offload_fwd_mark) { struct dsa_switch_tree *dst = dp->ds->dst; - struct net_device *br = dp->bridge_dev; cmd = DSA_CMD_FORWARD; @@ -144,19 +141,6 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev, */ tag_dev = dst->last_switch + 1 + dp->bridge_num; tag_port = 0; - - /* If we are offloading forwarding for a VLAN-unaware bridge, - * inject packets to hardware using the bridge's pvid, since - * that's where the packets ingressed from. - */ - if (!br_vlan_enabled(br)) { - /* Safe because __dev_queue_xmit() runs under - * rcu_read_lock_bh() - */ - err = br_vlan_get_pvid_rcu(br, &pvid); - if (err) - return NULL; - } } else { cmd = DSA_CMD_FROM_CPU; tag_dev = dp->ds->index; @@ -188,8 +172,8 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev, dsa_header[0] = (cmd << 6) | tag_dev; dsa_header[1] = tag_port << 3; - dsa_header[2] = pvid >> 8; - dsa_header[3] = pvid & 0xff; + dsa_header[2] = 0; + dsa_header[3] = 0; } return skb; -- cgit From 8b6836d824702cacf68190982181f8ca3aff9c3e Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Thu, 7 Oct 2021 19:47:10 +0300 Subject: net: dsa: mv88e6xxx: keep the pvid at 0 when VLAN-unaware The VLAN support in mv88e6xxx has a loaded history. Commit 2ea7a679ca2a ("net: dsa: Don't add vlans when vlan filtering is disabled") noticed some issues with VLAN and decided the best way to deal with them was to make the DSA core ignore VLANs added by the bridge while VLAN awareness is turned off. Those issues were never explained, just presented as "at least one corner case". That approach had problems of its own, presented by commit 54a0ed0df496 ("net: dsa: provide an option for drivers to always receive bridge VLANs") for the DSA core, followed by commit 1fb74191988f ("net: dsa: mv88e6xxx: fix vlan setup") which applied ds->configure_vlan_while_not_filtering = true for mv88e6xxx in particular. We still don't know what corner case Andrew saw when he wrote commit 2ea7a679ca2a ("net: dsa: Don't add vlans when vlan filtering is disabled"), but Tobias now reports that when we use TX forwarding offload, pinging an external station from the bridge device is broken if the front-facing DSA user port has flooding turned off. The full description is in the link below, but for short, when a mv88e6xxx port is under a VLAN-unaware bridge, it inherits that bridge's pvid. So packets ingressing a user port will be classified to e.g. VID 1 (assuming that value for the bridge_default_pvid), whereas when tag_dsa.c xmits towards a user port, it always sends packets using a VID of 0 if that port is standalone or under a VLAN-unaware bridge - or at least it did so prior to commit d82f8ab0d874 ("net: dsa: tag_dsa: offload the bridge forwarding process"). In any case, when there is a conversation between the CPU and a station connected to a user port, the station's MAC address is learned in VID 1 but the CPU tries to transmit through VID 0. The packets reach the intended station, but via flooding and not by virtue of matching the existing ATU entry. DSA has established (and enforced in other drivers: sja1105, felix, mt7530) that a VLAN-unaware port should use a private pvid, and not inherit the one from the bridge. The bridge's pvid should only be inherited when that bridge is VLAN-aware, so all state transitions need to be handled. On the other hand, all bridge VLANs should sit in the VTU starting with the moment when the bridge offloads them via switchdev, they are just not used. This solves the problem that Tobias sees because packets ingressing on VLAN-unaware user ports now get classified to VID 0, which is also the VID used by tag_dsa.c on xmit. Fixes: d82f8ab0d874 ("net: dsa: tag_dsa: offload the bridge forwarding process") Link: https://patchwork.kernel.org/project/netdevbpf/patch/20211003222312.284175-2-vladimir.oltean@nxp.com/#24491503 Reported-by: Tobias Waldekranz Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/dsa/mv88e6xxx/chip.c | 53 +++++++++++++++++++++++++++++++++++----- drivers/net/dsa/mv88e6xxx/chip.h | 6 +++++ drivers/net/dsa/mv88e6xxx/port.c | 21 ++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 2 ++ 4 files changed, 76 insertions(+), 6 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 03744d1c43fc..d672112afffd 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1677,6 +1677,26 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, return 0; } +static int mv88e6xxx_port_commit_pvid(struct mv88e6xxx_chip *chip, int port) +{ + struct dsa_port *dp = dsa_to_port(chip->ds, port); + struct mv88e6xxx_port *p = &chip->ports[port]; + bool drop_untagged = false; + u16 pvid = 0; + int err; + + if (dp->bridge_dev && br_vlan_enabled(dp->bridge_dev)) { + pvid = p->bridge_pvid.vid; + drop_untagged = !p->bridge_pvid.valid; + } + + err = mv88e6xxx_port_set_pvid(chip, port, pvid); + if (err) + return err; + + return mv88e6xxx_port_drop_untagged(chip, port, drop_untagged); +} + static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, struct netlink_ext_ack *extack) @@ -1690,7 +1710,16 @@ static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, return -EOPNOTSUPP; mv88e6xxx_reg_lock(chip); + err = mv88e6xxx_port_set_8021q_mode(chip, port, mode); + if (err) + goto unlock; + + err = mv88e6xxx_port_commit_pvid(chip, port); + if (err) + goto unlock; + +unlock: mv88e6xxx_reg_unlock(chip); return err; @@ -2123,6 +2152,7 @@ static int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, struct mv88e6xxx_chip *chip = ds->priv; bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; + struct mv88e6xxx_port *p = &chip->ports[port]; bool warn; u8 member; int err; @@ -2156,13 +2186,21 @@ static int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, } if (pvid) { - err = mv88e6xxx_port_set_pvid(chip, port, vlan->vid); - if (err) { - dev_err(ds->dev, "p%d: failed to set PVID %d\n", - port, vlan->vid); + p->bridge_pvid.vid = vlan->vid; + p->bridge_pvid.valid = true; + + err = mv88e6xxx_port_commit_pvid(chip, port); + if (err) + goto out; + } else if (vlan->vid && p->bridge_pvid.vid == vlan->vid) { + /* The old pvid was reinstalled as a non-pvid VLAN */ + p->bridge_pvid.valid = false; + + err = mv88e6xxx_port_commit_pvid(chip, port); + if (err) goto out; - } } + out: mv88e6xxx_reg_unlock(chip); @@ -2212,6 +2250,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan) { struct mv88e6xxx_chip *chip = ds->priv; + struct mv88e6xxx_port *p = &chip->ports[port]; int err = 0; u16 pvid; @@ -2229,7 +2268,9 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, goto unlock; if (vlan->vid == pvid) { - err = mv88e6xxx_port_set_pvid(chip, port, 0); + p->bridge_pvid.valid = false; + + err = mv88e6xxx_port_commit_pvid(chip, port); if (err) goto unlock; } diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 59f316cc8583..33d067e8396d 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -246,9 +246,15 @@ struct mv88e6xxx_policy { u16 vid; }; +struct mv88e6xxx_vlan { + u16 vid; + bool valid; +}; + struct mv88e6xxx_port { struct mv88e6xxx_chip *chip; int port; + struct mv88e6xxx_vlan bridge_pvid; u64 serdes_stats[2]; u64 atu_member_violation; u64 atu_miss_violation; diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 451028c57af8..d9817b20ea64 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -1257,6 +1257,27 @@ int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port, return 0; } +int mv88e6xxx_port_drop_untagged(struct mv88e6xxx_chip *chip, int port, + bool drop_untagged) +{ + u16 old, new; + int err; + + err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &old); + if (err) + return err; + + if (drop_untagged) + new = old | MV88E6XXX_PORT_CTL2_DISCARD_UNTAGGED; + else + new = old & ~MV88E6XXX_PORT_CTL2_DISCARD_UNTAGGED; + + if (new == old) + return 0; + + return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, new); +} + int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port) { u16 reg; diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index b10e5aebacf6..03382b66f800 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -423,6 +423,8 @@ int mv88e6393x_port_set_cmode(struct mv88e6xxx_chip *chip, int port, phy_interface_t mode); int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode); int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode); +int mv88e6xxx_port_drop_untagged(struct mv88e6xxx_chip *chip, int port, + bool drop_untagged); int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port); int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port, int upstream_port); -- cgit From 5bded8259ee3815a91791462dfb3312480779c3d Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Thu, 7 Oct 2021 19:47:11 +0300 Subject: net: dsa: mv88e6xxx: isolate the ATU databases of standalone and bridged ports Similar to commit 6087175b7991 ("net: dsa: mt7530: use independent VLAN learning on VLAN-unaware bridges"), software forwarding between an unoffloaded LAG port (a bonding interface with an unsupported policy) and a mv88e6xxx user port directly under a bridge is broken. We adopt the same strategy, which is to make the standalone ports not find any ATU entry learned on a bridge port. Theory: the mv88e6xxx ATU is looked up by FID and MAC address. There are as many FIDs as VIDs (4096). The FID is derived from the VID when possible (the VTU maps a VID to a FID), with a fallback to the port based default FID value when not (802.1Q Mode is disabled on the port, or the classified VID isn't present in the VTU). The mv88e6xxx driver makes the following use of FIDs and VIDs: - the port's DefaultVID (to which untagged & pvid-tagged packets get classified) is 0 and is absent from the VTU, so this kind of packets is processed in FID 0, the default FID assigned by mv88e6xxx_setup_port. - every time a bridge VLAN is created, mv88e6xxx_port_vlan_join() -> mv88e6xxx_atu_new() associates a FID with that VID which increases linearly starting from 1. Like this: bridge vlan add dev lan0 vid 100 # FID 1 bridge vlan add dev lan1 vid 100 # still FID 1 bridge vlan add dev lan2 vid 1024 # FID 2 The FID allocation made by the driver is sub-optimal for the following reasons: (a) A standalone port has a DefaultPVID of 0 and a default FID of 0 too. A VLAN-unaware bridged port has a DefaultPVID of 0 and a default FID of 0 too. The difference is that the bridged ports may learn ATU entries, while the standalone port has the requirement that it must not, and must not find them either. Standalone ports must not use the same FID as ports belonging to a bridge. All standalone ports can use the same FID, since the ATU will never have an entry in that FID. (b) Multiple VLAN-unaware bridges will all use a DefaultPVID of 0 and a default FID of 0 on all their ports. The FDBs will not be isolated between these bridges. Every VLAN-unaware bridge must use the same FID on all its ports, different from the FID of other bridge ports. (c) Each bridge VLAN uses a unique FID which is useful for Independent VLAN Learning, but the same VLAN ID on multiple VLAN-aware bridges will result in the same FID being used by mv88e6xxx_atu_new(). The correct behavior is for VLAN 1 in br0 to have a different FID compared to VLAN 1 in br1. This patch cannot fix all the above. Traditionally the DSA framework did not care about this, and the reality is that DSA core involvement is needed for the aforementioned issues to be solved. The only thing we can solve here is an issue which does not require API changes, and that is issue (a), aka use a different FID for standalone ports vs ports under VLAN-unaware bridges. The first step is deciding what VID and FID to use for standalone ports, and what VID and FID for bridged ports. The 0/0 pair for standalone ports is what they used up till now, let's keep using that. For bridged ports, there are 2 cases: - VLAN-aware ports will never end up using the port default FID, because packets will always be classified to a VID in the VTU or dropped otherwise. The FID is the one associated with the VID in the VTU. - On VLAN-unaware ports, we _could_ leave their DefaultVID (pvid) at zero (just as in the case of standalone ports), and just change the port's default FID from 0 to a different number (say 1). However, Tobias points out that there is one more requirement to cater to: cross-chip bridging. The Marvell DSA header does not carry the FID in it, only the VID. So once a packet crosses a DSA link, if it has a VID of zero it will get classified to the default FID of that cascade port. Relying on a port default FID for upstream cascade ports results in contradictions: a default FID of 0 breaks ATU isolation of bridged ports on the downstream switch, a default FID of 1 breaks standalone ports on the downstream switch. So not only must standalone ports have different FIDs compared to bridged ports, they must also have different DefaultVID values. IEEE 802.1Q defines two reserved VID values: 0 and 4095. So we simply choose 4095 as the DefaultVID of ports belonging to VLAN-unaware bridges, and VID 4095 maps to FID 1. For the xmit operation to look up the same ATU database, we need to put VID 4095 in DSA tags sent to ports belonging to VLAN-unaware bridges too. All shared ports are configured to map this VID to the bridging FID, because they are members of that VLAN in the VTU. Shared ports don't need to have 802.1QMode enabled in any way, they always parse the VID from the DSA header, they don't need to look at the 802.1Q header. We install VID 4095 to the VTU in mv88e6xxx_setup_port(), with the mention that mv88e6xxx_vtu_setup() which was located right below that call was flushing the VTU so those entries wouldn't be preserved. So we need to relocate the VTU flushing prior to the port initialization during ->setup(). Also note that this is why it is safe to assume that VID 4095 will get associated with FID 1: the user ports haven't been created, so there is no avenue for the user to create a bridge VLAN which could otherwise race with the creation of another FID which would otherwise use up the non-reserved FID value of 1. [ Currently mv88e6xxx_port_vlan_join() doesn't have the option of specifying a preferred FID, it always calls mv88e6xxx_atu_new(). ] mv88e6xxx_port_db_load_purge() is the function to access the ATU for FDB/MDB entries, and it used to determine the FID to use for VLAN-unaware FDB entries (VID=0) using mv88e6xxx_port_get_fid(). But the driver only called mv88e6xxx_port_set_fid() once, during probe, so no surprises, the port FID was always 0, the call to get_fid() was redundant. As much as I would have wanted to not touch that code, the logic is broken when we add a new FID which is not the port-based default. Now the port-based default FID only corresponds to standalone ports, and FDB/MDB entries belong to the bridging service. So while in the future, when the DSA API will support FDB isolation, we will have to figure out the FID based on the bridge number, for now there's a single bridging FID, so hardcode that. Lastly, the tagger needs to check, when it is transmitting a VLAN untagged skb, whether it is sending it towards a bridged or a standalone port. When we see it is bridged we assume the bridge is VLAN-unaware. Not because it cannot be VLAN-aware but: - if we are transmitting from a VLAN-aware bridge we are likely doing so using TX forwarding offload. That code path guarantees that skbs have a vlan hwaccel tag in them, so we would not enter the "else" branch of the "if (skb->protocol == htons(ETH_P_8021Q))" condition. - if we are transmitting on behalf of a VLAN-aware bridge but with no TX forwarding offload (no PVT support, out of space in the PVT, whatever), we would indeed be transmitting with VLAN 4095 instead of the bridge device's pvid. However we would be injecting a "From CPU" frame, and the switch won't learn from that - it only learns from "Forward" frames. So it is inconsequential for address learning. And VLAN 4095 is absolutely enough for the frame to exit the switch, since we never remove that VLAN from any port. Fixes: 57e661aae6a8 ("net: dsa: mv88e6xxx: Link aggregation support") Reported-by: Tobias Waldekranz Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- MAINTAINERS | 1 + drivers/net/dsa/mv88e6xxx/chip.c | 67 ++++++++++++++++++++++++++++++++-------- drivers/net/dsa/mv88e6xxx/chip.h | 3 ++ include/linux/dsa/mv88e6xxx.h | 13 ++++++++ net/dsa/tag_dsa.c | 12 +++++-- 5 files changed, 80 insertions(+), 16 deletions(-) create mode 100644 include/linux/dsa/mv88e6xxx.h diff --git a/MAINTAINERS b/MAINTAINERS index a4a0c2baaf27..17f652b2f653 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11153,6 +11153,7 @@ S: Maintained F: Documentation/devicetree/bindings/net/dsa/marvell.txt F: Documentation/networking/devlink/mv88e6xxx.rst F: drivers/net/dsa/mv88e6xxx/ +F: include/linux/dsa/mv88e6xxx.h F: include/linux/platform_data/mv88e6xxx.h MARVELL ARMADA 3700 PHY DRIVERS diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index d672112afffd..d7b29792732b 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -1681,13 +1682,17 @@ static int mv88e6xxx_port_commit_pvid(struct mv88e6xxx_chip *chip, int port) { struct dsa_port *dp = dsa_to_port(chip->ds, port); struct mv88e6xxx_port *p = &chip->ports[port]; + u16 pvid = MV88E6XXX_VID_STANDALONE; bool drop_untagged = false; - u16 pvid = 0; int err; - if (dp->bridge_dev && br_vlan_enabled(dp->bridge_dev)) { - pvid = p->bridge_pvid.vid; - drop_untagged = !p->bridge_pvid.valid; + if (dp->bridge_dev) { + if (br_vlan_enabled(dp->bridge_dev)) { + pvid = p->bridge_pvid.vid; + drop_untagged = !p->bridge_pvid.valid; + } else { + pvid = MV88E6XXX_VID_BRIDGED; + } } err = mv88e6xxx_port_set_pvid(chip, port, pvid); @@ -1754,11 +1759,15 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port, u16 fid; int err; - /* Null VLAN ID corresponds to the port private database */ + /* Ports have two private address databases: one for when the port is + * standalone and one for when the port is under a bridge and the + * 802.1Q mode is disabled. When the port is standalone, DSA wants its + * address database to remain 100% empty, so we never load an ATU entry + * into a standalone port's database. Therefore, translate the null + * VLAN ID into the port's database used for VLAN-unaware bridging. + */ if (vid == 0) { - err = mv88e6xxx_port_get_fid(chip, port, &fid); - if (err) - return err; + fid = MV88E6XXX_FID_BRIDGED; } else { err = mv88e6xxx_vtu_get(chip, vid, &vlan); if (err) @@ -2434,7 +2443,16 @@ static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, int err; mv88e6xxx_reg_lock(chip); + err = mv88e6xxx_bridge_map(chip, br); + if (err) + goto unlock; + + err = mv88e6xxx_port_commit_pvid(chip, port); + if (err) + goto unlock; + +unlock: mv88e6xxx_reg_unlock(chip); return err; @@ -2444,11 +2462,20 @@ static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br) { struct mv88e6xxx_chip *chip = ds->priv; + int err; mv88e6xxx_reg_lock(chip); + if (mv88e6xxx_bridge_map(chip, br) || mv88e6xxx_port_vlan_map(chip, port)) dev_err(ds->dev, "failed to remap in-chip Port VLAN\n"); + + err = mv88e6xxx_port_commit_pvid(chip, port); + if (err) + dev_err(ds->dev, + "port %d failed to restore standalone pvid: %pe\n", + port, ERR_PTR(err)); + mv88e6xxx_reg_unlock(chip); } @@ -2894,6 +2921,20 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) if (err) return err; + /* Associate MV88E6XXX_VID_BRIDGED with MV88E6XXX_FID_BRIDGED in the + * ATU by virtue of the fact that mv88e6xxx_atu_new() will pick it as + * the first free FID after MV88E6XXX_FID_STANDALONE. This will be used + * as the private PVID on ports under a VLAN-unaware bridge. + * Shared (DSA and CPU) ports must also be members of it, to translate + * the VID from the DSA tag into MV88E6XXX_FID_BRIDGED, instead of + * relying on their port default FID. + */ + err = mv88e6xxx_port_vlan_join(chip, port, MV88E6XXX_VID_BRIDGED, + MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNTAGGED, + false); + if (err) + return err; + if (chip->info->ops->port_set_jumbo_size) { err = chip->info->ops->port_set_jumbo_size(chip, port, 10218); if (err) @@ -2966,7 +3007,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) * database, and allow bidirectional communication between the * CPU and DSA port(s), and the other ports. */ - err = mv88e6xxx_port_set_fid(chip, port, 0); + err = mv88e6xxx_port_set_fid(chip, port, MV88E6XXX_FID_STANDALONE); if (err) return err; @@ -3156,6 +3197,10 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) } } + err = mv88e6xxx_vtu_setup(chip); + if (err) + goto unlock; + /* Setup Switch Port Registers */ for (i = 0; i < mv88e6xxx_num_ports(chip); i++) { if (dsa_is_unused_port(ds, i)) @@ -3185,10 +3230,6 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) if (err) goto unlock; - err = mv88e6xxx_vtu_setup(chip); - if (err) - goto unlock; - err = mv88e6xxx_pvt_setup(chip); if (err) goto unlock; diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 33d067e8396d..8271b8aa7b71 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -21,6 +21,9 @@ #define EDSA_HLEN 8 #define MV88E6XXX_N_FID 4096 +#define MV88E6XXX_FID_STANDALONE 0 +#define MV88E6XXX_FID_BRIDGED 1 + /* PVT limits for 4-bit port and 5-bit switch */ #define MV88E6XXX_MAX_PVT_SWITCHES 32 #define MV88E6XXX_MAX_PVT_PORTS 16 diff --git a/include/linux/dsa/mv88e6xxx.h b/include/linux/dsa/mv88e6xxx.h new file mode 100644 index 000000000000..8c3d45eca46b --- /dev/null +++ b/include/linux/dsa/mv88e6xxx.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 + * Copyright 2021 NXP + */ + +#ifndef _NET_DSA_TAG_MV88E6XXX_H +#define _NET_DSA_TAG_MV88E6XXX_H + +#include + +#define MV88E6XXX_VID_STANDALONE 0 +#define MV88E6XXX_VID_BRIDGED (VLAN_N_VID - 1) + +#endif diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c index 68d5ddc3ef35..b3da4b2ea11c 100644 --- a/net/dsa/tag_dsa.c +++ b/net/dsa/tag_dsa.c @@ -45,6 +45,7 @@ * 6 6 2 2 4 2 N */ +#include #include #include #include @@ -164,16 +165,21 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev, dsa_header[2] &= ~0x10; } } else { + struct net_device *br = dp->bridge_dev; + u16 vid; + + vid = br ? MV88E6XXX_VID_BRIDGED : MV88E6XXX_VID_STANDALONE; + skb_push(skb, DSA_HLEN + extra); dsa_alloc_etype_header(skb, DSA_HLEN + extra); - /* Construct untagged DSA tag. */ + /* Construct DSA header from untagged frame. */ dsa_header = dsa_etype_header_pos_tx(skb) + extra; dsa_header[0] = (cmd << 6) | tag_dev; dsa_header[1] = tag_port << 3; - dsa_header[2] = 0; - dsa_header[3] = 0; + dsa_header[2] = vid >> 8; + dsa_header[3] = vid & 0xff; } return skb; -- cgit From 14132690860e4d06aa3e1c4d7d8e9866ba7756dd Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 7 Oct 2021 19:49:57 +0200 Subject: mqprio: Correct stats in mqprio_dump_class_stats(). Introduction of lockless subqueues broke the class statistics. Before the change stats were accumulated in `bstats' and `qstats' on the stack which was then copied to struct gnet_dump. After the change the `bstats' and `qstats' are initialized to 0 and never updated, yet still fed to gnet_dump. The code updates the global qdisc->cpu_bstats and qdisc->cpu_qstats instead, clobbering them. Most likely a copy-paste error from the code in mqprio_dump(). __gnet_stats_copy_basic() and __gnet_stats_copy_queue() accumulate the values for per-CPU case but for global stats they overwrite the value, so only stats from the last loop iteration / tc end up in sch->[bq]stats. Use the on-stack [bq]stats variables again and add the stats manually in the global case. Fixes: ce679e8df7ed2 ("net: sched: add support for TCQ_F_NOLOCK subqueues to sch_mqprio") Cc: John Fastabend Signed-off-by: Sebastian Andrzej Siewior https://lore.kernel.org/all/20211007175000.2334713-2-bigeasy@linutronix.de/ Signed-off-by: Jakub Kicinski --- net/sched/sch_mqprio.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c index 8766ab5b8788..5eb3b1b7ae5e 100644 --- a/net/sched/sch_mqprio.c +++ b/net/sched/sch_mqprio.c @@ -529,22 +529,28 @@ static int mqprio_dump_class_stats(struct Qdisc *sch, unsigned long cl, for (i = tc.offset; i < tc.offset + tc.count; i++) { struct netdev_queue *q = netdev_get_tx_queue(dev, i); struct Qdisc *qdisc = rtnl_dereference(q->qdisc); - struct gnet_stats_basic_cpu __percpu *cpu_bstats = NULL; - struct gnet_stats_queue __percpu *cpu_qstats = NULL; spin_lock_bh(qdisc_lock(qdisc)); + if (qdisc_is_percpu_stats(qdisc)) { - cpu_bstats = qdisc->cpu_bstats; - cpu_qstats = qdisc->cpu_qstats; + qlen = qdisc_qlen_sum(qdisc); + + __gnet_stats_copy_basic(NULL, &bstats, + qdisc->cpu_bstats, + &qdisc->bstats); + __gnet_stats_copy_queue(&qstats, + qdisc->cpu_qstats, + &qdisc->qstats, + qlen); + } else { + qlen += qdisc->q.qlen; + bstats.bytes += qdisc->bstats.bytes; + bstats.packets += qdisc->bstats.packets; + qstats.backlog += qdisc->qstats.backlog; + qstats.drops += qdisc->qstats.drops; + qstats.requeues += qdisc->qstats.requeues; + qstats.overlimits += qdisc->qstats.overlimits; } - - qlen = qdisc_qlen_sum(qdisc); - __gnet_stats_copy_basic(NULL, &sch->bstats, - cpu_bstats, &qdisc->bstats); - __gnet_stats_copy_queue(&sch->qstats, - cpu_qstats, - &qdisc->qstats, - qlen); spin_unlock_bh(qdisc_lock(qdisc)); } -- cgit From 1f3e2e97c003f80c4b087092b225c8787ff91e4d Mon Sep 17 00:00:00 2001 From: Xiaolong Huang Date: Fri, 8 Oct 2021 14:58:30 +0800 Subject: isdn: cpai: check ctr->cnr to avoid array index out of bound The cmtp_add_connection() would add a cmtp session to a controller and run a kernel thread to process cmtp. __module_get(THIS_MODULE); session->task = kthread_run(cmtp_session, session, "kcmtpd_ctr_%d", session->num); During this process, the kernel thread would call detach_capi_ctr() to detach a register controller. if the controller was not attached yet, detach_capi_ctr() would trigger an array-index-out-bounds bug. [ 46.866069][ T6479] UBSAN: array-index-out-of-bounds in drivers/isdn/capi/kcapi.c:483:21 [ 46.867196][ T6479] index -1 is out of range for type 'capi_ctr *[32]' [ 46.867982][ T6479] CPU: 1 PID: 6479 Comm: kcmtpd_ctr_0 Not tainted 5.15.0-rc2+ #8 [ 46.869002][ T6479] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014 [ 46.870107][ T6479] Call Trace: [ 46.870473][ T6479] dump_stack_lvl+0x57/0x7d [ 46.870974][ T6479] ubsan_epilogue+0x5/0x40 [ 46.871458][ T6479] __ubsan_handle_out_of_bounds.cold+0x43/0x48 [ 46.872135][ T6479] detach_capi_ctr+0x64/0xc0 [ 46.872639][ T6479] cmtp_session+0x5c8/0x5d0 [ 46.873131][ T6479] ? __init_waitqueue_head+0x60/0x60 [ 46.873712][ T6479] ? cmtp_add_msgpart+0x120/0x120 [ 46.874256][ T6479] kthread+0x147/0x170 [ 46.874709][ T6479] ? set_kthread_struct+0x40/0x40 [ 46.875248][ T6479] ret_from_fork+0x1f/0x30 [ 46.875773][ T6479] Signed-off-by: Xiaolong Huang Acked-by: Arnd Bergmann Link: https://lore.kernel.org/r/20211008065830.305057-1-butterflyhuangxx@gmail.com Signed-off-by: Jakub Kicinski --- drivers/isdn/capi/kcapi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index cb0afe897162..7313454e403a 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -480,6 +480,11 @@ int detach_capi_ctr(struct capi_ctr *ctr) ctr_down(ctr, CAPI_CTR_DETACHED); + if (ctr->cnr < 1 || ctr->cnr - 1 >= CAPI_MAXCONTR) { + err = -EINVAL; + goto unlock_out; + } + if (capi_controller[ctr->cnr - 1] != ctr) { err = -EINVAL; goto unlock_out; -- cgit From be0499369d6376e70b5b80bbced94c0c32d508b1 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Fri, 8 Oct 2021 06:11:31 -0700 Subject: net: mana: Fix error handling in mana_create_rxq() Fix error handling in mana_create_rxq() when cq->gdma_id >= gc->max_num_cqs. Fixes: ca9c54d2d6a5 ("net: mana: Add a driver for Microsoft Azure Network Adapter (MANA)") Signed-off-by: Haiyang Zhang Link: https://lore.kernel.org/r/1633698691-31721-1-git-send-email-haiyangz@microsoft.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/microsoft/mana/mana_en.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index 1b21030308e5..030ae89f3a33 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c @@ -1477,8 +1477,10 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc, if (err) goto out; - if (cq->gdma_id >= gc->max_num_cqs) + if (WARN_ON(cq->gdma_id >= gc->max_num_cqs)) { + err = -EINVAL; goto out; + } gc->cq_table[cq->gdma_id] = cq->gdma_cq; -- cgit From 5c976a56570f29aaf4a2f9a1bf99789c252183c9 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Fri, 8 Oct 2021 12:38:01 -0700 Subject: ionic: don't remove netdev->dev_addr when syncing uc list Bridging, and possibly other upper stack gizmos, adds the lower device's netdev->dev_addr to its own uc list, and then requests it be deleted when the upper bridge device is removed. This delete request also happens with the bridging vlan_filtering is enabled and then disabled. Bonding has a similar behavior with the uc list, but since it also uses set_mac to manage netdev->dev_addr, it doesn't have the same the failure case. Because we store our netdev->dev_addr in our uc list, we need to ignore the delete request from dev_uc_sync so as to not lose the address and all hope of communicating. Note that ndo_set_mac_address is expressly changing netdev->dev_addr, so no limitation is set there. Fixes: 2a654540be10 ("ionic: Add Rx filter and rx_mode ndo support") Signed-off-by: Shannon Nelson Signed-off-by: David S. Miller --- drivers/net/ethernet/pensando/ionic/ionic_lif.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index ccf3ffcd3939..7f3322ce044c 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -1379,6 +1379,10 @@ static int ionic_addr_add(struct net_device *netdev, const u8 *addr) static int ionic_addr_del(struct net_device *netdev, const u8 *addr) { + /* Don't delete our own address from the uc list */ + if (ether_addr_equal(addr, netdev->dev_addr)) + return 0; + return ionic_lif_list_addr(netdev_priv(netdev), addr, DEL_ADDR); } -- cgit From 6510e80a0b81b5d814e3aea6297ba42f5e76f73c Mon Sep 17 00:00:00 2001 From: Zheyu Ma Date: Sat, 9 Oct 2021 11:33:49 +0000 Subject: isdn: mISDN: Fix sleeping function called from invalid context The driver can call card->isac.release() function from an atomic context. Fix this by calling this function after releasing the lock. The following log reveals it: [ 44.168226 ] BUG: sleeping function called from invalid context at kernel/workqueue.c:3018 [ 44.168941 ] in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 5475, name: modprobe [ 44.169574 ] INFO: lockdep is turned off. [ 44.169899 ] irq event stamp: 0 [ 44.170160 ] hardirqs last enabled at (0): [<0000000000000000>] 0x0 [ 44.170627 ] hardirqs last disabled at (0): [] copy_process+0x132d/0x3e00 [ 44.171240 ] softirqs last enabled at (0): [] copy_process+0x135a/0x3e00 [ 44.171852 ] softirqs last disabled at (0): [<0000000000000000>] 0x0 [ 44.172318 ] Preemption disabled at: [ 44.172320 ] [] nj_release+0x69/0x500 [netjet] [ 44.174441 ] Call Trace: [ 44.174630 ] dump_stack_lvl+0xa8/0xd1 [ 44.174912 ] dump_stack+0x15/0x17 [ 44.175166 ] ___might_sleep+0x3a2/0x510 [ 44.175459 ] ? nj_release+0x69/0x500 [netjet] [ 44.175791 ] __might_sleep+0x82/0xe0 [ 44.176063 ] ? start_flush_work+0x20/0x7b0 [ 44.176375 ] start_flush_work+0x33/0x7b0 [ 44.176672 ] ? trace_irq_enable_rcuidle+0x85/0x170 [ 44.177034 ] ? kasan_quarantine_put+0xaa/0x1f0 [ 44.177372 ] ? kasan_quarantine_put+0xaa/0x1f0 [ 44.177711 ] __flush_work+0x11a/0x1a0 [ 44.177991 ] ? flush_work+0x20/0x20 [ 44.178257 ] ? lock_release+0x13c/0x8f0 [ 44.178550 ] ? __kasan_check_write+0x14/0x20 [ 44.178872 ] ? do_raw_spin_lock+0x148/0x360 [ 44.179187 ] ? read_lock_is_recursive+0x20/0x20 [ 44.179530 ] ? __kasan_check_read+0x11/0x20 [ 44.179846 ] ? do_raw_spin_unlock+0x55/0x900 [ 44.180168 ] ? ____kasan_slab_free+0x116/0x140 [ 44.180505 ] ? _raw_spin_unlock_irqrestore+0x41/0x60 [ 44.180878 ] ? skb_queue_purge+0x1a3/0x1c0 [ 44.181189 ] ? kfree+0x13e/0x290 [ 44.181438 ] flush_work+0x17/0x20 [ 44.181695 ] mISDN_freedchannel+0xe8/0x100 [ 44.182006 ] isac_release+0x210/0x260 [mISDNipac] [ 44.182366 ] nj_release+0xf6/0x500 [netjet] [ 44.182685 ] nj_remove+0x48/0x70 [netjet] [ 44.182989 ] pci_device_remove+0xa9/0x250 Signed-off-by: Zheyu Ma Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/netjet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c index 2a1ddd47a096..a52f275f8263 100644 --- a/drivers/isdn/hardware/mISDN/netjet.c +++ b/drivers/isdn/hardware/mISDN/netjet.c @@ -949,8 +949,8 @@ nj_release(struct tiger_hw *card) nj_disable_hwirq(card); mode_tiger(&card->bc[0], ISDN_P_NONE); mode_tiger(&card->bc[1], ISDN_P_NONE); - card->isac.release(&card->isac); spin_unlock_irqrestore(&card->lock, flags); + card->isac.release(&card->isac); release_region(card->base, card->base_s); card->base_s = 0; } -- cgit From 1951b3f19cfe822709c890a337906823c223c7c3 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 9 Oct 2021 15:26:07 +0300 Subject: net: dsa: hold rtnl_lock in dsa_switch_setup_tag_protocol It was a documented fact that ds->ops->change_tag_protocol() offered rtnetlink mutex protection to the switch driver, since there was an ASSERT_RTNL right before the call in dsa_switch_change_tag_proto() (initiated from sysfs). The blamed commit introduced another call path for ds->ops->change_tag_protocol() which does not hold the rtnl_mutex. This is: dsa_tree_setup -> dsa_tree_setup_switches -> dsa_switch_setup -> dsa_switch_setup_tag_protocol -> ds->ops->change_tag_protocol() -> dsa_port_setup -> dsa_slave_create -> register_netdevice(slave_dev) -> dsa_tree_setup_master -> dsa_master_setup -> dev->dsa_ptr = cpu_dp The reason why the rtnl_mutex is held in the sysfs call path is to ensure that, once the master and all the DSA interfaces are down (which is required so that no packets flow), they remain down during the tagging protocol change. The above calling order illustrates the fact that it should not be risky to change the initial tagging protocol to the one specified in the device tree at the given time: - packets cannot enter the dsa_switch_rcv() packet type handler since netdev_uses_dsa() for the master will not yet return true, since dev->dsa_ptr has not yet been populated - packets cannot enter the dsa_slave_xmit() function because no DSA interface has yet been registered So from the DSA core's perspective, holding the rtnl_mutex is indeed not necessary. Yet, drivers may need to do things which need rtnl_mutex protection. For example: felix_set_tag_protocol -> felix_setup_tag_8021q -> dsa_tag_8021q_register -> dsa_tag_8021q_setup -> dsa_tag_8021q_port_setup -> vlan_vid_add -> ASSERT_RTNL These drivers do not really have a choice to take the rtnl_mutex themselves, since in the sysfs case, the rtnl_mutex is already held. Fixes: deff710703d8 ("net: dsa: Allow default tag protocol to be overridden from DT") Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- net/dsa/dsa2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index 6d5cc0217133..da18094b5a04 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -811,7 +811,9 @@ static int dsa_switch_setup_tag_protocol(struct dsa_switch *ds) if (!dsa_is_cpu_port(ds, port)) continue; + rtnl_lock(); err = ds->ops->change_tag_protocol(ds, port, tag_ops->proto); + rtnl_unlock(); if (err) { dev_err(ds->dev, "Unable to use tag protocol \"%s\": %pe\n", tag_ops->name, ERR_PTR(err)); -- cgit From a5a14ea7b4e55604acb0dc9d88fdb4cb6945bc77 Mon Sep 17 00:00:00 2001 From: chongjiapeng Date: Sat, 9 Oct 2021 16:09:26 +0800 Subject: qed: Fix missing error code in qed_slowpath_start() The error code is missing in this code scenario, add the error code '-EINVAL' to the return value 'rc'. Eliminate the follow smatch warning: drivers/net/ethernet/qlogic/qed/qed_main.c:1298 qed_slowpath_start() warn: missing error code 'rc'. Reported-by: Abaci Robot Fixes: d51e4af5c209 ("qed: aRFS infrastructure support") Signed-off-by: chongjiapeng Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 15ef59aa34ff..d10e1cd6d2ba 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -1299,6 +1299,7 @@ static int qed_slowpath_start(struct qed_dev *cdev, } else { DP_NOTICE(cdev, "Failed to acquire PTT for aRFS\n"); + rc = -EINVAL; goto err; } } -- cgit From f49823939e41121fdffada4d583e3e38d28336f9 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 8 Oct 2021 14:42:52 -0700 Subject: net: phy: Do not shutdown PHYs in READY state In case a PHY device was probed thus in the PHY_READY state, but not configured and with no network device attached yet, we should not be trying to shut it down because it has been brought back into reset by phy_device_reset() towards the end of phy_probe() and anyway we have not configured the PHY yet. Fixes: e2f016cf7751 ("net: phy: add a shutdown procedure") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index ba5ad86ec826..4f9990b47a37 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -3125,6 +3125,9 @@ static void phy_shutdown(struct device *dev) { struct phy_device *phydev = to_phy_device(dev); + if (phydev->state == PHY_READY || !phydev->attached_dev) + return; + phy_disable_interrupts(phydev); } -- cgit From 732b74d647048668f0f8dc0c848f0746c69e2e2f Mon Sep 17 00:00:00 2001 From: Xuan Zhuo Date: Sat, 9 Oct 2021 05:17:53 -0400 Subject: virtio-net: fix for skb_over_panic inside big mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 126285651b7f ("Merge ra.kernel.org:/pub/scm/linux/kernel/git/netdev/net") accidentally reverted the effect of commit 1a8024239da ("virtio-net: fix for skb_over_panic inside big mode") on drivers/net/virtio_net.c As a result, users of crosvm (which is using large packet mode) are experiencing crashes with 5.14-rc1 and above that do not occur with 5.13. Crash trace: [ 61.346677] skbuff: skb_over_panic: text:ffffffff881ae2c7 len:3762 put:3762 head:ffff8a5ec8c22000 data:ffff8a5ec8c22010 tail:0xec2 end:0xec0 dev: [ 61.369192] kernel BUG at net/core/skbuff.c:111! [ 61.372840] invalid opcode: 0000 [#1] SMP PTI [ 61.374892] CPU: 5 PID: 0 Comm: swapper/5 Not tainted 5.14.0-rc1 linux-v5.14-rc1-for-mesa-ci.tar.bz2 #1 [ 61.376450] Hardware name: ChromiumOS crosvm, BIOS 0 .. [ 61.393635] Call Trace: [ 61.394127] [ 61.394488] skb_put.cold+0x10/0x10 [ 61.395095] page_to_skb+0xf7/0x410 [ 61.395689] receive_buf+0x81/0x1660 [ 61.396228] ? netif_receive_skb_list_internal+0x1ad/0x2b0 [ 61.397180] ? napi_gro_flush+0x97/0xe0 [ 61.397896] ? detach_buf_split+0x67/0x120 [ 61.398573] virtnet_poll+0x2cf/0x420 [ 61.399197] __napi_poll+0x25/0x150 [ 61.399764] net_rx_action+0x22f/0x280 [ 61.400394] __do_softirq+0xba/0x257 [ 61.401012] irq_exit_rcu+0x8e/0xb0 [ 61.401618] common_interrupt+0x7b/0xa0 [ 61.402270] See https://lore.kernel.org/r/5edaa2b7c2fe4abd0347b8454b2ac032b6694e2c.camel%40collabora.com for the report. Apply the original 1a8024239da ("virtio-net: fix for skb_over_panic inside big mode") again, the original logic still holds: In virtio-net's large packet mode, there is a hole in the space behind buf. hdr_padded_len - hdr_len We must take this into account when calculating tailroom. Cc: Greg KH Fixes: fb32856b16ad ("virtio-net: page_to_skb() use build_skb when there's sufficient tailroom") Fixes: 126285651b7f ("Merge ra.kernel.org:/pub/scm/linux/kernel/git/netdev/net") Signed-off-by: Xuan Zhuo Reported-by: Corentin Noël Tested-by: Corentin Noël Signed-off-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 79bd2585ec6b..4ad25a8b0870 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -406,7 +406,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, * add_recvbuf_mergeable() + get_mergeable_buf_len() */ truesize = headroom ? PAGE_SIZE : truesize; - tailroom = truesize - len - headroom; + tailroom = truesize - len - headroom - (hdr_padded_len - hdr_len); buf = p - headroom; len -= hdr_len; -- cgit From 6675880fc4b7c5137a2640b0725505c21b1ac525 Mon Sep 17 00:00:00 2001 From: Vamshi K Sthambamkadi Date: Fri, 8 Oct 2021 12:48:06 +0530 Subject: tracing: Fix memory leak in eprobe_register() kmemleak report: unreferenced object 0xffff900a70ec7ec0 (size 32): comm "ftracetest", pid 2770, jiffies 4295042510 (age 311.464s) hex dump (first 32 bytes): c8 31 23 45 0a 90 ff ff 40 85 c7 6e 0a 90 ff ff .1#E....@..n.... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<000000009d3751fd>] kmem_cache_alloc_trace+0x2a2/0x440 [<0000000088b8124b>] eprobe_register+0x1e3/0x350 [<000000002a9a0517>] __ftrace_event_enable_disable+0x7c/0x240 [<0000000019109321>] event_enable_write+0x93/0xe0 [<000000007d85b320>] vfs_write+0xb9/0x260 [<00000000b94c5e41>] ksys_write+0x67/0xe0 [<000000005a08c81d>] __x64_sys_write+0x1a/0x20 [<00000000240bf576>] do_syscall_64+0x3b/0xc0 [<0000000043d5d9f6>] entry_SYSCALL_64_after_hwframe+0x44/0xae unreferenced object 0xffff900a56bbf280 (size 128): comm "ftracetest", pid 2770, jiffies 4295042510 (age 311.464s) hex dump (first 32 bytes): ff ff ff ff ff ff ff ff 00 00 00 00 01 00 00 00 ................ 80 69 3b b2 ff ff ff ff 20 69 3b b2 ff ff ff ff .i;..... i;..... backtrace: [<000000009d3751fd>] kmem_cache_alloc_trace+0x2a2/0x440 [<00000000c4e90fad>] eprobe_register+0x1fc/0x350 [<000000002a9a0517>] __ftrace_event_enable_disable+0x7c/0x240 [<0000000019109321>] event_enable_write+0x93/0xe0 [<000000007d85b320>] vfs_write+0xb9/0x260 [<00000000b94c5e41>] ksys_write+0x67/0xe0 [<000000005a08c81d>] __x64_sys_write+0x1a/0x20 [<00000000240bf576>] do_syscall_64+0x3b/0xc0 [<0000000043d5d9f6>] entry_SYSCALL_64_after_hwframe+0x44/0xae In new_eprobe_trigger(), allocated edata and trigger variables are never freed. To fix, free memory in disable_eprobe(). Link: https://lkml.kernel.org/r/20211008071802.GA2098@cosmos Fixes: 7491e2c442781 ("tracing: Add a probe that attaches to trace events") Signed-off-by: Vamshi K Sthambamkadi Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace_eprobe.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c index 3044b762cbd7..570d081929fb 100644 --- a/kernel/trace/trace_eprobe.c +++ b/kernel/trace/trace_eprobe.c @@ -632,6 +632,13 @@ static int disable_eprobe(struct trace_eprobe *ep, trace_event_trigger_enable_disable(file, 0); update_cond_flag(file); + + /* Make sure nothing is using the edata or trigger */ + tracepoint_synchronize_unregister(); + + kfree(edata); + kfree(trigger); + return 0; } -- cgit From 1ae43851b18afe861120ebd7c426dc44f06bb2bd Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 16 Sep 2021 15:23:12 +0900 Subject: bootconfig: init: Fix memblock leak in xbc_make_cmdline() Free unused memblock in a error case to fix memblock leak in xbc_make_cmdline(). Link: https://lkml.kernel.org/r/163177339181.682366.8713781325929549256.stgit@devnote2 Fixes: 51887d03aca1 ("bootconfig: init: Allow admin to use bootconfig for kernel command line") Signed-off-by: Masami Hiramatsu Signed-off-by: Steven Rostedt (VMware) --- init/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/init/main.c b/init/main.c index 81a79a77db46..3c4054a95545 100644 --- a/init/main.c +++ b/init/main.c @@ -382,6 +382,7 @@ static char * __init xbc_make_cmdline(const char *key) ret = xbc_snprint_cmdline(new_cmdline, len + 1, root); if (ret < 0 || ret > len) { pr_err("Failed to print extra kernel cmdline.\n"); + memblock_free_ptr(new_cmdline, len + 1); return NULL; } -- cgit From b26503b15631229583e925de774e95b11d8144e8 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 6 Oct 2021 18:28:30 +0100 Subject: tracing: Fix missing * in comment block There is a missing * in a comment block, add it in. Link: https://lkml.kernel.org/r/20211006172830.1025336-1-colin.king@canonical.com Signed-off-by: Colin Ian King Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace_events_hist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index a6061a69aa84..f01e442716e2 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -2506,7 +2506,7 @@ find_synthetic_field_var(struct hist_trigger_data *target_hist_data, * events. However, for convenience, users are allowed to directly * specify an event field in an action, which will be automatically * converted into a variable on their behalf. - + * * If a user specifies a field on an event that isn't the event the * histogram currently being defined (the target event histogram), the * only way that can be accomplished is if a new hist trigger is -- cgit From a01ba2a3378be85538e0183ae5367c1bc1d5aaf3 Mon Sep 17 00:00:00 2001 From: Jonathan Bell Date: Fri, 8 Oct 2021 12:25:43 +0300 Subject: xhci: guard accesses to ep_state in xhci_endpoint_reset() See https://github.com/raspberrypi/linux/issues/3981 Two read-modify-write cycles on ep->ep_state are not guarded by xhci->lock. Fix these. Fixes: f5249461b504 ("xhci: Clear the host side toggle manually when endpoint is soft reset") Cc: stable@vger.kernel.org Signed-off-by: Jonathan Bell Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20211008092547.3996295-2-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 93c38b557afd..541fe4dcc43a 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3214,10 +3214,13 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd, return; /* Bail out if toggle is already being cleared by a endpoint reset */ + spin_lock_irqsave(&xhci->lock, flags); if (ep->ep_state & EP_HARD_CLEAR_TOGGLE) { ep->ep_state &= ~EP_HARD_CLEAR_TOGGLE; + spin_unlock_irqrestore(&xhci->lock, flags); return; } + spin_unlock_irqrestore(&xhci->lock, flags); /* Only interrupt and bulk ep's use data toggle, USB2 spec 5.5.4-> */ if (usb_endpoint_xfer_control(&host_ep->desc) || usb_endpoint_xfer_isoc(&host_ep->desc)) @@ -3303,8 +3306,10 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd, xhci_free_command(xhci, cfg_cmd); cleanup: xhci_free_command(xhci, stop_cmd); + spin_lock_irqsave(&xhci->lock, flags); if (ep->ep_state & EP_SOFT_CLEAR_TOGGLE) ep->ep_state &= ~EP_SOFT_CLEAR_TOGGLE; + spin_unlock_irqrestore(&xhci->lock, flags); } static int xhci_check_streams_endpoint(struct xhci_hcd *xhci, -- cgit From 5255660b208aebfdb71d574f3952cf48392f4306 Mon Sep 17 00:00:00 2001 From: Jonathan Bell Date: Fri, 8 Oct 2021 12:25:44 +0300 Subject: xhci: add quirk for host controllers that don't update endpoint DCS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seen on a VLI VL805 PCIe to USB controller. For non-stream endpoints at least, if the xHC halts on a particular TRB due to an error then the DCS field in the Out Endpoint Context maintained by the hardware is not updated with the current cycle state. Using the quirk XHCI_EP_CTX_BROKEN_DCS and instead fetch the DCS bit from the TRB that the xHC stopped on. [ bjorn: rebased to v5.14-rc2 ] Link: https://github.com/raspberrypi/linux/issues/3060 Cc: stable@vger.kernel.org Signed-off-by: Jonathan Bell Signed-off-by: Bjørn Mork Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20211008092547.3996295-3-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 4 +++- drivers/usb/host/xhci-ring.c | 25 ++++++++++++++++++++++++- drivers/usb/host/xhci.h | 1 + 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 2c9f25ca8edd..633413d78380 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -279,8 +279,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == 0x3432) xhci->quirks |= XHCI_BROKEN_STREAMS; - if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483) + if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483) { xhci->quirks |= XHCI_LPM_SUPPORT; + xhci->quirks |= XHCI_EP_CTX_BROKEN_DCS; + } if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index e676749f543b..7dbd26a9bc24 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -559,8 +559,11 @@ static int xhci_move_dequeue_past_td(struct xhci_hcd *xhci, struct xhci_ring *ep_ring; struct xhci_command *cmd; struct xhci_segment *new_seg; + struct xhci_segment *halted_seg = NULL; union xhci_trb *new_deq; int new_cycle; + union xhci_trb *halted_trb; + int index = 0; dma_addr_t addr; u64 hw_dequeue; bool cycle_found = false; @@ -598,7 +601,27 @@ static int xhci_move_dequeue_past_td(struct xhci_hcd *xhci, hw_dequeue = xhci_get_hw_deq(xhci, dev, ep_index, stream_id); new_seg = ep_ring->deq_seg; new_deq = ep_ring->dequeue; - new_cycle = hw_dequeue & 0x1; + + /* + * Quirk: xHC write-back of the DCS field in the hardware dequeue + * pointer is wrong - use the cycle state of the TRB pointed to by + * the dequeue pointer. + */ + if (xhci->quirks & XHCI_EP_CTX_BROKEN_DCS && + !(ep->ep_state & EP_HAS_STREAMS)) + halted_seg = trb_in_td(xhci, td->start_seg, + td->first_trb, td->last_trb, + hw_dequeue & ~0xf, false); + if (halted_seg) { + index = ((dma_addr_t)(hw_dequeue & ~0xf) - halted_seg->dma) / + sizeof(*halted_trb); + halted_trb = &halted_seg->trbs[index]; + new_cycle = halted_trb->generic.field[3] & 0x1; + xhci_dbg(xhci, "Endpoint DCS = %d TRB index = %d cycle = %d\n", + (u8)(hw_dequeue & 0x1), index, new_cycle); + } else { + new_cycle = hw_dequeue & 0x1; + } /* * We want to find the pointer, segment and cycle state of the new trb diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index dca6181c33fd..5a75fe563123 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1899,6 +1899,7 @@ struct xhci_hcd { #define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39) #define XHCI_NO_SOFT_RETRY BIT_ULL(40) #define XHCI_BROKEN_D3COLD BIT_ULL(41) +#define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42) unsigned int num_active_eps; unsigned int limit_active_eps; -- cgit From 880de403777376e50bdf60def359fa50a722006f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 8 Oct 2021 12:25:45 +0300 Subject: USB: xhci: dbc: fix tty registration race Make sure to allocate resources before registering the tty device to avoid having a racing open() and write() fail to enable rx or dereference a NULL pointer when accessing the uninitialised fifo. Fixes: dfba2174dc42 ("usb: xhci: Add DbC support in xHCI driver") Cc: stable@vger.kernel.org # 4.16 Cc: Lu Baolu Signed-off-by: Johan Hovold Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20211008092547.3996295-4-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-dbgtty.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c index 6e784f2fc26d..eb46e642e87a 100644 --- a/drivers/usb/host/xhci-dbgtty.c +++ b/drivers/usb/host/xhci-dbgtty.c @@ -408,40 +408,38 @@ static int xhci_dbc_tty_register_device(struct xhci_dbc *dbc) return -EBUSY; xhci_dbc_tty_init_port(dbc, port); - tty_dev = tty_port_register_device(&port->port, - dbc_tty_driver, 0, NULL); - if (IS_ERR(tty_dev)) { - ret = PTR_ERR(tty_dev); - goto register_fail; - } ret = kfifo_alloc(&port->write_fifo, DBC_WRITE_BUF_SIZE, GFP_KERNEL); if (ret) - goto buf_alloc_fail; + goto err_exit_port; ret = xhci_dbc_alloc_requests(dbc, BULK_IN, &port->read_pool, dbc_read_complete); if (ret) - goto request_fail; + goto err_free_fifo; ret = xhci_dbc_alloc_requests(dbc, BULK_OUT, &port->write_pool, dbc_write_complete); if (ret) - goto request_fail; + goto err_free_requests; + + tty_dev = tty_port_register_device(&port->port, + dbc_tty_driver, 0, NULL); + if (IS_ERR(tty_dev)) { + ret = PTR_ERR(tty_dev); + goto err_free_requests; + } port->registered = true; return 0; -request_fail: +err_free_requests: xhci_dbc_free_requests(&port->read_pool); xhci_dbc_free_requests(&port->write_pool); +err_free_fifo: kfifo_free(&port->write_fifo); - -buf_alloc_fail: - tty_unregister_device(dbc_tty_driver, 0); - -register_fail: +err_exit_port: xhci_dbc_tty_exit_port(port); dev_err(dbc->dev, "can't register tty port, err %d\n", ret); -- cgit From ff0e50d3564f33b7f4b35cadeabd951d66cfc570 Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Fri, 8 Oct 2021 12:25:46 +0300 Subject: xhci: Fix command ring pointer corruption while aborting a command The command ring pointer is located at [6:63] bits of the command ring control register (CRCR). All the control bits like command stop, abort are located at [0:3] bits. While aborting a command, we read the CRCR and set the abort bit and write to the CRCR. The read will always give command ring pointer as all zeros. So we essentially write only the control bits. Since we split the 64 bit write into two 32 bit writes, there is a possibility of xHC command ring stopped before the upper dword (all zeros) is written. If that happens, xHC updates the upper dword of its internal command ring pointer with all zeros. Next time, when the command ring is restarted, we see xHC memory access failures. Fix this issue by only writing to the lower dword of CRCR where all control bits are located. Cc: stable@vger.kernel.org Signed-off-by: Pavankumar Kondeti Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20211008092547.3996295-5-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 7dbd26a9bc24..311597bba80e 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -366,16 +366,22 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci, /* Must be called with xhci->lock held, releases and aquires lock back */ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags) { - u64 temp_64; + u32 temp_32; int ret; xhci_dbg(xhci, "Abort command ring\n"); reinit_completion(&xhci->cmd_ring_stop_completion); - temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); - xhci_write_64(xhci, temp_64 | CMD_RING_ABORT, - &xhci->op_regs->cmd_ring); + /* + * The control bits like command stop, abort are located in lower + * dword of the command ring control register. Limit the write + * to the lower dword to avoid corrupting the command ring pointer + * in case if the command ring is stopped by the time upper dword + * is written. + */ + temp_32 = readl(&xhci->op_regs->cmd_ring); + writel(temp_32 | CMD_RING_ABORT, &xhci->op_regs->cmd_ring); /* Section 4.6.1.2 of xHCI 1.0 spec says software should also time the * completion of the Command Abort operation. If CRR is not negated in 5 -- cgit From ea0f69d8211963c4b2cc1998b86779a500adb502 Mon Sep 17 00:00:00 2001 From: Nikolay Martynov Date: Fri, 8 Oct 2021 12:25:47 +0300 Subject: xhci: Enable trust tx length quirk for Fresco FL11 USB controller Tested on SD5200T TB3 dock which has Fresco Logic FL1100 USB 3.0 Host Controller. Before this patch streaming video from USB cam made mouse and keyboard connected to the same USB bus unusable. Also video was jerky. With this patch streaming video doesn't have any effect on other periferals and video is smooth. Cc: stable@vger.kernel.org Signed-off-by: Nikolay Martynov Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20211008092547.3996295-6-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 633413d78380..2484a9d38ce2 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -30,6 +30,7 @@ #define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73 #define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000 #define PCI_DEVICE_ID_FRESCO_LOGIC_FL1009 0x1009 +#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1100 0x1100 #define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400 0x1400 #define PCI_VENDOR_ID_ETRON 0x1b6f @@ -113,6 +114,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) /* Look for vendor-specific quirks */ if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC && (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK || + pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1100 || pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1400)) { if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK && pdev->revision == 0x0) { -- cgit From 023a062f238129e8a542b5163c4350ceb076283e Mon Sep 17 00:00:00 2001 From: Cameron Berkenpas Date: Sun, 10 Oct 2021 15:54:11 -0700 Subject: ALSA: hda/realtek: Fix for quirk to enable speaker output on the Lenovo 13s Gen2 The previous patch's HDA verb initialization for the Lenovo 13s sequence was slightly off. This updated verb sequence has been tested and confirmed working. Fixes: ad7cc2d41b7a ("ALSA: hda/realtek: Quirks to enable speaker output for Lenovo Legion 7i 15IMHG05, Yoga 7i 14ITL5/15ITL5, and 13s Gen2 laptops.") BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=208555 Cc: Signed-off-by: Cameron Berkenpas Link: https://lore.kernel.org/r/20211010225410.23423-1-cam@neo-zeon.de Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 73e7a92c3728..bca5830ff706 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -8367,7 +8367,7 @@ static const struct hda_fixup alc269_fixups[] = { .v.verbs = (const struct hda_verb[]) { { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 }, { 0x20, AC_VERB_SET_PROC_COEF, 0x41 }, - { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, + { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, { 0x20, AC_VERB_SET_PROC_COEF, 0x2 }, { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, -- cgit From 75b3cb97eb1f05042745c0655a7145b0262d4c5c Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Fri, 8 Oct 2021 16:36:02 -0400 Subject: spi: bcm-qspi: clear MSPI spifie interrupt during probe Intermittent Kernel crash has been observed on probe in bcm_qspi_mspi_l2_isr() handler when the MSPI spifie interrupt bit has not been cleared before registering for interrupts. Fix the driver to move SoC specific custom interrupt handling code before we register IRQ in probe. Also clear MSPI interrupt status resgiter prior to registering IRQ handlers. Fixes: cc20a38612db ("spi: iproc-qspi: Add Broadcom iProc SoCs support") Signed-off-by: Kamal Dasu Acked-by: Florian Fainelli Link: https://lore.kernel.org/r/20211008203603.40915-3-kdasu.kdev@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-bcm-qspi.c | 77 +++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 32 deletions(-) diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index a78e56f566dd..3043677ba222 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -1250,10 +1250,14 @@ static void bcm_qspi_hw_init(struct bcm_qspi *qspi) static void bcm_qspi_hw_uninit(struct bcm_qspi *qspi) { + u32 status = bcm_qspi_read(qspi, MSPI, MSPI_MSPI_STATUS); + bcm_qspi_write(qspi, MSPI, MSPI_SPCR2, 0); if (has_bspi(qspi)) bcm_qspi_write(qspi, MSPI, MSPI_WRITE_LOCK, 0); + /* clear interrupt */ + bcm_qspi_write(qspi, MSPI, MSPI_MSPI_STATUS, status & ~1); } static const struct spi_controller_mem_ops bcm_qspi_mem_ops = { @@ -1397,6 +1401,47 @@ int bcm_qspi_probe(struct platform_device *pdev, if (!qspi->dev_ids) return -ENOMEM; + /* + * Some SoCs integrate spi controller (e.g., its interrupt bits) + * in specific ways + */ + if (soc_intc) { + qspi->soc_intc = soc_intc; + soc_intc->bcm_qspi_int_set(soc_intc, MSPI_DONE, true); + } else { + qspi->soc_intc = NULL; + } + + if (qspi->clk) { + ret = clk_prepare_enable(qspi->clk); + if (ret) { + dev_err(dev, "failed to prepare clock\n"); + goto qspi_probe_err; + } + qspi->base_clk = clk_get_rate(qspi->clk); + } else { + qspi->base_clk = MSPI_BASE_FREQ; + } + + if (data->has_mspi_rev) { + rev = bcm_qspi_read(qspi, MSPI, MSPI_REV); + /* some older revs do not have a MSPI_REV register */ + if ((rev & 0xff) == 0xff) + rev = 0; + } + + qspi->mspi_maj_rev = (rev >> 4) & 0xf; + qspi->mspi_min_rev = rev & 0xf; + qspi->mspi_spcr3_sysclk = data->has_spcr3_sysclk; + + qspi->max_speed_hz = qspi->base_clk / (bcm_qspi_spbr_min(qspi) * 2); + + /* + * On SW resets it is possible to have the mask still enabled + * Need to disable the mask and clear the status while we init + */ + bcm_qspi_hw_uninit(qspi); + for (val = 0; val < num_irqs; val++) { irq = -1; name = qspi_irq_tab[val].irq_name; @@ -1433,38 +1478,6 @@ int bcm_qspi_probe(struct platform_device *pdev, goto qspi_probe_err; } - /* - * Some SoCs integrate spi controller (e.g., its interrupt bits) - * in specific ways - */ - if (soc_intc) { - qspi->soc_intc = soc_intc; - soc_intc->bcm_qspi_int_set(soc_intc, MSPI_DONE, true); - } else { - qspi->soc_intc = NULL; - } - - ret = clk_prepare_enable(qspi->clk); - if (ret) { - dev_err(dev, "failed to prepare clock\n"); - goto qspi_probe_err; - } - - qspi->base_clk = clk_get_rate(qspi->clk); - - if (data->has_mspi_rev) { - rev = bcm_qspi_read(qspi, MSPI, MSPI_REV); - /* some older revs do not have a MSPI_REV register */ - if ((rev & 0xff) == 0xff) - rev = 0; - } - - qspi->mspi_maj_rev = (rev >> 4) & 0xf; - qspi->mspi_min_rev = rev & 0xf; - qspi->mspi_spcr3_sysclk = data->has_spcr3_sysclk; - - qspi->max_speed_hz = qspi->base_clk / (bcm_qspi_spbr_min(qspi) * 2); - bcm_qspi_hw_init(qspi); init_completion(&qspi->mspi_done); init_completion(&qspi->bspi_done); -- cgit From 9b024201693e397441668cca0d2df7055fe572eb Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Mon, 27 Sep 2021 17:22:13 +0300 Subject: platform/mellanox: mlxreg-io: Fix argument base in kstrtou32() call Change kstrtou32() argument 'base' to be zero instead of 'len'. It works by chance for setting one bit value, but it is not supposed to work in case value passed to mlxreg_io_attr_store() is greater than 1. It works for example, for: echo 1 > /sys/devices/platform/mlxplat/mlxreg-io/hwmon/.../jtag_enable But it will fail for: echo n > /sys/devices/platform/mlxplat/mlxreg-io/hwmon/.../jtag_enable, where n > 1. The flow for input buffer conversion is as below: _kstrtoull(const char *s, unsigned int base, unsigned long long *res) calls: rv = _parse_integer(s, base, &_res); For the second case, where n > 1: - _parse_integer() converts 's' to 'val'. For n=2, 'len' is set to 2 (string buffer is 0x32 0x0a), for n=3 'len' is set to 3 (string buffer 0x33 0x0a), etcetera. - 'base' is equal or greater then '2' (length of input buffer). As a result, _parse_integer() exits with result zero (rv): rv = 0; while (1) { ... if (val >= base)-> (2 >= 2) break; ... rv++; ... } And _kstrtoull() in their turn will fail: if (rv == 0) return -EINVAL; Fixes: 5ec4a8ace06c ("platform/mellanox: Introduce support for Mellanox register access driver") Signed-off-by: Vadim Pasternak Link: https://lore.kernel.org/r/20210927142214.2613929-2-vadimp@nvidia.com Signed-off-by: Hans de Goede --- drivers/platform/mellanox/mlxreg-io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/mellanox/mlxreg-io.c b/drivers/platform/mellanox/mlxreg-io.c index 7646708d57e4..a023ec02126b 100644 --- a/drivers/platform/mellanox/mlxreg-io.c +++ b/drivers/platform/mellanox/mlxreg-io.c @@ -141,7 +141,7 @@ mlxreg_io_attr_store(struct device *dev, struct device_attribute *attr, return -EINVAL; /* Convert buffer to input value. */ - ret = kstrtou32(buf, len, &input_val); + ret = kstrtou32(buf, 0, &input_val); if (ret) return ret; -- cgit From db9cc7d6f95e7d89b0ce57e785cfd9d67a7505d8 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Mon, 27 Sep 2021 17:22:14 +0300 Subject: platform/mellanox: mlxreg-io: Fix read access of n-bytes size attributes Fix shift argument for function rol32(). It should be provided in bits, while was provided in bytes. Fixes: 86148190a7db ("platform/mellanox: mlxreg-io: Add support for complex attributes") Signed-off-by: Vadim Pasternak Link: https://lore.kernel.org/r/20210927142214.2613929-3-vadimp@nvidia.com Signed-off-by: Hans de Goede --- drivers/platform/mellanox/mlxreg-io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/mellanox/mlxreg-io.c b/drivers/platform/mellanox/mlxreg-io.c index a023ec02126b..a916cd89cbbe 100644 --- a/drivers/platform/mellanox/mlxreg-io.c +++ b/drivers/platform/mellanox/mlxreg-io.c @@ -98,7 +98,7 @@ mlxreg_io_get_reg(void *regmap, struct mlxreg_core_data *data, u32 in_val, if (ret) goto access_error; - *regval |= rol32(val, regsize * i); + *regval |= rol32(val, regsize * i * 8); } } -- cgit From 92813dafcd8cae40b6256fd9392a44ecd5c9f505 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 11 Oct 2021 15:23:38 +0200 Subject: platform/x86: dell: Make DELL_WMI_PRIVACY depend on DELL_WMI DELL_WMI_PRIVACY is a feature toggle for the main dell-wmi driver, so it must depend on the Kconfig option which enables the main dell-wmi driver. Fixes: 8af9fa37b8a3 ("platform/x86: dell-privacy: Add support for Dell hardware privacy") Reported-by: Randy Dunlap Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20211011132338.407571-1-hdegoede@redhat.com --- drivers/platform/x86/dell/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig index 42513eab1d06..2fffa57e596e 100644 --- a/drivers/platform/x86/dell/Kconfig +++ b/drivers/platform/x86/dell/Kconfig @@ -167,6 +167,7 @@ config DELL_WMI config DELL_WMI_PRIVACY bool "Dell WMI Hardware Privacy Support" depends on LEDS_TRIGGER_AUDIO = y || DELL_WMI = LEDS_TRIGGER_AUDIO + depends on DELL_WMI help This option adds integration with the "Dell Hardware Privacy" feature of Dell laptops to the dell-wmi driver. -- cgit From 41512e4dc0b84525495e784295092592adb87f1b Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Tue, 28 Sep 2021 03:19:30 -0700 Subject: platform/x86: intel_scu_ipc: Fix busy loop expiry time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The macro IPC_TIMEOUT is already in jiffies (it is also used like that elsewhere in the file when calling wait_for_completion_timeout()). Don’t convert it using helper functions for the purposes of calculating the busy loop expiry time. Fixes: e7b7ab3847c9 (“platform/x86: intel_scu_ipc: Sleeping is fine when polling”) Signed-off-by: Prashant Malani Cc: Benson Leung Reviewed-by: Mika Westerberg Link: https://lore.kernel.org/r/20210928101932.2543937-2-pmalani@chromium.org Signed-off-by: Hans de Goede --- drivers/platform/x86/intel_scu_ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index bfa0cc20750d..cfb249da2a7b 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c @@ -232,7 +232,7 @@ static inline u32 ipc_data_readl(struct intel_scu_ipc_dev *scu, u32 offset) /* Wait till scu status is busy */ static inline int busy_loop(struct intel_scu_ipc_dev *scu) { - unsigned long end = jiffies + msecs_to_jiffies(IPC_TIMEOUT); + unsigned long end = jiffies + IPC_TIMEOUT; do { u32 status; -- cgit From 5c02b581ce84eea240d25c8318a1f65133a04415 Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Tue, 28 Sep 2021 03:19:32 -0700 Subject: platform/x86: intel_scu_ipc: Increase virtual timeout to 10s Commit a7d53dbbc70a ("platform/x86: intel_scu_ipc: Increase virtual timeout from 3 to 5 seconds") states that the recommended timeout range is 5-10 seconds. Adjust the timeout value to the higher of those i.e 10 seconds, to account for situations where the 5 seconds is insufficient for disconnect command success. Signed-off-by: Prashant Malani Cc: Benson Leung Reviewed-by: Mika Westerberg Link: https://lore.kernel.org/r/20210928101932.2543937-3-pmalani@chromium.org Signed-off-by: Hans de Goede --- drivers/platform/x86/intel_scu_ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index cfb249da2a7b..d71a1dce781c 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c @@ -75,7 +75,7 @@ struct intel_scu_ipc_dev { #define IPC_READ_BUFFER 0x90 /* Timeout in jiffies */ -#define IPC_TIMEOUT (5 * HZ) +#define IPC_TIMEOUT (10 * HZ) static struct intel_scu_ipc_dev *ipcdev; /* Only one for now */ static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */ -- cgit From a0c5814b9933f25ecb6de169483c5b88cf632bca Mon Sep 17 00:00:00 2001 From: Prashant Malani Date: Tue, 28 Sep 2021 03:19:34 -0700 Subject: platform/x86: intel_scu_ipc: Update timeout value in comment The comment decribing the IPC timeout hadn't been updated when the actual timeout was changed from 3 to 5 seconds in commit a7d53dbbc70a ("platform/x86: intel_scu_ipc: Increase virtual timeout from 3 to 5 seconds") . Since the value is anyway updated to 10s now, take this opportunity to update the value in the comment too. Signed-off-by: Prashant Malani Cc: Benson Leung Reviewed-by: Mika Westerberg Link: https://lore.kernel.org/r/20210928101932.2543937-4-pmalani@chromium.org Signed-off-by: Hans de Goede --- drivers/platform/x86/intel_scu_ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index d71a1dce781c..7cc9089d1e14 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c @@ -247,7 +247,7 @@ static inline int busy_loop(struct intel_scu_ipc_dev *scu) return -ETIMEDOUT; } -/* Wait till ipc ioc interrupt is received or timeout in 3 HZ */ +/* Wait till ipc ioc interrupt is received or timeout in 10 HZ */ static inline int ipc_wait_for_interrupt(struct intel_scu_ipc_dev *scu) { int status; -- cgit From c0d84d2c7c23e9cf23a5abdda40eeaa79eabfe69 Mon Sep 17 00:00:00 2001 From: Sachi King Date: Sat, 2 Oct 2021 14:18:39 +1000 Subject: platform/x86: amd-pmc: Add alternative acpi id for PMC controller The Surface Laptop 4 AMD has used the AMD0005 to identify this controller instead of using the appropriate ACPI ID AMDI0005. Include AMD0005 in the acpi id list. Link: https://github.com/linux-surface/acpidumps/tree/master/surface_laptop_4_amd Link: https://gist.github.com/nakato/2a1a7df1a45fe680d7a08c583e1bf863 Cc: # 5.14+ Signed-off-by: Sachi King Reviewed-by: Mario Limonciello Link: https://lore.kernel.org/r/20211002041840.2058647-1-nakato@nakato.io Signed-off-by: Hans de Goede --- drivers/platform/x86/amd-pmc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/amd-pmc.c b/drivers/platform/x86/amd-pmc.c index d6a7c896ac86..fc95620101e8 100644 --- a/drivers/platform/x86/amd-pmc.c +++ b/drivers/platform/x86/amd-pmc.c @@ -476,6 +476,7 @@ static const struct acpi_device_id amd_pmc_acpi_ids[] = { {"AMDI0006", 0}, {"AMDI0007", 0}, {"AMD0004", 0}, + {"AMD0005", 0}, { } }; MODULE_DEVICE_TABLE(acpi, amd_pmc_acpi_ids); -- cgit From 0f607d6b227470456a69a37d7c7badea51d52844 Mon Sep 17 00:00:00 2001 From: "Zephaniah E. Loss-Cutler-Hull" Date: Mon, 4 Oct 2021 21:48:55 -0700 Subject: platform/x86: gigabyte-wmi: add support for B550 AORUS ELITE AX V2 This works just fine on my system. Signed-off-by: Zephaniah E. Loss-Cutler-Hull Cc: Link: https://lore.kernel.org/r/20211005044855.1429724-1-zephaniah@gmail.com Signed-off-by: Hans de Goede --- drivers/platform/x86/gigabyte-wmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/gigabyte-wmi.c b/drivers/platform/x86/gigabyte-wmi.c index d53634c8a6e0..658bab4b7964 100644 --- a/drivers/platform/x86/gigabyte-wmi.c +++ b/drivers/platform/x86/gigabyte-wmi.c @@ -141,6 +141,7 @@ static u8 gigabyte_wmi_detect_sensor_usability(struct wmi_device *wdev) static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = { DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M S2H V2"), + DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE AX V2"), DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE"), DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE V2"), DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 GAMING X V2"), -- cgit From c005828744f584bfcd2cf3ed64dfef15a5078960 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Fri, 8 Oct 2021 23:46:08 +0100 Subject: platform/x86: intel_skl_int3472: Correct null check The int3472-discrete driver can enter an error path after initialising int3472->clock.ena_gpio, but before it has registered the clock. This will cause a NULL pointer dereference, because clkdev_drop() is not null aware. Instead of guarding the call to skl_int3472_unregister_clock() by checking for .ena_gpio, check specifically for the presence of the clk_lookup, which will guarantee clkdev_create() has already been called. Bug: https://bugzilla.kernel.org/show_bug.cgi?id=214453 Fixes: 7540599a5ef1 ("platform/x86: intel_skl_int3472: Provide skl_int3472_unregister_clock()") Signed-off-by: Daniel Scally Link: https://lore.kernel.org/r/20211008224608.415949-1-djrscally@gmail.com Signed-off-by: Hans de Goede --- drivers/platform/x86/intel/int3472/intel_skl_int3472_discrete.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/intel/int3472/intel_skl_int3472_discrete.c b/drivers/platform/x86/intel/int3472/intel_skl_int3472_discrete.c index 9fe0a2527e1c..e59d79c7e82f 100644 --- a/drivers/platform/x86/intel/int3472/intel_skl_int3472_discrete.c +++ b/drivers/platform/x86/intel/int3472/intel_skl_int3472_discrete.c @@ -401,7 +401,7 @@ int skl_int3472_discrete_remove(struct platform_device *pdev) gpiod_remove_lookup_table(&int3472->gpios); - if (int3472->clock.ena_gpio) + if (int3472->clock.cl) skl_int3472_unregister_clock(int3472); gpiod_put(int3472->clock.ena_gpio); -- cgit From 7df227847ab562c42d318bceccebb0c911c87b04 Mon Sep 17 00:00:00 2001 From: Shravan S Date: Wed, 6 Oct 2021 13:05:25 +0530 Subject: platform/x86: int1092: Fix non sequential device mode handling SAR information from BIOS may come in non sequential pattern. To overcome the issue, a check is made to extract the right SAR information using the device mode which is currently being used. Remove .owner field if calls are used which set it automatically. Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci Signed-off-by: Shravan S Link: https://lore.kernel.org/r/20211006073525.1332925-1-s.shravan@intel.com Signed-off-by: Hans de Goede Reviewed-by: Hans de Goede --- MAINTAINERS | 2 +- drivers/platform/x86/intel/int1092/intel_sar.c | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index eeb4c70b3d5b..6cfad2bf9d81 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9302,7 +9302,7 @@ S: Maintained F: drivers/platform/x86/intel/atomisp2/led.c INTEL BIOS SAR INT1092 DRIVER -M: Shravan S +M: Shravan Sudhakar M: Intel Corporation L: platform-driver-x86@vger.kernel.org S: Maintained diff --git a/drivers/platform/x86/intel/int1092/intel_sar.c b/drivers/platform/x86/intel/int1092/intel_sar.c index 379560fe5df9..e03943e6380a 100644 --- a/drivers/platform/x86/intel/int1092/intel_sar.c +++ b/drivers/platform/x86/intel/int1092/intel_sar.c @@ -42,12 +42,20 @@ static void update_sar_data(struct wwan_sar_context *context) if (config->device_mode_info && context->sar_data.device_mode < config->total_dev_mode) { - struct wwan_device_mode_info *dev_mode = - &config->device_mode_info[context->sar_data.device_mode]; - - context->sar_data.antennatable_index = dev_mode->antennatable_index; - context->sar_data.bandtable_index = dev_mode->bandtable_index; - context->sar_data.sartable_index = dev_mode->sartable_index; + int itr = 0; + + for (itr = 0; itr < config->total_dev_mode; itr++) { + if (context->sar_data.device_mode == + config->device_mode_info[itr].device_mode) { + struct wwan_device_mode_info *dev_mode = + &config->device_mode_info[itr]; + + context->sar_data.antennatable_index = dev_mode->antennatable_index; + context->sar_data.bandtable_index = dev_mode->bandtable_index; + context->sar_data.sartable_index = dev_mode->sartable_index; + break; + } + } } } @@ -305,7 +313,6 @@ static struct platform_driver sar_driver = { .remove = sar_remove, .driver = { .name = DRVNAME, - .owner = THIS_MODULE, .acpi_match_table = ACPI_PTR(sar_device_ids) } }; @@ -313,4 +320,4 @@ module_platform_driver(sar_driver); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Platform device driver for INTEL MODEM BIOS SAR"); -MODULE_AUTHOR("Shravan S "); +MODULE_AUTHOR("Shravan Sudhakar "); -- cgit From ce46ae0c3e31400dc89d1e4620a812647cab9c72 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Fri, 1 Oct 2021 18:48:49 +0300 Subject: fs/ntfs3: Keep prealloc for all types of files Before we haven't kept prealloc for sparse files because we thought that it will speed up create / write operations. It lead to situation, when user reserved some space for sparse file, filled volume, and wasn't able to write in reserved file. With this commit we keep prealloc. Now xfstest generic/274 pass. Fixes: be71b5cba2e6 ("fs/ntfs3: Add attrib operations") Signed-off-by: Konstantin Komarov --- fs/ntfs3/attrib.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index 8a00fa978f5f..e8c00dda42ad 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -447,11 +447,8 @@ again: again_1: align = sbi->cluster_size; - if (is_ext) { + if (is_ext) align <<= attr_b->nres.c_unit; - if (is_attr_sparsed(attr_b)) - keep_prealloc = false; - } old_valid = le64_to_cpu(attr_b->nres.valid_size); old_size = le64_to_cpu(attr_b->nres.data_size); @@ -461,9 +458,6 @@ again_1: new_alloc = (new_size + align - 1) & ~(u64)(align - 1); new_alen = new_alloc >> cluster_bits; - if (keep_prealloc && is_ext) - keep_prealloc = false; - if (keep_prealloc && new_size < old_size) { attr_b->nres.data_size = cpu_to_le64(new_size); mi_b->dirty = true; -- cgit From 228af5a4fa3a8293bd8b7ac5cf59548ee29627bf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 10 Oct 2021 09:55:46 +0200 Subject: ALSA: pcm: Workaround for a wrong offset in SYNC_PTR compat ioctl Michael Forney reported an incorrect padding type that was defined in the commit 80fe7430c708 ("ALSA: add new 32-bit layout for snd_pcm_mmap_status/control") for PCM control mmap data. His analysis is correct, and this caused the misplacements of PCM control data on 32bit arch and 32bit compat mode. The bug is that the __pad2 definition in __snd_pcm_mmap_control64 struct was wrongly with __pad_before_uframe, which should have been __pad_after_uframe instead. This struct is used in SYNC_PTR ioctl and control mmap. Basically this bug leads to two problems: - The offset of avail_min field becomes wrong, it's placed right after appl_ptr without padding on little-endian - When appl_ptr and avail_min are read as 64bit values in kernel side, the values become either zero or corrupted (mixed up) One good news is that, because both user-space and kernel misunderstand the wrong offset, at least, 32bit application running on 32bit kernel works as is. Also, 64bit applications are unaffected because the padding size is zero. The remaining problem is the 32bit compat mode; as mentioned in the above, avail_min is placed right after appl_ptr on little-endian archs, 64bit kernel reads bogus values for appl_ptr updates, which may lead to streaming bugs like jumping, XRUN or whatever unexpected. (However, we haven't heard any serious bug reports due to this over years, so practically seen, it's fairly safe to assume that the impact by this bug is limited.) Ideally speaking, we should correct the wrong mmap status control definition. But this would cause again incompatibility with the existing binaries, and fixing it (e.g. by renumbering ioctls) would be really messy. So, as of this patch, we only correct the behavior of 32bit compat mode and keep the rest as is. Namely, the SYNC_PTR ioctl is now handled differently in compat mode to read/write the 32bit values at the right offsets. The control mmap of 32bit apps on 64bit kernels has been already disabled (which is likely rather an overlook, but this worked fine at this time :), so covering SYNC_PTR ioctl should suffice as a fallback. Fixes: 80fe7430c708 ("ALSA: add new 32-bit layout for snd_pcm_mmap_status/control") Reported-by: Michael Forney Reviewed-by: Arnd Bergmann Cc: Cc: Rich Felker Link: https://lore.kernel.org/r/29QBMJU8DE71E.2YZSH8IHT5HMH@mforney.org Link: https://lore.kernel.org/r/20211010075546.23220-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/pcm_compat.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index a59de24695ec..dfe5a64e19d2 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -468,6 +468,76 @@ static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream, } #endif /* CONFIG_X86_X32 */ +#ifdef __BIG_ENDIAN +typedef char __pad_before_u32[4]; +typedef char __pad_after_u32[0]; +#else +typedef char __pad_before_u32[0]; +typedef char __pad_after_u32[4]; +#endif + +/* PCM 2.0.15 API definition had a bug in mmap control; it puts the avail_min + * at the wrong offset due to a typo in padding type. + * The bug hits only 32bit. + * A workaround for incorrect read/write is needed only in 32bit compat mode. + */ +struct __snd_pcm_mmap_control64_buggy { + __pad_before_u32 __pad1; + __u32 appl_ptr; + __pad_before_u32 __pad2; /* SiC! here is the bug */ + __pad_before_u32 __pad3; + __u32 avail_min; + __pad_after_uframe __pad4; +}; + +static int snd_pcm_ioctl_sync_ptr_buggy(struct snd_pcm_substream *substream, + struct snd_pcm_sync_ptr __user *_sync_ptr) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_pcm_sync_ptr sync_ptr; + struct __snd_pcm_mmap_control64_buggy *sync_cp; + volatile struct snd_pcm_mmap_status *status; + volatile struct snd_pcm_mmap_control *control; + int err; + + memset(&sync_ptr, 0, sizeof(sync_ptr)); + sync_cp = (struct __snd_pcm_mmap_control64_buggy *)&sync_ptr.c.control; + if (get_user(sync_ptr.flags, (unsigned __user *)&(_sync_ptr->flags))) + return -EFAULT; + if (copy_from_user(sync_cp, &(_sync_ptr->c.control), sizeof(*sync_cp))) + return -EFAULT; + status = runtime->status; + control = runtime->control; + if (sync_ptr.flags & SNDRV_PCM_SYNC_PTR_HWSYNC) { + err = snd_pcm_hwsync(substream); + if (err < 0) + return err; + } + snd_pcm_stream_lock_irq(substream); + if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) { + err = pcm_lib_apply_appl_ptr(substream, sync_cp->appl_ptr); + if (err < 0) { + snd_pcm_stream_unlock_irq(substream); + return err; + } + } else { + sync_cp->appl_ptr = control->appl_ptr; + } + if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) + control->avail_min = sync_cp->avail_min; + else + sync_cp->avail_min = control->avail_min; + sync_ptr.s.status.state = status->state; + sync_ptr.s.status.hw_ptr = status->hw_ptr; + sync_ptr.s.status.tstamp = status->tstamp; + sync_ptr.s.status.suspended_state = status->suspended_state; + sync_ptr.s.status.audio_tstamp = status->audio_tstamp; + snd_pcm_stream_unlock_irq(substream); + if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr))) + return -EFAULT; + return 0; +} + /* */ enum { @@ -537,7 +607,7 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l if (in_x32_syscall()) return snd_pcm_ioctl_sync_ptr_x32(substream, argp); #endif /* CONFIG_X86_X32 */ - return snd_pcm_common_ioctl(file, substream, cmd, argp); + return snd_pcm_ioctl_sync_ptr_buggy(substream, argp); case SNDRV_PCM_IOCTL_HW_REFINE32: return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); case SNDRV_PCM_IOCTL_HW_PARAMS32: -- cgit From 9b75450d6c580100611743fa7e690ea3cb47cd4a Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Tue, 28 Sep 2021 19:00:30 +0300 Subject: fs/ntfs3: Fix memory leak if fill_super failed In ntfs_init_fs_context we allocate memory in fc->s_fs_info. In case of failed mount we must free it in ntfs_fill_super. We can't do it in ntfs_fs_free, because ntfs_fs_free called with fc->s_fs_info == NULL. fc->s_fs_info became NULL in sget_fc. Signed-off-by: Konstantin Komarov --- fs/ntfs3/super.c | 90 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 34 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 705d8b4f4894..d41d76979e12 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -908,7 +908,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) if (IS_ERR(sbi->options->nls)) { sbi->options->nls = NULL; errorf(fc, "Cannot load nls %s", sbi->options->nls_name); - return -EINVAL; + err = -EINVAL; + goto out; } rq = bdev_get_queue(bdev); @@ -922,7 +923,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) err = ntfs_init_from_boot(sb, rq ? queue_logical_block_size(rq) : 512, bdev->bd_inode->i_size); if (err) - return err; + goto out; /* * Load $Volume. This should be done before $LogFile @@ -933,7 +934,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) inode = ntfs_iget5(sb, &ref, &NAME_VOLUME); if (IS_ERR(inode)) { ntfs_err(sb, "Failed to load $Volume."); - return PTR_ERR(inode); + err = PTR_ERR(inode); + goto out; } ni = ntfs_i(inode); @@ -954,19 +956,19 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) } else { /* Should we break mounting here? */ //err = -EINVAL; - //goto out; + //goto put_inode_out; } attr = ni_find_attr(ni, attr, NULL, ATTR_VOL_INFO, NULL, 0, NULL, NULL); if (!attr || is_attr_ext(attr)) { err = -EINVAL; - goto out; + goto put_inode_out; } info = resident_data_ex(attr, SIZEOF_ATTRIBUTE_VOLUME_INFO); if (!info) { err = -EINVAL; - goto out; + goto put_inode_out; } sbi->volume.major_ver = info->major_ver; @@ -980,7 +982,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) inode = ntfs_iget5(sb, &ref, &NAME_MIRROR); if (IS_ERR(inode)) { ntfs_err(sb, "Failed to load $MFTMirr."); - return PTR_ERR(inode); + err = PTR_ERR(inode); + goto out; } sbi->mft.recs_mirr = @@ -994,14 +997,15 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) inode = ntfs_iget5(sb, &ref, &NAME_LOGFILE); if (IS_ERR(inode)) { ntfs_err(sb, "Failed to load \x24LogFile."); - return PTR_ERR(inode); + err = PTR_ERR(inode); + goto out; } ni = ntfs_i(inode); err = ntfs_loadlog_and_replay(ni, sbi); if (err) - goto out; + goto put_inode_out; iput(inode); @@ -1009,14 +1013,16 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) if (!sb_rdonly(sb)) { ntfs_warn(sb, "failed to replay log file. Can't mount rw!"); - return -EINVAL; + err = -EINVAL; + goto out; } } else if (sbi->volume.flags & VOLUME_FLAG_DIRTY) { if (!sb_rdonly(sb) && !sbi->options->force) { ntfs_warn( sb, "volume is dirty and \"force\" flag is not set!"); - return -EINVAL; + err = -EINVAL; + goto out; } } @@ -1027,7 +1033,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) inode = ntfs_iget5(sb, &ref, &NAME_MFT); if (IS_ERR(inode)) { ntfs_err(sb, "Failed to load $MFT."); - return PTR_ERR(inode); + err = PTR_ERR(inode); + goto out; } ni = ntfs_i(inode); @@ -1038,11 +1045,11 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) err = wnd_init(&sbi->mft.bitmap, sb, tt); if (err) - goto out; + goto put_inode_out; err = ni_load_all_mi(ni); if (err) - goto out; + goto put_inode_out; sbi->mft.ni = ni; @@ -1052,7 +1059,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) inode = ntfs_iget5(sb, &ref, &NAME_BADCLUS); if (IS_ERR(inode)) { ntfs_err(sb, "Failed to load $BadClus."); - return PTR_ERR(inode); + err = PTR_ERR(inode); + goto out; } ni = ntfs_i(inode); @@ -1075,13 +1083,14 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) inode = ntfs_iget5(sb, &ref, &NAME_BITMAP); if (IS_ERR(inode)) { ntfs_err(sb, "Failed to load $Bitmap."); - return PTR_ERR(inode); + err = PTR_ERR(inode); + goto out; } #ifndef CONFIG_NTFS3_64BIT_CLUSTER if (inode->i_size >> 32) { err = -EINVAL; - goto out; + goto put_inode_out; } #endif @@ -1089,21 +1098,21 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) tt = sbi->used.bitmap.nbits; if (inode->i_size < bitmap_size(tt)) { err = -EINVAL; - goto out; + goto put_inode_out; } /* Not necessary. */ sbi->used.bitmap.set_tail = true; err = wnd_init(&sbi->used.bitmap, sb, tt); if (err) - goto out; + goto put_inode_out; iput(inode); /* Compute the MFT zone. */ err = ntfs_refresh_zone(sbi); if (err) - return err; + goto out; /* Load $AttrDef. */ ref.low = cpu_to_le32(MFT_REC_ATTR); @@ -1111,18 +1120,19 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) inode = ntfs_iget5(sb, &ref, &NAME_ATTRDEF); if (IS_ERR(inode)) { ntfs_err(sb, "Failed to load $AttrDef -> %d", err); - return PTR_ERR(inode); + err = PTR_ERR(inode); + goto out; } if (inode->i_size < sizeof(struct ATTR_DEF_ENTRY)) { err = -EINVAL; - goto out; + goto put_inode_out; } bytes = inode->i_size; sbi->def_table = t = kmalloc(bytes, GFP_NOFS); if (!t) { err = -ENOMEM; - goto out; + goto put_inode_out; } for (done = idx = 0; done < bytes; done += PAGE_SIZE, idx++) { @@ -1131,7 +1141,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) if (IS_ERR(page)) { err = PTR_ERR(page); - goto out; + goto put_inode_out; } memcpy(Add2Ptr(t, done), page_address(page), min(PAGE_SIZE, tail)); @@ -1139,7 +1149,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) if (!idx && ATTR_STD != t->type) { err = -EINVAL; - goto out; + goto put_inode_out; } } @@ -1173,12 +1183,13 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) inode = ntfs_iget5(sb, &ref, &NAME_UPCASE); if (IS_ERR(inode)) { ntfs_err(sb, "Failed to load $UpCase."); - return PTR_ERR(inode); + err = PTR_ERR(inode); + goto out; } if (inode->i_size != 0x10000 * sizeof(short)) { err = -EINVAL; - goto out; + goto put_inode_out; } for (idx = 0; idx < (0x10000 * sizeof(short) >> PAGE_SHIFT); idx++) { @@ -1188,7 +1199,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) if (IS_ERR(page)) { err = PTR_ERR(page); - goto out; + goto put_inode_out; } src = page_address(page); @@ -1214,7 +1225,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc) /* Load $Secure. */ err = ntfs_security_init(sbi); if (err) - return err; + goto out; /* Load $Extend. */ err = ntfs_extend_init(sbi); @@ -1239,19 +1250,30 @@ load_root: inode = ntfs_iget5(sb, &ref, &NAME_ROOT); if (IS_ERR(inode)) { ntfs_err(sb, "Failed to load root."); - return PTR_ERR(inode); + err = PTR_ERR(inode); + goto out; } sb->s_root = d_make_root(inode); - if (!sb->s_root) - return -ENOMEM; + if (!sb->s_root) { + err = -ENOMEM; + goto put_inode_out; + } fc->fs_private = NULL; - fc->s_fs_info = NULL; return 0; -out: + +put_inode_out: iput(inode); +out: + /* + * Free resources here. + * ntfs_fs_free will be called with fc->s_fs_info = NULL + */ + put_ntfs(sbi); + sb->s_fs_info = NULL; + return err; } -- cgit From e02083f0bcc250c0556ec9e6f7ddb74220c72572 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Mon, 11 Oct 2021 17:13:38 +0100 Subject: drm/i915: remember to call i915_sw_fence_fini MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seems to fix some object-debug splat which appeared while debugging something unrelated. v2: s/guc_blocked/guc_state.blocked/ Signed-off-by: Matthew Auld Cc: Ville Syrjälä Cc: Matthew Brost Tested-by: Ville Syrjälä Reviewed-by: Matthew Brost Fixes: 62eaf0ae217d ("drm/i915/guc: Support request cancellation") Link: https://patchwork.freedesktop.org/patch/msgid/20210924144646.4096402-1-matthew.auld@intel.com (cherry picked from commit d576b31bdece7b5034047cbe21170e948198d32f) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/gt/intel_context.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index e866105dd174..17ca4dc4d0cb 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -421,6 +421,7 @@ void intel_context_fini(struct intel_context *ce) mutex_destroy(&ce->pin_mutex); i915_active_fini(&ce->active); + i915_sw_fence_fini(&ce->guc_blocked); } void i915_context_module_exit(void) -- cgit From 2c69078851b3d7495eb191158d0bcb9c91a6d148 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 4 Oct 2021 18:22:45 +0300 Subject: fs/ntfs3: Rework ntfs_utf16_to_nls Now ntfs_utf16_to_nls takes length as one of arguments. If length of symlink > 255, then we tried to convert length of symlink +- some random number. Now 255 symbols limit was removed. Signed-off-by: Konstantin Komarov --- fs/ntfs3/dir.c | 19 ++++++++----------- fs/ntfs3/ntfs_fs.h | 2 +- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/fs/ntfs3/dir.c b/fs/ntfs3/dir.c index 785e72d4392e..fb438d604040 100644 --- a/fs/ntfs3/dir.c +++ b/fs/ntfs3/dir.c @@ -15,11 +15,10 @@ #include "ntfs_fs.h" /* Convert little endian UTF-16 to NLS string. */ -int ntfs_utf16_to_nls(struct ntfs_sb_info *sbi, const struct le_str *uni, +int ntfs_utf16_to_nls(struct ntfs_sb_info *sbi, const __le16 *name, u32 len, u8 *buf, int buf_len) { - int ret, uni_len, warn; - const __le16 *ip; + int ret, warn; u8 *op; struct nls_table *nls = sbi->options->nls; @@ -27,18 +26,16 @@ int ntfs_utf16_to_nls(struct ntfs_sb_info *sbi, const struct le_str *uni, if (!nls) { /* UTF-16 -> UTF-8 */ - ret = utf16s_to_utf8s((wchar_t *)uni->name, uni->len, - UTF16_LITTLE_ENDIAN, buf, buf_len); + ret = utf16s_to_utf8s(name, len, UTF16_LITTLE_ENDIAN, buf, + buf_len); buf[ret] = '\0'; return ret; } - ip = uni->name; op = buf; - uni_len = uni->len; warn = 0; - while (uni_len--) { + while (len--) { u16 ec; int charlen; char dump[5]; @@ -49,7 +46,7 @@ int ntfs_utf16_to_nls(struct ntfs_sb_info *sbi, const struct le_str *uni, break; } - ec = le16_to_cpu(*ip++); + ec = le16_to_cpu(*name++); charlen = nls->uni2char(ec, op, buf_len); if (charlen > 0) { @@ -304,8 +301,8 @@ static inline int ntfs_filldir(struct ntfs_sb_info *sbi, struct ntfs_inode *ni, if (sbi->options->nohidden && (fname->dup.fa & FILE_ATTRIBUTE_HIDDEN)) return 0; - name_len = ntfs_utf16_to_nls(sbi, (struct le_str *)&fname->name_len, - name, PATH_MAX); + name_len = ntfs_utf16_to_nls(sbi, fname->name, fname->name_len, name, + PATH_MAX); if (name_len <= 0) { ntfs_warn(sbi->sb, "failed to convert name for inode %lx.", ino); diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 38b7c1a9dc52..9277b552f257 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -475,7 +475,7 @@ bool are_bits_set(const ulong *map, size_t bit, size_t nbits); size_t get_set_bits_ex(const ulong *map, size_t bit, size_t nbits); /* Globals from dir.c */ -int ntfs_utf16_to_nls(struct ntfs_sb_info *sbi, const struct le_str *uni, +int ntfs_utf16_to_nls(struct ntfs_sb_info *sbi, const __le16 *name, u32 len, u8 *buf, int buf_len); int ntfs_nls_to_utf16(struct ntfs_sb_info *sbi, const u8 *name, u32 name_len, struct cpu_str *uni, u32 max_ulen, -- cgit From 4dbe8e4413d70ac4f163592d69eef74d7824783a Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 4 Oct 2021 18:59:55 +0300 Subject: fs/ntfs3: Refactor ntfs_readlink_hlp Rename some variables. Returned err by default is EINVAL. Signed-off-by: Konstantin Komarov --- fs/ntfs3/inode.c | 91 ++++++++++++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 7dd162f6a7e2..d618b0573533 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -1763,15 +1763,15 @@ void ntfs_evict_inode(struct inode *inode) static noinline int ntfs_readlink_hlp(struct inode *inode, char *buffer, int buflen) { - int i, err = 0; + int i, err = -EINVAL; struct ntfs_inode *ni = ntfs_i(inode); struct super_block *sb = inode->i_sb; struct ntfs_sb_info *sbi = sb->s_fs_info; - u64 i_size = inode->i_size; - u16 nlen = 0; + u64 size; + u16 ulen = 0; void *to_free = NULL; struct REPARSE_DATA_BUFFER *rp; - struct le_str *uni; + const __le16 *uname; struct ATTRIB *attr; /* Reparse data present. Try to parse it. */ @@ -1780,68 +1780,64 @@ static noinline int ntfs_readlink_hlp(struct inode *inode, char *buffer, *buffer = 0; - /* Read into temporal buffer. */ - if (i_size > sbi->reparse.max_size || i_size <= sizeof(u32)) { - err = -EINVAL; - goto out; - } - attr = ni_find_attr(ni, NULL, NULL, ATTR_REPARSE, NULL, 0, NULL, NULL); - if (!attr) { - err = -EINVAL; + if (!attr) goto out; - } if (!attr->non_res) { - rp = resident_data_ex(attr, i_size); - if (!rp) { - err = -EINVAL; + rp = resident_data_ex(attr, sizeof(struct REPARSE_DATA_BUFFER)); + if (!rp) goto out; - } + size = le32_to_cpu(attr->res.data_size); } else { - rp = kmalloc(i_size, GFP_NOFS); + size = le64_to_cpu(attr->nres.data_size); + rp = NULL; + } + + if (size > sbi->reparse.max_size || size <= sizeof(u32)) + goto out; + + if (!rp) { + rp = kmalloc(size, GFP_NOFS); if (!rp) { err = -ENOMEM; goto out; } to_free = rp; - err = ntfs_read_run_nb(sbi, &ni->file.run, 0, rp, i_size, NULL); + /* Read into temporal buffer. */ + err = ntfs_read_run_nb(sbi, &ni->file.run, 0, rp, size, NULL); if (err) goto out; } - err = -EINVAL; - /* Microsoft Tag. */ switch (rp->ReparseTag) { case IO_REPARSE_TAG_MOUNT_POINT: /* Mount points and junctions. */ /* Can we use 'Rp->MountPointReparseBuffer.PrintNameLength'? */ - if (i_size <= offsetof(struct REPARSE_DATA_BUFFER, - MountPointReparseBuffer.PathBuffer)) + if (size <= offsetof(struct REPARSE_DATA_BUFFER, + MountPointReparseBuffer.PathBuffer)) goto out; - uni = Add2Ptr(rp, - offsetof(struct REPARSE_DATA_BUFFER, - MountPointReparseBuffer.PathBuffer) + - le16_to_cpu(rp->MountPointReparseBuffer - .PrintNameOffset) - - 2); - nlen = le16_to_cpu(rp->MountPointReparseBuffer.PrintNameLength); + uname = Add2Ptr(rp, + offsetof(struct REPARSE_DATA_BUFFER, + MountPointReparseBuffer.PathBuffer) + + le16_to_cpu(rp->MountPointReparseBuffer + .PrintNameOffset)); + ulen = le16_to_cpu(rp->MountPointReparseBuffer.PrintNameLength); break; case IO_REPARSE_TAG_SYMLINK: /* FolderSymbolicLink */ /* Can we use 'Rp->SymbolicLinkReparseBuffer.PrintNameLength'? */ - if (i_size <= offsetof(struct REPARSE_DATA_BUFFER, - SymbolicLinkReparseBuffer.PathBuffer)) + if (size <= offsetof(struct REPARSE_DATA_BUFFER, + SymbolicLinkReparseBuffer.PathBuffer)) goto out; - uni = Add2Ptr(rp, - offsetof(struct REPARSE_DATA_BUFFER, - SymbolicLinkReparseBuffer.PathBuffer) + - le16_to_cpu(rp->SymbolicLinkReparseBuffer - .PrintNameOffset) - - 2); - nlen = le16_to_cpu( + uname = Add2Ptr( + rp, offsetof(struct REPARSE_DATA_BUFFER, + SymbolicLinkReparseBuffer.PathBuffer) + + le16_to_cpu(rp->SymbolicLinkReparseBuffer + .PrintNameOffset)); + ulen = le16_to_cpu( rp->SymbolicLinkReparseBuffer.PrintNameLength); break; @@ -1873,29 +1869,28 @@ static noinline int ntfs_readlink_hlp(struct inode *inode, char *buffer, goto out; } if (!IsReparseTagNameSurrogate(rp->ReparseTag) || - i_size <= sizeof(struct REPARSE_POINT)) { + size <= sizeof(struct REPARSE_POINT)) { goto out; } /* Users tag. */ - uni = Add2Ptr(rp, sizeof(struct REPARSE_POINT) - 2); - nlen = le16_to_cpu(rp->ReparseDataLength) - + uname = Add2Ptr(rp, sizeof(struct REPARSE_POINT)); + ulen = le16_to_cpu(rp->ReparseDataLength) - sizeof(struct REPARSE_POINT); } /* Convert nlen from bytes to UNICODE chars. */ - nlen >>= 1; + ulen >>= 1; /* Check that name is available. */ - if (!nlen || &uni->name[nlen] > (__le16 *)Add2Ptr(rp, i_size)) + if (!ulen || uname + ulen > (__le16 *)Add2Ptr(rp, size)) goto out; /* If name is already zero terminated then truncate it now. */ - if (!uni->name[nlen - 1]) - nlen -= 1; - uni->len = nlen; + if (!uname[ulen - 1]) + ulen -= 1; - err = ntfs_utf16_to_nls(sbi, uni, buffer, buflen); + err = ntfs_utf16_to_nls(sbi, uname, ulen, buffer, buflen); if (err < 0) goto out; -- cgit From 14a981193e409d8ca3f89768cfbd7a9a516d9927 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 4 Oct 2021 18:52:24 +0300 Subject: fs/ntfs3: Refactor ntfs_create_inode Set size for symlink, so we don't need to calculate it on the fly. Signed-off-by: Konstantin Komarov --- fs/ntfs3/inode.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index d618b0573533..bdebbbd53e76 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -1488,7 +1488,10 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns, asize = ALIGN(SIZEOF_RESIDENT + nsize, 8); t16 = PtrOffset(rec, attr); - /* 0x78 - the size of EA + EAINFO to store WSL */ + /* + * Below function 'ntfs_save_wsl_perm' requires 0x78 bytes. + * It is good idea to keep extened attributes resident. + */ if (asize + t16 + 0x78 + 8 > sbi->record_size) { CLST alen; CLST clst = bytes_to_cluster(sbi, nsize); @@ -1523,14 +1526,14 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns, } asize = SIZEOF_NONRESIDENT + ALIGN(err, 8); - inode->i_size = nsize; } else { attr->res.data_off = SIZEOF_RESIDENT_LE; attr->res.data_size = cpu_to_le32(nsize); memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), rp, nsize); - inode->i_size = nsize; nsize = 0; } + /* Size of symlink equals the length of input string. */ + inode->i_size = size; attr->size = cpu_to_le32(asize); @@ -1567,6 +1570,8 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns, inode->i_op = &ntfs_link_inode_operations; inode->i_fop = NULL; inode->i_mapping->a_ops = &ntfs_aops; + inode->i_size = size; + inode_nohighmem(inode); } else if (S_ISREG(mode)) { inode->i_op = &ntfs_file_inode_operations; inode->i_fop = &ntfs_file_operations; -- cgit From cd4c76ff807c1afeed89f1b7e311760c0e296349 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Tue, 5 Oct 2021 19:08:08 +0300 Subject: fs/ntfs3: Refactor ni_parse_reparse Change argument from void* to struct REPARSE_DATA_BUFFER* We copy data to buffer, so we can read it later in ntfs_read_mft. Signed-off-by: Konstantin Komarov --- fs/ntfs3/frecord.c | 9 +++++---- fs/ntfs3/ntfs_fs.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index 007602badd90..ecb965e4afd0 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -1710,18 +1710,16 @@ out: /* * ni_parse_reparse * - * Buffer is at least 24 bytes. + * buffer - memory for reparse buffer header */ enum REPARSE_SIGN ni_parse_reparse(struct ntfs_inode *ni, struct ATTRIB *attr, - void *buffer) + struct REPARSE_DATA_BUFFER *buffer) { const struct REPARSE_DATA_BUFFER *rp = NULL; u8 bits; u16 len; typeof(rp->CompressReparseBuffer) *cmpr; - static_assert(sizeof(struct REPARSE_DATA_BUFFER) <= 24); - /* Try to estimate reparse point. */ if (!attr->non_res) { rp = resident_data_ex(attr, sizeof(struct REPARSE_DATA_BUFFER)); @@ -1807,6 +1805,9 @@ enum REPARSE_SIGN ni_parse_reparse(struct ntfs_inode *ni, struct ATTRIB *attr, return REPARSE_NONE; } + if (buffer != rp) + memcpy(buffer, rp, sizeof(struct REPARSE_DATA_BUFFER)); + /* Looks like normal symlink. */ return REPARSE_LINK; } diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h index 9277b552f257..e95d93c683ed 100644 --- a/fs/ntfs3/ntfs_fs.h +++ b/fs/ntfs3/ntfs_fs.h @@ -547,7 +547,7 @@ struct ATTR_FILE_NAME *ni_fname_type(struct ntfs_inode *ni, u8 name_type, struct ATTR_LIST_ENTRY **entry); int ni_new_attr_flags(struct ntfs_inode *ni, enum FILE_ATTRIBUTE new_fa); enum REPARSE_SIGN ni_parse_reparse(struct ntfs_inode *ni, struct ATTRIB *attr, - void *buffer); + struct REPARSE_DATA_BUFFER *buffer); int ni_write_inode(struct inode *inode, int sync, const char *hint); #define _ni_write_inode(i, w) ni_write_inode(i, w, __func__) int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, -- cgit From 22b05f1ac0332cb47701649206997d8d9a1a7f24 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Tue, 5 Oct 2021 19:33:26 +0300 Subject: fs/ntfs3: Refactor ntfs_read_mft Don't save size of attribute reparse point as size of symlink. Signed-off-by: Konstantin Komarov --- fs/ntfs3/inode.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index bdebbbd53e76..859951d785cb 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -222,9 +222,6 @@ next_attr: if (!attr->non_res) { ni->i_valid = inode->i_size = rsize; inode_set_bytes(inode, rsize); - t32 = asize; - } else { - t32 = le16_to_cpu(attr->nres.run_off); } mode = S_IFREG | (0777 & sbi->options->fs_fmask_inv); @@ -313,17 +310,14 @@ next_attr: rp_fa = ni_parse_reparse(ni, attr, &rp); switch (rp_fa) { case REPARSE_LINK: - if (!attr->non_res) { - inode->i_size = rsize; - inode_set_bytes(inode, rsize); - t32 = asize; - } else { - inode->i_size = - le64_to_cpu(attr->nres.data_size); - t32 = le16_to_cpu(attr->nres.run_off); - } + /* + * Normal symlink. + * Assume one unicode symbol == one utf8. + */ + inode->i_size = le16_to_cpu(rp.SymbolicLinkReparseBuffer + .PrintNameLength) / + sizeof(u16); - /* Looks like normal symlink. */ ni->i_valid = inode->i_size; /* Clear directory bit. */ @@ -420,7 +414,7 @@ end_enum: ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY; inode->i_op = &ntfs_link_inode_operations; inode->i_fop = NULL; - inode_nohighmem(inode); // ?? + inode_nohighmem(inode); } else if (S_ISREG(mode)) { ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY; inode->i_op = &ntfs_file_inode_operations; -- cgit From 57116ce17b04fde2fe30f0859df69d8dbe5809f6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 6 Oct 2021 13:58:52 +0200 Subject: workqueue: fix state-dump console deadlock Console drivers often queue work while holding locks also taken in their console write paths, something which can lead to deadlocks on SMP when dumping workqueue state (e.g. sysrq-t or on suspend failures). For serial console drivers this could look like: CPU0 CPU1 ---- ---- show_workqueue_state(); lock(&pool->lock); lock(&port->lock); schedule_work(); lock(&pool->lock); printk(); lock(console_owner); lock(&port->lock); where workqueues are, for example, used to push data to the line discipline, process break signals and handle modem-status changes. Line disciplines and serdev drivers can also queue work on write-wakeup notifications, etc. Reworking every console driver to avoid queuing work while holding locks also taken in their write paths would complicate drivers and is neither desirable or feasible. Instead use the deferred-printk mechanism to avoid printing while holding pool locks when dumping workqueue state. Note that there are a few WARN_ON() assertions in the workqueue code which could potentially also trigger a deadlock. Hopefully the ongoing printk rework will provide a general solution for this eventually. This was originally reported after a lockdep splat when executing sysrq-t with the imx serial driver. Fixes: 3494fc30846d ("workqueue: dump workqueues on sysrq-t") Cc: stable@vger.kernel.org # 4.0 Reported-by: Fabio Estevam Tested-by: Fabio Estevam Signed-off-by: Johan Hovold Reviewed-by: John Ogness Signed-off-by: Tejun Heo --- kernel/workqueue.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 33a6b4a2443d..1b3eb1e9531f 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -4830,8 +4830,16 @@ void show_workqueue_state(void) for_each_pwq(pwq, wq) { raw_spin_lock_irqsave(&pwq->pool->lock, flags); - if (pwq->nr_active || !list_empty(&pwq->inactive_works)) + if (pwq->nr_active || !list_empty(&pwq->inactive_works)) { + /* + * Defer printing to avoid deadlocks in console + * drivers that queue work while holding locks + * also taken in their write paths. + */ + printk_deferred_enter(); show_pwq(pwq); + printk_deferred_exit(); + } raw_spin_unlock_irqrestore(&pwq->pool->lock, flags); /* * We could be printing a lot from atomic context, e.g. @@ -4849,7 +4857,12 @@ void show_workqueue_state(void) raw_spin_lock_irqsave(&pool->lock, flags); if (pool->nr_workers == pool->nr_idle) goto next_pool; - + /* + * Defer printing to avoid deadlocks in console drivers that + * queue work while holding locks also taken in their write + * paths. + */ + printk_deferred_enter(); pr_info("pool %d:", pool->id); pr_cont_pool_info(pool); pr_cont(" hung=%us workers=%d", @@ -4864,6 +4877,7 @@ void show_workqueue_state(void) first = false; } pr_cont("\n"); + printk_deferred_exit(); next_pool: raw_spin_unlock_irqrestore(&pool->lock, flags); /* -- cgit From 711885906b5c2df90746a51f4cd674f1ab9fbb1d Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 6 Oct 2021 19:34:55 +0200 Subject: x86/Kconfig: Do not enable AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT automatically This Kconfig option was added initially so that memory encryption is enabled by default on machines which support it. However, devices which have DMA masks that are less than the bit position of the encryption bit, aka C-bit, require the use of an IOMMU or the use of SWIOTLB. If the IOMMU is disabled or in passthrough mode, the kernel would switch to SWIOTLB bounce-buffering for those transfers. In order to avoid that, 2cc13bb4f59f ("iommu: Disable passthrough mode when SME is active") disables the default IOMMU passthrough mode so that devices for which the default 256K DMA is insufficient, can use the IOMMU instead. However 2, there are cases where the IOMMU is disabled in the BIOS, etc. (think the usual hardware folk "oops, I dropped the ball there" cases) or a driver doesn't properly use the DMA APIs or a device has a firmware or hardware bug, e.g.: ea68573d408f ("drm/amdgpu: Fail to load on RAVEN if SME is active") However 3, in the above GPU use case, there are APIs like Vulkan and some OpenGL/OpenCL extensions which are under the assumption that user-allocated memory can be passed in to the kernel driver and both the GPU and CPU can do coherent and concurrent access to the same memory. That cannot work with SWIOTLB bounce buffers, of course. So, in order for those devices to function, drop the "default y" for the SME by default active option so that users who want to have SME enabled, will need to either enable it in their config or use "mem_encrypt=on" on the kernel command line. [ tlendacky: Generalize commit message. ] Fixes: 7744ccdbc16f ("x86/mm: Add Secure Memory Encryption (SME) support") Reported-by: Paul Menzel Signed-off-by: Borislav Petkov Acked-by: Alex Deucher Acked-by: Tom Lendacky Cc: Link: https://lkml.kernel.org/r/8bbacd0e-4580-3194-19d2-a0ecad7df09c@molgen.mpg.de --- arch/x86/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index bd70e8a39fbf..d9830e7e1060 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1525,7 +1525,6 @@ config AMD_MEM_ENCRYPT config AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT bool "Activate AMD Secure Memory Encryption (SME) by default" - default y depends on AMD_MEM_ENCRYPT help Say yes to have system memory encrypted by default if running on -- cgit From 2e5809a4ddb15969503e43b06662a9a725f613ea Mon Sep 17 00:00:00 2001 From: Mike Kravetz Date: Tue, 5 Oct 2021 13:25:29 -0700 Subject: arm64/hugetlb: fix CMA gigantic page order for non-4K PAGE_SIZE For non-4K PAGE_SIZE configs, the largest gigantic huge page size is CONT_PMD_SHIFT order. On arm64 with 64K PAGE_SIZE, the gigantic page is 16G. Therefore, one should be able to specify 'hugetlb_cma=16G' on the kernel command line so that one gigantic page can be allocated from CMA. However, when adding such an option the following message is produced: hugetlb_cma: cma area should be at least 8796093022208 MiB This is because the calculation for non-4K gigantic page order is incorrect in the arm64 specific routine arm64_hugetlb_cma_reserve(). Fixes: abb7962adc80 ("arm64/hugetlb: Reserve CMA areas for gigantic pages on 16K and 64K configs") Cc: # 5.9.x Signed-off-by: Mike Kravetz Reviewed-by: Anshuman Khandual Link: https://lore.kernel.org/r/20211005202529.213812-1-mike.kravetz@oracle.com Signed-off-by: Catalin Marinas --- arch/arm64/mm/hugetlbpage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c index 23505fc35324..a8158c948966 100644 --- a/arch/arm64/mm/hugetlbpage.c +++ b/arch/arm64/mm/hugetlbpage.c @@ -43,7 +43,7 @@ void __init arm64_hugetlb_cma_reserve(void) #ifdef CONFIG_ARM64_4K_PAGES order = PUD_SHIFT - PAGE_SHIFT; #else - order = CONT_PMD_SHIFT + PMD_SHIFT - PAGE_SHIFT; + order = CONT_PMD_SHIFT - PAGE_SHIFT; #endif /* * HugeTLB CMA reservation is required for gigantic -- cgit From bdefc6b23be33add5e075fb76b97271dad4f813c Mon Sep 17 00:00:00 2001 From: Chun-Kuang Hu Date: Fri, 8 Oct 2021 07:11:20 +0800 Subject: Revert "drm/mediatek: Clear pending flag when cmdq packet is done" This reverts commit 9efb16c2fdd647d3888fd8dae84509f485cd554e. Commit c1ec54b7b5af ("drm/mediatek: Use mailbox rx_callback instead of cmdq_task_cb") would cause numerous mtk cmdq mailbox driver warning: WARNING: CPU: 0 PID: 0 at drivers/mailbox/mtk-cmdq-mailbox.c:198 cmdq_task_exec_done+0xb8/0xe0 So revert that patch and all the patches depend on that patch. Reported-by: Enric Balletbo Serra Tested-by: Enric Balletbo Serra Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 47 ++++----------------------------- 1 file changed, 5 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 5f81489fc60c..9840b8d035dc 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -267,36 +267,6 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) { struct mtk_drm_crtc *mtk_crtc = container_of(cl, struct mtk_drm_crtc, cmdq_cl); struct cmdq_cb_data *data = mssg; - struct mtk_crtc_state *state; - unsigned int i; - - state = to_mtk_crtc_state(mtk_crtc->base.state); - - state->pending_config = false; - - if (mtk_crtc->pending_planes) { - for (i = 0; i < mtk_crtc->layer_nr; i++) { - struct drm_plane *plane = &mtk_crtc->planes[i]; - struct mtk_plane_state *plane_state; - - plane_state = to_mtk_plane_state(plane->state); - - plane_state->pending.config = false; - } - mtk_crtc->pending_planes = false; - } - - if (mtk_crtc->pending_async_planes) { - for (i = 0; i < mtk_crtc->layer_nr; i++) { - struct drm_plane *plane = &mtk_crtc->planes[i]; - struct mtk_plane_state *plane_state; - - plane_state = to_mtk_plane_state(plane->state); - - plane_state->pending.async_config = false; - } - mtk_crtc->pending_async_planes = false; - } mtk_crtc->cmdq_vblank_cnt = 0; mtk_drm_cmdq_pkt_destroy(mtk_crtc->cmdq_chan, data->pkt); @@ -453,8 +423,7 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc, state->pending_vrefresh, 0, cmdq_handle); - if (!cmdq_handle) - state->pending_config = false; + state->pending_config = false; } if (mtk_crtc->pending_planes) { @@ -474,12 +443,9 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc, mtk_ddp_comp_layer_config(comp, local_layer, plane_state, cmdq_handle); - if (!cmdq_handle) - plane_state->pending.config = false; + plane_state->pending.config = false; } - - if (!cmdq_handle) - mtk_crtc->pending_planes = false; + mtk_crtc->pending_planes = false; } if (mtk_crtc->pending_async_planes) { @@ -499,12 +465,9 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc, mtk_ddp_comp_layer_config(comp, local_layer, plane_state, cmdq_handle); - if (!cmdq_handle) - plane_state->pending.async_config = false; + plane_state->pending.async_config = false; } - - if (!cmdq_handle) - mtk_crtc->pending_async_planes = false; + mtk_crtc->pending_async_planes = false; } } -- cgit From be7d2d837363e2d36bc9d87b89207f1b8f5c997d Mon Sep 17 00:00:00 2001 From: Chun-Kuang Hu Date: Fri, 8 Oct 2021 07:23:02 +0800 Subject: Revert "drm/mediatek: Add cmdq_handle in mtk_crtc" This reverts commit bc9241be73d9b2b3bcb7033598521fd669639848. Commit c1ec54b7b5af ("drm/mediatek: Use mailbox rx_callback instead of cmdq_task_cb") would cause numerous mtk cmdq mailbox driver warning: WARNING: CPU: 0 PID: 0 at drivers/mailbox/mtk-cmdq-mailbox.c:198 cmdq_task_exec_done+0xb8/0xe0 So revert that patch and all the patches depend on that patch. Reported-by: Enric Balletbo Serra Tested-by: Enric Balletbo Serra Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 9840b8d035dc..697c4dec1890 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -54,7 +54,6 @@ struct mtk_drm_crtc { #if IS_REACHABLE(CONFIG_MTK_CMDQ) struct mbox_client cmdq_cl; struct mbox_chan *cmdq_chan; - struct cmdq_pkt cmdq_handle; u32 cmdq_event; u32 cmdq_vblank_cnt; #endif @@ -227,16 +226,19 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc, } #if IS_REACHABLE(CONFIG_MTK_CMDQ) -static int mtk_drm_cmdq_pkt_create(struct mbox_chan *chan, struct cmdq_pkt *pkt, - size_t size) +static struct cmdq_pkt *mtk_drm_cmdq_pkt_create(struct mbox_chan *chan, size_t size) { + struct cmdq_pkt *pkt; struct device *dev; dma_addr_t dma_addr; + pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); + if (!pkt) + return ERR_PTR(-ENOMEM); pkt->va_base = kzalloc(size, GFP_KERNEL); if (!pkt->va_base) { kfree(pkt); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } pkt->buf_size = size; @@ -247,12 +249,12 @@ static int mtk_drm_cmdq_pkt_create(struct mbox_chan *chan, struct cmdq_pkt *pkt, dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); kfree(pkt->va_base); kfree(pkt); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } pkt->pa_base = dma_addr; - return 0; + return pkt; } static void mtk_drm_cmdq_pkt_destroy(struct mbox_chan *chan, struct cmdq_pkt *pkt) @@ -475,7 +477,7 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc, bool needs_vblank) { #if IS_REACHABLE(CONFIG_MTK_CMDQ) - struct cmdq_pkt *cmdq_handle = &mtk_crtc->cmdq_handle; + struct cmdq_pkt *cmdq_handle; #endif struct drm_crtc *crtc = &mtk_crtc->base; struct mtk_drm_private *priv = crtc->dev->dev_private; @@ -515,7 +517,7 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc, #if IS_REACHABLE(CONFIG_MTK_CMDQ) if (mtk_crtc->cmdq_chan) { mbox_flush(mtk_crtc->cmdq_chan, 2000); - cmdq_handle->cmd_buf_size = 0; + cmdq_handle = mtk_drm_cmdq_pkt_create(mtk_crtc->cmdq_chan, PAGE_SIZE); cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event); cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false); mtk_crtc_ddp_config(crtc, cmdq_handle); @@ -910,16 +912,6 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, drm_crtc_index(&mtk_crtc->base)); mbox_free_channel(mtk_crtc->cmdq_chan); mtk_crtc->cmdq_chan = NULL; - } else { - ret = mtk_drm_cmdq_pkt_create(mtk_crtc->cmdq_chan, - &mtk_crtc->cmdq_handle, - PAGE_SIZE); - if (ret) { - dev_dbg(dev, "mtk_crtc %d failed to create cmdq packet\n", - drm_crtc_index(&mtk_crtc->base)); - mbox_free_channel(mtk_crtc->cmdq_chan); - mtk_crtc->cmdq_chan = NULL; - } } } #endif -- cgit From 0cf54fff9bcffa69bb96f2da8539858402aea404 Mon Sep 17 00:00:00 2001 From: Chun-Kuang Hu Date: Fri, 8 Oct 2021 07:25:32 +0800 Subject: Revert "drm/mediatek: Detect CMDQ execution timeout" This reverts commit 8cdcb365342402fdeb664479b0a04e9debef8efb. Commit c1ec54b7b5af ("drm/mediatek: Use mailbox rx_callback instead of cmdq_task_cb") would cause numerous mtk cmdq mailbox driver warning: WARNING: CPU: 0 PID: 0 at drivers/mailbox/mtk-cmdq-mailbox.c:198 cmdq_task_exec_done+0xb8/0xe0 So revert that patch and all the patches depend on that patch. Reported-by: Enric Balletbo Serra Tested-by: Enric Balletbo Serra Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 697c4dec1890..0cd5b9ed8956 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -55,7 +55,6 @@ struct mtk_drm_crtc { struct mbox_client cmdq_cl; struct mbox_chan *cmdq_chan; u32 cmdq_event; - u32 cmdq_vblank_cnt; #endif struct device *mmsys_dev; @@ -270,7 +269,6 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) struct mtk_drm_crtc *mtk_crtc = container_of(cl, struct mtk_drm_crtc, cmdq_cl); struct cmdq_cb_data *data = mssg; - mtk_crtc->cmdq_vblank_cnt = 0; mtk_drm_cmdq_pkt_destroy(mtk_crtc->cmdq_chan, data->pkt); } #endif @@ -526,11 +524,6 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc, cmdq_handle->pa_base, cmdq_handle->cmd_buf_size, DMA_TO_DEVICE); - /* - * CMDQ command should execute in next vblank, - * If it fail to execute in next 2 vblank, timeout happen. - */ - mtk_crtc->cmdq_vblank_cnt = 2; mbox_send_message(mtk_crtc->cmdq_chan, cmdq_handle); mbox_client_txdone(mtk_crtc->cmdq_chan, 0); } @@ -547,14 +540,11 @@ static void mtk_crtc_ddp_irq(void *data) #if IS_REACHABLE(CONFIG_MTK_CMDQ) if (!priv->data->shadow_register && !mtk_crtc->cmdq_chan) - mtk_crtc_ddp_config(crtc, NULL); - else if (mtk_crtc->cmdq_vblank_cnt > 0 && --mtk_crtc->cmdq_vblank_cnt == 0) - DRM_ERROR("mtk_crtc %d CMDQ execute command timeout!\n", - drm_crtc_index(&mtk_crtc->base)); #else if (!priv->data->shadow_register) - mtk_crtc_ddp_config(crtc, NULL); #endif + mtk_crtc_ddp_config(crtc, NULL); + mtk_drm_finish_page_flip(mtk_crtc); } -- cgit From 8a4a099f843890504d4942b93b3290a53a53ff3a Mon Sep 17 00:00:00 2001 From: Chun-Kuang Hu Date: Fri, 8 Oct 2021 07:27:11 +0800 Subject: Revert "drm/mediatek: Remove struct cmdq_client" This reverts commit f4be17cd5b14dd73545b0e014a63ebe9ab5ef837. Commit c1ec54b7b5af ("drm/mediatek: Use mailbox rx_callback instead of cmdq_task_cb") would cause numerous mtk cmdq mailbox driver warning: WARNING: CPU: 0 PID: 0 at drivers/mailbox/mtk-cmdq-mailbox.c:198 cmdq_task_exec_done+0xb8/0xe0 So revert that patch and all the patches depend on that patch. Reported-by: Enric Balletbo Serra Tested-by: Enric Balletbo Serra Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 80 ++++++++------------------------- 1 file changed, 18 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 0cd5b9ed8956..3f9802d21bf0 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -52,8 +52,7 @@ struct mtk_drm_crtc { bool pending_async_planes; #if IS_REACHABLE(CONFIG_MTK_CMDQ) - struct mbox_client cmdq_cl; - struct mbox_chan *cmdq_chan; + struct cmdq_client *cmdq_client; u32 cmdq_event; #endif @@ -225,51 +224,11 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc, } #if IS_REACHABLE(CONFIG_MTK_CMDQ) -static struct cmdq_pkt *mtk_drm_cmdq_pkt_create(struct mbox_chan *chan, size_t size) -{ - struct cmdq_pkt *pkt; - struct device *dev; - dma_addr_t dma_addr; - - pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); - if (!pkt) - return ERR_PTR(-ENOMEM); - pkt->va_base = kzalloc(size, GFP_KERNEL); - if (!pkt->va_base) { - kfree(pkt); - return ERR_PTR(-ENOMEM); - } - pkt->buf_size = size; - - dev = chan->mbox->dev; - dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size, - DMA_TO_DEVICE); - if (dma_mapping_error(dev, dma_addr)) { - dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); - kfree(pkt->va_base); - kfree(pkt); - return ERR_PTR(-ENOMEM); - } - - pkt->pa_base = dma_addr; - - return pkt; -} - -static void mtk_drm_cmdq_pkt_destroy(struct mbox_chan *chan, struct cmdq_pkt *pkt) -{ - dma_unmap_single(chan->mbox->dev, pkt->pa_base, pkt->buf_size, - DMA_TO_DEVICE); - kfree(pkt->va_base); - kfree(pkt); -} - static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) { - struct mtk_drm_crtc *mtk_crtc = container_of(cl, struct mtk_drm_crtc, cmdq_cl); struct cmdq_cb_data *data = mssg; - mtk_drm_cmdq_pkt_destroy(mtk_crtc->cmdq_chan, data->pkt); + cmdq_pkt_destroy(data->pkt); } #endif @@ -513,19 +472,19 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc, mtk_mutex_release(mtk_crtc->mutex); } #if IS_REACHABLE(CONFIG_MTK_CMDQ) - if (mtk_crtc->cmdq_chan) { - mbox_flush(mtk_crtc->cmdq_chan, 2000); - cmdq_handle = mtk_drm_cmdq_pkt_create(mtk_crtc->cmdq_chan, PAGE_SIZE); + if (mtk_crtc->cmdq_client) { + mbox_flush(mtk_crtc->cmdq_client->chan, 2000); + cmdq_handle = cmdq_pkt_create(mtk_crtc->cmdq_client, PAGE_SIZE); cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event); cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false); mtk_crtc_ddp_config(crtc, cmdq_handle); cmdq_pkt_finalize(cmdq_handle); - dma_sync_single_for_device(mtk_crtc->cmdq_chan->mbox->dev, + dma_sync_single_for_device(mtk_crtc->cmdq_client->chan->mbox->dev, cmdq_handle->pa_base, cmdq_handle->cmd_buf_size, DMA_TO_DEVICE); - mbox_send_message(mtk_crtc->cmdq_chan, cmdq_handle); - mbox_client_txdone(mtk_crtc->cmdq_chan, 0); + mbox_send_message(mtk_crtc->cmdq_client->chan, cmdq_handle); + mbox_client_txdone(mtk_crtc->cmdq_client->chan, 0); } #endif mtk_crtc->config_updating = false; @@ -539,7 +498,7 @@ static void mtk_crtc_ddp_irq(void *data) struct mtk_drm_private *priv = crtc->dev->dev_private; #if IS_REACHABLE(CONFIG_MTK_CMDQ) - if (!priv->data->shadow_register && !mtk_crtc->cmdq_chan) + if (!priv->data->shadow_register && !mtk_crtc->cmdq_client) #else if (!priv->data->shadow_register) #endif @@ -879,20 +838,17 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, mutex_init(&mtk_crtc->hw_lock); #if IS_REACHABLE(CONFIG_MTK_CMDQ) - mtk_crtc->cmdq_cl.dev = mtk_crtc->mmsys_dev; - mtk_crtc->cmdq_cl.tx_block = false; - mtk_crtc->cmdq_cl.knows_txdone = true; - mtk_crtc->cmdq_cl.rx_callback = ddp_cmdq_cb; - mtk_crtc->cmdq_chan = - mbox_request_channel(&mtk_crtc->cmdq_cl, - drm_crtc_index(&mtk_crtc->base)); - if (IS_ERR(mtk_crtc->cmdq_chan)) { + mtk_crtc->cmdq_client = + cmdq_mbox_create(mtk_crtc->mmsys_dev, + drm_crtc_index(&mtk_crtc->base)); + if (IS_ERR(mtk_crtc->cmdq_client)) { dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, writing register by CPU now\n", drm_crtc_index(&mtk_crtc->base)); - mtk_crtc->cmdq_chan = NULL; + mtk_crtc->cmdq_client = NULL; } - if (mtk_crtc->cmdq_chan) { + if (mtk_crtc->cmdq_client) { + mtk_crtc->cmdq_client->client.rx_callback = ddp_cmdq_cb; ret = of_property_read_u32_index(priv->mutex_node, "mediatek,gce-events", drm_crtc_index(&mtk_crtc->base), @@ -900,8 +856,8 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, if (ret) { dev_dbg(dev, "mtk_crtc %d failed to get mediatek,gce-events property\n", drm_crtc_index(&mtk_crtc->base)); - mbox_free_channel(mtk_crtc->cmdq_chan); - mtk_crtc->cmdq_chan = NULL; + cmdq_mbox_destroy(mtk_crtc->cmdq_client); + mtk_crtc->cmdq_client = NULL; } } #endif -- cgit From 4157a441ff068cc406513e7b8069efa19bba89d0 Mon Sep 17 00:00:00 2001 From: Chun-Kuang Hu Date: Fri, 8 Oct 2021 07:28:40 +0800 Subject: Revert "drm/mediatek: Use mailbox rx_callback instead of cmdq_task_cb" This reverts commit c1ec54b7b5af25c779192253f5a9f05e95cb43d7. Commit c1ec54b7b5af ("drm/mediatek: Use mailbox rx_callback instead of cmdq_task_cb") would cause numerous mtk cmdq mailbox driver warning: WARNING: CPU: 0 PID: 0 at drivers/mailbox/mtk-cmdq-mailbox.c:198 cmdq_task_exec_done+0xb8/0xe0 So revert that patch. Reported-by: Enric Balletbo Serra Tested-by: Enric Balletbo Serra Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 3f9802d21bf0..a4e80e499674 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -4,8 +4,6 @@ */ #include -#include -#include #include #include #include @@ -224,11 +222,9 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc, } #if IS_REACHABLE(CONFIG_MTK_CMDQ) -static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) +static void ddp_cmdq_cb(struct cmdq_cb_data data) { - struct cmdq_cb_data *data = mssg; - - cmdq_pkt_destroy(data->pkt); + cmdq_pkt_destroy(data.data); } #endif @@ -479,12 +475,7 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc, cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event, false); mtk_crtc_ddp_config(crtc, cmdq_handle); cmdq_pkt_finalize(cmdq_handle); - dma_sync_single_for_device(mtk_crtc->cmdq_client->chan->mbox->dev, - cmdq_handle->pa_base, - cmdq_handle->cmd_buf_size, - DMA_TO_DEVICE); - mbox_send_message(mtk_crtc->cmdq_client->chan, cmdq_handle); - mbox_client_txdone(mtk_crtc->cmdq_client->chan, 0); + cmdq_pkt_flush_async(cmdq_handle, ddp_cmdq_cb, cmdq_handle); } #endif mtk_crtc->config_updating = false; @@ -848,7 +839,6 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, } if (mtk_crtc->cmdq_client) { - mtk_crtc->cmdq_client->client.rx_callback = ddp_cmdq_cb; ret = of_property_read_u32_index(priv->mutex_node, "mediatek,gce-events", drm_crtc_index(&mtk_crtc->base), -- cgit From 9463b64d1a34fc4d18f9de63f07b2400c86f8da8 Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Wed, 29 Sep 2021 09:17:04 -0700 Subject: drm/msm/dp: only signal audio when disconnected detected at dp_pm_resume Currently there is audio not working problem after system resume from suspend if hdmi monitor stay plugged in at DUT. However this problem does not happen at normal operation but at a particular test case. The root cause is DP driver signal audio with connected state at resume which trigger audio trying to setup audio data path through DP main link but failed due to display port is not setup and enabled by upper layer framework yet. This patch only have DP driver signal audio only when DP is in disconnected state so that audio option shows correct state after system resume. DP driver will not signal audio with connected state until display enabled executed by upper layer framework where display port is setup completed and main link is running. Changes in V2: -- add details commit text Fixes: afc9b8b6bab8 ("drm/msm/dp: signal audio plugged change at dp_pm_resume") Signed-off-by: Kuogee Hsieh Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/1632932224-25102-1-git-send-email-khsieh@codeaurora.org Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dp/dp_display.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index fbe4c2cd52a3..a0392e4d8134 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1309,14 +1309,14 @@ static int dp_pm_resume(struct device *dev) * can not declared display is connected unless * HDMI cable is plugged in and sink_count of * dongle become 1 + * also only signal audio when disconnected */ - if (dp->link->sink_count) + if (dp->link->sink_count) { dp->dp_display.is_connected = true; - else + } else { dp->dp_display.is_connected = false; - - dp_display_handle_plugged_change(g_dp_display, - dp->dp_display.is_connected); + dp_display_handle_plugged_change(g_dp_display, false); + } DRM_DEBUG_DP("After, sink_count=%d is_connected=%d core_inited=%d power_on=%d\n", dp->link->sink_count, dp->dp_display.is_connected, -- cgit From efb8a170a367fa898d7848c4e74c1c20222e0d91 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Mon, 13 Sep 2021 18:45:56 +0200 Subject: drm/msm: Fix devfreq NULL pointer dereference on a3xx There is no devfreq on a3xx at the moment since gpu_busy is not implemented. This means that msm_devfreq_init() will return early and the entire devfreq setup is skipped. However, msm_devfreq_active() and msm_devfreq_idle() are still called unconditionally later, causing a NULL pointer dereference: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010 Internal error: Oops: 96000004 [#1] PREEMPT SMP CPU: 0 PID: 133 Comm: ring0 Not tainted 5.15.0-rc1 #4 Hardware name: Longcheer L8150 (DT) pc : mutex_lock_io+0x2bc/0x2f0 lr : msm_devfreq_active+0x3c/0xe0 [msm] Call trace: mutex_lock_io+0x2bc/0x2f0 msm_gpu_submit+0x164/0x180 [msm] msm_job_run+0x54/0xe0 [msm] drm_sched_main+0x2b0/0x4a0 [gpu_sched] kthread+0x154/0x160 ret_from_fork+0x10/0x20 Fix this by adding a check in msm_devfreq_active/idle() which ensures that devfreq was actually initialized earlier. Fixes: 9bc95570175a ("drm/msm: Devfreq tuning") Reported-by: Nikita Travkin Tested-by: Nikita Travkin Signed-off-by: Stephan Gerhold Link: https://lore.kernel.org/r/20210913164556.16284-1-stephan@gerhold.net Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gpu_devfreq.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c index 0a1ee20296a2..84e98c07c900 100644 --- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c @@ -151,6 +151,9 @@ void msm_devfreq_active(struct msm_gpu *gpu) unsigned int idle_time; unsigned long target_freq = df->idle_freq; + if (!df->devfreq) + return; + /* * Hold devfreq lock to synchronize with get_dev_status()/ * target() callbacks @@ -186,6 +189,9 @@ void msm_devfreq_idle(struct msm_gpu *gpu) struct msm_gpu_devfreq *df = &gpu->devfreq; unsigned long idle_freq, target_freq = 0; + if (!df->devfreq) + return; + /* * Hold devfreq lock to synchronize with get_dev_status()/ * target() callbacks -- cgit From 171316a68d9a8e0d9e28b7cf4c15afc4c6244a4e Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 17 Sep 2021 02:59:13 +0200 Subject: drm/msm: Avoid potential overflow in timeout_to_jiffies() The return type of ktime_divns() is s64. The timeout_to_jiffies() currently assigns the result of this ktime_divns() to unsigned long, which on 32 bit systems may overflow. Furthermore, the result of this function is sometimes also passed to functions which expect signed long, dma_fence_wait_timeout() is one such example. Fix this by adjusting the type of remaining_jiffies to s64, so we do not suffer overflow there, and return a value limited to range of 0..INT_MAX, which is safe for all usecases of this timeout. The above overflow can be triggered if userspace passes in too large timeout value, larger than INT_MAX / HZ seconds. The kernel detects it and complains about "schedule_timeout: wrong timeout value %lx" and generates a warning backtrace. Note that this fixes commit 6cedb8b377bb ("drm/msm: avoid using 'timespec'"), because the previously used timespec_to_jiffies() function returned unsigned long instead of s64: static inline unsigned long timespec_to_jiffies(const struct timespec *value) Fixes: 6cedb8b377bb ("drm/msm: avoid using 'timespec'") Signed-off-by: Marek Vasut Cc: Arnd Bergmann Cc: Jordan Crouse Cc: Rob Clark Cc: stable@vger.kernel.org # 5.6+ Acked-by: Arnd Bergmann Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20210917005913.157379-1-marex@denx.de Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index e99242164076..c552f0c3890c 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -504,7 +504,7 @@ static inline int align_pitch(int width, int bpp) static inline unsigned long timeout_to_jiffies(const ktime_t *timeout) { ktime_t now = ktime_get(); - unsigned long remaining_jiffies; + s64 remaining_jiffies; if (ktime_compare(*timeout, now) < 0) { remaining_jiffies = 0; @@ -513,7 +513,7 @@ static inline unsigned long timeout_to_jiffies(const ktime_t *timeout) remaining_jiffies = ktime_divns(rem, NSEC_PER_SEC / HZ); } - return remaining_jiffies; + return clamp(remaining_jiffies, 0LL, (s64)INT_MAX); } #endif /* __MSM_DRV_H__ */ -- cgit From c491a0c7bbf3a64732cb8414021429d15ec08eec Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 25 Sep 2021 22:28:24 +0300 Subject: drm/msm/mdp5: fix cursor-related warnings Since f35a2a99100f ("drm/encoder: make encoder control functions optional") drm_mode_config_validate would print warnings if both cursor plane and cursor functions are provided. Restore separate set of drm_crtc_funcs to be used if separate cursor plane is provided. [ 6.556046] ------------[ cut here ]------------ [ 6.556071] [CRTC:93:crtc-0] must not have both a cursor plane and a cursor_set func [ 6.556091] WARNING: CPU: 1 PID: 76 at drivers/gpu/drm/drm_mode_config.c:648 drm_mode_config_validate+0x238/0x4d0 [ 6.567453] Modules linked in: [ 6.577604] CPU: 1 PID: 76 Comm: kworker/u8:2 Not tainted 5.15.0-rc1-dirty #43 [ 6.580557] Hardware name: Qualcomm Technologies, Inc. DB820c (DT) [ 6.587763] Workqueue: events_unbound deferred_probe_work_func [ 6.593926] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 6.599740] pc : drm_mode_config_validate+0x238/0x4d0 [ 6.606596] lr : drm_mode_config_validate+0x238/0x4d0 [ 6.611804] sp : ffff8000121b3980 [ 6.616838] x29: ffff8000121b3990 x28: 0000000000000000 x27: 0000000000000001 [ 6.620140] x26: ffff8000114cde50 x25: ffff8000114cdd40 x24: ffff0000987282d8 [ 6.627258] x23: 0000000000000000 x22: 0000000000000000 x21: 0000000000000001 [ 6.634376] x20: ffff000098728000 x19: ffff000080a39000 x18: ffffffffffffffff [ 6.641494] x17: 3136564e3631564e x16: 0000000000000324 x15: ffff800011c78709 [ 6.648613] x14: 0000000000000000 x13: ffff800011a22850 x12: 00000000000009ab [ 6.655730] x11: 0000000000000339 x10: ffff800011a22850 x9 : ffff800011a22850 [ 6.662848] x8 : 00000000ffffefff x7 : ffff800011a7a850 x6 : ffff800011a7a850 [ 6.669966] x5 : 000000000000bff4 x4 : 40000000fffff339 x3 : 0000000000000000 [ 6.677084] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff00008093b800 [ 6.684205] Call trace: [ 6.691319] drm_mode_config_validate+0x238/0x4d0 [ 6.693577] drm_dev_register+0x17c/0x210 [ 6.698435] msm_drm_bind+0x4b4/0x694 [ 6.702429] try_to_bring_up_master+0x164/0x1d0 [ 6.706075] __component_add+0xa0/0x170 [ 6.710415] component_add+0x14/0x20 [ 6.714234] msm_hdmi_dev_probe+0x1c/0x2c [ 6.718053] platform_probe+0x68/0xe0 [ 6.721959] really_probe.part.0+0x9c/0x30c [ 6.725606] __driver_probe_device+0x98/0x144 [ 6.729600] driver_probe_device+0xc8/0x15c [ 6.734114] __device_attach_driver+0xb4/0x120 [ 6.738106] bus_for_each_drv+0x78/0xd0 [ 6.742619] __device_attach+0xdc/0x184 [ 6.746351] device_initial_probe+0x14/0x20 [ 6.750172] bus_probe_device+0x9c/0xa4 [ 6.754337] deferred_probe_work_func+0x88/0xc0 [ 6.758158] process_one_work+0x1d0/0x370 [ 6.762671] worker_thread+0x2c8/0x470 [ 6.766839] kthread+0x15c/0x170 [ 6.770483] ret_from_fork+0x10/0x20 [ 6.773870] ---[ end trace 5884eb76cd26d274 ]--- [ 6.777500] ------------[ cut here ]------------ [ 6.782043] [CRTC:93:crtc-0] must not have both a cursor plane and a cursor_move func [ 6.782063] WARNING: CPU: 1 PID: 76 at drivers/gpu/drm/drm_mode_config.c:654 drm_mode_config_validate+0x290/0x4d0 [ 6.794362] Modules linked in: [ 6.804600] CPU: 1 PID: 76 Comm: kworker/u8:2 Tainted: G W 5.15.0-rc1-dirty #43 [ 6.807555] Hardware name: Qualcomm Technologies, Inc. DB820c (DT) [ 6.816148] Workqueue: events_unbound deferred_probe_work_func [ 6.822311] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 6.828126] pc : drm_mode_config_validate+0x290/0x4d0 [ 6.834981] lr : drm_mode_config_validate+0x290/0x4d0 [ 6.840189] sp : ffff8000121b3980 [ 6.845223] x29: ffff8000121b3990 x28: 0000000000000000 x27: 0000000000000001 [ 6.848525] x26: ffff8000114cde50 x25: ffff8000114cdd40 x24: ffff0000987282d8 [ 6.855643] x23: 0000000000000000 x22: 0000000000000000 x21: 0000000000000001 [ 6.862763] x20: ffff000098728000 x19: ffff000080a39000 x18: ffffffffffffffff [ 6.869879] x17: 3136564e3631564e x16: 0000000000000324 x15: ffff800011c790c2 [ 6.876998] x14: 0000000000000000 x13: ffff800011a22850 x12: 0000000000000a2f [ 6.884116] x11: 0000000000000365 x10: ffff800011a22850 x9 : ffff800011a22850 [ 6.891234] x8 : 00000000ffffefff x7 : ffff800011a7a850 x6 : ffff800011a7a850 [ 6.898351] x5 : 000000000000bff4 x4 : 40000000fffff365 x3 : 0000000000000000 [ 6.905470] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff00008093b800 [ 6.912590] Call trace: [ 6.919702] drm_mode_config_validate+0x290/0x4d0 [ 6.921960] drm_dev_register+0x17c/0x210 [ 6.926821] msm_drm_bind+0x4b4/0x694 [ 6.930813] try_to_bring_up_master+0x164/0x1d0 [ 6.934459] __component_add+0xa0/0x170 [ 6.938799] component_add+0x14/0x20 [ 6.942619] msm_hdmi_dev_probe+0x1c/0x2c [ 6.946438] platform_probe+0x68/0xe0 [ 6.950345] really_probe.part.0+0x9c/0x30c [ 6.953991] __driver_probe_device+0x98/0x144 [ 6.957984] driver_probe_device+0xc8/0x15c [ 6.962498] __device_attach_driver+0xb4/0x120 [ 6.966492] bus_for_each_drv+0x78/0xd0 [ 6.971004] __device_attach+0xdc/0x184 [ 6.974737] device_initial_probe+0x14/0x20 [ 6.978556] bus_probe_device+0x9c/0xa4 [ 6.982722] deferred_probe_work_func+0x88/0xc0 [ 6.986543] process_one_work+0x1d0/0x370 [ 6.991057] worker_thread+0x2c8/0x470 [ 6.995223] kthread+0x15c/0x170 [ 6.998869] ret_from_fork+0x10/0x20 [ 7.002255] ---[ end trace 5884eb76cd26d275 ]--- Fixes: aa649e875daf ("drm/msm/mdp5: mdp5_crtc: Restore cursor state only if LM cursors are enabled") Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20210925192824.3416259-1-dmitry.baryshkov@linaro.org Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c index f482e0911d03..bb7d066618e6 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c @@ -1125,6 +1125,20 @@ static void mdp5_crtc_reset(struct drm_crtc *crtc) __drm_atomic_helper_crtc_reset(crtc, &mdp5_cstate->base); } +static const struct drm_crtc_funcs mdp5_crtc_no_lm_cursor_funcs = { + .set_config = drm_atomic_helper_set_config, + .destroy = mdp5_crtc_destroy, + .page_flip = drm_atomic_helper_page_flip, + .reset = mdp5_crtc_reset, + .atomic_duplicate_state = mdp5_crtc_duplicate_state, + .atomic_destroy_state = mdp5_crtc_destroy_state, + .atomic_print_state = mdp5_crtc_atomic_print_state, + .get_vblank_counter = mdp5_crtc_get_vblank_counter, + .enable_vblank = msm_crtc_enable_vblank, + .disable_vblank = msm_crtc_disable_vblank, + .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, +}; + static const struct drm_crtc_funcs mdp5_crtc_funcs = { .set_config = drm_atomic_helper_set_config, .destroy = mdp5_crtc_destroy, @@ -1313,6 +1327,8 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, mdp5_crtc->lm_cursor_enabled = cursor_plane ? false : true; drm_crtc_init_with_planes(dev, crtc, plane, cursor_plane, + cursor_plane ? + &mdp5_crtc_no_lm_cursor_funcs : &mdp5_crtc_funcs, NULL); drm_flip_work_init(&mdp5_crtc->unref_cursor_work, -- cgit From 2133c4fc8e1348dcb752f267a143fe2254613b34 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 29 Sep 2021 13:18:57 +0100 Subject: drm/msm: Fix null pointer dereference on pointer edp The initialization of pointer dev dereferences pointer edp before edp is null checked, so there is a potential null pointer deference issue. Fix this by only dereferencing edp after edp has been null checked. Addresses-Coverity: ("Dereference before null check") Fixes: ab5b0107ccf3 ("drm/msm: Initial add eDP support in msm drm driver (v5)") Signed-off-by: Colin Ian King Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20210929121857.213922-1-colin.king@canonical.com Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/edp/edp_ctrl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/edp/edp_ctrl.c b/drivers/gpu/drm/msm/edp/edp_ctrl.c index 4fb397ee7c84..fe1366b4c49f 100644 --- a/drivers/gpu/drm/msm/edp/edp_ctrl.c +++ b/drivers/gpu/drm/msm/edp/edp_ctrl.c @@ -1116,7 +1116,7 @@ void msm_edp_ctrl_power(struct edp_ctrl *ctrl, bool on) int msm_edp_ctrl_init(struct msm_edp *edp) { struct edp_ctrl *ctrl = NULL; - struct device *dev = &edp->pdev->dev; + struct device *dev; int ret; if (!edp) { @@ -1124,6 +1124,7 @@ int msm_edp_ctrl_init(struct msm_edp *edp) return -EINVAL; } + dev = &edp->pdev->dev; ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); if (!ctrl) return -ENOMEM; -- cgit From 980d74e7d03ccf2eaa11d133416946bd880c7c08 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 1 Oct 2021 15:57:59 +0300 Subject: drm/msm/a4xx: fix error handling in a4xx_gpu_init() This code returns 1 on error instead of a negative error. It leads to an Oops in the caller. A second problem is that the check for "if (ret != -ENODATA)" cannot be true because "ret" is set to 1. Fixes: 5785dd7a8ef0 ("drm/msm: Fix duplicate gpu node in icc summary") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/20211001125759.GJ2283@kili Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a4xx_gpu.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index 82bebb40234d..a96ee79cc5e0 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c @@ -699,13 +699,14 @@ struct msm_gpu *a4xx_gpu_init(struct drm_device *dev) } icc_path = devm_of_icc_get(&pdev->dev, "gfx-mem"); - ret = IS_ERR(icc_path); - if (ret) + if (IS_ERR(icc_path)) { + ret = PTR_ERR(icc_path); goto fail; + } ocmem_icc_path = devm_of_icc_get(&pdev->dev, "ocmem"); - ret = IS_ERR(ocmem_icc_path); - if (ret) { + if (IS_ERR(ocmem_icc_path)) { + ret = PTR_ERR(ocmem_icc_path); /* allow -ENODATA, ocmem icc is optional */ if (ret != -ENODATA) goto fail; -- cgit From 3eda901995371d390ef82d0b6462f4ea8efbcfdf Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 1 Oct 2021 15:59:04 +0300 Subject: drm/msm/a3xx: fix error handling in a3xx_gpu_init() These error paths returned 1 on failure, instead of a negative error code. This would lead to an Oops in the caller. A second problem is that the check for "if (ret != -ENODATA)" did not work because "ret" was set to 1. Fixes: 5785dd7a8ef0 ("drm/msm: Fix duplicate gpu node in icc summary") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/20211001125904.GK2283@kili Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a3xx_gpu.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index 4534633fe7cd..8fb847c174ff 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c @@ -571,13 +571,14 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) } icc_path = devm_of_icc_get(&pdev->dev, "gfx-mem"); - ret = IS_ERR(icc_path); - if (ret) + if (IS_ERR(icc_path)) { + ret = PTR_ERR(icc_path); goto fail; + } ocmem_icc_path = devm_of_icc_get(&pdev->dev, "ocmem"); - ret = IS_ERR(ocmem_icc_path); - if (ret) { + if (IS_ERR(ocmem_icc_path)) { + ret = PTR_ERR(ocmem_icc_path); /* allow -ENODATA, ocmem icc is optional */ if (ret != -ENODATA) goto fail; -- cgit From 6a7e0b0e9fb839caa7c7f25bcf91a95b1c2cbef1 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 14 Sep 2021 14:48:31 -0300 Subject: drm/msm: Do not run snapshot on non-DPU devices Since commit 98659487b845 ("drm/msm: add support to take dpu snapshot") the following NULL pointer dereference is seen on i.MX53: [ 3.275493] msm msm: bound 30000000.gpu (ops a3xx_ops) [ 3.287174] [drm] Initialized msm 1.8.0 20130625 for msm on minor 0 [ 3.293915] 8<--- cut here --- [ 3.297012] Unable to handle kernel NULL pointer dereference at virtual address 00000028 [ 3.305244] pgd = (ptrval) [ 3.307989] [00000028] *pgd=00000000 [ 3.311624] Internal error: Oops: 805 [#1] SMP ARM [ 3.316430] Modules linked in: [ 3.319503] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.14.0+g682d702b426b #1 [ 3.326652] Hardware name: Freescale i.MX53 (Device Tree Support) [ 3.332754] PC is at __mutex_init+0x14/0x54 [ 3.336969] LR is at msm_disp_snapshot_init+0x24/0xa0 i.MX53 does not use the DPU controller. Fix the problem by only calling msm_disp_snapshot_init() on platforms that use the DPU controller. Cc: stable@vger.kernel.org Fixes: 98659487b845 ("drm/msm: add support to take dpu snapshot") Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20210914174831.2044420-1-festevam@gmail.com Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_drv.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 4443d7b48618..d4e09703a87d 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -630,10 +630,11 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) if (ret) goto err_msm_uninit; - ret = msm_disp_snapshot_init(ddev); - if (ret) - DRM_DEV_ERROR(dev, "msm_disp_snapshot_init failed ret = %d\n", ret); - + if (kms) { + ret = msm_disp_snapshot_init(ddev); + if (ret) + DRM_DEV_ERROR(dev, "msm_disp_snapshot_init failed ret = %d\n", ret); + } drm_mode_config_reset(ddev); #ifdef CONFIG_DRM_FBDEV_EMULATION -- cgit From 3431c17b75c62f8a28db887441bced2007bd3ffc Mon Sep 17 00:00:00 2001 From: Robert Foss Date: Thu, 19 Aug 2021 15:36:36 +0200 Subject: drm/msm/dpu: Fix address of SM8150 PINGPONG5 IRQ register Both PINGPONG4 and PINGPONG5 IRQ registers are using the same address, which is incorrect. PINGPONG4 should use the register offset 30, and PINGPONG5 should use the register offset 31 according to the downstream driver. Fixes: 667e9985ee24 ("drm/msm/dpu: replace IRQ lookup with the data in hw catalog") Signed-off-by: Robert Foss Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20210819133636.2045766-1-robert.foss@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index b131fd376192..700d65e39feb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -794,7 +794,7 @@ static const struct dpu_pingpong_cfg sm8150_pp[] = { DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), -1), PP_BLK("pingpong_5", PINGPONG_5, 0x72800, MERGE_3D_2, sdm845_pp_sblk, - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), -1), }; -- cgit From ad69b73add8967bc92b62a1cf23a911705781488 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 21 Sep 2021 19:22:45 +0300 Subject: drm/msm/dsi/phy: fix clock names in 28nm_8960 phy The commit 9f91f22aafcd ("drm/msm/dsi: remove duplicate fields from dsi_pll_Nnm instances") mistakenly changed registered clock names. While the platform is in progress of migration to using clock properties in the dts rather than the global clock names, we should provide backwards compatibility. Thus restore registerd global clock names. Fixes: 9f91f22aafcd ("drm/msm/dsi: remove duplicate fields from dsi_pll_Nnm instances") Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Link: https://lore.kernel.org/r/20210921162245.1858118-1-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c index aaa37456f4ee..71ed4aa0dc67 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c @@ -428,7 +428,7 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov bytediv->reg = pll_28nm->phy->pll_base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9; snprintf(parent_name, 32, "dsi%dvco_clk", pll_28nm->phy->id); - snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->phy->id); + snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->phy->id + 1); bytediv_init.name = clk_name; bytediv_init.ops = &clk_bytediv_ops; @@ -442,7 +442,7 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **prov return ret; provided_clocks[DSI_BYTE_PLL_CLK] = &bytediv->hw; - snprintf(clk_name, 32, "dsi%dpll", pll_28nm->phy->id); + snprintf(clk_name, 32, "dsi%dpll", pll_28nm->phy->id + 1); /* DIV3 */ hw = devm_clk_hw_register_divider(dev, clk_name, parent_name, 0, pll_28nm->phy->pll_base + -- cgit From 90b7c1c66132c20e8a550006011a3cbfb73dbfc1 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Mon, 6 Sep 2021 22:25:51 +0200 Subject: drm/msm/dsi: dsi_phy_14nm: Take ready-bit into account in poll_for_ready The downstream driver models this PLL lock check as an if-elseif-else. The only way to reach the else case where pll_locked=true [1] is by succeeding both readl_poll_timeout_atomic calls (which return zero on success) in the if _and_ elseif condition. Hence both the "lock" and "ready" bit need to be tested in the SM_READY_STATUS register before considering the PLL locked and ready to go. Tested on the Sony Xperia XA2 Ultra (nile-discovery, sdm630). [1]: https://source.codeaurora.org/quic/la/kernel/msm-4.19/tree/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c?h=LA.UM.9.2.1.r1-08000-sdm660.0#n302 Fixes: f079f6d999cb ("drm/msm/dsi: Add PHY/PLL for 8x96") Signed-off-by: Marijn Suijten Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20210906202552.824598-1-marijn.suijten@somainline.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c index d13552b2213b..5b4e991f220d 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c @@ -110,14 +110,13 @@ static struct dsi_pll_14nm *pll_14nm_list[DSI_MAX]; static bool pll_14nm_poll_for_ready(struct dsi_pll_14nm *pll_14nm, u32 nb_tries, u32 timeout_us) { - bool pll_locked = false; + bool pll_locked = false, pll_ready = false; void __iomem *base = pll_14nm->phy->pll_base; u32 tries, val; tries = nb_tries; while (tries--) { - val = dsi_phy_read(base + - REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS); + val = dsi_phy_read(base + REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS); pll_locked = !!(val & BIT(5)); if (pll_locked) @@ -126,23 +125,24 @@ static bool pll_14nm_poll_for_ready(struct dsi_pll_14nm *pll_14nm, udelay(timeout_us); } - if (!pll_locked) { - tries = nb_tries; - while (tries--) { - val = dsi_phy_read(base + - REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS); - pll_locked = !!(val & BIT(0)); + if (!pll_locked) + goto out; - if (pll_locked) - break; + tries = nb_tries; + while (tries--) { + val = dsi_phy_read(base + REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS); + pll_ready = !!(val & BIT(0)); - udelay(timeout_us); - } + if (pll_ready) + break; + + udelay(timeout_us); } - DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* "); +out: + DBG("DSI PLL is %slocked, %sready", pll_locked ? "" : "*not* ", pll_ready ? "" : "*not* "); - return pll_locked; + return pll_locked && pll_ready; } static void dsi_pll_14nm_config_init(struct dsi_pll_config *pconf) -- cgit From 739b4e7756d3301dd673ca517afca46a5f635562 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 1 Oct 2021 15:33:08 +0300 Subject: drm/msm/dsi: Fix an error code in msm_dsi_modeset_init() Return an error code if msm_dsi_manager_validate_current_config(). Don't return success. Fixes: 8b03ad30e314 ("drm/msm/dsi: Use one connector for dual DSI mode") Signed-off-by: Dan Carpenter Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20211001123308.GF2283@kili Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 614dc7f26f2c..75ae3008b68f 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -215,8 +215,10 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, goto fail; } - if (!msm_dsi_manager_validate_current_config(msm_dsi->id)) + if (!msm_dsi_manager_validate_current_config(msm_dsi->id)) { + ret = -EINVAL; goto fail; + } msm_dsi->encoder = encoder; -- cgit From c8f01ffc83923a91e8087aaa077de13354a7aa59 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 1 Oct 2021 15:34:09 +0300 Subject: drm/msm/dsi: fix off by one in dsi_bus_clk_enable error handling This disables a lock which wasn't enabled and it does not disable the first lock in the array. Fixes: 6e0eb52eba9e ("drm/msm/dsi: Parse bus clocks from a list") Signed-off-by: Dan Carpenter Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20211001123409.GG2283@kili Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index e269df285136..c86b5090fae6 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -451,7 +451,7 @@ static int dsi_bus_clk_enable(struct msm_dsi_host *msm_host) return 0; err: - for (; i > 0; i--) + while (--i >= 0) clk_disable_unprepare(msm_host->bus_clks[i]); return ret; -- cgit From 013923477cb311293df9079332cf8b806ed0e6f2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 6 Oct 2021 10:34:19 +0300 Subject: pata_legacy: fix a couple uninitialized variable bugs The last byte of "pad" is used without being initialized. Fixes: 55dba3120fbc ("libata: update ->data_xfer hook for ATAPI") Signed-off-by: Dan Carpenter Signed-off-by: Damien Le Moal --- drivers/ata/pata_legacy.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index c3e6592712c4..0a8bf09a5c19 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -352,7 +352,8 @@ static unsigned int pdc_data_xfer_vlb(struct ata_queued_cmd *qc, iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); if (unlikely(slop)) { - __le32 pad; + __le32 pad = 0; + if (rw == READ) { pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); memcpy(buf + buflen - slop, &pad, slop); @@ -742,7 +743,8 @@ static unsigned int vlb32_data_xfer(struct ata_queued_cmd *qc, ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); if (unlikely(slop)) { - __le32 pad; + __le32 pad = 0; + if (rw == WRITE) { memcpy(&pad, buf + buflen - slop, slop); iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); -- cgit From 0edf0824e0dc359ed76bf96af986e6570ca2c0b9 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 8 Oct 2021 14:59:45 -0700 Subject: af_unix: Rename UNIX-DGRAM to UNIX to maintain backwards compatability Then name of this protocol changed in commit 94531cfcbe79 ("af_unix: Add unix_stream_proto for sockmap") because that commit added stream support to the af_unix protocol. Renaming the existing protocol makes a ChromeOS protocol test[1] fail now that the name has changed in /proc/net/protocols from "UNIX" to "UNIX-DGRAM". Let's put the name back to how it was while keeping the stream protocol as "UNIX-STREAM" so that the procfs interface doesn't change. This fixes the test and maintains backwards compatibility in proc. Cc: Jiang Wang Cc: Andrii Nakryiko Cc: Cong Wang Cc: Jakub Sitnicki Cc: John Fastabend Cc: Dmitry Osipenko Link: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/tast-tests/src/chromiumos/tast/local/bundles/cros/network/supported_protocols.go;l=50;drc=e8b1c3f94cb40a054f4aa1ef1aff61e75dc38f18 [1] Fixes: 94531cfcbe79 ("af_unix: Add unix_stream_proto for sockmap") Signed-off-by: Stephen Boyd Signed-off-by: David S. Miller --- net/unix/af_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 0878ab86597b..89f9e85ae970 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -828,7 +828,7 @@ static void unix_unhash(struct sock *sk) } struct proto unix_dgram_proto = { - .name = "UNIX-DGRAM", + .name = "UNIX", .owner = THIS_MODULE, .obj_size = sizeof(struct unix_sock), .close = unix_close, -- cgit From 74a3bc42fe514098030a78c1ad5e6024463dd378 Mon Sep 17 00:00:00 2001 From: Wan Jiabing Date: Mon, 11 Oct 2021 10:27:41 +0800 Subject: net: mscc: ocelot: Fix dumplicated argument in ocelot Fix the following coccicheck warning: drivers/net/ethernet/mscc/ocelot.c:474:duplicated argument to & or | drivers/net/ethernet/mscc/ocelot.c:476:duplicated argument to & or | drivers/net/ethernet/mscc/ocelot_net.c:1627:duplicated argument to & or | These DEV_CLOCK_CFG_MAC_TX_RST are duplicate here. Here should be DEV_CLOCK_CFG_MAC_RX_RST. Fixes: e6e12df625f2 ("net: mscc: ocelot: convert to phylink") Signed-off-by: Wan Jiabing Reviewed-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/ethernet/mscc/ocelot.c | 4 ++-- drivers/net/ethernet/mscc/ocelot_net.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 559177e6ded4..4de58321907c 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -472,9 +472,9 @@ void ocelot_phylink_mac_link_down(struct ocelot *ocelot, int port, !(quirks & OCELOT_QUIRK_QSGMII_PORTS_MUST_BE_UP)) ocelot_port_rmwl(ocelot_port, DEV_CLOCK_CFG_MAC_TX_RST | - DEV_CLOCK_CFG_MAC_TX_RST, + DEV_CLOCK_CFG_MAC_RX_RST, DEV_CLOCK_CFG_MAC_TX_RST | - DEV_CLOCK_CFG_MAC_TX_RST, + DEV_CLOCK_CFG_MAC_RX_RST, DEV_CLOCK_CFG); } EXPORT_SYMBOL_GPL(ocelot_phylink_mac_link_down); diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index e54b9fb2a97a..2a85bcb5d0c2 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -1625,7 +1625,7 @@ static int ocelot_port_phylink_create(struct ocelot *ocelot, int port, if (phy_mode == PHY_INTERFACE_MODE_QSGMII) ocelot_port_rmwl(ocelot_port, 0, DEV_CLOCK_CFG_MAC_TX_RST | - DEV_CLOCK_CFG_MAC_TX_RST, + DEV_CLOCK_CFG_MAC_RX_RST, DEV_CLOCK_CFG); ocelot_port->phy_mode = phy_mode; -- cgit From 4a3e0aeddf091f00974b02627c157843ce382a24 Mon Sep 17 00:00:00 2001 From: Maarten Zanders Date: Mon, 11 Oct 2021 16:27:20 +0200 Subject: net: dsa: mv88e6xxx: don't use PHY_DETECT on internal PHY's mv88e6xxx_port_ppu_updates() interpretes data in the PORT_STS register incorrectly for internal ports (ie no PPU). In these cases, the PHY_DETECT bit indicates link status. This results in forcing the MAC state whenever the PHY link goes down which is not intended. As a side effect, LED's configured to show link status stay lit even though the physical link is down. Add a check in mac_link_down and mac_link_up to see if it concerns an external port and only then, look at PPU status. Fixes: 5d5b231da7ac (net: dsa: mv88e6xxx: use PHY_DETECT in mac_link_up/mac_link_down) Reported-by: Maarten Zanders Reviewed-by: Maxime Chevallier Signed-off-by: Maarten Zanders Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index d7b29792732b..8dadcae93c9b 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -750,7 +750,11 @@ static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port, ops = chip->info->ops; mv88e6xxx_reg_lock(chip); - if ((!mv88e6xxx_port_ppu_updates(chip, port) || + /* Internal PHYs propagate their configuration directly to the MAC. + * External PHYs depend on whether the PPU is enabled for this port. + */ + if (((!mv88e6xxx_phy_is_internal(ds, port) && + !mv88e6xxx_port_ppu_updates(chip, port)) || mode == MLO_AN_FIXED) && ops->port_sync_link) err = ops->port_sync_link(chip, port, mode, false); mv88e6xxx_reg_unlock(chip); @@ -773,7 +777,12 @@ static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port, ops = chip->info->ops; mv88e6xxx_reg_lock(chip); - if (!mv88e6xxx_port_ppu_updates(chip, port) || mode == MLO_AN_FIXED) { + /* Internal PHYs propagate their configuration directly to the MAC. + * External PHYs depend on whether the PPU is enabled for this port. + */ + if ((!mv88e6xxx_phy_is_internal(ds, port) && + !mv88e6xxx_port_ppu_updates(chip, port)) || + mode == MLO_AN_FIXED) { /* FIXME: for an automedia port, should we force the link * down here - what if the link comes up due to "other" media * while we're bringing the port up, how is the exclusivity -- cgit From 9973a43012b6ad1720dbc4d5faf5302c28635b8c Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Mon, 11 Oct 2021 17:22:49 +0200 Subject: r8152: select CRC32 and CRYPTO/CRYPTO_HASH/CRYPTO_SHA256 Fix the following build/link errors by adding a dependency on CRYPTO, CRYPTO_HASH, CRYPTO_SHA256 and CRC32: ld: drivers/net/usb/r8152.o: in function `rtl8152_fw_verify_checksum': r8152.c:(.text+0x2b2a): undefined reference to `crypto_alloc_shash' ld: r8152.c:(.text+0x2bed): undefined reference to `crypto_shash_digest' ld: r8152.c:(.text+0x2c50): undefined reference to `crypto_destroy_tfm' ld: drivers/net/usb/r8152.o: in function `_rtl8152_set_rx_mode': r8152.c:(.text+0xdcb0): undefined reference to `crc32_le' Fixes: 9370f2d05a2a1 ("r8152: support request_firmware for RTL8153") Fixes: ac718b69301c7 ("net/usb: new driver for RTL8152") Signed-off-by: Vegard Nossum Signed-off-by: David S. Miller --- drivers/net/usb/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 4c5d69732a7e..f87f17503373 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -99,6 +99,10 @@ config USB_RTL8150 config USB_RTL8152 tristate "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters" select MII + select CRC32 + select CRYPTO + select CRYPTO_HASH + select CRYPTO_SHA256 help This option adds support for Realtek RTL8152 based USB 2.0 10/100 Ethernet adapters and RTL8153 based USB 3.0 10/100/1000 -- cgit From ef1100ef20f29aec4e62abeccdb5bdbebba1e378 Mon Sep 17 00:00:00 2001 From: Arun Ramadoss Date: Mon, 11 Oct 2021 21:18:08 +0530 Subject: net: dsa: microchip: Added the condition for scheduling ksz_mib_read_work When the ksz module is installed and removed using rmmod, kernel crashes with null pointer dereferrence error. During rmmod, ksz_switch_remove function tries to cancel the mib_read_workqueue using cancel_delayed_work_sync routine and unregister switch from dsa. During dsa_unregister_switch it calls ksz_mac_link_down, which in turn reschedules the workqueue since mib_interval is non-zero. Due to which queue executed after mib_interval and it tries to access dp->slave. But the slave is unregistered in the ksz_switch_remove function. Hence kernel crashes. To avoid this crash, before canceling the workqueue, resetted the mib_interval to 0. v1 -> v2: -Removed the if condition in ksz_mib_read_work Fixes: 469b390e1ba3 ("net: dsa: microchip: use delayed_work instead of timer + work") Signed-off-by: Arun Ramadoss Signed-off-by: David S. Miller --- drivers/net/dsa/microchip/ksz_common.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 1542bfb8b5e5..7c2968a639eb 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -449,8 +449,10 @@ EXPORT_SYMBOL(ksz_switch_register); void ksz_switch_remove(struct ksz_device *dev) { /* timer started */ - if (dev->mib_read_interval) + if (dev->mib_read_interval) { + dev->mib_read_interval = 0; cancel_delayed_work_sync(&dev->mib_read); + } dev->dev_ops->exit(dev); dsa_unregister_switch(dev->ds); -- cgit From 2bbc977ca689e5e18e8cf98f68854f92bd053c97 Mon Sep 17 00:00:00 2001 From: Justin Iurman Date: Mon, 11 Oct 2021 20:04:11 +0200 Subject: ipv6: ioam: move the check for undefined bits The check for undefined bits in the trace type is moved from the input side to the output side, while the input side is relaxed and now inserts default empty values when an undefined bit is set. Signed-off-by: Justin Iurman Signed-off-by: David S. Miller --- net/ipv6/ioam6.c | 70 +++++++++++++++++++++++++++++++++++++++++------ net/ipv6/ioam6_iptunnel.c | 6 +++- 2 files changed, 67 insertions(+), 9 deletions(-) diff --git a/net/ipv6/ioam6.c b/net/ipv6/ioam6.c index 5e8961004832..d128172bb549 100644 --- a/net/ipv6/ioam6.c +++ b/net/ipv6/ioam6.c @@ -770,6 +770,66 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb, data += sizeof(__be32); } + /* bit12 undefined: filled with empty value */ + if (trace->type.bit12) { + *(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE); + data += sizeof(__be32); + } + + /* bit13 undefined: filled with empty value */ + if (trace->type.bit13) { + *(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE); + data += sizeof(__be32); + } + + /* bit14 undefined: filled with empty value */ + if (trace->type.bit14) { + *(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE); + data += sizeof(__be32); + } + + /* bit15 undefined: filled with empty value */ + if (trace->type.bit15) { + *(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE); + data += sizeof(__be32); + } + + /* bit16 undefined: filled with empty value */ + if (trace->type.bit16) { + *(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE); + data += sizeof(__be32); + } + + /* bit17 undefined: filled with empty value */ + if (trace->type.bit17) { + *(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE); + data += sizeof(__be32); + } + + /* bit18 undefined: filled with empty value */ + if (trace->type.bit18) { + *(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE); + data += sizeof(__be32); + } + + /* bit19 undefined: filled with empty value */ + if (trace->type.bit19) { + *(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE); + data += sizeof(__be32); + } + + /* bit20 undefined: filled with empty value */ + if (trace->type.bit20) { + *(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE); + data += sizeof(__be32); + } + + /* bit21 undefined: filled with empty value */ + if (trace->type.bit21) { + *(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE); + data += sizeof(__be32); + } + /* opaque state snapshot */ if (trace->type.bit22) { if (!sc) { @@ -791,16 +851,10 @@ void ioam6_fill_trace_data(struct sk_buff *skb, struct ioam6_schema *sc; u8 sclen = 0; - /* Skip if Overflow flag is set OR - * if an unknown type (bit 12-21) is set + /* Skip if Overflow flag is set */ - if (trace->overflow || - trace->type.bit12 | trace->type.bit13 | trace->type.bit14 | - trace->type.bit15 | trace->type.bit16 | trace->type.bit17 | - trace->type.bit18 | trace->type.bit19 | trace->type.bit20 | - trace->type.bit21) { + if (trace->overflow) return; - } /* NodeLen does not include Opaque State Snapshot length. We need to * take it into account if the corresponding bit is set (bit 22) and diff --git a/net/ipv6/ioam6_iptunnel.c b/net/ipv6/ioam6_iptunnel.c index f9ee04541c17..9b7b726f8f45 100644 --- a/net/ipv6/ioam6_iptunnel.c +++ b/net/ipv6/ioam6_iptunnel.c @@ -75,7 +75,11 @@ static bool ioam6_validate_trace_hdr(struct ioam6_trace_hdr *trace) u32 fields; if (!trace->type_be32 || !trace->remlen || - trace->remlen > IOAM6_TRACE_DATA_SIZE_MAX / 4) + trace->remlen > IOAM6_TRACE_DATA_SIZE_MAX / 4 || + trace->type.bit12 | trace->type.bit13 | trace->type.bit14 | + trace->type.bit15 | trace->type.bit16 | trace->type.bit17 | + trace->type.bit18 | trace->type.bit19 | trace->type.bit20 | + trace->type.bit21) return false; trace->nodelen = 0; -- cgit From 7b1700e009cc17702e8db3af1d983860c0eb7164 Mon Sep 17 00:00:00 2001 From: Justin Iurman Date: Mon, 11 Oct 2021 20:04:12 +0200 Subject: selftests: net: modify IOAM tests for undef bits The output behavior for undefined bits is now directly tested inside the bash script. Trying to set an undefined bit should be refused. The input behavior for undefined bits has been removed due to the fact that we would need another sender allowed to set undefined bits. Signed-off-by: Justin Iurman Signed-off-by: David S. Miller --- tools/testing/selftests/net/ioam6.sh | 26 ++++- tools/testing/selftests/net/ioam6_parser.c | 164 +++++++++++------------------ 2 files changed, 81 insertions(+), 109 deletions(-) diff --git a/tools/testing/selftests/net/ioam6.sh b/tools/testing/selftests/net/ioam6.sh index 3caf72bb9c6a..a2489ec398fe 100755 --- a/tools/testing/selftests/net/ioam6.sh +++ b/tools/testing/selftests/net/ioam6.sh @@ -468,10 +468,26 @@ out_bits() for i in {0..22} do ip -netns ioam-node-alpha route change db01::/64 encap ioam6 trace \ - prealloc type ${bit2type[$i]} ns 123 size ${bit2size[$i]} dev veth0 - - run_test "out_bit$i" "${desc//$i}" ioam-node-alpha ioam-node-beta \ - db01::2 db01::1 veth0 ${bit2type[$i]} 123 + prealloc type ${bit2type[$i]} ns 123 size ${bit2size[$i]} \ + dev veth0 &>/dev/null + + local cmd_res=$? + local descr="${desc//$i}" + + if [[ $i -ge 12 && $i -le 21 ]] + then + if [ $cmd_res != 0 ] + then + npassed=$((npassed+1)) + log_test_passed "$descr" + else + nfailed=$((nfailed+1)) + log_test_failed "$descr" + fi + else + run_test "out_bit$i" "$descr" ioam-node-alpha ioam-node-beta \ + db01::2 db01::1 veth0 ${bit2type[$i]} 123 + fi done bit2size[22]=$tmp @@ -544,7 +560,7 @@ in_bits() local tmp=${bit2size[22]} bit2size[22]=$(( $tmp + ${#BETA[9]} + ((4 - (${#BETA[9]} % 4)) % 4) )) - for i in {0..22} + for i in {0..11} {22..22} do ip -netns ioam-node-alpha route change db01::/64 encap ioam6 trace \ prealloc type ${bit2type[$i]} ns 123 size ${bit2size[$i]} dev veth0 diff --git a/tools/testing/selftests/net/ioam6_parser.c b/tools/testing/selftests/net/ioam6_parser.c index d376cb2c383c..8f6997d35816 100644 --- a/tools/testing/selftests/net/ioam6_parser.c +++ b/tools/testing/selftests/net/ioam6_parser.c @@ -94,16 +94,6 @@ enum { TEST_OUT_BIT9, TEST_OUT_BIT10, TEST_OUT_BIT11, - TEST_OUT_BIT12, - TEST_OUT_BIT13, - TEST_OUT_BIT14, - TEST_OUT_BIT15, - TEST_OUT_BIT16, - TEST_OUT_BIT17, - TEST_OUT_BIT18, - TEST_OUT_BIT19, - TEST_OUT_BIT20, - TEST_OUT_BIT21, TEST_OUT_BIT22, TEST_OUT_FULL_SUPP_TRACE, @@ -125,16 +115,6 @@ enum { TEST_IN_BIT9, TEST_IN_BIT10, TEST_IN_BIT11, - TEST_IN_BIT12, - TEST_IN_BIT13, - TEST_IN_BIT14, - TEST_IN_BIT15, - TEST_IN_BIT16, - TEST_IN_BIT17, - TEST_IN_BIT18, - TEST_IN_BIT19, - TEST_IN_BIT20, - TEST_IN_BIT21, TEST_IN_BIT22, TEST_IN_FULL_SUPP_TRACE, @@ -199,30 +179,6 @@ static int check_ioam_header(int tid, struct ioam6_trace_hdr *ioam6h, ioam6h->nodelen != 2 || ioam6h->remlen; - case TEST_OUT_BIT12: - case TEST_IN_BIT12: - case TEST_OUT_BIT13: - case TEST_IN_BIT13: - case TEST_OUT_BIT14: - case TEST_IN_BIT14: - case TEST_OUT_BIT15: - case TEST_IN_BIT15: - case TEST_OUT_BIT16: - case TEST_IN_BIT16: - case TEST_OUT_BIT17: - case TEST_IN_BIT17: - case TEST_OUT_BIT18: - case TEST_IN_BIT18: - case TEST_OUT_BIT19: - case TEST_IN_BIT19: - case TEST_OUT_BIT20: - case TEST_IN_BIT20: - case TEST_OUT_BIT21: - case TEST_IN_BIT21: - return ioam6h->overflow || - ioam6h->nodelen || - ioam6h->remlen != 1; - case TEST_OUT_BIT22: case TEST_IN_BIT22: return ioam6h->overflow || @@ -326,6 +282,66 @@ static int check_ioam6_data(__u8 **p, struct ioam6_trace_hdr *ioam6h, *p += sizeof(__u32); } + if (ioam6h->type.bit12) { + if (__be32_to_cpu(*((__u32 *)*p)) != 0xffffffff) + return 1; + *p += sizeof(__u32); + } + + if (ioam6h->type.bit13) { + if (__be32_to_cpu(*((__u32 *)*p)) != 0xffffffff) + return 1; + *p += sizeof(__u32); + } + + if (ioam6h->type.bit14) { + if (__be32_to_cpu(*((__u32 *)*p)) != 0xffffffff) + return 1; + *p += sizeof(__u32); + } + + if (ioam6h->type.bit15) { + if (__be32_to_cpu(*((__u32 *)*p)) != 0xffffffff) + return 1; + *p += sizeof(__u32); + } + + if (ioam6h->type.bit16) { + if (__be32_to_cpu(*((__u32 *)*p)) != 0xffffffff) + return 1; + *p += sizeof(__u32); + } + + if (ioam6h->type.bit17) { + if (__be32_to_cpu(*((__u32 *)*p)) != 0xffffffff) + return 1; + *p += sizeof(__u32); + } + + if (ioam6h->type.bit18) { + if (__be32_to_cpu(*((__u32 *)*p)) != 0xffffffff) + return 1; + *p += sizeof(__u32); + } + + if (ioam6h->type.bit19) { + if (__be32_to_cpu(*((__u32 *)*p)) != 0xffffffff) + return 1; + *p += sizeof(__u32); + } + + if (ioam6h->type.bit20) { + if (__be32_to_cpu(*((__u32 *)*p)) != 0xffffffff) + return 1; + *p += sizeof(__u32); + } + + if (ioam6h->type.bit21) { + if (__be32_to_cpu(*((__u32 *)*p)) != 0xffffffff) + return 1; + *p += sizeof(__u32); + } + if (ioam6h->type.bit22) { len = cnf.sc_data ? strlen(cnf.sc_data) : 0; aligned = cnf.sc_data ? __ALIGN_KERNEL(len, 4) : 0; @@ -455,26 +471,6 @@ static int str2id(const char *tname) return TEST_OUT_BIT10; if (!strcmp("out_bit11", tname)) return TEST_OUT_BIT11; - if (!strcmp("out_bit12", tname)) - return TEST_OUT_BIT12; - if (!strcmp("out_bit13", tname)) - return TEST_OUT_BIT13; - if (!strcmp("out_bit14", tname)) - return TEST_OUT_BIT14; - if (!strcmp("out_bit15", tname)) - return TEST_OUT_BIT15; - if (!strcmp("out_bit16", tname)) - return TEST_OUT_BIT16; - if (!strcmp("out_bit17", tname)) - return TEST_OUT_BIT17; - if (!strcmp("out_bit18", tname)) - return TEST_OUT_BIT18; - if (!strcmp("out_bit19", tname)) - return TEST_OUT_BIT19; - if (!strcmp("out_bit20", tname)) - return TEST_OUT_BIT20; - if (!strcmp("out_bit21", tname)) - return TEST_OUT_BIT21; if (!strcmp("out_bit22", tname)) return TEST_OUT_BIT22; if (!strcmp("out_full_supp_trace", tname)) @@ -509,26 +505,6 @@ static int str2id(const char *tname) return TEST_IN_BIT10; if (!strcmp("in_bit11", tname)) return TEST_IN_BIT11; - if (!strcmp("in_bit12", tname)) - return TEST_IN_BIT12; - if (!strcmp("in_bit13", tname)) - return TEST_IN_BIT13; - if (!strcmp("in_bit14", tname)) - return TEST_IN_BIT14; - if (!strcmp("in_bit15", tname)) - return TEST_IN_BIT15; - if (!strcmp("in_bit16", tname)) - return TEST_IN_BIT16; - if (!strcmp("in_bit17", tname)) - return TEST_IN_BIT17; - if (!strcmp("in_bit18", tname)) - return TEST_IN_BIT18; - if (!strcmp("in_bit19", tname)) - return TEST_IN_BIT19; - if (!strcmp("in_bit20", tname)) - return TEST_IN_BIT20; - if (!strcmp("in_bit21", tname)) - return TEST_IN_BIT21; if (!strcmp("in_bit22", tname)) return TEST_IN_BIT22; if (!strcmp("in_full_supp_trace", tname)) @@ -606,16 +582,6 @@ static int (*func[__TEST_MAX])(int, struct ioam6_trace_hdr *, __u32, __u16) = { [TEST_OUT_BIT9] = check_ioam_header_and_data, [TEST_OUT_BIT10] = check_ioam_header_and_data, [TEST_OUT_BIT11] = check_ioam_header_and_data, - [TEST_OUT_BIT12] = check_ioam_header, - [TEST_OUT_BIT13] = check_ioam_header, - [TEST_OUT_BIT14] = check_ioam_header, - [TEST_OUT_BIT15] = check_ioam_header, - [TEST_OUT_BIT16] = check_ioam_header, - [TEST_OUT_BIT17] = check_ioam_header, - [TEST_OUT_BIT18] = check_ioam_header, - [TEST_OUT_BIT19] = check_ioam_header, - [TEST_OUT_BIT20] = check_ioam_header, - [TEST_OUT_BIT21] = check_ioam_header, [TEST_OUT_BIT22] = check_ioam_header_and_data, [TEST_OUT_FULL_SUPP_TRACE] = check_ioam_header_and_data, [TEST_IN_UNDEF_NS] = check_ioam_header, @@ -633,16 +599,6 @@ static int (*func[__TEST_MAX])(int, struct ioam6_trace_hdr *, __u32, __u16) = { [TEST_IN_BIT9] = check_ioam_header_and_data, [TEST_IN_BIT10] = check_ioam_header_and_data, [TEST_IN_BIT11] = check_ioam_header_and_data, - [TEST_IN_BIT12] = check_ioam_header, - [TEST_IN_BIT13] = check_ioam_header, - [TEST_IN_BIT14] = check_ioam_header, - [TEST_IN_BIT15] = check_ioam_header, - [TEST_IN_BIT16] = check_ioam_header, - [TEST_IN_BIT17] = check_ioam_header, - [TEST_IN_BIT18] = check_ioam_header, - [TEST_IN_BIT19] = check_ioam_header, - [TEST_IN_BIT20] = check_ioam_header, - [TEST_IN_BIT21] = check_ioam_header, [TEST_IN_BIT22] = check_ioam_header_and_data, [TEST_IN_FULL_SUPP_TRACE] = check_ioam_header_and_data, [TEST_FWD_FULL_SUPP_TRACE] = check_ioam_header_and_data, -- cgit From 1606520a24542d6566077f99f3678e18d05bdd28 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 6 Oct 2021 18:01:19 +0200 Subject: KVM: s390: remove myself as reviewer I currently don't have time anymore to review KVM/s390 code. Signed-off-by: Cornelia Huck Acked-by: Janosch Frank Acked-by: Christian Borntraeger Link: https://lore.kernel.org/r/20211006160120.217636-2-cohuck@redhat.com Signed-off-by: Vasily Gorbik --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index abdcbcfef73d..0149e1a3e65e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10275,7 +10275,6 @@ KERNEL VIRTUAL MACHINE for s390 (KVM/s390) M: Christian Borntraeger M: Janosch Frank R: David Hildenbrand -R: Cornelia Huck R: Claudio Imbrenda L: kvm@vger.kernel.org S: Supported -- cgit From 4540938952d47eec558ae69e190e0fe3076ec8ad Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 6 Oct 2021 18:01:20 +0200 Subject: vfio-ccw: step down as maintainer I currently don't have time to act as vfio-ccw maintainer anymore, but I trust that I leave it in capable hands. Signed-off-by: Cornelia Huck Acked-by: Eric Farman Acked-by: Matthew Rosato Acked-by: Christian Borntraeger Link: https://lore.kernel.org/r/20211006160120.217636-3-cohuck@redhat.com Signed-off-by: Vasily Gorbik --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 0149e1a3e65e..92db89512678 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16374,7 +16374,6 @@ F: drivers/s390/crypto/vfio_ap_ops.c F: drivers/s390/crypto/vfio_ap_private.h S390 VFIO-CCW DRIVER -M: Cornelia Huck M: Eric Farman M: Matthew Rosato R: Halil Pasic -- cgit From 8e0ab8e26b72a80e991c66a8abc16e6c856abe3d Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Tue, 5 Oct 2021 14:08:36 +0200 Subject: s390: fix strrchr() implementation Fix two problems found in the strrchr() implementation for s390 architectures: evaluate empty strings (return the string address instead of NULL, if '\0' is passed as second argument); evaluate the first character of non-empty strings (the current implementation stops at the second). Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Reported-by: Heiko Carstens (incorrect behavior with empty strings) Signed-off-by: Roberto Sassu Link: https://lore.kernel.org/r/20211005120836.60630-1-roberto.sassu@huawei.com Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/lib/string.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/s390/lib/string.c b/arch/s390/lib/string.c index cfcdf76d6a95..a95ca6df4e5e 100644 --- a/arch/s390/lib/string.c +++ b/arch/s390/lib/string.c @@ -259,14 +259,13 @@ EXPORT_SYMBOL(strcmp); #ifdef __HAVE_ARCH_STRRCHR char *strrchr(const char *s, int c) { - size_t len = __strend(s) - s; - - if (len) - do { - if (s[len] == (char) c) - return (char *) s + len; - } while (--len > 0); - return NULL; + ssize_t len = __strend(s) - s; + + do { + if (s[len] == (char)c) + return (char *)s + len; + } while (--len >= 0); + return NULL; } EXPORT_SYMBOL(strrchr); #endif -- cgit From 4d4a223a86afe658cd878800f09458e8bb54415d Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 11 Oct 2021 13:48:06 -0700 Subject: ice: fix locking for Tx timestamp tracking flush Commit 4dd0d5c33c3e ("ice: add lock around Tx timestamp tracker flush") added a lock around the Tx timestamp tracker flow which is used to cleanup any left over SKBs and prepare for device removal. This lock is problematic because it is being held around a call to ice_clear_phy_tstamp. The clear function takes a mutex to send a PHY write command to firmware. This could lead to a deadlock if the mutex actually sleeps, and causes the following warning on a kernel with preemption debugging enabled: [ 715.419426] BUG: sleeping function called from invalid context at kernel/locking/mutex.c:573 [ 715.427900] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 3100, name: rmmod [ 715.435652] INFO: lockdep is turned off. [ 715.439591] Preemption disabled at: [ 715.439594] [<0000000000000000>] 0x0 [ 715.446678] CPU: 52 PID: 3100 Comm: rmmod Tainted: G W OE 5.15.0-rc4+ #42 bdd7ec3018e725f159ca0d372ce8c2c0e784891c [ 715.458058] Hardware name: Intel Corporation S2600STQ/S2600STQ, BIOS SE5C620.86B.02.01.0010.010620200716 01/06/2020 [ 715.468483] Call Trace: [ 715.470940] dump_stack_lvl+0x6a/0x9a [ 715.474613] ___might_sleep.cold+0x224/0x26a [ 715.478895] __mutex_lock+0xb3/0x1440 [ 715.482569] ? stack_depot_save+0x378/0x500 [ 715.486763] ? ice_sq_send_cmd+0x78/0x14c0 [ice 9a7e1ec00971c89ecd3fe0d4dc7da2b3786a421d] [ 715.494979] ? kfree+0xc1/0x520 [ 715.498128] ? mutex_lock_io_nested+0x12a0/0x12a0 [ 715.502837] ? kasan_set_free_info+0x20/0x30 [ 715.507110] ? __kasan_slab_free+0x10b/0x140 [ 715.511385] ? slab_free_freelist_hook+0xc7/0x220 [ 715.516092] ? kfree+0xc1/0x520 [ 715.519235] ? ice_deinit_lag+0x16c/0x220 [ice 9a7e1ec00971c89ecd3fe0d4dc7da2b3786a421d] [ 715.527359] ? ice_remove+0x1cf/0x6a0 [ice 9a7e1ec00971c89ecd3fe0d4dc7da2b3786a421d] [ 715.535133] ? pci_device_remove+0xab/0x1d0 [ 715.539318] ? __device_release_driver+0x35b/0x690 [ 715.544110] ? driver_detach+0x214/0x2f0 [ 715.548035] ? bus_remove_driver+0x11d/0x2f0 [ 715.552309] ? pci_unregister_driver+0x26/0x250 [ 715.556840] ? ice_module_exit+0xc/0x2f [ice 9a7e1ec00971c89ecd3fe0d4dc7da2b3786a421d] [ 715.564799] ? __do_sys_delete_module.constprop.0+0x2d8/0x4e0 [ 715.570554] ? do_syscall_64+0x3b/0x90 [ 715.574303] ? entry_SYSCALL_64_after_hwframe+0x44/0xae [ 715.579529] ? start_flush_work+0x542/0x8f0 [ 715.583719] ? ice_sq_send_cmd+0x78/0x14c0 [ice 9a7e1ec00971c89ecd3fe0d4dc7da2b3786a421d] [ 715.591923] ice_sq_send_cmd+0x78/0x14c0 [ice 9a7e1ec00971c89ecd3fe0d4dc7da2b3786a421d] [ 715.599960] ? wait_for_completion_io+0x250/0x250 [ 715.604662] ? lock_acquire+0x196/0x200 [ 715.608504] ? do_raw_spin_trylock+0xa5/0x160 [ 715.612864] ice_sbq_rw_reg+0x1e6/0x2f0 [ice 9a7e1ec00971c89ecd3fe0d4dc7da2b3786a421d] [ 715.620813] ? ice_reset+0x130/0x130 [ice 9a7e1ec00971c89ecd3fe0d4dc7da2b3786a421d] [ 715.628497] ? __debug_check_no_obj_freed+0x1e8/0x3c0 [ 715.633550] ? trace_hardirqs_on+0x1c/0x130 [ 715.637748] ice_write_phy_reg_e810+0x70/0xf0 [ice 9a7e1ec00971c89ecd3fe0d4dc7da2b3786a421d] [ 715.646220] ? do_raw_spin_trylock+0xa5/0x160 [ 715.650581] ? ice_ptp_release+0x910/0x910 [ice 9a7e1ec00971c89ecd3fe0d4dc7da2b3786a421d] [ 715.658797] ? ice_ptp_release+0x255/0x910 [ice 9a7e1ec00971c89ecd3fe0d4dc7da2b3786a421d] [ 715.667013] ice_clear_phy_tstamp+0x2c/0x110 [ice 9a7e1ec00971c89ecd3fe0d4dc7da2b3786a421d] [ 715.675403] ice_ptp_release+0x408/0x910 [ice 9a7e1ec00971c89ecd3fe0d4dc7da2b3786a421d] [ 715.683440] ice_remove+0x560/0x6a0 [ice 9a7e1ec00971c89ecd3fe0d4dc7da2b3786a421d] [ 715.691037] ? _raw_spin_unlock_irqrestore+0x46/0x73 [ 715.696005] pci_device_remove+0xab/0x1d0 [ 715.700018] __device_release_driver+0x35b/0x690 [ 715.704637] driver_detach+0x214/0x2f0 [ 715.708389] bus_remove_driver+0x11d/0x2f0 [ 715.712489] pci_unregister_driver+0x26/0x250 [ 715.716857] ice_module_exit+0xc/0x2f [ice 9a7e1ec00971c89ecd3fe0d4dc7da2b3786a421d] [ 715.724637] __do_sys_delete_module.constprop.0+0x2d8/0x4e0 [ 715.730210] ? free_module+0x6d0/0x6d0 [ 715.733963] ? task_work_run+0xe1/0x170 [ 715.737803] ? exit_to_user_mode_loop+0x17f/0x1d0 [ 715.742509] ? rcu_read_lock_sched_held+0x12/0x80 [ 715.747215] ? trace_hardirqs_on+0x1c/0x130 [ 715.751401] do_syscall_64+0x3b/0x90 [ 715.754981] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 715.760033] RIP: 0033:0x7f4dfe59000b [ 715.763612] Code: 73 01 c3 48 8b 0d 6d 1e 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 b8 b0 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 3d 1e 0c 00 f7 d8 64 89 01 48 [ 715.782357] RSP: 002b:00007ffe8c891708 EFLAGS: 00000206 ORIG_RAX: 00000000000000b0 [ 715.789923] RAX: ffffffffffffffda RBX: 00005558a20468b0 RCX: 00007f4dfe59000b [ 715.797054] RDX: 000000000000000a RSI: 0000000000000800 RDI: 00005558a2046918 [ 715.804189] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 [ 715.811319] R10: 00007f4dfe603ac0 R11: 0000000000000206 R12: 00007ffe8c891940 [ 715.818455] R13: 00007ffe8c8920a3 R14: 00005558a20462a0 R15: 00005558a20468b0 Notice that this is the only case where we use the lock in this way. In the cleanup kthread and work kthread the lock is only taken around the bit accesses. This was done intentionally to avoid this kind of issue. The way the lock is used, we only protect ordering of bit sets vs bit clears. The Tx writers in the hot path don't need to be protected against the entire kthread loop. The Tx queues threads only need to ensure that they do not re-use an index that is currently in use. The cleanup loop does not need to block all new set bits, since it will re-queue itself if new timestamps are present. Fix the tracker flow so that it uses the same flow as the standard cleanup thread. In addition, ensure the in_use bitmap actually gets cleared properly. This fixes the warning and also avoids the potential deadlock that might have occurred otherwise. Fixes: 4dd0d5c33c3e ("ice: add lock around Tx timestamp tracker flush") Signed-off-by: Jacob Keller Signed-off-by: Tony Nguyen Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ice/ice_ptp.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c index 05cc5870e4ef..80380aed8882 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c @@ -1313,22 +1313,21 @@ ice_ptp_flush_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx) { u8 idx; - spin_lock(&tx->lock); - for (idx = 0; idx < tx->len; idx++) { u8 phy_idx = idx + tx->quad_offset; - /* Clear any potential residual timestamp in the PHY block */ - if (!pf->hw.reset_ongoing) - ice_clear_phy_tstamp(&pf->hw, tx->quad, phy_idx); - + spin_lock(&tx->lock); if (tx->tstamps[idx].skb) { dev_kfree_skb_any(tx->tstamps[idx].skb); tx->tstamps[idx].skb = NULL; } - } + clear_bit(idx, tx->in_use); + spin_unlock(&tx->lock); - spin_unlock(&tx->lock); + /* Clear any potential residual timestamp in the PHY block */ + if (!pf->hw.reset_ongoing) + ice_clear_phy_tstamp(&pf->hw, tx->quad, phy_idx); + } } /** -- cgit From 7f565d0ead264329749c0da488de9c8dfa2f18ce Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Tue, 12 Oct 2021 13:01:16 +0530 Subject: tee: optee: Fix missing devices unregister during optee_remove When OP-TEE driver is built as a module, OP-TEE client devices registered on TEE bus during probe should be unregistered during optee_remove. So implement optee_unregister_devices() accordingly. Fixes: c3fa24af9244 ("tee: optee: add TEE bus device enumeration support") Reported-by: Sudeep Holla Signed-off-by: Sumit Garg Signed-off-by: Jens Wiklander --- drivers/tee/optee/core.c | 3 +++ drivers/tee/optee/device.c | 22 ++++++++++++++++++++++ drivers/tee/optee/optee_private.h | 1 + 3 files changed, 26 insertions(+) diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index 5ce13b099d7d..5363ebebfc35 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -585,6 +585,9 @@ static int optee_remove(struct platform_device *pdev) { struct optee *optee = platform_get_drvdata(pdev); + /* Unregister OP-TEE specific client devices on TEE bus */ + optee_unregister_devices(); + /* * Ask OP-TEE to free all cached shared memory objects to decrease * reference counters and also avoid wild pointers in secure world diff --git a/drivers/tee/optee/device.c b/drivers/tee/optee/device.c index ec1d24693eba..128a2d2a50a1 100644 --- a/drivers/tee/optee/device.c +++ b/drivers/tee/optee/device.c @@ -53,6 +53,13 @@ static int get_devices(struct tee_context *ctx, u32 session, return 0; } +static void optee_release_device(struct device *dev) +{ + struct tee_client_device *optee_device = to_tee_client_device(dev); + + kfree(optee_device); +} + static int optee_register_device(const uuid_t *device_uuid) { struct tee_client_device *optee_device = NULL; @@ -63,6 +70,7 @@ static int optee_register_device(const uuid_t *device_uuid) return -ENOMEM; optee_device->dev.bus = &tee_bus_type; + optee_device->dev.release = optee_release_device; if (dev_set_name(&optee_device->dev, "optee-ta-%pUb", device_uuid)) { kfree(optee_device); return -ENOMEM; @@ -154,3 +162,17 @@ int optee_enumerate_devices(u32 func) { return __optee_enumerate_devices(func); } + +static int __optee_unregister_device(struct device *dev, void *data) +{ + if (!strncmp(dev_name(dev), "optee-ta", strlen("optee-ta"))) + device_unregister(dev); + + return 0; +} + +void optee_unregister_devices(void) +{ + bus_for_each_dev(&tee_bus_type, NULL, NULL, + __optee_unregister_device); +} diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index dbdd367be156..f6bb4a763ba9 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -184,6 +184,7 @@ void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages, #define PTA_CMD_GET_DEVICES 0x0 #define PTA_CMD_GET_DEVICES_SUPP 0x1 int optee_enumerate_devices(u32 func); +void optee_unregister_devices(void); /* * Small helpers -- cgit From a3fd1a986e499a06ac5ef95c3a39aa4611e7444c Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Tue, 12 Oct 2021 19:47:48 +0800 Subject: ALSA: hda/realtek: Fix the mic type detection issue for ASUS G551JW We need to define the codec pin 0x1b to be the mic, but somehow the mic doesn't support hot plugging detection, and Windows also has this issue, so we set it to phantom headset-mic. Also the determine_headset_type() often returns the omtp type by a mistake when we plug a ctia headset, this makes the mic can't record sound at all. Because most of the headset are ctia type nowadays and some machines have the fixed ctia type audio jack, it is possible this machine has the fixed ctia jack too. Here we set this mic jack to fixed ctia type, this could avoid the mic type detection mistake and make the ctia headset work stable. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=214537 Reported-and-tested-by: msd Cc: Signed-off-by: Hui Wang Link: https://lore.kernel.org/r/20211012114748.5238-1-hui.wang@canonical.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index bca5830ff706..22d27b12c4e7 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -10197,6 +10197,9 @@ enum { ALC671_FIXUP_HP_HEADSET_MIC2, ALC662_FIXUP_ACER_X2660G_HEADSET_MODE, ALC662_FIXUP_ACER_NITRO_HEADSET_MODE, + ALC668_FIXUP_ASUS_NO_HEADSET_MIC, + ALC668_FIXUP_HEADSET_MIC, + ALC668_FIXUP_MIC_DET_COEF, }; static const struct hda_fixup alc662_fixups[] = { @@ -10580,6 +10583,29 @@ static const struct hda_fixup alc662_fixups[] = { .chained = true, .chain_id = ALC662_FIXUP_USI_FUNC }, + [ALC668_FIXUP_ASUS_NO_HEADSET_MIC] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x1b, 0x04a1112c }, + { } + }, + .chained = true, + .chain_id = ALC668_FIXUP_HEADSET_MIC + }, + [ALC668_FIXUP_HEADSET_MIC] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc269_fixup_headset_mic, + .chained = true, + .chain_id = ALC668_FIXUP_MIC_DET_COEF + }, + [ALC668_FIXUP_MIC_DET_COEF] = { + .type = HDA_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { + { 0x20, AC_VERB_SET_COEF_INDEX, 0x15 }, + { 0x20, AC_VERB_SET_PROC_COEF, 0x0d60 }, + {} + }, + }, }; static const struct snd_pci_quirk alc662_fixup_tbl[] = { @@ -10615,6 +10641,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16), SND_PCI_QUIRK(0x1043, 0x177d, "ASUS N551", ALC668_FIXUP_ASUS_Nx51), SND_PCI_QUIRK(0x1043, 0x17bd, "ASUS N751", ALC668_FIXUP_ASUS_Nx51), + SND_PCI_QUIRK(0x1043, 0x185d, "ASUS G551JW", ALC668_FIXUP_ASUS_NO_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71SL", ALC662_FIXUP_ASUS_MODE8), SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16), SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_MODE4_CHMAP), -- cgit From 1ea1dbf1f54c3345072c963b3acf8830e2468c1b Mon Sep 17 00:00:00 2001 From: Sachi King Date: Sat, 2 Oct 2021 14:18:40 +1000 Subject: ACPI: PM: Include alternate AMDI0005 id in special behaviour The Surface Laptop 4 AMD has used the AMD0005 to identify this controller instead of using the appropriate ACPI ID AMDI0005. The AMD0005 needs the same special casing as AMDI0005. Link: https://github.com/linux-surface/acpidumps/tree/master/surface_laptop_4_amd Link: https://gist.github.com/nakato/2a1a7df1a45fe680d7a08c583e1bf863 Signed-off-by: Sachi King Reviewed-by: Mario Limonciello Cc: 5.14+ # 5.14+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/x86/s2idle.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c index bd92b549fd5a..1c48358b43ba 100644 --- a/drivers/acpi/x86/s2idle.c +++ b/drivers/acpi/x86/s2idle.c @@ -371,7 +371,7 @@ static int lps0_device_attach(struct acpi_device *adev, return 0; if (acpi_s2idle_vendor_amd()) { - /* AMD0004, AMDI0005: + /* AMD0004, AMD0005, AMDI0005: * - Should use rev_id 0x0 * - function mask > 0x3: Should use AMD method, but has off by one bug * - function mask = 0x3: Should use Microsoft method @@ -390,6 +390,7 @@ static int lps0_device_attach(struct acpi_device *adev, ACPI_LPS0_DSM_UUID_MICROSOFT, 0, &lps0_dsm_guid_microsoft); if (lps0_dsm_func_mask > 0x3 && (!strcmp(hid, "AMD0004") || + !strcmp(hid, "AMD0005") || !strcmp(hid, "AMDI0005"))) { lps0_dsm_func_mask = (lps0_dsm_func_mask << 1) | 0x1; acpi_handle_debug(adev->handle, "_DSM UUID %s: Adjusted function mask: 0x%x\n", -- cgit From 8607954cf255329d1c6dfc073ff1508b7585573c Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 11 Oct 2021 19:43:29 +0300 Subject: fs/ntfs3: Check for NULL pointers in ni_try_remove_attr_list Check for potential NULL pointers. Print error message if found. Thread, that leads to this commit: https://lore.kernel.org/ntfs3/227c13e3-5a22-0cba-41eb-fcaf41940711@paragon-software.com/ Reported-by: Mohammad Rasim Signed-off-by: Konstantin Komarov --- fs/ntfs3/frecord.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index ecb965e4afd0..6f47a9c17f89 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -705,18 +705,35 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni) continue; mi = ni_find_mi(ni, ino_get(&le->ref)); + if (!mi) { + /* Should never happened, 'cause already checked. */ + goto bad; + } 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; + } asize = le32_to_cpu(attr->size); /* Insert into primary record. */ attr_ins = mi_insert_attr(&ni->mi, le->type, le_name(le), le->name_len, asize, le16_to_cpu(attr->name_off)); - id = attr_ins->id; + if (!attr_ins) { + /* + * Internal error. + * Either no space in primary record (already checked). + * Either tried to insert another + * non indexed attribute (logic error). + */ + goto bad; + } /* Copy all except id. */ + id = attr_ins->id; memcpy(attr_ins, attr, asize); attr_ins->id = id; @@ -732,6 +749,10 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni) ni->attr_list.dirty = false; return 0; +bad: + ntfs_inode_err(&ni->vfs_inode, "Internal error"); + make_bad_inode(&ni->vfs_inode); + return -EINVAL; } /* -- cgit From b37a15188eae9d4c49c5bb035e0c8d4058e4d9b3 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 12 Oct 2021 17:29:35 +0300 Subject: ALSA: hda: avoid write to STATESTS if controller is in reset The snd_hdac_bus_reset_link() contains logic to clear STATESTS register before performing controller reset. This code dates back to an old bugfix in commit e8a7f136f5ed ("[ALSA] hda-intel - Improve HD-audio codec probing robustness"). Originally the code was added to azx_reset(). The code was moved around in commit a41d122449be ("ALSA: hda - Embed bus into controller object") and ended up to snd_hdac_bus_reset_link() and called primarily via snd_hdac_bus_init_chip(). The logic to clear STATESTS is correct when snd_hdac_bus_init_chip() is called when controller is not in reset. In this case, STATESTS can be cleared. This can be useful e.g. when forcing a controller reset to retry codec probe. A normal non-power-on reset will not clear the bits. However, this old logic is problematic when controller is already in reset. The HDA specification states that controller must be taken out of reset before writing to registers other than GCTL.CRST (1.0a spec, 3.3.7). The write to STATESTS in snd_hdac_bus_reset_link() will be lost if the controller is already in reset per the HDA specification mentioned. This has been harmless on older hardware. On newer generation of Intel PCIe based HDA controllers, if configured to report issues, this write will emit an unsupported request error. If ACPI Platform Error Interface (APEI) is enabled in kernel, this will end up to kernel log. Fix the code in snd_hdac_bus_reset_link() to only clear the STATESTS if the function is called when controller is not in reset. Otherwise clearing the bits is not possible and should be skipped. Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20211012142935.3731820-1-kai.vehmanen@linux.intel.com Signed-off-by: Takashi Iwai --- sound/hda/hdac_controller.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index 062da7a7a586..f7bd6e2db085 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c @@ -421,8 +421,9 @@ int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset) if (!full_reset) goto skip_reset; - /* clear STATESTS */ - snd_hdac_chip_writew(bus, STATESTS, STATESTS_INT_MASK); + /* clear STATESTS if not in reset */ + if (snd_hdac_chip_readb(bus, GCTL) & AZX_GCTL_RESET) + snd_hdac_chip_writew(bus, STATESTS, STATESTS_INT_MASK); /* reset controller */ snd_hdac_bus_enter_link_reset(bus); -- cgit From 13dbc954b3c9a9de0ad5b7279e8d3b708d31068b Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Tue, 31 Aug 2021 14:58:42 +0200 Subject: ARM: dts: bcm2711-rpi-4-b: Fix pcie0's unit address formatting dtbs_check currently complains that: arch/arm/boot/dts/bcm2711-rpi-4-b.dts:220.10-231.4: Warning (pci_device_reg): /scb/pcie@7d500000/pci@1,0: PCI unit address format error, expected "0,0" Unsurprisingly pci@0,0 is the right address, as illustrated by its reg property: &pcie0 { pci@0,0 { /* * As defined in the IEEE Std 1275-1994 document, * reg is a five-cell address encoded as (phys.hi * phys.mid phys.lo size.hi size.lo). phys.hi * should contain the device's BDF as 0b00000000 * bbbbbbbb dddddfff 00000000. The other cells * should be zero. */ reg = <0 0 0 0 0>; }; }; The device is clearly 0. So fix it. Also add a missing 'device_type = "pci"'. Fixes: 258f92d2f840 ("ARM: dts: bcm2711: Add reset controller to xHCI node") Suggested-by: Rob Herring Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20210831125843.1233488-1-nsaenzju@redhat.com Signed-off-by: Nicolas Saenz Julienne --- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts index abf8298610a7..43cd71574115 100644 --- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts +++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts @@ -217,7 +217,8 @@ }; &pcie0 { - pci@1,0 { + pci@0,0 { + device_type = "pci"; #address-cells = <3>; #size-cells = <2>; ranges; -- cgit From 3f32472854614d6f53b09b4812372dba9fc5c7de Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Tue, 31 Aug 2021 14:58:43 +0200 Subject: ARM: dts: bcm2711-rpi-4-b: Fix usb's unit address The unit address is supposed to represent ','. Which are both 0 for RPi4b's XHCI controller. On top of that although OpenFirmware states bus number goes in the high part of the last reg parameter, FDT doesn't seem to care for it[1], so remove it. [1] https://patchwork.kernel.org/project/linux-arm-kernel/patch/20210830103909.323356-1-nsaenzju@redhat.com/#24414633 Fixes: 258f92d2f840 ("ARM: dts: bcm2711: Add reset controller to xHCI node") Suggested-by: Rob Herring Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20210831125843.1233488-2-nsaenzju@redhat.com Signed-off-by: Nicolas Saenz Julienne --- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts index 43cd71574115..72ce80fbf266 100644 --- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts +++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts @@ -225,8 +225,8 @@ reg = <0 0 0 0 0>; - usb@1,0 { - reg = <0x10000 0 0 0 0>; + usb@0,0 { + reg = <0 0 0 0 0>; resets = <&reset RASPBERRYPI_FIRMWARE_RESET_ID_USB>; }; }; -- cgit From 7904022decc260a19dd65b56ac896387f5da6f8c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 12 Oct 2021 11:44:43 +0300 Subject: block/rnbd-clt-sysfs: fix a couple uninitialized variable bugs These variables are printed on the error path if match_int() fails so they have to be initialized. Fixes: 2958a995edc9 ("block/rnbd-clt: Support polling mode for IO latency optimization") Fixes: 1eb54f8f5dd8 ("block/rnbd: client: sysfs interface functions") Signed-off-by: Dan Carpenter Acked-by: Gioh Kim Link: https://lore.kernel.org/r/20211012084443.GA31472@kili Signed-off-by: Jens Axboe --- drivers/block/rnbd/rnbd-clt-sysfs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/block/rnbd/rnbd-clt-sysfs.c b/drivers/block/rnbd/rnbd-clt-sysfs.c index 4b93fd83bf79..44e45af00e83 100644 --- a/drivers/block/rnbd/rnbd-clt-sysfs.c +++ b/drivers/block/rnbd/rnbd-clt-sysfs.c @@ -71,8 +71,10 @@ static int rnbd_clt_parse_map_options(const char *buf, size_t max_path_cnt, int opt_mask = 0; int token; int ret = -EINVAL; - int i, dest_port, nr_poll_queues; + int nr_poll_queues = 0; + int dest_port = 0; int p_cnt = 0; + int i; options = kstrdup(buf, GFP_KERNEL); if (!options) -- cgit From 596143e3aec35c93508d6b7a05ddc999ee209b61 Mon Sep 17 00:00:00 2001 From: Jackie Liu Date: Mon, 23 Aug 2021 17:25:26 +0800 Subject: acpi/arm64: fix next_platform_timer() section mismatch error Fix modpost Section mismatch error in next_platform_timer(). [...] WARNING: modpost: vmlinux.o(.text.unlikely+0x26e60): Section mismatch in reference from the function next_platform_timer() to the variable .init.data:acpi_gtdt_desc The function next_platform_timer() references the variable __initdata acpi_gtdt_desc. This is often because next_platform_timer lacks a __initdata annotation or the annotation of acpi_gtdt_desc is wrong. WARNING: modpost: vmlinux.o(.text.unlikely+0x26e64): Section mismatch in reference from the function next_platform_timer() to the variable .init.data:acpi_gtdt_desc The function next_platform_timer() references the variable __initdata acpi_gtdt_desc. This is often because next_platform_timer lacks a __initdata annotation or the annotation of acpi_gtdt_desc is wrong. ERROR: modpost: Section mismatches detected. Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them. make[1]: *** [scripts/Makefile.modpost:59: vmlinux.symvers] Error 1 make[1]: *** Deleting file 'vmlinux.symvers' make: *** [Makefile:1176: vmlinux] Error 2 [...] Fixes: a712c3ed9b8a ("acpi/arm64: Add memory-mapped timer support in GTDT driver") Signed-off-by: Jackie Liu Acked-by: Hanjun Guo Link: https://lore.kernel.org/r/20210823092526.2407526-1-liu.yun@linux.dev Signed-off-by: Catalin Marinas --- drivers/acpi/arm64/gtdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c index 0a0a982f9c28..c0e77c1c8e09 100644 --- a/drivers/acpi/arm64/gtdt.c +++ b/drivers/acpi/arm64/gtdt.c @@ -36,7 +36,7 @@ struct acpi_gtdt_descriptor { static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata; -static inline void *next_platform_timer(void *platform_timer) +static inline __init void *next_platform_timer(void *platform_timer) { struct acpi_gtdt_header *gh = platform_timer; -- cgit From 2c0468e054c0adb660ac055fc396622ec7235df9 Mon Sep 17 00:00:00 2001 From: Akilesh Kailash Date: Mon, 13 Sep 2021 09:26:42 +0000 Subject: dm verity: skip redundant verity_handle_err() on I/O errors Without FEC, dm-verity won't call verity_handle_err() when I/O fails, but with FEC enabled, it currently does even if an I/O error has occurred. If there is an I/O error and FEC correction fails, return the error instead of calling verity_handle_err() again. Suggested-by: Sami Tolvanen Signed-off-by: Akilesh Kailash Reviewed-by: Sami Tolvanen Signed-off-by: Mike Snitzer --- drivers/md/dm-verity-target.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index 22a5ac82446a..88288c8d6bc8 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -475,6 +475,7 @@ static int verity_verify_io(struct dm_verity_io *io) struct bvec_iter start; unsigned b; struct crypto_wait wait; + struct bio *bio = dm_bio_from_per_bio_data(io, v->ti->per_io_data_size); for (b = 0; b < io->n_blocks; b++) { int r; @@ -529,9 +530,17 @@ static int verity_verify_io(struct dm_verity_io *io) else if (verity_fec_decode(v, io, DM_VERITY_BLOCK_TYPE_DATA, cur_block, NULL, &start) == 0) continue; - else if (verity_handle_err(v, DM_VERITY_BLOCK_TYPE_DATA, - cur_block)) - return -EIO; + else { + if (bio->bi_status) { + /* + * Error correction failed; Just return error + */ + return -EIO; + } + if (verity_handle_err(v, DM_VERITY_BLOCK_TYPE_DATA, + cur_block)) + return -EIO; + } } return 0; -- cgit From ec132ef2d1d94d43d9dce1400521526bbed89a8b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 15 Sep 2021 12:14:40 +0100 Subject: dm clone: make array 'descs' static Don't populate the read-only array descs on the stack but instead it static and add extra const. Also makes the object code smaller by 66 bytes: Before: text data bss dec hex filename 42382 11140 512 54034 d312 ./drivers/md/dm-clone-target.o After: text data bss dec hex filename 42220 11236 512 53968 d2d0 ./drivers/md/dm-clone-target.o (gcc version 11.2.0) Signed-off-by: Colin Ian King Signed-off-by: Mike Snitzer --- drivers/md/dm-clone-target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/dm-clone-target.c b/drivers/md/dm-clone-target.c index 84dbe08ad205..edd22e4d65df 100644 --- a/drivers/md/dm-clone-target.c +++ b/drivers/md/dm-clone-target.c @@ -161,7 +161,7 @@ static const char *clone_device_name(struct clone *clone) static void __set_clone_mode(struct clone *clone, enum clone_metadata_mode new_mode) { - const char *descs[] = { + static const char * const descs[] = { "read-write", "read-only", "fail" -- cgit From b4459b11e84092658fa195a2587aff3b9637f0e7 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 23 Sep 2021 17:11:31 +0800 Subject: dm rq: don't queue request to blk-mq during DM suspend DM uses blk-mq's quiesce/unquiesce to stop/start device mapper queue. But blk-mq's unquiesce may come from outside events, such as elevator switch, updating nr_requests or others, and request may come during suspend, so simply ask for blk-mq to requeue it. Fixes one kernel panic issue when running updating nr_requests and dm-mpath suspend/resume stress test. Cc: stable@vger.kernel.org Signed-off-by: Ming Lei Signed-off-by: Mike Snitzer --- drivers/md/dm-rq.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index 5b95eea517d1..a896dea9750e 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -490,6 +490,14 @@ static blk_status_t dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx, struct mapped_device *md = tio->md; struct dm_target *ti = md->immutable_target; + /* + * blk-mq's unquiesce may come from outside events, such as + * elevator switch, updating nr_requests or others, and request may + * come during suspend, so simply ask for blk-mq to requeue it. + */ + if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags))) + return BLK_STS_RESOURCE; + if (unlikely(!ti)) { int srcu_idx; struct dm_table *map = dm_get_live_table(md, &srcu_idx); -- cgit From d208b89401e073de986dc891037c5a668f5d5d95 Mon Sep 17 00:00:00 2001 From: Jiazi Li Date: Wed, 29 Sep 2021 19:59:28 +0800 Subject: dm: fix mempool NULL pointer race when completing IO dm_io_dec_pending() calls end_io_acct() first and will then dec md in-flight pending count. But if a task is swapping DM table at same time this can result in a crash due to mempool->elements being NULL: task1 task2 do_resume ->do_suspend ->dm_wait_for_completion bio_endio ->clone_endio ->dm_io_dec_pending ->end_io_acct ->wakeup task1 ->dm_swap_table ->__bind ->__bind_mempools ->bioset_exit ->mempool_exit ->free_io [ 67.330330] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 ...... [ 67.330494] pstate: 80400085 (Nzcv daIf +PAN -UAO) [ 67.330510] pc : mempool_free+0x70/0xa0 [ 67.330515] lr : mempool_free+0x4c/0xa0 [ 67.330520] sp : ffffff8008013b20 [ 67.330524] x29: ffffff8008013b20 x28: 0000000000000004 [ 67.330530] x27: ffffffa8c2ff40a0 x26: 00000000ffff1cc8 [ 67.330535] x25: 0000000000000000 x24: ffffffdada34c800 [ 67.330541] x23: 0000000000000000 x22: ffffffdada34c800 [ 67.330547] x21: 00000000ffff1cc8 x20: ffffffd9a1304d80 [ 67.330552] x19: ffffffdada34c970 x18: 000000b312625d9c [ 67.330558] x17: 00000000002dcfbf x16: 00000000000006dd [ 67.330563] x15: 000000000093b41e x14: 0000000000000010 [ 67.330569] x13: 0000000000007f7a x12: 0000000034155555 [ 67.330574] x11: 0000000000000001 x10: 0000000000000001 [ 67.330579] x9 : 0000000000000000 x8 : 0000000000000000 [ 67.330585] x7 : 0000000000000000 x6 : ffffff80148b5c1a [ 67.330590] x5 : ffffff8008013ae0 x4 : 0000000000000001 [ 67.330596] x3 : ffffff80080139c8 x2 : ffffff801083bab8 [ 67.330601] x1 : 0000000000000000 x0 : ffffffdada34c970 [ 67.330609] Call trace: [ 67.330616] mempool_free+0x70/0xa0 [ 67.330627] bio_put+0xf8/0x110 [ 67.330638] dec_pending+0x13c/0x230 [ 67.330644] clone_endio+0x90/0x180 [ 67.330649] bio_endio+0x198/0x1b8 [ 67.330655] dec_pending+0x190/0x230 [ 67.330660] clone_endio+0x90/0x180 [ 67.330665] bio_endio+0x198/0x1b8 [ 67.330673] blk_update_request+0x214/0x428 [ 67.330683] scsi_end_request+0x2c/0x300 [ 67.330688] scsi_io_completion+0xa0/0x710 [ 67.330695] scsi_finish_command+0xd8/0x110 [ 67.330700] scsi_softirq_done+0x114/0x148 [ 67.330708] blk_done_softirq+0x74/0xd0 [ 67.330716] __do_softirq+0x18c/0x374 [ 67.330724] irq_exit+0xb4/0xb8 [ 67.330732] __handle_domain_irq+0x84/0xc0 [ 67.330737] gic_handle_irq+0x148/0x1b0 [ 67.330744] el1_irq+0xe8/0x190 [ 67.330753] lpm_cpuidle_enter+0x4f8/0x538 [ 67.330759] cpuidle_enter_state+0x1fc/0x398 [ 67.330764] cpuidle_enter+0x18/0x20 [ 67.330772] do_idle+0x1b4/0x290 [ 67.330778] cpu_startup_entry+0x20/0x28 [ 67.330786] secondary_start_kernel+0x160/0x170 Fix this by: 1) Establishing pointers to 'struct dm_io' members in dm_io_dec_pending() so that they may be passed into end_io_acct() _after_ free_io() is called. 2) Moving end_io_acct() after free_io(). Cc: stable@vger.kernel.org Signed-off-by: Jiazi Li Signed-off-by: Mike Snitzer --- drivers/md/dm.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index a011d09cb0fa..76d9da49fda7 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -496,18 +496,17 @@ static void start_io_acct(struct dm_io *io) false, 0, &io->stats_aux); } -static void end_io_acct(struct dm_io *io) +static void end_io_acct(struct mapped_device *md, struct bio *bio, + unsigned long start_time, struct dm_stats_aux *stats_aux) { - struct mapped_device *md = io->md; - struct bio *bio = io->orig_bio; - unsigned long duration = jiffies - io->start_time; + unsigned long duration = jiffies - start_time; - bio_end_io_acct(bio, io->start_time); + bio_end_io_acct(bio, start_time); if (unlikely(dm_stats_used(&md->stats))) dm_stats_account_io(&md->stats, bio_data_dir(bio), bio->bi_iter.bi_sector, bio_sectors(bio), - true, duration, &io->stats_aux); + true, duration, stats_aux); /* nudge anyone waiting on suspend queue */ if (unlikely(wq_has_sleeper(&md->wait))) @@ -790,6 +789,8 @@ void dm_io_dec_pending(struct dm_io *io, blk_status_t error) blk_status_t io_error; struct bio *bio; struct mapped_device *md = io->md; + unsigned long start_time = 0; + struct dm_stats_aux stats_aux; /* Push-back supersedes any I/O errors */ if (unlikely(error)) { @@ -821,8 +822,10 @@ void dm_io_dec_pending(struct dm_io *io, blk_status_t error) } io_error = io->status; - end_io_acct(io); + start_time = io->start_time; + stats_aux = io->stats_aux; free_io(md, io); + end_io_acct(md, bio, start_time, &stats_aux); if (io_error == BLK_STS_DM_REQUEUE) return; -- cgit From 48827e1d6af58f219e89c7ec08dccbca28c7694e Mon Sep 17 00:00:00 2001 From: Jonas Hahnfeld Date: Tue, 12 Oct 2021 22:09:07 +0200 Subject: ALSA: usb-audio: Add quirk for VF0770 The device advertises 8 formats, but only a rate of 48kHz is honored by the hardware and 24 bits give chopped audio, so only report the one working combination. This fixes out-of-the-box audio experience with PipeWire which otherwise attempts to choose S24_3LE (while PulseAudio defaulted to S16_LE). Signed-off-by: Jonas Hahnfeld Cc: Link: https://lore.kernel.org/r/20211012200906.3492-1-hahnjo@hahnjo.de Signed-off-by: Takashi Iwai --- sound/usb/quirks-table.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index e03043f7dad3..de18fff69280 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -77,6 +77,48 @@ /* E-Mu 0204 USB */ { USB_DEVICE_VENDOR_SPEC(0x041e, 0x3f19) }, +/* + * Creative Technology, Ltd Live! Cam Sync HD [VF0770] + * The device advertises 8 formats, but only a rate of 48kHz is honored by the + * hardware and 24 bits give chopped audio, so only report the one working + * combination. + */ +{ + USB_DEVICE(0x041e, 0x4095), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = &(const struct snd_usb_audio_quirk[]) { + { + .ifnum = 2, + .type = QUIRK_AUDIO_STANDARD_MIXER, + }, + { + .ifnum = 3, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .channels = 2, + .fmt_bits = 16, + .iface = 3, + .altsetting = 4, + .altset_idx = 4, + .endpoint = 0x82, + .ep_attr = 0x05, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { 48000 }, + }, + }, + { + .ifnum = -1 + }, + }, + }, +}, + /* * HP Wireless Audio * When not ignored, causes instability issues for some users, forcing them to -- cgit From 2266bb1e122a4f7cdf3427defcfb48e5c6a8f205 Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Mon, 13 Sep 2021 15:48:11 +0300 Subject: net/mlx5: Fix cleanup of bridge delayed work Currently, bridge cleanup is calling to cancel_delayed_work(). When this function is finished, there is a chance that the delayed work is still running. Also, the delayed work is queueing itself. As a result, we might execute the delayed work after the bridge cleanup have finished and hit a null-ptr oops[1]. Fix it by using cancel_delayed_work_sync(), which is waiting until the work is done and will cancel the queue work. [1] [ 8202.143043 ] BUG: kernel NULL pointer dereference, address: 0000000000000000 [ 8202.144438 ] #PF: supervisor write access in kernel mode [ 8202.145476 ] #PF: error_code(0x0002) - not-present page [ 8202.146520 ] PGD 0 P4D 0 [ 8202.147126 ] Oops: 0002 [#1] SMP NOPTI [ 8202.147899 ] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 5.14.0-rc6_for_upstream_min_debug_2021_08_25_16_06 #1 [ 8202.149741 ] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 [ 8202.151908 ] RIP: 0010:_raw_spin_lock+0xc/0x20 [ 8202.156234 ] RSP: 0018:ffff88846f885ea0 EFLAGS: 00010046 [ 8202.157289 ] RAX: 0000000000000000 RBX: ffff88846f880000 RCX: 0000000000000000 [ 8202.158731 ] RDX: 0000000000000001 RSI: ffff8881004000c8 RDI: 0000000000000000 [ 8202.160177 ] RBP: ffff8881fe684978 R08: ffff888100140000 R09: ffffffff824455b8 [ 8202.161569 ] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000001 [ 8202.163004 ] R13: 0000000000000012 R14: 0000000000000200 R15: ffff88812992d000 [ 8202.164018 ] FS: 0000000000000000(0000) GS:ffff88846f880000(0000) knlGS:0000000000000000 [ 8202.164960 ] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 8202.165634 ] CR2: 0000000000000000 CR3: 0000000108cac004 CR4: 0000000000370ea0 [ 8202.166450 ] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 8202.167807 ] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 8202.168852 ] Call Trace: [ 8202.169421 ] [ 8202.169792 ] __queue_work+0xf2/0x3d0 [ 8202.170481 ] ? queue_work_node+0x40/0x40 [ 8202.171270 ] call_timer_fn+0x2b/0x100 [ 8202.171932 ] __run_timers.part.0+0x152/0x220 [ 8202.172717 ] ? __hrtimer_run_queues+0x171/0x290 [ 8202.173526 ] ? kvm_clock_get_cycles+0xd/0x10 [ 8202.174232 ] ? ktime_get+0x35/0x90 [ 8202.174943 ] run_timer_softirq+0x26/0x50 [ 8202.175745 ] __do_softirq+0xc7/0x271 [ 8202.176373 ] irq_exit_rcu+0x93/0xb0 [ 8202.176983 ] sysvec_apic_timer_interrupt+0x72/0x90 [ 8202.177755 ] [ 8202.178245 ] asm_sysvec_apic_timer_interrupt+0x12/0x20 Fixes: c636a0f0f3f0 ("net/mlx5: Bridge, dynamic entry ageing") Signed-off-by: Shay Drory Reviewed-by: Vlad Buslov Reviewed-by: Leon Romanovsky Reviewed-by: Maor Gottlieb Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c index b5ddaa82755f..c6d2f8c78db7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c @@ -475,9 +475,6 @@ void mlx5e_rep_bridge_init(struct mlx5e_priv *priv) esw_warn(mdev, "Failed to allocate bridge offloads workqueue\n"); goto err_alloc_wq; } - INIT_DELAYED_WORK(&br_offloads->update_work, mlx5_esw_bridge_update_work); - queue_delayed_work(br_offloads->wq, &br_offloads->update_work, - msecs_to_jiffies(MLX5_ESW_BRIDGE_UPDATE_INTERVAL)); br_offloads->nb.notifier_call = mlx5_esw_bridge_switchdev_event; err = register_switchdev_notifier(&br_offloads->nb); @@ -500,6 +497,9 @@ void mlx5e_rep_bridge_init(struct mlx5e_priv *priv) err); goto err_register_netdev; } + INIT_DELAYED_WORK(&br_offloads->update_work, mlx5_esw_bridge_update_work); + queue_delayed_work(br_offloads->wq, &br_offloads->update_work, + msecs_to_jiffies(MLX5_ESW_BRIDGE_UPDATE_INTERVAL)); return; err_register_netdev: @@ -523,10 +523,10 @@ void mlx5e_rep_bridge_cleanup(struct mlx5e_priv *priv) if (!br_offloads) return; + cancel_delayed_work_sync(&br_offloads->update_work); unregister_netdevice_notifier(&br_offloads->netdev_nb); unregister_switchdev_blocking_notifier(&br_offloads->nb_blk); unregister_switchdev_notifier(&br_offloads->nb); - cancel_delayed_work(&br_offloads->update_work); destroy_workqueue(br_offloads->wq); rtnl_lock(); mlx5_esw_bridge_cleanup(esw); -- cgit From ca20dfda05ae0531c8f5117b6ac989816f6cf658 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Mon, 4 Oct 2021 15:04:25 +0300 Subject: net/mlx5e: Allow only complete TXQs partition in MQPRIO channel mode Do not allow configurations of MQPRIO channel mode that do not fully define and utilize the channels txqs. Fixes: ec60c4581bd9 ("net/mlx5e: Support MQPRIO channel mode") Signed-off-by: Tariq Toukan Reviewed-by: Maxim Mikityanskiy Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 0c5197f9cea3..336aa07313da 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2981,8 +2981,8 @@ static int mlx5e_mqprio_channel_validate(struct mlx5e_priv *priv, agg_count += mqprio->qopt.count[i]; } - if (priv->channels.params.num_channels < agg_count) { - netdev_err(netdev, "Num of queues (%d) exceeds available (%d)\n", + if (priv->channels.params.num_channels != agg_count) { + netdev_err(netdev, "Num of queues (%d) does not match available (%d)\n", agg_count, priv->channels.params.num_channels); return -EINVAL; } -- cgit From 94b960b9deffc02fc0747afc01f72cc62ab099e3 Mon Sep 17 00:00:00 2001 From: Valentine Fatiev Date: Sun, 15 Aug 2021 17:43:19 +0300 Subject: net/mlx5e: Fix memory leak in mlx5_core_destroy_cq() error path Prior to this patch in case mlx5_core_destroy_cq() failed it returns without completing all destroy operations and that leads to memory leak. Instead, complete the destroy flow before return error. Also move mlx5_debug_cq_remove() to the beginning of mlx5_core_destroy_cq() to be symmetrical with mlx5_core_create_cq(). kmemleak complains on: unreferenced object 0xc000000038625100 (size 64): comm "ethtool", pid 28301, jiffies 4298062946 (age 785.380s) hex dump (first 32 bytes): 60 01 48 94 00 00 00 c0 b8 05 34 c3 00 00 00 c0 `.H.......4..... 02 00 00 00 00 00 00 00 00 db 7d c1 00 00 00 c0 ..........}..... backtrace: [<000000009e8643cb>] add_res_tree+0xd0/0x270 [mlx5_core] [<00000000e7cb8e6c>] mlx5_debug_cq_add+0x5c/0xc0 [mlx5_core] [<000000002a12918f>] mlx5_core_create_cq+0x1d0/0x2d0 [mlx5_core] [<00000000cef0a696>] mlx5e_create_cq+0x210/0x3f0 [mlx5_core] [<000000009c642c26>] mlx5e_open_cq+0xb4/0x130 [mlx5_core] [<0000000058dfa578>] mlx5e_ptp_open+0x7f4/0xe10 [mlx5_core] [<0000000081839561>] mlx5e_open_channels+0x9cc/0x13e0 [mlx5_core] [<0000000009cf05d4>] mlx5e_switch_priv_channels+0xa4/0x230 [mlx5_core] [<0000000042bbedd8>] mlx5e_safe_switch_params+0x14c/0x300 [mlx5_core] [<0000000004bc9db8>] set_pflag_tx_port_ts+0x9c/0x160 [mlx5_core] [<00000000a0553443>] mlx5e_set_priv_flags+0xd0/0x1b0 [mlx5_core] [<00000000a8f3d84b>] ethnl_set_privflags+0x234/0x2d0 [<00000000fd27f27c>] genl_family_rcv_msg_doit+0x108/0x1d0 [<00000000f495e2bb>] genl_family_rcv_msg+0xe4/0x1f0 [<00000000646c5c2c>] genl_rcv_msg+0x78/0x120 [<00000000d53e384e>] netlink_rcv_skb+0x74/0x1a0 Fixes: e126ba97dba9 ("mlx5: Add driver for Mellanox Connect-IB adapters") Signed-off-by: Valentine Fatiev Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/cq.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cq.c b/drivers/net/ethernet/mellanox/mlx5/core/cq.c index cf97985628ab..02e77ffe5c3e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cq.c @@ -155,6 +155,8 @@ int mlx5_core_destroy_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq) u32 in[MLX5_ST_SZ_DW(destroy_cq_in)] = {}; int err; + mlx5_debug_cq_remove(dev, cq); + mlx5_eq_del_cq(mlx5_get_async_eq(dev), cq); mlx5_eq_del_cq(&cq->eq->core, cq); @@ -162,16 +164,13 @@ int mlx5_core_destroy_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq) MLX5_SET(destroy_cq_in, in, cqn, cq->cqn); MLX5_SET(destroy_cq_in, in, uid, cq->uid); err = mlx5_cmd_exec_in(dev, destroy_cq, in); - if (err) - return err; synchronize_irq(cq->irqn); - mlx5_debug_cq_remove(dev, cq); mlx5_cq_put(cq); wait_for_completion(&cq->free); - return 0; + return err; } EXPORT_SYMBOL(mlx5_core_destroy_cq); -- cgit From b2107cdc43d8601f2cadfba990ae844cc1f44e68 Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Mon, 4 Oct 2021 21:20:25 -0700 Subject: net/mlx5e: Switchdev representors are not vlan challenged Before this patch, mlx5 representors advertised the NETIF_F_VLAN_CHALLENGED bit, this could lead to missing features when using reps with vxlan/bridge and maybe other virtual interfaces, when such interfaces inherit this bit and block vlan usage in their topology. Example: $ip link add dev bridge type bridge # add representor interface to the bridge $ip link set dev pf0hpf master $ip link add link bridge name vlan10 type vlan id 10 protocol 802.1q Error: 8021q: VLANs not supported on device. Reps are perfectly capable of handling vlan traffic, although they don't implement vlan_{add,kill}_vid ndos, hence, remove NETIF_F_VLAN_CHALLENGED advertisement. Fixes: cb67b832921c ("net/mlx5e: Introduce SRIOV VF representors") Reported-by: Roopa Prabhu Signed-off-by: Saeed Mahameed Reviewed-by: Roi Dayan --- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 3dd1101cc693..0439203fc7d9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -643,7 +643,6 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev, netdev->hw_features |= NETIF_F_RXCSUM; netdev->features |= netdev->hw_features; - netdev->features |= NETIF_F_VLAN_CHALLENGED; netdev->features |= NETIF_F_NETNS_LOCAL; } -- cgit From 0bc73ad46a76ed6ece4dcacb28858e7b38561e1c Mon Sep 17 00:00:00 2001 From: Aya Levin Date: Sun, 26 Sep 2021 17:55:41 +0300 Subject: net/mlx5e: Mutually exclude RX-FCS and RX-port-timestamp Due to current HW arch limitations, RX-FCS (scattering FCS frame field to software) and RX-port-timestamp (improved timestamp accuracy on the receive side) can't work together. RX-port-timestamp is not controlled by the user and it is enabled by default when supported by the HW/FW. This patch sets RX-port-timestamp opposite to RX-FCS configuration. Fixes: 102722fc6832 ("net/mlx5e: Add support for RXFCS feature flag") Signed-off-by: Aya Levin Reviewed-by: Tariq Toukan Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 57 +++++++++++++++++++++-- include/linux/mlx5/mlx5_ifc.h | 10 +++- 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 336aa07313da..09c8b71b186c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -3325,20 +3325,67 @@ static int set_feature_rx_all(struct net_device *netdev, bool enable) return mlx5_set_port_fcs(mdev, !enable); } +static int mlx5e_set_rx_port_ts(struct mlx5_core_dev *mdev, bool enable) +{ + u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {}; + bool supported, curr_state; + int err; + + if (!MLX5_CAP_GEN(mdev, ports_check)) + return 0; + + err = mlx5_query_ports_check(mdev, in, sizeof(in)); + if (err) + return err; + + supported = MLX5_GET(pcmr_reg, in, rx_ts_over_crc_cap); + curr_state = MLX5_GET(pcmr_reg, in, rx_ts_over_crc); + + if (!supported || enable == curr_state) + return 0; + + MLX5_SET(pcmr_reg, in, local_port, 1); + MLX5_SET(pcmr_reg, in, rx_ts_over_crc, enable); + + return mlx5_set_ports_check(mdev, in, sizeof(in)); +} + static int set_feature_rx_fcs(struct net_device *netdev, bool enable) { struct mlx5e_priv *priv = netdev_priv(netdev); + struct mlx5e_channels *chs = &priv->channels; + struct mlx5_core_dev *mdev = priv->mdev; int err; mutex_lock(&priv->state_lock); - priv->channels.params.scatter_fcs_en = enable; - err = mlx5e_modify_channels_scatter_fcs(&priv->channels, enable); - if (err) - priv->channels.params.scatter_fcs_en = !enable; + if (enable) { + err = mlx5e_set_rx_port_ts(mdev, false); + if (err) + goto out; - mutex_unlock(&priv->state_lock); + chs->params.scatter_fcs_en = true; + err = mlx5e_modify_channels_scatter_fcs(chs, true); + if (err) { + chs->params.scatter_fcs_en = false; + mlx5e_set_rx_port_ts(mdev, true); + } + } else { + chs->params.scatter_fcs_en = false; + err = mlx5e_modify_channels_scatter_fcs(chs, false); + if (err) { + chs->params.scatter_fcs_en = true; + goto out; + } + err = mlx5e_set_rx_port_ts(mdev, true); + if (err) { + mlx5_core_warn(mdev, "Failed to set RX port timestamp %d\n", err); + err = 0; + } + } +out: + mutex_unlock(&priv->state_lock); return err; } diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index f3638d09ba77..993204a6c1a1 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -9475,16 +9475,22 @@ struct mlx5_ifc_pcmr_reg_bits { u8 reserved_at_0[0x8]; u8 local_port[0x8]; u8 reserved_at_10[0x10]; + u8 entropy_force_cap[0x1]; u8 entropy_calc_cap[0x1]; u8 entropy_gre_calc_cap[0x1]; - u8 reserved_at_23[0x1b]; + u8 reserved_at_23[0xf]; + u8 rx_ts_over_crc_cap[0x1]; + u8 reserved_at_33[0xb]; u8 fcs_cap[0x1]; u8 reserved_at_3f[0x1]; + u8 entropy_force[0x1]; u8 entropy_calc[0x1]; u8 entropy_gre_calc[0x1]; - u8 reserved_at_43[0x1b]; + u8 reserved_at_43[0xf]; + u8 rx_ts_over_crc[0x1]; + u8 reserved_at_53[0xb]; u8 fcs_chk[0x1]; u8 reserved_at_5f[0x1]; }; -- cgit From 84c8a87402cf073ba7948dd62d4815a3f4a224c8 Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Mon, 11 Oct 2021 18:39:35 +0300 Subject: net/mlx5e: Fix division by 0 in mlx5e_select_queue for representors Commit 846d6da1fcdb ("net/mlx5e: Fix division by 0 in mlx5e_select_queue") makes mlx5e_build_nic_params assign a non-zero initial value to priv->num_tc_x_num_ch, so that mlx5e_select_queue doesn't fail with division by 0 if called before the first activation of channels. However, the initialization flow of representors doesn't call mlx5e_build_nic_params, so this bug can still happen with representors. This commit fixes the bug by adding the missing assignment to mlx5e_build_rep_params. Fixes: 846d6da1fcdb ("net/mlx5e: Fix division by 0 in mlx5e_select_queue") Signed-off-by: Maxim Mikityanskiy Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 0439203fc7d9..0684ac6699b2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -618,6 +618,11 @@ static void mlx5e_build_rep_params(struct net_device *netdev) params->mqprio.num_tc = 1; params->tunneled_offload_en = false; + /* Set an initial non-zero value, so that mlx5e_select_queue won't + * divide by zero if called before first activating channels. + */ + priv->num_tc_x_num_ch = params->num_channels * params->mqprio.num_tc; + mlx5_query_min_inline(mdev, ¶ms->tx_min_inline_mode); } -- cgit From 0dee6f70fd40e3375d45d3f93abdf6a57fc0e549 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 22 Aug 2021 02:44:27 +0300 Subject: drm: rcar-du: Don't create encoder for unconnected LVDS outputs On R-Car D3 and E3, the LVDS encoders provide the pixel clock to the DU, even when LVDS outputs are not used. For this reason, the rcar-lvds driver probes successfully on those platforms even if no further bridge or panel is connected to the LVDS output, in order to provide the rcar_lvds_clk_enable() and rcar_lvds_clk_disable() functions to the DU driver. If an LVDS output isn't connected, trying to create a DRM connector for the output will fail. Fix this by skipping connector creation in that case, and also skip creation of the DRM encoder as there's no point in an encoder without a connector. Fixes: e9e056949c92 ("drm: rcar-du: lvds: Convert to DRM panel bridge helper") Reported-by: Geert Uytterhoeven Signed-off-by: Laurent Pinchart Tested-by: Geert Uytterhoeven (cherry picked from commit 187502afe87a0fc96832056558978fa423920ee0) Signed-off-by: Dave Airlie --- drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 16 ++++++++++++---- drivers/gpu/drm/rcar-du/rcar_lvds.c | 11 +++++++++++ drivers/gpu/drm/rcar-du/rcar_lvds.h | 5 +++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index 0daa8bba50f5..4bf4e25d7f01 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c @@ -86,12 +86,20 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu, } /* - * Create and initialize the encoder. On Gen3 skip the LVDS1 output if + * Create and initialize the encoder. On Gen3, skip the LVDS1 output if * the LVDS1 encoder is used as a companion for LVDS0 in dual-link - * mode. + * mode, or any LVDS output if it isn't connected. The latter may happen + * on D3 or E3 as the LVDS encoders are needed to provide the pixel + * clock to the DU, even when the LVDS outputs are not used. */ - if (rcdu->info->gen >= 3 && output == RCAR_DU_OUTPUT_LVDS1) { - if (rcar_lvds_dual_link(bridge)) + if (rcdu->info->gen >= 3) { + if (output == RCAR_DU_OUTPUT_LVDS1 && + rcar_lvds_dual_link(bridge)) + return -ENOLINK; + + if ((output == RCAR_DU_OUTPUT_LVDS0 || + output == RCAR_DU_OUTPUT_LVDS1) && + !rcar_lvds_is_connected(bridge)) return -ENOLINK; } diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c index d061b8de748f..b672c5bd72ee 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c @@ -576,6 +576,9 @@ static int rcar_lvds_attach(struct drm_bridge *bridge, { struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); + if (!lvds->next_bridge) + return 0; + return drm_bridge_attach(bridge->encoder, lvds->next_bridge, bridge, flags); } @@ -598,6 +601,14 @@ bool rcar_lvds_dual_link(struct drm_bridge *bridge) } EXPORT_SYMBOL_GPL(rcar_lvds_dual_link); +bool rcar_lvds_is_connected(struct drm_bridge *bridge) +{ + struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); + + return lvds->next_bridge != NULL; +} +EXPORT_SYMBOL_GPL(rcar_lvds_is_connected); + /* ----------------------------------------------------------------------------- * Probe & Remove */ diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.h b/drivers/gpu/drm/rcar-du/rcar_lvds.h index 222ec0e60785..eb7c6ef03b00 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds.h +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.h @@ -16,6 +16,7 @@ struct drm_bridge; int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq); void rcar_lvds_clk_disable(struct drm_bridge *bridge); bool rcar_lvds_dual_link(struct drm_bridge *bridge); +bool rcar_lvds_is_connected(struct drm_bridge *bridge); #else static inline int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq) @@ -27,6 +28,10 @@ static inline bool rcar_lvds_dual_link(struct drm_bridge *bridge) { return false; } +static inline bool rcar_lvds_is_connected(struct drm_bridge *bridge) +{ + return false; +} #endif /* CONFIG_DRM_RCAR_LVDS */ #endif /* __RCAR_LVDS_H__ */ -- cgit From 60d950f443a52d950126ad664fbd4a1eb8353dc9 Mon Sep 17 00:00:00 2001 From: Baowen Zheng Date: Tue, 12 Oct 2021 14:48:50 +0200 Subject: nfp: flow_offload: move flow_indr_dev_register from app init to app start In commit 74fc4f828769 ("net: Fix offloading indirect devices dependency on qdisc order creation"), it adds a process to trigger the callback to setup the bo callback when the driver regists a callback. In our current implement, we are not ready to run the callback when nfp call the function flow_indr_dev_register, then there will be error message as: kernel: Oops: 0000 [#1] SMP PTI kernel: CPU: 0 PID: 14119 Comm: kworker/0:0 Tainted: G kernel: Workqueue: events work_for_cpu_fn kernel: RIP: 0010:nfp_flower_indr_setup_tc_cb+0x258/0x410 kernel: RSP: 0018:ffffbc1e02c57bf8 EFLAGS: 00010286 kernel: RAX: 0000000000000000 RBX: ffff9c761fabc000 RCX: 0000000000000001 kernel: RDX: 0000000000000001 RSI: fffffffffffffff0 RDI: ffffffffc0be9ef1 kernel: RBP: ffffbc1e02c57c58 R08: ffffffffc08f33aa R09: ffff9c6db7478800 kernel: R10: 0000009c003f6e00 R11: ffffbc1e02800000 R12: ffffbc1e000d9000 kernel: R13: ffffbc1e000db428 R14: ffff9c6db7478800 R15: ffff9c761e884e80 kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 kernel: CR2: fffffffffffffff0 CR3: 00000009e260a004 CR4: 00000000007706f0 kernel: DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 kernel: DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 kernel: PKRU: 55555554 kernel: Call Trace: kernel: ? flow_indr_dev_register+0xab/0x210 kernel: ? __cond_resched+0x15/0x30 kernel: ? kmem_cache_alloc_trace+0x44/0x4b0 kernel: ? nfp_flower_setup_tc+0x1d0/0x1d0 [nfp] kernel: flow_indr_dev_register+0x158/0x210 kernel: ? tcf_block_unbind+0xe0/0xe0 kernel: nfp_flower_init+0x40b/0x650 [nfp] kernel: nfp_net_pci_probe+0x25f/0x960 [nfp] kernel: ? nfp_rtsym_read_le+0x76/0x130 [nfp] kernel: nfp_pci_probe+0x6a9/0x820 [nfp] kernel: local_pci_probe+0x45/0x80 So we need to call flow_indr_dev_register in app start process instead of init stage. Fixes: 74fc4f828769 ("net: Fix offloading indirect devices dependency on qdisc order creation") Signed-off-by: Baowen Zheng Signed-off-by: Simon Horman Signed-off-by: Louis Peens Link: https://lore.kernel.org/r/20211012124850.13025-1-louis.peens@corigine.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/netronome/nfp/flower/main.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.c b/drivers/net/ethernet/netronome/nfp/flower/main.c index c029950a81e2..ac1dcfa1d179 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.c +++ b/drivers/net/ethernet/netronome/nfp/flower/main.c @@ -830,10 +830,6 @@ static int nfp_flower_init(struct nfp_app *app) if (err) goto err_cleanup; - err = flow_indr_dev_register(nfp_flower_indr_setup_tc_cb, app); - if (err) - goto err_cleanup; - if (app_priv->flower_ext_feats & NFP_FL_FEATS_VF_RLIM) nfp_flower_qos_init(app); @@ -942,7 +938,20 @@ static int nfp_flower_start(struct nfp_app *app) return err; } - return nfp_tunnel_config_start(app); + err = flow_indr_dev_register(nfp_flower_indr_setup_tc_cb, app); + if (err) + return err; + + err = nfp_tunnel_config_start(app); + if (err) + goto err_tunnel_config; + + return 0; + +err_tunnel_config: + flow_indr_dev_unregister(nfp_flower_indr_setup_tc_cb, app, + nfp_flower_setup_indr_tc_release); + return err; } static void nfp_flower_stop(struct nfp_app *app) -- cgit From 43a4b4dbd48c9006ef64df3a12acf33bdfe11c61 Mon Sep 17 00:00:00 2001 From: Alvin Šipraga Date: Tue, 12 Oct 2021 13:27:31 +0200 Subject: net: dsa: fix spurious error message when unoffloaded port leaves bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flip the sign of a return value check, thereby suppressing the following spurious error: port 2 failed to notify DSA_NOTIFIER_BRIDGE_LEAVE: -EOPNOTSUPP ... which is emitted when removing an unoffloaded DSA switch port from a bridge. Fixes: d371b7c92d19 ("net: dsa: Unset vlan_filtering when ports leave the bridge") Signed-off-by: Alvin Šipraga Reviewed-by: Vladimir Oltean Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20211012112730.3429157-1-alvin@pqrs.dk Signed-off-by: Jakub Kicinski --- net/dsa/switch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/dsa/switch.c b/net/dsa/switch.c index 1c797ec8e2c2..6466d0539af9 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -168,7 +168,7 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds, if (extack._msg) dev_err(ds->dev, "port %d: %s\n", info->port, extack._msg); - if (err && err != EOPNOTSUPP) + if (err && err != -EOPNOTSUPP) return err; } -- cgit From 28da0555c3b542d605e4ca26eea6a740cf2c9174 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Wed, 22 Sep 2021 17:37:25 +0300 Subject: net: dsa: move sja1110_process_meta_tstamp inside the tagging protocol driver The problem is that DSA tagging protocols really must not depend on the switch driver, because this creates a circular dependency at insmod time, and the switch driver will effectively not load when the tagging protocol driver is missing. The code was structured in the way it was for a reason, though. The DSA driver-facing API for PTP timestamping relies on the assumption that two-step TX timestamps are provided by the hardware in an out-of-band manner, typically by raising an interrupt and making that timestamp available inside some sort of FIFO which is to be accessed over SPI/MDIO/etc. So the API puts .port_txtstamp into dsa_switch_ops, because it is expected that the switch driver needs to save some state (like put the skb into a queue until its TX timestamp arrives). On SJA1110, TX timestamps are provided by the switch as Ethernet packets, so this makes them be received and processed by the tagging protocol driver. This in itself is great, because the timestamps are full 64-bit and do not require reconstruction, and since Ethernet is the fastest I/O method available to/from the switch, PTP timestamps arrive very quickly, no matter how bottlenecked the SPI connection is, because SPI interaction is not needed at all. DSA's code structure and strict isolation between the tagging protocol driver and the switch driver break the natural code organization. When the tagging protocol driver receives a packet which is classified as a metadata packet containing timestamps, it passes those timestamps one by one to the switch driver, which then proceeds to compare them based on the recorded timestamp ID that was generated in .port_txtstamp. The communication between the tagging protocol and the switch driver is done through a method exported by the switch driver, sja1110_process_meta_tstamp. To satisfy build requirements, we force a dependency to build the tagging protocol driver as a module when the switch driver is a module. However, as explained in the first paragraph, that causes the circular dependency. To solve this, move the skb queue from struct sja1105_private :: struct sja1105_ptp_data to struct sja1105_private :: struct sja1105_tagger_data. The latter is a data structure for which hacks have already been put into place to be able to create persistent storage per switch that is accessible from the tagging protocol driver (see sja1105_setup_ports). With the skb queue directly accessible from the tagging protocol driver, we can now move sja1110_process_meta_tstamp into the tagging driver itself, and avoid exporting a symbol. Fixes: 566b18c8b752 ("net: dsa: sja1105: implement TX timestamping for SJA1110") Link: https://lore.kernel.org/netdev/20210908220834.d7gmtnwrorhharna@skbuf/ Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/dsa/sja1105/sja1105_ptp.c | 45 +++++------------------------------ drivers/net/dsa/sja1105/sja1105_ptp.h | 19 --------------- include/linux/dsa/sja1105.h | 29 +++++++++++----------- net/dsa/tag_sja1105.c | 43 +++++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 73 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105_ptp.c b/drivers/net/dsa/sja1105/sja1105_ptp.c index 691f6dd7e669..54396992a919 100644 --- a/drivers/net/dsa/sja1105/sja1105_ptp.c +++ b/drivers/net/dsa/sja1105/sja1105_ptp.c @@ -64,6 +64,7 @@ enum sja1105_ptp_clk_mode { static int sja1105_change_rxtstamping(struct sja1105_private *priv, bool on) { + struct sja1105_tagger_data *tagger_data = &priv->tagger_data; struct sja1105_ptp_data *ptp_data = &priv->ptp_data; struct sja1105_general_params_entry *general_params; struct sja1105_table *table; @@ -79,7 +80,7 @@ static int sja1105_change_rxtstamping(struct sja1105_private *priv, priv->tagger_data.stampable_skb = NULL; } ptp_cancel_worker_sync(ptp_data->clock); - skb_queue_purge(&ptp_data->skb_txtstamp_queue); + skb_queue_purge(&tagger_data->skb_txtstamp_queue); skb_queue_purge(&ptp_data->skb_rxtstamp_queue); return sja1105_static_config_reload(priv, SJA1105_RX_HWTSTAMPING); @@ -452,40 +453,6 @@ bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port, return priv->info->rxtstamp(ds, port, skb); } -void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, u8 ts_id, - enum sja1110_meta_tstamp dir, u64 tstamp) -{ - struct sja1105_private *priv = ds->priv; - struct sja1105_ptp_data *ptp_data = &priv->ptp_data; - struct sk_buff *skb, *skb_tmp, *skb_match = NULL; - struct skb_shared_hwtstamps shwt = {0}; - - /* We don't care about RX timestamps on the CPU port */ - if (dir == SJA1110_META_TSTAMP_RX) - return; - - spin_lock(&ptp_data->skb_txtstamp_queue.lock); - - skb_queue_walk_safe(&ptp_data->skb_txtstamp_queue, skb, skb_tmp) { - if (SJA1105_SKB_CB(skb)->ts_id != ts_id) - continue; - - __skb_unlink(skb, &ptp_data->skb_txtstamp_queue); - skb_match = skb; - - break; - } - - spin_unlock(&ptp_data->skb_txtstamp_queue.lock); - - if (WARN_ON(!skb_match)) - return; - - shwt.hwtstamp = ns_to_ktime(sja1105_ticks_to_ns(tstamp)); - skb_complete_tx_timestamp(skb_match, &shwt); -} -EXPORT_SYMBOL_GPL(sja1110_process_meta_tstamp); - /* In addition to cloning the skb which is done by the common * sja1105_port_txtstamp, we need to generate a timestamp ID and save the * packet to the TX timestamping queue. @@ -494,7 +461,6 @@ void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb) { struct sk_buff *clone = SJA1105_SKB_CB(skb)->clone; struct sja1105_private *priv = ds->priv; - struct sja1105_ptp_data *ptp_data = &priv->ptp_data; struct sja1105_port *sp = &priv->ports[port]; u8 ts_id; @@ -510,7 +476,7 @@ void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb) spin_unlock(&sp->data->meta_lock); - skb_queue_tail(&ptp_data->skb_txtstamp_queue, clone); + skb_queue_tail(&sp->data->skb_txtstamp_queue, clone); } /* Called from dsa_skb_tx_timestamp. This callback is just to clone @@ -953,7 +919,7 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds) /* Only used on SJA1105 */ skb_queue_head_init(&ptp_data->skb_rxtstamp_queue); /* Only used on SJA1110 */ - skb_queue_head_init(&ptp_data->skb_txtstamp_queue); + skb_queue_head_init(&tagger_data->skb_txtstamp_queue); spin_lock_init(&tagger_data->meta_lock); ptp_data->clock = ptp_clock_register(&ptp_data->caps, ds->dev); @@ -971,6 +937,7 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds) void sja1105_ptp_clock_unregister(struct dsa_switch *ds) { struct sja1105_private *priv = ds->priv; + struct sja1105_tagger_data *tagger_data = &priv->tagger_data; struct sja1105_ptp_data *ptp_data = &priv->ptp_data; if (IS_ERR_OR_NULL(ptp_data->clock)) @@ -978,7 +945,7 @@ void sja1105_ptp_clock_unregister(struct dsa_switch *ds) del_timer_sync(&ptp_data->extts_timer); ptp_cancel_worker_sync(ptp_data->clock); - skb_queue_purge(&ptp_data->skb_txtstamp_queue); + skb_queue_purge(&tagger_data->skb_txtstamp_queue); skb_queue_purge(&ptp_data->skb_rxtstamp_queue); ptp_clock_unregister(ptp_data->clock); ptp_data->clock = NULL; diff --git a/drivers/net/dsa/sja1105/sja1105_ptp.h b/drivers/net/dsa/sja1105/sja1105_ptp.h index 3c874bb4c17b..3ae6b9fdd492 100644 --- a/drivers/net/dsa/sja1105/sja1105_ptp.h +++ b/drivers/net/dsa/sja1105/sja1105_ptp.h @@ -8,21 +8,6 @@ #if IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP) -/* Timestamps are in units of 8 ns clock ticks (equivalent to - * a fixed 125 MHz clock). - */ -#define SJA1105_TICK_NS 8 - -static inline s64 ns_to_sja1105_ticks(s64 ns) -{ - return ns / SJA1105_TICK_NS; -} - -static inline s64 sja1105_ticks_to_ns(s64 ticks) -{ - return ticks * SJA1105_TICK_NS; -} - /* Calculate the first base_time in the future that satisfies this * relationship: * @@ -77,10 +62,6 @@ struct sja1105_ptp_data { struct timer_list extts_timer; /* Used only on SJA1105 to reconstruct partial timestamps */ struct sk_buff_head skb_rxtstamp_queue; - /* Used on SJA1110 where meta frames are generated only for - * 2-step TX timestamps - */ - struct sk_buff_head skb_txtstamp_queue; struct ptp_clock_info caps; struct ptp_clock *clock; struct sja1105_ptp_cmd cmd; diff --git a/include/linux/dsa/sja1105.h b/include/linux/dsa/sja1105.h index 171106202fe5..0485ab2fcc46 100644 --- a/include/linux/dsa/sja1105.h +++ b/include/linux/dsa/sja1105.h @@ -48,6 +48,10 @@ struct sja1105_tagger_data { spinlock_t meta_lock; unsigned long state; u8 ts_id; + /* Used on SJA1110 where meta frames are generated only for + * 2-step TX timestamps + */ + struct sk_buff_head skb_txtstamp_queue; }; struct sja1105_skb_cb { @@ -69,25 +73,20 @@ struct sja1105_port { bool hwts_tx_en; }; -enum sja1110_meta_tstamp { - SJA1110_META_TSTAMP_TX = 0, - SJA1110_META_TSTAMP_RX = 1, -}; - -#if IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP) - -void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, u8 ts_id, - enum sja1110_meta_tstamp dir, u64 tstamp); - -#else +/* Timestamps are in units of 8 ns clock ticks (equivalent to + * a fixed 125 MHz clock). + */ +#define SJA1105_TICK_NS 8 -static inline void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, - u8 ts_id, enum sja1110_meta_tstamp dir, - u64 tstamp) +static inline s64 ns_to_sja1105_ticks(s64 ns) { + return ns / SJA1105_TICK_NS; } -#endif /* IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP) */ +static inline s64 sja1105_ticks_to_ns(s64 ticks) +{ + return ticks * SJA1105_TICK_NS; +} #if IS_ENABLED(CONFIG_NET_DSA_SJA1105) diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c index c054f48541c8..2edede9ddac9 100644 --- a/net/dsa/tag_sja1105.c +++ b/net/dsa/tag_sja1105.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "dsa_priv.h" @@ -53,6 +54,11 @@ #define SJA1110_TX_TRAILER_LEN 4 #define SJA1110_MAX_PADDING_LEN 15 +enum sja1110_meta_tstamp { + SJA1110_META_TSTAMP_TX = 0, + SJA1110_META_TSTAMP_RX = 1, +}; + /* Similar to is_link_local_ether_addr(hdr->h_dest) but also covers PTP */ static inline bool sja1105_is_link_local(const struct sk_buff *skb) { @@ -520,6 +526,43 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, is_meta); } +static void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, + u8 ts_id, enum sja1110_meta_tstamp dir, + u64 tstamp) +{ + struct sk_buff *skb, *skb_tmp, *skb_match = NULL; + struct dsa_port *dp = dsa_to_port(ds, port); + struct skb_shared_hwtstamps shwt = {0}; + struct sja1105_port *sp = dp->priv; + + if (!dsa_port_is_sja1105(dp)) + return; + + /* We don't care about RX timestamps on the CPU port */ + if (dir == SJA1110_META_TSTAMP_RX) + return; + + spin_lock(&sp->data->skb_txtstamp_queue.lock); + + skb_queue_walk_safe(&sp->data->skb_txtstamp_queue, skb, skb_tmp) { + if (SJA1105_SKB_CB(skb)->ts_id != ts_id) + continue; + + __skb_unlink(skb, &sp->data->skb_txtstamp_queue); + skb_match = skb; + + break; + } + + spin_unlock(&sp->data->skb_txtstamp_queue.lock); + + if (WARN_ON(!skb_match)) + return; + + shwt.hwtstamp = ns_to_ktime(sja1105_ticks_to_ns(tstamp)); + skb_complete_tx_timestamp(skb_match, &shwt); +} + static struct sk_buff *sja1110_rcv_meta(struct sk_buff *skb, u16 rx_header) { u8 *buf = dsa_etype_header_pos_rx(skb) + SJA1110_HEADER_LEN; -- cgit From 4ac0567e40b334b54988e3c28a2425ff9c8bdd35 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Wed, 22 Sep 2021 17:37:26 +0300 Subject: net: dsa: sja1105: break dependency between dsa_port_is_sja1105 and switch driver It's nice to be able to test a tagging protocol with dsa_loop, but not at the cost of losing the ability of building the tagging protocol and switch driver as modules, because as things stand, there is a circular dependency between the two. Tagging protocol drivers cannot depend on switch drivers, that is a hard fact. The reasoning behind the blamed patch was that accessing dp->priv should first make sure that the structure behind that pointer is what we really think it is. Currently the "sja1105" and "sja1110" tagging protocols only operate with the sja1105 switch driver, just like any other tagging protocol and switch combination. The only way to mix and match them is by modifying the code, and this applies to dsa_loop as well (by default that uses DSA_TAG_PROTO_NONE). So while in principle there is an issue, in practice there isn't one. Until we extend dsa_loop to allow user space configuration, treat the problem as a non-issue and just say that DSA ports found by tag_sja1105 are always sja1105 ports, which is in fact true. But keep the dsa_port_is_sja1105 function so that it's easy to patch it during testing, and rely on dead code elimination. Fixes: 994d2cbb08ca ("net: dsa: tag_sja1105: be dsa_loop-safe") Link: https://lore.kernel.org/netdev/20210908220834.d7gmtnwrorhharna@skbuf/ Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/dsa/sja1105/sja1105_main.c | 3 +-- include/linux/dsa/sja1105.h | 15 +-------------- net/dsa/Kconfig | 1 - 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 7c0db80eff00..924c3f129992 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -3117,7 +3117,7 @@ static void sja1105_teardown(struct dsa_switch *ds) sja1105_static_config_free(&priv->static_config); } -const struct dsa_switch_ops sja1105_switch_ops = { +static const struct dsa_switch_ops sja1105_switch_ops = { .get_tag_protocol = sja1105_get_tag_protocol, .setup = sja1105_setup, .teardown = sja1105_teardown, @@ -3166,7 +3166,6 @@ const struct dsa_switch_ops sja1105_switch_ops = { .port_bridge_tx_fwd_offload = dsa_tag_8021q_bridge_tx_fwd_offload, .port_bridge_tx_fwd_unoffload = dsa_tag_8021q_bridge_tx_fwd_unoffload, }; -EXPORT_SYMBOL_GPL(sja1105_switch_ops); static const struct of_device_id sja1105_dt_ids[]; diff --git a/include/linux/dsa/sja1105.h b/include/linux/dsa/sja1105.h index 0485ab2fcc46..9e07079528a5 100644 --- a/include/linux/dsa/sja1105.h +++ b/include/linux/dsa/sja1105.h @@ -88,22 +88,9 @@ static inline s64 sja1105_ticks_to_ns(s64 ticks) return ticks * SJA1105_TICK_NS; } -#if IS_ENABLED(CONFIG_NET_DSA_SJA1105) - -extern const struct dsa_switch_ops sja1105_switch_ops; - -static inline bool dsa_port_is_sja1105(struct dsa_port *dp) -{ - return dp->ds->ops == &sja1105_switch_ops; -} - -#else - static inline bool dsa_port_is_sja1105(struct dsa_port *dp) { - return false; + return true; } -#endif - #endif /* _NET_DSA_SJA1105_H */ diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index 548285539752..bca1b5d66df2 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -138,7 +138,6 @@ config NET_DSA_TAG_LAN9303 config NET_DSA_TAG_SJA1105 tristate "Tag driver for NXP SJA1105 switches" - depends on NET_DSA_SJA1105 || !NET_DSA_SJA1105 select PACKING help Say Y or M if you want to enable support for tagging frames with the -- cgit From c57fe0037a4e3863d9b740f8c14df9c51ac31aa1 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 12 Oct 2021 14:40:35 +0300 Subject: net: mscc: ocelot: make use of all 63 PTP timestamp identifiers At present, there is a problem when user space bombards a port with PTP event frames which have TX timestamping requests (or when a tc-taprio offload is installed on a port, which delays the TX timestamps by a significant amount of time). The driver will happily roll over the 2-bit timestamp ID and this will cause incorrect matches between an skb and the TX timestamp collected from the FIFO. The Ocelot switches have a 6-bit PTP timestamp identifier, and the value 63 is reserved, so that leaves identifiers 0-62 to be used. The timestamp identifiers are selected by the REW_OP packet field, and are actually shared between CPU-injected frames and frames which match a VCAP IS2 rule that modifies the REW_OP. The hardware supports partitioning between the two uses of the REW_OP field through the PTP_ID_LOW and PTP_ID_HIGH registers, and by default reserves the PTP IDs 0-3 for CPU-injected traffic and the rest for VCAP IS2. The driver does not use VCAP IS2 to set REW_OP for 2-step timestamping, and it also writes 0xffffffff to both PTP_ID_HIGH and PTP_ID_LOW in ocelot_init_timestamp() which makes all timestamp identifiers available to CPU injection. Therefore, we can make use of all 63 timestamp identifiers, which should allow more timestampable packets to be in flight on each port. This is only part of the solution, more issues will be addressed in future changes. Fixes: 4e3b0468e6d7 ("net: mscc: PTP Hardware Clock (PHC) support") Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mscc/ocelot.c | 4 +++- include/soc/mscc/ocelot_ptp.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 4de58321907c..c43c8f53faaf 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -579,7 +579,9 @@ static void ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port, skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS; /* Store timestamp ID in OCELOT_SKB_CB(clone)->ts_id */ OCELOT_SKB_CB(clone)->ts_id = ocelot_port->ts_id; - ocelot_port->ts_id = (ocelot_port->ts_id + 1) % 4; + ocelot_port->ts_id++; + if (ocelot_port->ts_id == OCELOT_MAX_PTP_ID) + ocelot_port->ts_id = 0; skb_queue_tail(&ocelot_port->tx_skbs, clone); spin_unlock(&ocelot_port->ts_id_lock); diff --git a/include/soc/mscc/ocelot_ptp.h b/include/soc/mscc/ocelot_ptp.h index ded497d72bdb..6e54442b49ad 100644 --- a/include/soc/mscc/ocelot_ptp.h +++ b/include/soc/mscc/ocelot_ptp.h @@ -13,6 +13,8 @@ #include #include +#define OCELOT_MAX_PTP_ID 63 + #define PTP_PIN_CFG_RSZ 0x20 #define PTP_PIN_TOD_SEC_MSB_RSZ PTP_PIN_CFG_RSZ #define PTP_PIN_TOD_SEC_LSB_RSZ PTP_PIN_CFG_RSZ -- cgit From 52849bcf0029ccc553be304e4f804938a39112e2 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 12 Oct 2021 14:40:36 +0300 Subject: net: mscc: ocelot: avoid overflowing the PTP timestamp FIFO PTP packets with 2-step TX timestamp requests are matched to packets based on the egress port number and a 6-bit timestamp identifier. All PTP timestamps are held in a common FIFO that is 128 entry deep. This patch ensures that back-to-back timestamping requests cannot exceed the hardware FIFO capacity. If that happens, simply send the packets without requesting a TX timestamp to be taken (in the case of felix, since the DSA API has a void return code in ds->ops->port_txtstamp) or drop them (in the case of ocelot). I've moved the ts_id_lock from a per-port basis to a per-switch basis, because we need separate accounting for both numbers of PTP frames in flight. And since we need locking to inc/dec the per-switch counter, that also offers protection for the per-port counter and hence there is no reason to have a per-port counter anymore. Fixes: 4e3b0468e6d7 ("net: mscc: PTP Hardware Clock (PHC) support") Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/dsa/ocelot/felix.c | 6 +++++- drivers/net/ethernet/mscc/ocelot.c | 37 ++++++++++++++++++++++++++++++------- include/soc/mscc/ocelot.h | 5 ++++- include/soc/mscc/ocelot_ptp.h | 1 + 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index a3a9636430d6..50ef20724958 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -1291,8 +1291,12 @@ static void felix_txtstamp(struct dsa_switch *ds, int port, if (!ocelot->ptp) return; - if (ocelot_port_txtstamp_request(ocelot, port, skb, &clone)) + if (ocelot_port_txtstamp_request(ocelot, port, skb, &clone)) { + dev_err_ratelimited(ds->dev, + "port %d delivering skb without TX timestamp\n", + port); return; + } if (clone) OCELOT_SKB_CB(skb)->clone = clone; diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index c43c8f53faaf..9c62f1d13adc 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -569,22 +569,36 @@ void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port, } EXPORT_SYMBOL_GPL(ocelot_phylink_mac_link_up); -static void ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port, - struct sk_buff *clone) +static int ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port, + struct sk_buff *clone) { struct ocelot_port *ocelot_port = ocelot->ports[port]; + unsigned long flags; + + spin_lock_irqsave(&ocelot->ts_id_lock, flags); - spin_lock(&ocelot_port->ts_id_lock); + if (ocelot_port->ptp_skbs_in_flight == OCELOT_MAX_PTP_ID || + ocelot->ptp_skbs_in_flight == OCELOT_PTP_FIFO_SIZE) { + spin_unlock_irqrestore(&ocelot->ts_id_lock, flags); + return -EBUSY; + } skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS; /* Store timestamp ID in OCELOT_SKB_CB(clone)->ts_id */ OCELOT_SKB_CB(clone)->ts_id = ocelot_port->ts_id; + ocelot_port->ts_id++; if (ocelot_port->ts_id == OCELOT_MAX_PTP_ID) ocelot_port->ts_id = 0; + + ocelot_port->ptp_skbs_in_flight++; + ocelot->ptp_skbs_in_flight++; + skb_queue_tail(&ocelot_port->tx_skbs, clone); - spin_unlock(&ocelot_port->ts_id_lock); + spin_unlock_irqrestore(&ocelot->ts_id_lock, flags); + + return 0; } u32 ocelot_ptp_rew_op(struct sk_buff *skb) @@ -633,6 +647,7 @@ int ocelot_port_txtstamp_request(struct ocelot *ocelot, int port, { struct ocelot_port *ocelot_port = ocelot->ports[port]; u8 ptp_cmd = ocelot_port->ptp_cmd; + int err; /* Store ptp_cmd in OCELOT_SKB_CB(skb)->ptp_cmd */ if (ptp_cmd == IFH_REW_OP_ORIGIN_PTP) { @@ -650,7 +665,10 @@ int ocelot_port_txtstamp_request(struct ocelot *ocelot, int port, if (!(*clone)) return -ENOMEM; - ocelot_port_add_txtstamp_skb(ocelot, port, *clone); + err = ocelot_port_add_txtstamp_skb(ocelot, port, *clone); + if (err) + return err; + OCELOT_SKB_CB(skb)->ptp_cmd = ptp_cmd; } @@ -709,9 +727,14 @@ void ocelot_get_txtstamp(struct ocelot *ocelot) id = SYS_PTP_STATUS_PTP_MESS_ID_X(val); txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val); - /* Retrieve its associated skb */ port = ocelot->ports[txport]; + spin_lock(&ocelot->ts_id_lock); + port->ptp_skbs_in_flight--; + ocelot->ptp_skbs_in_flight--; + spin_unlock(&ocelot->ts_id_lock); + + /* Retrieve its associated skb */ spin_lock_irqsave(&port->tx_skbs.lock, flags); skb_queue_walk_safe(&port->tx_skbs, skb, skb_tmp) { @@ -1950,7 +1973,6 @@ void ocelot_init_port(struct ocelot *ocelot, int port) struct ocelot_port *ocelot_port = ocelot->ports[port]; skb_queue_head_init(&ocelot_port->tx_skbs); - spin_lock_init(&ocelot_port->ts_id_lock); /* Basic L2 initialization */ @@ -2083,6 +2105,7 @@ int ocelot_init(struct ocelot *ocelot) mutex_init(&ocelot->stats_lock); mutex_init(&ocelot->ptp_lock); spin_lock_init(&ocelot->ptp_clock_lock); + spin_lock_init(&ocelot->ts_id_lock); snprintf(queue_name, sizeof(queue_name), "%s-stats", dev_name(ocelot->dev)); ocelot->stats_queue = create_singlethread_workqueue(queue_name); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 06706a9fd5b1..b0ece85d9a76 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -603,10 +603,10 @@ struct ocelot_port { /* The VLAN ID that will be transmitted as untagged, on egress */ struct ocelot_vlan native_vlan; + unsigned int ptp_skbs_in_flight; u8 ptp_cmd; struct sk_buff_head tx_skbs; u8 ts_id; - spinlock_t ts_id_lock; phy_interface_t phy_mode; @@ -680,6 +680,9 @@ struct ocelot { struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_info; struct hwtstamp_config hwtstamp_config; + unsigned int ptp_skbs_in_flight; + /* Protects the 2-step TX timestamp ID logic */ + spinlock_t ts_id_lock; /* Protects the PTP interface state */ struct mutex ptp_lock; /* Protects the PTP clock */ diff --git a/include/soc/mscc/ocelot_ptp.h b/include/soc/mscc/ocelot_ptp.h index 6e54442b49ad..f085884b1fa2 100644 --- a/include/soc/mscc/ocelot_ptp.h +++ b/include/soc/mscc/ocelot_ptp.h @@ -14,6 +14,7 @@ #include #define OCELOT_MAX_PTP_ID 63 +#define OCELOT_PTP_FIFO_SIZE 128 #define PTP_PIN_CFG_RSZ 0x20 #define PTP_PIN_TOD_SEC_MSB_RSZ PTP_PIN_CFG_RSZ -- cgit From 9fde506e0c53b8309f69b18b4b8144c544b4b3b1 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 12 Oct 2021 14:40:37 +0300 Subject: net: mscc: ocelot: warn when a PTP IRQ is raised for an unknown skb When skb_match is NULL, it means we received a PTP IRQ for a timestamp ID that the kernel has no idea about, since there is no skb in the timestamping queue with that timestamp ID. This is a grave error and not something to just "continue" over. So print a big warning in case this happens. Also, move the check above ocelot_get_hwtimestamp(), there is no point in reading the full 64-bit current PTP time if we're not going to do anything with it anyway for this skb. Fixes: 4e3b0468e6d7 ("net: mscc: PTP Hardware Clock (PHC) support") Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mscc/ocelot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 9c62f1d13adc..687c07c338cd 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -747,12 +747,12 @@ void ocelot_get_txtstamp(struct ocelot *ocelot) spin_unlock_irqrestore(&port->tx_skbs.lock, flags); + if (WARN_ON(!skb_match)) + continue; + /* Get the h/w timestamp */ ocelot_get_hwtimestamp(ocelot, &ts); - if (unlikely(!skb_match)) - continue; - /* Set the timestamp into the skb */ memset(&shhwtstamps, 0, sizeof(shhwtstamps)); shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec); -- cgit From fba01283d85a09e0e2ef552c6e764b903111d90a Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 12 Oct 2021 14:40:38 +0300 Subject: net: mscc: ocelot: deny TX timestamping of non-PTP packets It appears that Ocelot switches cannot timestamp non-PTP frames, I tested this using the isochron program at: https://github.com/vladimiroltean/tsn-scripts with the result that the driver increments the ocelot_port->ts_id counter as expected, puts it in the REW_OP, but the hardware seems to not timestamp these packets at all, since no IRQ is emitted. Therefore check whether we are sending PTP frames, and refuse to populate REW_OP otherwise. Fixes: 4e3b0468e6d7 ("net: mscc: PTP Hardware Clock (PHC) support") Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mscc/ocelot.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 687c07c338cd..3b1f0bb6a414 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -618,16 +618,12 @@ u32 ocelot_ptp_rew_op(struct sk_buff *skb) } EXPORT_SYMBOL(ocelot_ptp_rew_op); -static bool ocelot_ptp_is_onestep_sync(struct sk_buff *skb) +static bool ocelot_ptp_is_onestep_sync(struct sk_buff *skb, + unsigned int ptp_class) { struct ptp_header *hdr; - unsigned int ptp_class; u8 msgtype, twostep; - ptp_class = ptp_classify_raw(skb); - if (ptp_class == PTP_CLASS_NONE) - return false; - hdr = ptp_parse_header(skb, ptp_class); if (!hdr) return false; @@ -647,11 +643,20 @@ int ocelot_port_txtstamp_request(struct ocelot *ocelot, int port, { struct ocelot_port *ocelot_port = ocelot->ports[port]; u8 ptp_cmd = ocelot_port->ptp_cmd; + unsigned int ptp_class; int err; + /* Don't do anything if PTP timestamping not enabled */ + if (!ptp_cmd) + return 0; + + ptp_class = ptp_classify_raw(skb); + if (ptp_class == PTP_CLASS_NONE) + return -EINVAL; + /* Store ptp_cmd in OCELOT_SKB_CB(skb)->ptp_cmd */ if (ptp_cmd == IFH_REW_OP_ORIGIN_PTP) { - if (ocelot_ptp_is_onestep_sync(skb)) { + if (ocelot_ptp_is_onestep_sync(skb, ptp_class)) { OCELOT_SKB_CB(skb)->ptp_cmd = ptp_cmd; return 0; } -- cgit From ebb4c6a990f786d7e0e4618a0d3766cd660125d8 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 12 Oct 2021 14:40:39 +0300 Subject: net: mscc: ocelot: cross-check the sequence id from the timestamp FIFO with the skb PTP header The sad reality is that when a PTP frame with a TX timestamping request is transmitted, it isn't guaranteed that it will make it all the way to the wire (due to congestion inside the switch), and that a timestamp will be taken by the hardware and placed in the timestamp FIFO where an IRQ will be raised for it. The implication is that if enough PTP frames are silently dropped by the hardware such that the timestamp ID has rolled over, it is possible to match a timestamp to an old skb. Furthermore, nobody will match on the real skb corresponding to this timestamp, since we stupidly matched on a previous one that was stale in the queue, and stopped there. So PTP timestamping will be broken and there will be no way to recover. It looks like the hardware parses the sequenceID from the PTP header, and also provides that metadata for each timestamp. The driver currently ignores this, but it shouldn't. As an extra resiliency measure, do the following: - check whether the PTP sequenceID also matches between the skb and the timestamp, treat the skb as stale otherwise and free it - if we see a stale skb, don't stop there and try to match an skb one more time, chances are there's one more skb in the queue with the same timestamp ID, otherwise we wouldn't have ever found the stale one (it is by timestamp ID that we matched it). While this does not prevent PTP packet drops, it at least prevents the catastrophic consequences of incorrect timestamp matching. Since we already call ptp_classify_raw in the TX path, save the result in the skb->cb of the clone, and just use that result in the interrupt code path. Fixes: 4e3b0468e6d7 ("net: mscc: PTP Hardware Clock (PHC) support") Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mscc/ocelot.c | 24 +++++++++++++++++++++++- include/soc/mscc/ocelot.h | 1 + 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 3b1f0bb6a414..f0044329e3d7 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -675,6 +675,7 @@ int ocelot_port_txtstamp_request(struct ocelot *ocelot, int port, return err; OCELOT_SKB_CB(skb)->ptp_cmd = ptp_cmd; + OCELOT_SKB_CB(*clone)->ptp_class = ptp_class; } return 0; @@ -708,6 +709,17 @@ static void ocelot_get_hwtimestamp(struct ocelot *ocelot, spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags); } +static bool ocelot_validate_ptp_skb(struct sk_buff *clone, u16 seqid) +{ + struct ptp_header *hdr; + + hdr = ptp_parse_header(clone, OCELOT_SKB_CB(clone)->ptp_class); + if (WARN_ON(!hdr)) + return false; + + return seqid == ntohs(hdr->sequence_id); +} + void ocelot_get_txtstamp(struct ocelot *ocelot) { int budget = OCELOT_PTP_QUEUE_SZ; @@ -715,10 +727,10 @@ void ocelot_get_txtstamp(struct ocelot *ocelot) while (budget--) { struct sk_buff *skb, *skb_tmp, *skb_match = NULL; struct skb_shared_hwtstamps shhwtstamps; + u32 val, id, seqid, txport; struct ocelot_port *port; struct timespec64 ts; unsigned long flags; - u32 val, id, txport; val = ocelot_read(ocelot, SYS_PTP_STATUS); @@ -731,6 +743,7 @@ void ocelot_get_txtstamp(struct ocelot *ocelot) /* Retrieve the ts ID and Tx port */ id = SYS_PTP_STATUS_PTP_MESS_ID_X(val); txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val); + seqid = SYS_PTP_STATUS_PTP_MESS_SEQ_ID(val); port = ocelot->ports[txport]; @@ -740,6 +753,7 @@ void ocelot_get_txtstamp(struct ocelot *ocelot) spin_unlock(&ocelot->ts_id_lock); /* Retrieve its associated skb */ +try_again: spin_lock_irqsave(&port->tx_skbs.lock, flags); skb_queue_walk_safe(&port->tx_skbs, skb, skb_tmp) { @@ -755,6 +769,14 @@ void ocelot_get_txtstamp(struct ocelot *ocelot) if (WARN_ON(!skb_match)) continue; + if (!ocelot_validate_ptp_skb(skb_match, seqid)) { + dev_err_ratelimited(ocelot->dev, + "port %d received stale TX timestamp for seqid %d, discarding\n", + txport, seqid); + dev_kfree_skb_any(skb); + goto try_again; + } + /* Get the h/w timestamp */ ocelot_get_hwtimestamp(ocelot, &ts); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index b0ece85d9a76..cabacef8731c 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -697,6 +697,7 @@ struct ocelot_policer { struct ocelot_skb_cb { struct sk_buff *clone; + unsigned int ptp_class; /* valid only for clones */ u8 ptp_cmd; u8 ts_id; }; -- cgit From deab6b1cd9789bb9bd466d5e76aecb8b336259b4 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 12 Oct 2021 14:40:40 +0300 Subject: net: dsa: tag_ocelot: break circular dependency with ocelot switch lib driver As explained here: https://lore.kernel.org/netdev/20210908220834.d7gmtnwrorhharna@skbuf/ DSA tagging protocol drivers cannot depend on symbols exported by switch drivers, because this creates a circular dependency that breaks module autoloading. The tag_ocelot.c file depends on the ocelot_ptp_rew_op() function exported by the common ocelot switch lib. This function looks at OCELOT_SKB_CB(skb) and computes how to populate the REW_OP field of the DSA tag, for PTP timestamping (the command: one-step/two-step, and the TX timestamp identifier). None of that requires deep insight into the driver, it is quite stateless, as it only depends upon the skb->cb. So let's make it a static inline function and put it in include/linux/dsa/ocelot.h, a file that despite its name is used by the ocelot switch driver for populating the injection header too - since commit 40d3f295b5fe ("net: mscc: ocelot: use common tag parsing code with DSA"). With that function declared as static inline, its body is expanded inside each call site, so the dependency is broken and the DSA tagger can be built without the switch library, upon which the felix driver depends. Fixes: 39e5308b3250 ("net: mscc: ocelot: support PTP Sync one-step timestamping") Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mscc/ocelot.c | 17 ---------------- drivers/net/ethernet/mscc/ocelot_net.c | 1 + include/linux/dsa/ocelot.h | 37 ++++++++++++++++++++++++++++++++++ include/soc/mscc/ocelot.h | 24 ---------------------- net/dsa/Kconfig | 2 -- net/dsa/tag_ocelot.c | 1 - net/dsa/tag_ocelot_8021q.c | 1 + 7 files changed, 39 insertions(+), 44 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index f0044329e3d7..a08e4f530c1c 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -601,23 +601,6 @@ static int ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port, return 0; } -u32 ocelot_ptp_rew_op(struct sk_buff *skb) -{ - struct sk_buff *clone = OCELOT_SKB_CB(skb)->clone; - u8 ptp_cmd = OCELOT_SKB_CB(skb)->ptp_cmd; - u32 rew_op = 0; - - if (ptp_cmd == IFH_REW_OP_TWO_STEP_PTP && clone) { - rew_op = ptp_cmd; - rew_op |= OCELOT_SKB_CB(clone)->ts_id << 3; - } else if (ptp_cmd == IFH_REW_OP_ORIGIN_PTP) { - rew_op = ptp_cmd; - } - - return rew_op; -} -EXPORT_SYMBOL(ocelot_ptp_rew_op); - static bool ocelot_ptp_is_onestep_sync(struct sk_buff *skb, unsigned int ptp_class) { diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index 2a85bcb5d0c2..2545727fd5b2 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -8,6 +8,7 @@ * Copyright 2020-2021 NXP */ +#include #include #include #include diff --git a/include/linux/dsa/ocelot.h b/include/linux/dsa/ocelot.h index 435777a0073c..50641a7529ad 100644 --- a/include/linux/dsa/ocelot.h +++ b/include/linux/dsa/ocelot.h @@ -6,6 +6,26 @@ #define _NET_DSA_TAG_OCELOT_H #include +#include + +struct ocelot_skb_cb { + struct sk_buff *clone; + unsigned int ptp_class; /* valid only for clones */ + u8 ptp_cmd; + u8 ts_id; +}; + +#define OCELOT_SKB_CB(skb) \ + ((struct ocelot_skb_cb *)((skb)->cb)) + +#define IFH_TAG_TYPE_C 0 +#define IFH_TAG_TYPE_S 1 + +#define IFH_REW_OP_NOOP 0x0 +#define IFH_REW_OP_DSCP 0x1 +#define IFH_REW_OP_ONE_STEP_PTP 0x2 +#define IFH_REW_OP_TWO_STEP_PTP 0x3 +#define IFH_REW_OP_ORIGIN_PTP 0x5 #define OCELOT_TAG_LEN 16 #define OCELOT_SHORT_PREFIX_LEN 4 @@ -215,4 +235,21 @@ static inline void ocelot_ifh_set_vid(void *injection, u64 vid) packing(injection, &vid, 11, 0, OCELOT_TAG_LEN, PACK, 0); } +/* Determine the PTP REW_OP to use for injecting the given skb */ +static inline u32 ocelot_ptp_rew_op(struct sk_buff *skb) +{ + struct sk_buff *clone = OCELOT_SKB_CB(skb)->clone; + u8 ptp_cmd = OCELOT_SKB_CB(skb)->ptp_cmd; + u32 rew_op = 0; + + if (ptp_cmd == IFH_REW_OP_TWO_STEP_PTP && clone) { + rew_op = ptp_cmd; + rew_op |= OCELOT_SKB_CB(clone)->ts_id << 3; + } else if (ptp_cmd == IFH_REW_OP_ORIGIN_PTP) { + rew_op = ptp_cmd; + } + + return rew_op; +} + #endif diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index cabacef8731c..66b2e65c1179 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -89,15 +89,6 @@ /* Source PGIDs, one per physical port */ #define PGID_SRC 80 -#define IFH_TAG_TYPE_C 0 -#define IFH_TAG_TYPE_S 1 - -#define IFH_REW_OP_NOOP 0x0 -#define IFH_REW_OP_DSCP 0x1 -#define IFH_REW_OP_ONE_STEP_PTP 0x2 -#define IFH_REW_OP_TWO_STEP_PTP 0x3 -#define IFH_REW_OP_ORIGIN_PTP 0x5 - #define OCELOT_NUM_TC 8 #define OCELOT_SPEED_2500 0 @@ -695,16 +686,6 @@ struct ocelot_policer { u32 burst; /* bytes */ }; -struct ocelot_skb_cb { - struct sk_buff *clone; - unsigned int ptp_class; /* valid only for clones */ - u8 ptp_cmd; - u8 ts_id; -}; - -#define OCELOT_SKB_CB(skb) \ - ((struct ocelot_skb_cb *)((skb)->cb)) - #define ocelot_read_ix(ocelot, reg, gi, ri) __ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi) + reg##_RSZ * (ri)) #define ocelot_read_gix(ocelot, reg, gi) __ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi)) #define ocelot_read_rix(ocelot, reg, ri) __ocelot_read_ix(ocelot, reg, reg##_RSZ * (ri)) @@ -765,7 +746,6 @@ void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp, int ocelot_xtr_poll_frame(struct ocelot *ocelot, int grp, struct sk_buff **skb); void ocelot_drain_cpu_queue(struct ocelot *ocelot, int grp); -u32 ocelot_ptp_rew_op(struct sk_buff *skb); #else static inline bool ocelot_can_inject(struct ocelot *ocelot, int grp) @@ -789,10 +769,6 @@ static inline void ocelot_drain_cpu_queue(struct ocelot *ocelot, int grp) { } -static inline u32 ocelot_ptp_rew_op(struct sk_buff *skb) -{ - return 0; -} #endif /* Hardware initialization */ diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index bca1b5d66df2..d166377d7085 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -101,8 +101,6 @@ config NET_DSA_TAG_RTL4_A config NET_DSA_TAG_OCELOT tristate "Tag driver for Ocelot family of switches, using NPI port" - depends on MSCC_OCELOT_SWITCH_LIB || \ - (MSCC_OCELOT_SWITCH_LIB=n && COMPILE_TEST) select PACKING help Say Y or M if you want to enable NPI tagging for the Ocelot switches diff --git a/net/dsa/tag_ocelot.c b/net/dsa/tag_ocelot.c index 8025ed778d33..605b51ca6921 100644 --- a/net/dsa/tag_ocelot.c +++ b/net/dsa/tag_ocelot.c @@ -2,7 +2,6 @@ /* Copyright 2019 NXP */ #include -#include #include "dsa_priv.h" static void ocelot_xmit_common(struct sk_buff *skb, struct net_device *netdev, diff --git a/net/dsa/tag_ocelot_8021q.c b/net/dsa/tag_ocelot_8021q.c index 59072930cb02..1e4e66ea6796 100644 --- a/net/dsa/tag_ocelot_8021q.c +++ b/net/dsa/tag_ocelot_8021q.c @@ -9,6 +9,7 @@ * that on egress */ #include +#include #include #include #include "dsa_priv.h" -- cgit From 49f885b2d97093451410e7279aa29d81e094e108 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 12 Oct 2021 14:40:41 +0300 Subject: net: dsa: tag_ocelot_8021q: break circular dependency with ocelot switch lib Michael reported that when using the "ocelot-8021q" tagging protocol, the switch driver module must be manually loaded before the tagging protocol can be loaded/is available. This appears to be the same problem described here: https://lore.kernel.org/netdev/20210908220834.d7gmtnwrorhharna@skbuf/ where due to the fact that DSA tagging protocols make use of symbols exported by the switch drivers, circular dependencies appear and this breaks module autoloading. The ocelot_8021q driver needs the ocelot_can_inject() and ocelot_port_inject_frame() functions from the switch library. Previously the wrong approach was taken to solve that dependency: shims were provided for the case where the ocelot switch library was compiled out, but that turns out to be insufficient, because the dependency when the switch lib _is_ compiled is problematic too. We cannot declare ocelot_can_inject() and ocelot_port_inject_frame() as static inline functions, because these access I/O functions like __ocelot_write_ix() which is called by ocelot_write_rix(). Making those static inline basically means exposing the whole guts of the ocelot switch library, not ideal... We already have one tagging protocol driver which calls into the switch driver during xmit but not using any exported symbol: sja1105_defer_xmit. We can do the same thing here: create a kthread worker and one work item per skb, and let the switch driver itself do the register accesses to send the skb, and then consume it. Fixes: 0a6f17c6ae21 ("net: dsa: tag_ocelot_8021q: add support for PTP timestamping") Reported-by: Michael Walle Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/dsa/ocelot/felix.c | 96 ++++++++++++++++++++++++++++++++++++++++-- drivers/net/dsa/ocelot/felix.h | 1 + include/linux/dsa/ocelot.h | 12 ++++++ include/soc/mscc/ocelot.h | 27 ------------ net/dsa/Kconfig | 2 - net/dsa/tag_ocelot_8021q.c | 38 +++++++++++------ 6 files changed, 130 insertions(+), 46 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 50ef20724958..f8603e068e7c 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -1074,6 +1074,73 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) return 0; } +#define work_to_xmit_work(w) \ + container_of((w), struct felix_deferred_xmit_work, work) + +static void felix_port_deferred_xmit(struct kthread_work *work) +{ + struct felix_deferred_xmit_work *xmit_work = work_to_xmit_work(work); + struct dsa_switch *ds = xmit_work->dp->ds; + struct sk_buff *skb = xmit_work->skb; + u32 rew_op = ocelot_ptp_rew_op(skb); + struct ocelot *ocelot = ds->priv; + int port = xmit_work->dp->index; + int retries = 10; + + do { + if (ocelot_can_inject(ocelot, 0)) + break; + + cpu_relax(); + } while (--retries); + + if (!retries) { + dev_err(ocelot->dev, "port %d failed to inject skb\n", + port); + kfree_skb(skb); + return; + } + + ocelot_port_inject_frame(ocelot, port, 0, rew_op, skb); + + consume_skb(skb); + kfree(xmit_work); +} + +static int felix_port_setup_tagger_data(struct dsa_switch *ds, int port) +{ + struct dsa_port *dp = dsa_to_port(ds, port); + struct ocelot *ocelot = ds->priv; + struct felix *felix = ocelot_to_felix(ocelot); + struct felix_port *felix_port; + + if (!dsa_port_is_user(dp)) + return 0; + + felix_port = kzalloc(sizeof(*felix_port), GFP_KERNEL); + if (!felix_port) + return -ENOMEM; + + felix_port->xmit_worker = felix->xmit_worker; + felix_port->xmit_work_fn = felix_port_deferred_xmit; + + dp->priv = felix_port; + + return 0; +} + +static void felix_port_teardown_tagger_data(struct dsa_switch *ds, int port) +{ + struct dsa_port *dp = dsa_to_port(ds, port); + struct felix_port *felix_port = dp->priv; + + if (!felix_port) + return; + + dp->priv = NULL; + kfree(felix_port); +} + /* Hardware initialization done here so that we can allocate structures with * devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing * us to allocate structures twice (leak memory) and map PCI memory twice @@ -1102,6 +1169,12 @@ static int felix_setup(struct dsa_switch *ds) } } + felix->xmit_worker = kthread_create_worker(0, "felix_xmit"); + if (IS_ERR(felix->xmit_worker)) { + err = PTR_ERR(felix->xmit_worker); + goto out_deinit_timestamp; + } + for (port = 0; port < ds->num_ports; port++) { if (dsa_is_unused_port(ds, port)) continue; @@ -1112,6 +1185,14 @@ static int felix_setup(struct dsa_switch *ds) * bits of vlan tag. */ felix_port_qos_map_init(ocelot, port); + + err = felix_port_setup_tagger_data(ds, port); + if (err) { + dev_err(ds->dev, + "port %d failed to set up tagger data: %pe\n", + port, ERR_PTR(err)); + goto out_deinit_ports; + } } err = ocelot_devlink_sb_register(ocelot); @@ -1138,9 +1219,13 @@ out_deinit_ports: if (dsa_is_unused_port(ds, port)) continue; + felix_port_teardown_tagger_data(ds, port); ocelot_deinit_port(ocelot, port); } + kthread_destroy_worker(felix->xmit_worker); + +out_deinit_timestamp: ocelot_deinit_timestamp(ocelot); ocelot_deinit(ocelot); @@ -1164,17 +1249,20 @@ static void felix_teardown(struct dsa_switch *ds) felix_del_tag_protocol(ds, port, felix->tag_proto); } - ocelot_devlink_sb_unregister(ocelot); - ocelot_deinit_timestamp(ocelot); - ocelot_deinit(ocelot); - for (port = 0; port < ocelot->num_phys_ports; port++) { if (dsa_is_unused_port(ds, port)) continue; + felix_port_teardown_tagger_data(ds, port); ocelot_deinit_port(ocelot, port); } + kthread_destroy_worker(felix->xmit_worker); + + ocelot_devlink_sb_unregister(ocelot); + ocelot_deinit_timestamp(ocelot); + ocelot_deinit(ocelot); + if (felix->info->mdio_bus_free) felix->info->mdio_bus_free(ocelot); } diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index 54024b6f9498..be3e42e135c0 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -62,6 +62,7 @@ struct felix { resource_size_t switch_base; resource_size_t imdio_base; enum dsa_tag_protocol tag_proto; + struct kthread_worker *xmit_worker; }; struct net_device *felix_port_to_netdev(struct ocelot *ocelot, int port); diff --git a/include/linux/dsa/ocelot.h b/include/linux/dsa/ocelot.h index 50641a7529ad..8ae999f587c4 100644 --- a/include/linux/dsa/ocelot.h +++ b/include/linux/dsa/ocelot.h @@ -5,6 +5,7 @@ #ifndef _NET_DSA_TAG_OCELOT_H #define _NET_DSA_TAG_OCELOT_H +#include #include #include @@ -160,6 +161,17 @@ struct ocelot_skb_cb { * +------+------+------+------+------+------+------+------+ */ +struct felix_deferred_xmit_work { + struct dsa_port *dp; + struct sk_buff *skb; + struct kthread_work work; +}; + +struct felix_port { + void (*xmit_work_fn)(struct kthread_work *work); + struct kthread_worker *xmit_worker; +}; + static inline void ocelot_xfh_get_rew_val(void *extraction, u64 *rew_val) { packing(extraction, rew_val, 116, 85, OCELOT_TAG_LEN, UNPACK, 0); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 66b2e65c1179..d7055b41982d 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -737,8 +737,6 @@ u32 __ocelot_target_read_ix(struct ocelot *ocelot, enum ocelot_target target, void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target, u32 val, u32 reg, u32 offset); -#if IS_ENABLED(CONFIG_MSCC_OCELOT_SWITCH_LIB) - /* Packet I/O */ bool ocelot_can_inject(struct ocelot *ocelot, int grp); void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp, @@ -746,31 +744,6 @@ void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp, int ocelot_xtr_poll_frame(struct ocelot *ocelot, int grp, struct sk_buff **skb); void ocelot_drain_cpu_queue(struct ocelot *ocelot, int grp); -#else - -static inline bool ocelot_can_inject(struct ocelot *ocelot, int grp) -{ - return false; -} - -static inline void ocelot_port_inject_frame(struct ocelot *ocelot, int port, - int grp, u32 rew_op, - struct sk_buff *skb) -{ -} - -static inline int ocelot_xtr_poll_frame(struct ocelot *ocelot, int grp, - struct sk_buff **skb) -{ - return -EIO; -} - -static inline void ocelot_drain_cpu_queue(struct ocelot *ocelot, int grp) -{ -} - -#endif - /* Hardware initialization */ int ocelot_regfields_init(struct ocelot *ocelot, const struct reg_field *const regfields); diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index d166377d7085..d8ee15f1c7a9 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -112,8 +112,6 @@ config NET_DSA_TAG_OCELOT config NET_DSA_TAG_OCELOT_8021Q tristate "Tag driver for Ocelot family of switches, using VLAN" - depends on MSCC_OCELOT_SWITCH_LIB || \ - (MSCC_OCELOT_SWITCH_LIB=n && COMPILE_TEST) help Say Y or M if you want to enable support for tagging frames with a custom VLAN-based header. Frames that require timestamping, such as diff --git a/net/dsa/tag_ocelot_8021q.c b/net/dsa/tag_ocelot_8021q.c index 1e4e66ea6796..d05c352f96e5 100644 --- a/net/dsa/tag_ocelot_8021q.c +++ b/net/dsa/tag_ocelot_8021q.c @@ -10,10 +10,31 @@ */ #include #include -#include -#include #include "dsa_priv.h" +static struct sk_buff *ocelot_defer_xmit(struct dsa_port *dp, + struct sk_buff *skb) +{ + struct felix_deferred_xmit_work *xmit_work; + struct felix_port *felix_port = dp->priv; + + xmit_work = kzalloc(sizeof(*xmit_work), GFP_ATOMIC); + if (!xmit_work) + return NULL; + + /* Calls felix_port_deferred_xmit in felix.c */ + kthread_init_work(&xmit_work->work, felix_port->xmit_work_fn); + /* Increase refcount so the kfree_skb in dsa_slave_xmit + * won't really free the packet. + */ + xmit_work->dp = dp; + xmit_work->skb = skb_get(skb); + + kthread_queue_work(felix_port->xmit_worker, &xmit_work->work); + + return NULL; +} + static struct sk_buff *ocelot_xmit(struct sk_buff *skb, struct net_device *netdev) { @@ -21,18 +42,9 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb, u16 tx_vid = dsa_8021q_tx_vid(dp->ds, dp->index); u16 queue_mapping = skb_get_queue_mapping(skb); u8 pcp = netdev_txq_to_tc(netdev, queue_mapping); - struct ocelot *ocelot = dp->ds->priv; - int port = dp->index; - u32 rew_op = 0; - rew_op = ocelot_ptp_rew_op(skb); - if (rew_op) { - if (!ocelot_can_inject(ocelot, 0)) - return NULL; - - ocelot_port_inject_frame(ocelot, port, 0, rew_op, skb); - return NULL; - } + if (ocelot_ptp_rew_op(skb)) + return ocelot_defer_xmit(dp, skb); return dsa_8021q_xmit(skb, netdev, ETH_P_8021Q, ((pcp << VLAN_PRIO_SHIFT) | tx_vid)); -- cgit From 1328a883258b4507909090ed0a9ad63771f9f780 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 12 Oct 2021 14:40:42 +0300 Subject: net: dsa: felix: purge skb from TX timestamping queue if it cannot be sent At present, when a PTP packet which requires TX timestamping gets dropped under congestion by the switch, things go downhill very fast. The driver keeps a clone of that skb in a queue of packets awaiting TX timestamp interrupts, but interrupts will never be raised for the dropped packets. Moreover, matching timestamped packets to timestamps is done by a 2-bit timestamp ID, and this can wrap around and we can match on the wrong skb. Since with the default NPI-based tagging protocol, we get no notification about packet drops, the best we can do is eventually recover from the drop of a PTP frame: its skb will be dead memory until another skb which was assigned the same timestamp ID happens to find it. However, with the ocelot-8021q tagger which injects packets using the manual register interface, it appears that we can check for more information, such as: - whether the input queue has reached the high watermark or not - whether the injection group's FIFO can accept additional data or not so we know that a PTP frame is likely to get dropped before actually sending it, and drop it ourselves (because DSA uses NETIF_F_LLTX, so it can't return NETDEV_TX_BUSY to ask the qdisc to requeue the packet). But when we do that, we can also remove the skb from the timestamping queue, because there surely won't be any timestamp that matches it. Fixes: 0a6f17c6ae21 ("net: dsa: tag_ocelot_8021q: add support for PTP timestamping") Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/dsa/ocelot/felix.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index f8603e068e7c..9af8f900aa56 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -1074,6 +1074,33 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) return 0; } +static void ocelot_port_purge_txtstamp_skb(struct ocelot *ocelot, int port, + struct sk_buff *skb) +{ + struct ocelot_port *ocelot_port = ocelot->ports[port]; + struct sk_buff *clone = OCELOT_SKB_CB(skb)->clone; + struct sk_buff *skb_match = NULL, *skb_tmp; + unsigned long flags; + + if (!clone) + return; + + spin_lock_irqsave(&ocelot_port->tx_skbs.lock, flags); + + skb_queue_walk_safe(&ocelot_port->tx_skbs, skb, skb_tmp) { + if (skb != clone) + continue; + __skb_unlink(skb, &ocelot_port->tx_skbs); + skb_match = skb; + break; + } + + spin_unlock_irqrestore(&ocelot_port->tx_skbs.lock, flags); + + WARN_ONCE(!skb_match, + "Could not find skb clone in TX timestamping list\n"); +} + #define work_to_xmit_work(w) \ container_of((w), struct felix_deferred_xmit_work, work) @@ -1097,6 +1124,7 @@ static void felix_port_deferred_xmit(struct kthread_work *work) if (!retries) { dev_err(ocelot->dev, "port %d failed to inject skb\n", port); + ocelot_port_purge_txtstamp_skb(ocelot, port, skb); kfree_skb(skb); return; } -- cgit From 43ba33b4f143965a451cfdc1e826b61f6933c887 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 12 Oct 2021 14:40:43 +0300 Subject: net: dsa: tag_ocelot_8021q: fix inability to inject STP BPDUs into BLOCKING ports When setting up a bridge with stp_state 1, topology changes are not detected and loops are not blocked. This is because the standard way of transmitting a packet, based on VLAN IDs redirected by VCAP IS2 to the right egress port, does not override the port STP state (in the case of Ocelot switches, that's really the PGID_SRC masks). To force a packet to be injected into a port that's BLOCKING, we must send it as a control packet, which means in the case of this tagger to send it using the manual register injection method. We already do this for PTP frames, extend the logic to apply to any link-local MAC DA. Fixes: 7c83a7c539ab ("net: dsa: add a second tagger for Ocelot switches based on tag_8021q") Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: Jakub Kicinski --- net/dsa/tag_ocelot_8021q.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/dsa/tag_ocelot_8021q.c b/net/dsa/tag_ocelot_8021q.c index d05c352f96e5..3412051981d7 100644 --- a/net/dsa/tag_ocelot_8021q.c +++ b/net/dsa/tag_ocelot_8021q.c @@ -42,8 +42,9 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb, u16 tx_vid = dsa_8021q_tx_vid(dp->ds, dp->index); u16 queue_mapping = skb_get_queue_mapping(skb); u8 pcp = netdev_txq_to_tc(netdev, queue_mapping); + struct ethhdr *hdr = eth_hdr(skb); - if (ocelot_ptp_rew_op(skb)) + if (ocelot_ptp_rew_op(skb) || is_link_local_ether_addr(hdr->h_dest)) return ocelot_defer_xmit(dp, skb); return dsa_8021q_xmit(skb, netdev, ETH_P_8021Q, -- cgit From 8d5f7954b7c8de54902a8beda141064a7e2e6ee0 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 12 Oct 2021 14:40:44 +0300 Subject: net: dsa: felix: break at first CPU port during init and teardown The NXP LS1028A switch has two Ethernet ports towards the CPU, but only one of them is capable of acting as an NPI port at a time (inject and extract packets using DSA tags). However, using the alternative ocelot-8021q tagging protocol, it should be possible to use both CPU ports symmetrically, but for that we need to mark both ports in the device tree as DSA masters. In the process of doing that, it can be seen that traffic to/from the network stack gets broken, and this is because the Felix driver iterates through all DSA CPU ports and configures them as NPI ports. But since there can only be a single NPI port, we effectively end up in a situation where DSA thinks the default CPU port is the first one, but the hardware port configured to be an NPI is the last one. I would like to treat this as a bug, because if the updated device trees are going to start circulating, it would be really good for existing kernels to support them, too. Fixes: adb3dccf090b ("net: dsa: felix: convert to the new .change_tag_protocol DSA API") Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: Jakub Kicinski --- drivers/net/dsa/ocelot/felix.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 9af8f900aa56..341236dcbdb4 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -266,12 +266,12 @@ static void felix_8021q_cpu_port_deinit(struct ocelot *ocelot, int port) */ static int felix_setup_mmio_filtering(struct felix *felix) { - unsigned long user_ports = 0, cpu_ports = 0; + unsigned long user_ports = dsa_user_ports(felix->ds); struct ocelot_vcap_filter *redirect_rule; struct ocelot_vcap_filter *tagging_rule; struct ocelot *ocelot = &felix->ocelot; struct dsa_switch *ds = felix->ds; - int port, ret; + int cpu = -1, port, ret; tagging_rule = kzalloc(sizeof(struct ocelot_vcap_filter), GFP_KERNEL); if (!tagging_rule) @@ -284,12 +284,15 @@ static int felix_setup_mmio_filtering(struct felix *felix) } for (port = 0; port < ocelot->num_phys_ports; port++) { - if (dsa_is_user_port(ds, port)) - user_ports |= BIT(port); - if (dsa_is_cpu_port(ds, port)) - cpu_ports |= BIT(port); + if (dsa_is_cpu_port(ds, port)) { + cpu = port; + break; + } } + if (cpu < 0) + return -EINVAL; + tagging_rule->key_type = OCELOT_VCAP_KEY_ETYPE; *(__be16 *)tagging_rule->key.etype.etype.value = htons(ETH_P_1588); *(__be16 *)tagging_rule->key.etype.etype.mask = htons(0xffff); @@ -325,7 +328,7 @@ static int felix_setup_mmio_filtering(struct felix *felix) * the CPU port module */ redirect_rule->action.mask_mode = OCELOT_MASK_MODE_REDIRECT; - redirect_rule->action.port_mask = cpu_ports; + redirect_rule->action.port_mask = BIT(cpu); } else { /* Trap PTP packets only to the CPU port module (which is * redirected to the NPI port) @@ -1235,6 +1238,7 @@ static int felix_setup(struct dsa_switch *ds) * there's no real point in checking for errors. */ felix_set_tag_protocol(ds, port, felix->tag_proto); + break; } ds->mtu_enforcement_ingress = true; @@ -1275,6 +1279,7 @@ static void felix_teardown(struct dsa_switch *ds) continue; felix_del_tag_protocol(ds, port, felix->tag_proto); + break; } for (port = 0; port < ocelot->num_phys_ports; port++) { -- cgit From 2b94b6b79b7c24092a6169db9e83c4565be0db42 Mon Sep 17 00:00:00 2001 From: Wang Hai Date: Tue, 12 Oct 2021 15:15:56 +0800 Subject: PCI/MSI: Handle msi_populate_sysfs() errors correctly Previously, when msi_populate_sysfs() failed, we saved the error return value as dev->msi_irq_groups, which leads to a page fault when free_msi_irqs() calls msi_destroy_sysfs(). To prevent this, leave dev->msi_irq_groups alone when msi_populate_sysfs() fails. Found by the Hulk Robot when injecting a memory allocation fault in msi_populate_sysfs(): BUG: unable to handle page fault for address: fffffffffffffff4 ... Call Trace: msi_destroy_sysfs+0x30/0xa0 free_msi_irqs+0x11d/0x1b0 Fixes: 2f170814bdd2 ("genirq/msi: Move MSI sysfs handling from PCI to MSI core") Link: https://lore.kernel.org/r/20211012071556.939137-1-wanghai38@huawei.com Reported-by: Hulk Robot Signed-off-by: Wang Hai Signed-off-by: Bjorn Helgaas Acked-by: Barry Song --- drivers/pci/msi.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 0099a00af361..4b4792940e86 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -535,6 +535,7 @@ static int msi_verify_entries(struct pci_dev *dev) static int msi_capability_init(struct pci_dev *dev, int nvec, struct irq_affinity *affd) { + const struct attribute_group **groups; struct msi_desc *entry; int ret; @@ -558,12 +559,14 @@ static int msi_capability_init(struct pci_dev *dev, int nvec, if (ret) goto err; - dev->msi_irq_groups = msi_populate_sysfs(&dev->dev); - if (IS_ERR(dev->msi_irq_groups)) { - ret = PTR_ERR(dev->msi_irq_groups); + groups = msi_populate_sysfs(&dev->dev); + if (IS_ERR(groups)) { + ret = PTR_ERR(groups); goto err; } + dev->msi_irq_groups = groups; + /* Set MSI enabled bits */ pci_intx_for_msi(dev, 0); pci_msi_set_enable(dev, 1); @@ -691,6 +694,7 @@ static void msix_mask_all(void __iomem *base, int tsize) static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, int nvec, struct irq_affinity *affd) { + const struct attribute_group **groups; void __iomem *base; int ret, tsize; u16 control; @@ -730,12 +734,14 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, msix_update_entries(dev, entries); - dev->msi_irq_groups = msi_populate_sysfs(&dev->dev); - if (IS_ERR(dev->msi_irq_groups)) { - ret = PTR_ERR(dev->msi_irq_groups); + groups = msi_populate_sysfs(&dev->dev); + if (IS_ERR(groups)) { + ret = PTR_ERR(groups); goto out_free; } + dev->msi_irq_groups = groups; + /* Set MSI-X enabled bits and unmask the function */ pci_intx_for_msi(dev, 0); dev->msix_enabled = 1; -- cgit From 6e44bd6d34d659c44cd8e7fc925c8a97f49b3c33 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 13 Oct 2021 08:36:59 +0300 Subject: memblock: exclude NOMAP regions from kmemleak Vladimir Zapolskiy reports: commit a7259df76702 ("memblock: make memblock_find_in_range method private") invokes a kernel panic while running kmemleak on OF platforms with nomaped regions: Unable to handle kernel paging request at virtual address fff000021e00000 [...] scan_block+0x64/0x170 scan_gray_list+0xe8/0x17c kmemleak_scan+0x270/0x514 kmemleak_write+0x34c/0x4ac Indeed, NOMAP regions don't have linear map entries so an attempt to scan these areas would fault. Prevent such faults by excluding NOMAP regions from kmemleak. Link: https://lore.kernel.org/all/8ade5174-b143-d621-8c8e-dc6a1898c6fb@linaro.org Fixes: a7259df76702 ("memblock: make memblock_find_in_range method private") Signed-off-by: Mike Rapoport Tested-by: Vladimir Zapolskiy --- mm/memblock.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mm/memblock.c b/mm/memblock.c index 184dcd2e5d99..5c3503c98b2f 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -936,7 +936,12 @@ int __init_memblock memblock_mark_mirror(phys_addr_t base, phys_addr_t size) */ int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size) { - return memblock_setclr_flag(base, size, 1, MEMBLOCK_NOMAP); + int ret = memblock_setclr_flag(base, size, 1, MEMBLOCK_NOMAP); + + if (!ret) + kmemleak_free_part_phys(base, size); + + return ret; } /** -- cgit From 6f779e1d359b8d5801f677c1d49dcfa10bf95674 Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Mon, 11 Oct 2021 09:02:03 +0200 Subject: powerpc/xive: Discard disabled interrupts in get_irqchip_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When an interrupt is passed through, the KVM XIVE device calls the set_vcpu_affinity() handler which raises the P bit to mask the interrupt and to catch any in-flight interrupts while routing the interrupt to the guest. On the guest side, drivers (like some Intels) can request at probe time some MSIs and call synchronize_irq() to check that there are no in flight interrupts. This will call the XIVE get_irqchip_state() handler which will always return true as the interrupt P bit has been set on the host side and lock the CPU in an infinite loop. Fix that by discarding disabled interrupts in get_irqchip_state(). Fixes: da15c03b047d ("powerpc/xive: Implement get_irqchip_state method for XIVE to fix shutdown race") Cc: stable@vger.kernel.org #v5.4+ Signed-off-by: Cédric Le Goater Tested-by: seeteena Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20211011070203.99726-1-clg@kaod.org --- arch/powerpc/sysdev/xive/common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c index c732ce5a3e1a..c5d75c02ad8b 100644 --- a/arch/powerpc/sysdev/xive/common.c +++ b/arch/powerpc/sysdev/xive/common.c @@ -945,7 +945,8 @@ static int xive_get_irqchip_state(struct irq_data *data, * interrupt to be inactive in that case. */ *state = (pq != XIVE_ESB_INVALID) && !xd->stale_p && - (xd->saved_p || !!(pq & XIVE_ESB_VAL_P)); + (xd->saved_p || (!!(pq & XIVE_ESB_VAL_P) && + !irqd_irq_disabled(data))); return 0; default: return -EINVAL; -- cgit From 6d7163f2c49fda5658e43105a96b555c89a4548d Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Wed, 13 Oct 2021 10:45:52 +0300 Subject: mei: hbm: drop hbm responses on early shutdown Drop HBM responses also in the early shutdown phase where the usual traffic is allowed. Extend the rule that drop HBM responses received during the shutdown phase by also in MEI_DEV_POWERING_DOWN state. This resolves the stall if the driver is stopping in the middle of the link init or link reset. Fixes: da3eb47c90d4 ("mei: hbm: drop hbm responses on shutdown") Fixes: 36edb1407c3c ("mei: allow clients on bus to communicate in remove callback") Cc: # v5.12+ Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Link: https://lore.kernel.org/r/20211013074552.2278419-1-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hbm.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index 99b5c1ecc444..be41843df75b 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -1298,7 +1298,8 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) if (dev->dev_state != MEI_DEV_INIT_CLIENTS || dev->hbm_state != MEI_HBM_STARTING) { - if (dev->dev_state == MEI_DEV_POWER_DOWN) { + if (dev->dev_state == MEI_DEV_POWER_DOWN || + dev->dev_state == MEI_DEV_POWERING_DOWN) { dev_dbg(dev->dev, "hbm: start: on shutdown, ignoring\n"); return 0; } @@ -1381,7 +1382,8 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) if (dev->dev_state != MEI_DEV_INIT_CLIENTS || dev->hbm_state != MEI_HBM_DR_SETUP) { - if (dev->dev_state == MEI_DEV_POWER_DOWN) { + if (dev->dev_state == MEI_DEV_POWER_DOWN || + dev->dev_state == MEI_DEV_POWERING_DOWN) { dev_dbg(dev->dev, "hbm: dma setup response: on shutdown, ignoring\n"); return 0; } @@ -1448,7 +1450,8 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) if (dev->dev_state != MEI_DEV_INIT_CLIENTS || dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) { - if (dev->dev_state == MEI_DEV_POWER_DOWN) { + if (dev->dev_state == MEI_DEV_POWER_DOWN || + dev->dev_state == MEI_DEV_POWERING_DOWN) { dev_dbg(dev->dev, "hbm: properties response: on shutdown, ignoring\n"); return 0; } @@ -1490,7 +1493,8 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) if (dev->dev_state != MEI_DEV_INIT_CLIENTS || dev->hbm_state != MEI_HBM_ENUM_CLIENTS) { - if (dev->dev_state == MEI_DEV_POWER_DOWN) { + if (dev->dev_state == MEI_DEV_POWER_DOWN || + dev->dev_state == MEI_DEV_POWERING_DOWN) { dev_dbg(dev->dev, "hbm: enumeration response: on shutdown, ignoring\n"); return 0; } -- cgit From af628cdd64e11f03181a5a19645768ed4687bda4 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Fri, 1 Oct 2021 08:58:25 -0700 Subject: drm/i915: Fix bug in user proto-context creation that leaked contexts Set number of engines before attempting to create contexts so the function free_engines can clean up properly. Also check return of alloc_engines for NULL. v2: (Tvrtko) - Send as stand alone patch (John Harrison) - Check for alloc_engines returning NULL v3: (Checkpatch / Tvrtko) - Remove braces around single line if statement Cc: Jason Ekstrand Fixes: d4433c7600f7 ("drm/i915/gem: Use the proto-context to handle create parameters (v5)") Reviewed-by: Tvrtko Ursulin Signed-off-by: Matthew Brost Cc: Signed-off-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20211001155825.6762-1-matthew.brost@intel.com (cherry picked from commit 84edf53776343d6b5bf5fa59a6f600a22ca23c40) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 9ccf4b29b82e..166bb46408a9 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -937,6 +937,10 @@ static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx, unsigned int n; e = alloc_engines(num_engines); + if (!e) + return ERR_PTR(-ENOMEM); + e->num_engines = num_engines; + for (n = 0; n < num_engines; n++) { struct intel_context *ce; int ret; @@ -970,7 +974,6 @@ static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx, goto free_engines; } } - e->num_engines = num_engines; return e; -- cgit From 82a59c7f456db9f2874e9f1e9cb4cc19e71e95c5 Mon Sep 17 00:00:00 2001 From: Zenghui Yu Date: Mon, 6 Sep 2021 11:35:41 +0800 Subject: drm/i915: Free the returned object of acpi_evaluate_dsm() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As per the comment on top of acpi_evaluate_dsm(): | * Evaluate device's _DSM method with specified GUID, revision id and | * function number. Caller needs to free the returned object. We should free the returned object of acpi_evaluate_dsm() to avoid memory leakage. Otherwise the kmemleak splat will be triggered at boot time (if we compile kernel with CONFIG_DEBUG_TEST_DRIVER_REMOVE=y). Fixes: 8e55f99c510f ("drm/i915: Invoke another _DSM to enable MUX on HP Workstation laptops") Cc: Kai-Heng Feng Signed-off-by: Zenghui Yu Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20210906033541.862-1-yuzenghui@huawei.com (cherry picked from commit 149ac2e7ae1845191bd18b66a725392ac83a0c47) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_acpi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c b/drivers/gpu/drm/i915/display/intel_acpi.c index 7cfe91fc05f2..68abeaf2d7d4 100644 --- a/drivers/gpu/drm/i915/display/intel_acpi.c +++ b/drivers/gpu/drm/i915/display/intel_acpi.c @@ -186,13 +186,16 @@ void intel_dsm_get_bios_data_funcs_supported(struct drm_i915_private *i915) { struct pci_dev *pdev = to_pci_dev(i915->drm.dev); acpi_handle dhandle; + union acpi_object *obj; dhandle = ACPI_HANDLE(&pdev->dev); if (!dhandle) return; - acpi_evaluate_dsm(dhandle, &intel_dsm_guid2, INTEL_DSM_REVISION_ID, - INTEL_DSM_FN_GET_BIOS_DATA_FUNCS_SUPPORTED, NULL); + obj = acpi_evaluate_dsm(dhandle, &intel_dsm_guid2, INTEL_DSM_REVISION_ID, + INTEL_DSM_FN_GET_BIOS_DATA_FUNCS_SUPPORTED, NULL); + if (obj) + ACPI_FREE(obj); } /* -- cgit From c2115b2b16421d93d4993f3fe4c520e91d6fe801 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Wed, 6 Oct 2021 00:16:31 +0200 Subject: usb: musb: dsps: Fix the probe error path Commit 7c75bde329d7 ("usb: musb: musb_dsps: request_irq() after initializing musb") has inverted the calls to dsps_setup_optional_vbus_irq() and dsps_create_musb_pdev() without updating correctly the error path. dsps_create_musb_pdev() allocates and registers a new platform device which must be unregistered and freed with platform_device_unregister(), and this is missing upon dsps_setup_optional_vbus_irq() error. While on the master branch it seems not to trigger any issue, I observed a kernel crash because of a NULL pointer dereference with a v5.10.70 stable kernel where the patch mentioned above was backported. With this kernel version, -EPROBE_DEFER is returned the first time dsps_setup_optional_vbus_irq() is called which triggers the probe to error out without unregistering the platform device. Unfortunately, on the Beagle Bone Black Wireless, the platform device still living in the system is being used by the USB Ethernet gadget driver, which during the boot phase triggers the crash. My limited knowledge of the musb world prevents me to revert this commit which was sent to silence a robot warning which, as far as I understand, does not make sense. The goal of this patch was to prevent an IRQ to fire before the platform device being registered. I think this cannot ever happen due to the fact that enabling the interrupts is done by the ->enable() callback of the platform musb device, and this platform device must be already registered in order for the core or any other user to use this callback. Hence, I decided to fix the error path, which might prevent future errors on mainline kernels while also fixing older ones. Fixes: 7c75bde329d7 ("usb: musb: musb_dsps: request_irq() after initializing musb") Cc: stable@vger.kernel.org Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/r/20211005221631.1529448-1-miquel.raynal@bootlin.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_dsps.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index ce9fc46c9266..b5935834f9d2 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -899,11 +899,13 @@ static int dsps_probe(struct platform_device *pdev) if (usb_get_dr_mode(&pdev->dev) == USB_DR_MODE_PERIPHERAL) { ret = dsps_setup_optional_vbus_irq(pdev, glue); if (ret) - goto err; + goto unregister_pdev; } return 0; +unregister_pdev: + platform_device_unregister(glue->musb); err: pm_runtime_disable(&pdev->dev); iounmap(glue->usbss_base); -- cgit From 2f9a174f918e29608564c7a4e8329893ab604fb4 Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Mon, 11 Oct 2021 07:39:21 +0200 Subject: virtio: write back F_VERSION_1 before validate The virtio specification virtio-v1.1-cs01 states: "Transitional devices MUST detect Legacy drivers by detecting that VIRTIO_F_VERSION_1 has not been acknowledged by the driver." This is exactly what QEMU as of 6.1 has done relying solely on VIRTIO_F_VERSION_1 for detecting that. However, the specification also says: "... the driver MAY read (but MUST NOT write) the device-specific configuration fields to check that it can support the device ..." before setting FEATURES_OK. In that case, any transitional device relying solely on VIRTIO_F_VERSION_1 for detecting legacy drivers will return data in legacy format. In particular, this implies that it is in big endian format for big endian guests. This naturally confuses the driver which expects little endian in the modern mode. It is probably a good idea to amend the spec to clarify that VIRTIO_F_VERSION_1 can only be relied on after the feature negotiation is complete. Before validate callback existed, config space was only read after FEATURES_OK. However, we already have two regressions, so let's address this here as well. The regressions affect the VIRTIO_NET_F_MTU feature of virtio-net and the VIRTIO_BLK_F_BLK_SIZE feature of virtio-blk for BE guests when virtio 1.0 is used on both sides. The latter renders virtio-blk unusable with DASD backing, because things simply don't work with the default. See Fixes tags for relevant commits. For QEMU, we can work around the issue by writing out the feature bits with VIRTIO_F_VERSION_1 bit set. We (ab)use the finalize_features config op for this. This isn't enough to address all vhost devices since these do not get the features until FEATURES_OK, however it looks like the affected devices actually never handled the endianness for legacy mode correctly, so at least that's not a regression. No devices except virtio net and virtio blk seem to be affected. Long term the right thing to do is to fix the hypervisors. Cc: #v4.11 Signed-off-by: Halil Pasic Fixes: 82e89ea077b9 ("virtio-blk: Add validation for block size in config space") Fixes: fe36cbe0671e ("virtio_net: clear MTU when out of range") Reported-by: markver@us.ibm.com Reviewed-by: Cornelia Huck Link: https://lore.kernel.org/r/20211011053921.1198936-1-pasic@linux.ibm.com Signed-off-by: Michael S. Tsirkin --- drivers/virtio/virtio.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 0a5b54034d4b..236081afe9a2 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -239,6 +239,17 @@ static int virtio_dev_probe(struct device *_d) driver_features_legacy = driver_features; } + /* + * Some devices detect legacy solely via F_VERSION_1. Write + * F_VERSION_1 to force LE config space accesses before FEATURES_OK for + * these when needed. + */ + if (drv->validate && !virtio_legacy_is_little_endian() + && device_features & BIT_ULL(VIRTIO_F_VERSION_1)) { + dev->features = BIT_ULL(VIRTIO_F_VERSION_1); + dev->config->finalize_features(dev); + } + if (device_features & (1ULL << VIRTIO_F_VERSION_1)) dev->features = driver_features & device_features; else -- cgit From 97f854be203883b61d24f230445bd533bbdf770c Mon Sep 17 00:00:00 2001 From: Wu Zongyong Date: Wed, 15 Sep 2021 14:39:32 +0800 Subject: vhost_vdpa: unset vq irq before freeing irq Currently we unset vq irq after freeing irq and that will result in error messages: pi_update_irte: failed to update PI IRTE irq bypass consumer (token 000000005a07a12b) unregistration fails: -22 This patch solves this. Signed-off-by: Wu Zongyong Link: https://lore.kernel.org/r/02637d38dcf4e4b836c5b3a65055fe92bf812b3b.1631687872.git.wuzongyong@linux.alibaba.com Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang --- drivers/vhost/vdpa.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index 35927ceb26ff..924751427cd2 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -173,6 +173,10 @@ static long vhost_vdpa_set_status(struct vhost_vdpa *v, u8 __user *statusp) if (status != 0 && (ops->get_status(vdpa) & ~status) != 0) return -EINVAL; + if ((status_old & VIRTIO_CONFIG_S_DRIVER_OK) && !(status & VIRTIO_CONFIG_S_DRIVER_OK)) + for (i = 0; i < nvqs; i++) + vhost_vdpa_unsetup_vq_irq(v, i); + if (status == 0) { ret = ops->reset(vdpa); if (ret) @@ -184,10 +188,6 @@ static long vhost_vdpa_set_status(struct vhost_vdpa *v, u8 __user *statusp) for (i = 0; i < nvqs; i++) vhost_vdpa_setup_vq_irq(v, i); - if ((status_old & VIRTIO_CONFIG_S_DRIVER_OK) && !(status & VIRTIO_CONFIG_S_DRIVER_OK)) - for (i = 0; i < nvqs; i++) - vhost_vdpa_unsetup_vq_irq(v, i); - return 0; } -- cgit From ff63198850f33eab54b2da6905380fd4d4fc0739 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 4 Oct 2021 11:31:00 -0400 Subject: Revert "virtio-blk: Add validation for block size in config space" It turns out that access to config space before completing the feature negotiation is broken for big endian guests at least with QEMU hosts up to 6.1 inclusive. This affects any device that accesses config space in the validate callback: at the moment that is virtio-net with VIRTIO_NET_F_MTU but since 82e89ea077b9 ("virtio-blk: Add validation for block size in config space") that also started affecting virtio-blk with VIRTIO_BLK_F_BLK_SIZE. Further, unlike VIRTIO_NET_F_MTU which is off by default on QEMU, VIRTIO_BLK_F_BLK_SIZE is on by default, which resulted in lots of people not being able to boot VMs on BE. The spec is very clear that what we are doing is legal so QEMU needs to be fixed, but given it's been broken for so many years and no one noticed, we need to give QEMU a bit more time before applying this. Further, this patch is incomplete (does not check blk size is a power of two) and it duplicates the logic from nbd. Revert for now, and we'll reapply a cleaner logic in the next release. Cc: stable@vger.kernel.org Fixes: 82e89ea077b9 ("virtio-blk: Add validation for block size in config space") Cc: Xie Yongji Signed-off-by: Michael S. Tsirkin --- drivers/block/virtio_blk.c | 37 ++++++------------------------------- 1 file changed, 6 insertions(+), 31 deletions(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 9b3bd083b411..303caf2d17d0 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -689,28 +689,6 @@ static const struct blk_mq_ops virtio_mq_ops = { static unsigned int virtblk_queue_depth; module_param_named(queue_depth, virtblk_queue_depth, uint, 0444); -static int virtblk_validate(struct virtio_device *vdev) -{ - u32 blk_size; - - if (!vdev->config->get) { - dev_err(&vdev->dev, "%s failure: config access disabled\n", - __func__); - return -EINVAL; - } - - if (!virtio_has_feature(vdev, VIRTIO_BLK_F_BLK_SIZE)) - return 0; - - blk_size = virtio_cread32(vdev, - offsetof(struct virtio_blk_config, blk_size)); - - if (blk_size < SECTOR_SIZE || blk_size > PAGE_SIZE) - __virtio_clear_bit(vdev, VIRTIO_BLK_F_BLK_SIZE); - - return 0; -} - static int virtblk_probe(struct virtio_device *vdev) { struct virtio_blk *vblk; @@ -722,6 +700,12 @@ static int virtblk_probe(struct virtio_device *vdev) u8 physical_block_exp, alignment_offset; unsigned int queue_depth; + if (!vdev->config->get) { + dev_err(&vdev->dev, "%s failure: config access disabled\n", + __func__); + return -EINVAL; + } + err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS), GFP_KERNEL); if (err < 0) @@ -836,14 +820,6 @@ static int virtblk_probe(struct virtio_device *vdev) else blk_size = queue_logical_block_size(q); - if (blk_size < SECTOR_SIZE || blk_size > PAGE_SIZE) { - dev_err(&vdev->dev, - "block size is changed unexpectedly, now is %u\n", - blk_size); - err = -EINVAL; - goto out_cleanup_disk; - } - /* Use topology information if available */ err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY, struct virtio_blk_config, physical_block_exp, @@ -1009,7 +985,6 @@ static struct virtio_driver virtio_blk = { .driver.name = KBUILD_MODNAME, .driver.owner = THIS_MODULE, .id_table = id_table, - .validate = virtblk_validate, .probe = virtblk_probe, .remove = virtblk_remove, .config_changed = virtblk_config_changed, -- cgit From 8b7216439e2e2128f6f1a19ad4b6be94d8b0e23d Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Oct 2021 11:45:38 +0200 Subject: s390: add Alexander Gordeev as reviewer Alexander Gordeev will help reviewing s390 code. Acked-by: Alexander Gordeev Acked-by: Vasily Gorbik Acked-by: Christian Borntraeger Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 92db89512678..888b329413d3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16296,6 +16296,7 @@ S390 M: Heiko Carstens M: Vasily Gorbik M: Christian Borntraeger +R: Alexander Gordeev L: linux-s390@vger.kernel.org S: Supported W: http://www.ibm.com/developerworks/linux/linux390/ -- cgit From 09b6addf64860bf7b0e3dddf03229c8c20eda4b5 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 6 Oct 2021 13:29:04 -0700 Subject: VDUSE: fix documentation underline warning Fix a VDUSE documentation build warning: Documentation/userspace-api/vduse.rst:21: WARNING: Title underline too short. Fixes: 7bc7f61897b6 ("Documentation: Add documentation for VDUSE") Signed-off-by: Randy Dunlap Cc: Xie Yongji Cc: Jason Wang Cc: Michael S. Tsirkin Cc: virtualization@lists.linux-foundation.org Cc: Jonathan Corbet Cc: linux-doc@vger.kernel.org Link: https://lore.kernel.org/r/20211006202904.30241-1-rdunlap@infradead.org Signed-off-by: Michael S. Tsirkin Reviewed-by: Xie Yongji Acked-by: Jason Wang --- Documentation/userspace-api/vduse.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/userspace-api/vduse.rst b/Documentation/userspace-api/vduse.rst index 42ef59ea5314..bdb880e01132 100644 --- a/Documentation/userspace-api/vduse.rst +++ b/Documentation/userspace-api/vduse.rst @@ -18,7 +18,7 @@ types can be added after the security issue of corresponding device driver is clarified or fixed in the future. Create/Destroy VDUSE devices ------------------------- +---------------------------- VDUSE devices are created as follows: -- cgit From bcef9356fc2e1302daf373c83c826aa27954d128 Mon Sep 17 00:00:00 2001 From: Cindy Lu Date: Wed, 29 Sep 2021 17:09:33 +0800 Subject: vhost-vdpa: Fix the wrong input in config_cb Fix the wrong input in for config_cb. In function vhost_vdpa_config_cb, the input cb.private was used as struct vhost_vdpa, so the input was wrong here, fix this issue Fixes: 776f395004d8 ("vhost_vdpa: Support config interrupt in vdpa") Signed-off-by: Cindy Lu Link: https://lore.kernel.org/r/20210929090933.20465-1-lulu@redhat.com Signed-off-by: Michael S. Tsirkin --- drivers/vhost/vdpa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index 924751427cd2..39039e046117 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -322,7 +322,7 @@ static long vhost_vdpa_set_config_call(struct vhost_vdpa *v, u32 __user *argp) struct eventfd_ctx *ctx; cb.callback = vhost_vdpa_config_cb; - cb.private = v->vdpa; + cb.private = v; if (copy_from_user(&fd, argp, sizeof(fd))) return -EFAULT; -- cgit From 5d388fa01fa6eb310ac023a363a6cb216d9d8fe9 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 13 Oct 2021 13:45:11 +0100 Subject: nvmem: Fix shift-out-of-bound (UBSAN) with byte size cells If a cell has 'nbits' equal to a multiple of BITS_PER_BYTE the logic *p &= GENMASK((cell->nbits%BITS_PER_BYTE) - 1, 0); will become undefined behavior because nbits modulo BITS_PER_BYTE is 0, and we subtract one from that making a large number that is then shifted more than the number of bits that fit into an unsigned long. UBSAN reports this problem: UBSAN: shift-out-of-bounds in drivers/nvmem/core.c:1386:8 shift exponent 64 is too large for 64-bit type 'unsigned long' CPU: 6 PID: 7 Comm: kworker/u16:0 Not tainted 5.15.0-rc3+ #9 Hardware name: Google Lazor (rev3+) with KB Backlight (DT) Workqueue: events_unbound deferred_probe_work_func Call trace: dump_backtrace+0x0/0x170 show_stack+0x24/0x30 dump_stack_lvl+0x64/0x7c dump_stack+0x18/0x38 ubsan_epilogue+0x10/0x54 __ubsan_handle_shift_out_of_bounds+0x180/0x194 __nvmem_cell_read+0x1ec/0x21c nvmem_cell_read+0x58/0x94 nvmem_cell_read_variable_common+0x4c/0xb0 nvmem_cell_read_variable_le_u32+0x40/0x100 a6xx_gpu_init+0x170/0x2f4 adreno_bind+0x174/0x284 component_bind_all+0xf0/0x264 msm_drm_bind+0x1d8/0x7a0 try_to_bring_up_master+0x164/0x1ac __component_add+0xbc/0x13c component_add+0x20/0x2c dp_display_probe+0x340/0x384 platform_probe+0xc0/0x100 really_probe+0x110/0x304 __driver_probe_device+0xb8/0x120 driver_probe_device+0x4c/0xfc __device_attach_driver+0xb0/0x128 bus_for_each_drv+0x90/0xdc __device_attach+0xc8/0x174 device_initial_probe+0x20/0x2c bus_probe_device+0x40/0xa4 deferred_probe_work_func+0x7c/0xb8 process_one_work+0x128/0x21c process_scheduled_works+0x40/0x54 worker_thread+0x1ec/0x2a8 kthread+0x138/0x158 ret_from_fork+0x10/0x20 Fix it by making sure there are any bits to mask out. Fixes: 69aba7948cbe ("nvmem: Add a simple NVMEM framework for consumers") Cc: Douglas Anderson Cc: stable@vger.kernel.org Signed-off-by: Stephen Boyd Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20211013124511.18726-1-srinivas.kandagatla@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 3d87fadaa160..8976da38b375 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -1383,7 +1383,8 @@ static void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell, void *buf) *p-- = 0; /* clear msb bits if any leftover in the last byte */ - *p &= GENMASK((cell->nbits%BITS_PER_BYTE) - 1, 0); + if (cell->nbits % BITS_PER_BYTE) + *p &= GENMASK((cell->nbits % BITS_PER_BYTE) - 1, 0); } static int __nvmem_cell_read(struct nvmem_device *nvmem, -- cgit From e599ee234ad4fdfe241d937bbabd96e0d8f9d868 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Tue, 12 Oct 2021 11:34:46 +0200 Subject: net: arc: select CRC32 Fix the following build/link error by adding a dependency on the CRC32 routines: ld: drivers/net/ethernet/arc/emac_main.o: in function `arc_emac_set_rx_mode': emac_main.c:(.text+0xb11): undefined reference to `crc32_le' The crc32_le() call comes through the ether_crc_le() call in arc_emac_set_rx_mode(). [v2: moved the select to ARC_EMAC_CORE; the Makefile is a bit confusing, but the error comes from emac_main.o, which is part of the arc_emac module, which in turn is enabled by CONFIG_ARC_EMAC_CORE. Note that arc_emac is different from emac_arc...] Fixes: 775dd682e2b0ec ("arc_emac: implement promiscuous mode and multicast filtering") Cc: Arnd Bergmann Signed-off-by: Vegard Nossum Link: https://lore.kernel.org/r/20211012093446.1575-1-vegard.nossum@oracle.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/arc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/arc/Kconfig b/drivers/net/ethernet/arc/Kconfig index 37a41773dd43..92a79c4ffa2c 100644 --- a/drivers/net/ethernet/arc/Kconfig +++ b/drivers/net/ethernet/arc/Kconfig @@ -21,6 +21,7 @@ config ARC_EMAC_CORE depends on ARC || ARCH_ROCKCHIP || COMPILE_TEST select MII select PHYLIB + select CRC32 config ARC_EMAC tristate "ARC EMAC support" -- cgit From e41bdd18644a5dde1f344b70eb262b5c426e6f16 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 19 Sep 2021 10:23:08 +0800 Subject: clk: qcom: gcc-sm6115: Fix offset for hlos1_vote_turing_mmu_tbu0_gdsc It looks that the offset 0x7d060 is a copy & paste from above hlos1_vote_turing_mmu_tbu1_gdsc. Correct it to 0x7d07c as per downstream kernel. Fixes: cbe63bfdc54f ("clk: qcom: Add Global Clock controller (GCC) driver for SM6115") Signed-off-by: Shawn Guo Link: https://lore.kernel.org/r/20210919022308.24046-1-shawn.guo@linaro.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-sm6115.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/gcc-sm6115.c b/drivers/clk/qcom/gcc-sm6115.c index bc09736ece76..68fe9f6f0d2f 100644 --- a/drivers/clk/qcom/gcc-sm6115.c +++ b/drivers/clk/qcom/gcc-sm6115.c @@ -3242,7 +3242,7 @@ static struct gdsc hlos1_vote_turing_mmu_tbu1_gdsc = { }; static struct gdsc hlos1_vote_turing_mmu_tbu0_gdsc = { - .gdscr = 0x7d060, + .gdscr = 0x7d07c, .pd = { .name = "hlos1_vote_turing_mmu_tbu0", }, -- cgit From 92c02ff1a43edce37cf1b092bfad37d84d7e4ea6 Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Thu, 7 Oct 2021 23:24:28 +0200 Subject: clk: qcom: add select QCOM_GDSC for SM6350 QCOM_GDSC is needed for the gcc driver to probe. Fixes: 131abae905df ("clk: qcom: Add SM6350 GCC driver") Signed-off-by: Luca Weiss Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20211007212444.328034-2-luca@z3ntu.xyz Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 0a5596797b93..9ef007b3cf9b 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -564,6 +564,7 @@ config SM_GCC_6125 config SM_GCC_6350 tristate "SM6350 Global Clock Controller" + select QCOM_GDSC help Support for the global clock controller on SM6350 devices. Say Y if you want to use peripheral devices such as UART, -- cgit From 0f0f80d9d5db0b9a78a6ec74714f08b7b8bda0de Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sun, 10 Oct 2021 19:27:03 +0200 Subject: iommu/arm: fix ARM_SMMU_QCOM compilation My previous bugfix ended up making things worse for the QCOM IOMMU driver when it forgot to add the Kconfig symbol that is getting used to control the compilation of the SMMU implementation specific code for Qualcomm. Fixes: 424953cf3c66 ("qcom_scm: hide Kconfig symbol") Reported-by: Daniel Lezcano Reported-by: Dmitry Baryshkov Reported-by: John Stultz Link: https://lore.kernel.org/lkml/20211010023350.978638-1-dmitry.baryshkov@linaro.org/ Acked-by: Will Deacon Signed-off-by: Arnd Bergmann --- drivers/iommu/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index c5c71b7ab7e8..3eb68fa1b8cc 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -355,6 +355,14 @@ config ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT 'arm-smmu.disable_bypass' will continue to override this config. +config ARM_SMMU_QCOM + def_tristate y + depends on ARM_SMMU && ARCH_QCOM + select QCOM_SCM + help + When running on a Qualcomm platform that has the custom variant + of the ARM SMMU, this needs to be built into the SMMU driver. + config ARM_SMMU_V3 tristate "ARM Ltd. System MMU Version 3 (SMMUv3) Support" depends on ARM64 -- cgit From 427f974d9727ca681085ddcd0530c97ab5811ae0 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Tue, 12 Oct 2021 17:25:09 +0200 Subject: net: korina: select CRC32 Fix the following build/link error by adding a dependency on the CRC32 routines: ld: drivers/net/ethernet/korina.o: in function `korina_multicast_list': korina.c:(.text+0x1af): undefined reference to `crc32_le' Fixes: ef11291bcd5f9 ("Add support the Korina (IDT RC32434) Ethernet MAC") Cc: Arnd Bergmann Signed-off-by: Vegard Nossum Acked-by: Florian fainelli Link: https://lore.kernel.org/r/20211012152509.21771-1-vegard.nossum@oracle.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index d796684ec9ca..412ae3e43ffb 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -100,6 +100,7 @@ config JME config KORINA tristate "Korina (IDT RC32434) Ethernet support" depends on MIKROTIK_RB532 || COMPILE_TEST + select CRC32 select MII help If you have a Mikrotik RouterBoard 500 or IDT RC32434 -- cgit From f03dca0c9e2297c84a018e306f8a9cd534ee4287 Mon Sep 17 00:00:00 2001 From: Nanyong Sun Date: Tue, 12 Oct 2021 20:59:01 +0800 Subject: net: encx24j600: check error in devm_regmap_init_encx24j600 devm_regmap_init may return error which caused by like out of memory, this will results in null pointer dereference later when reading or writing register: general protection fault in encx24j600_spi_probe KASAN: null-ptr-deref in range [0x0000000000000090-0x0000000000000097] CPU: 0 PID: 286 Comm: spi-encx24j600- Not tainted 5.15.0-rc2-00142-g9978db750e31-dirty #11 9c53a778c1306b1b02359f3c2bbedc0222cba652 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 RIP: 0010:regcache_cache_bypass drivers/base/regmap/regcache.c:540 Code: 54 41 89 f4 55 53 48 89 fb 48 83 ec 08 e8 26 94 a8 fe 48 8d bb a0 00 00 00 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 4a 03 00 00 4c 8d ab b0 00 00 00 48 8b ab a0 00 RSP: 0018:ffffc900010476b8 EFLAGS: 00010207 RAX: dffffc0000000000 RBX: fffffffffffffff4 RCX: 0000000000000000 RDX: 0000000000000012 RSI: ffff888002de0000 RDI: 0000000000000094 RBP: ffff888013c9a000 R08: 0000000000000000 R09: fffffbfff3f9cc6a R10: ffffc900010476e8 R11: fffffbfff3f9cc69 R12: 0000000000000001 R13: 000000000000000a R14: ffff888013c9af54 R15: ffff888013c9ad08 FS: 00007ffa984ab580(0000) GS:ffff88801fe00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055a6384136c8 CR3: 000000003bbe6003 CR4: 0000000000770ef0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: encx24j600_spi_probe drivers/net/ethernet/microchip/encx24j600.c:459 spi_probe drivers/spi/spi.c:397 really_probe drivers/base/dd.c:517 __driver_probe_device drivers/base/dd.c:751 driver_probe_device drivers/base/dd.c:782 __device_attach_driver drivers/base/dd.c:899 bus_for_each_drv drivers/base/bus.c:427 __device_attach drivers/base/dd.c:971 bus_probe_device drivers/base/bus.c:487 device_add drivers/base/core.c:3364 __spi_add_device drivers/spi/spi.c:599 spi_add_device drivers/spi/spi.c:641 spi_new_device drivers/spi/spi.c:717 new_device_store+0x18c/0x1f1 [spi_stub 4e02719357f1ff33f5a43d00630982840568e85e] dev_attr_store drivers/base/core.c:2074 sysfs_kf_write fs/sysfs/file.c:139 kernfs_fop_write_iter fs/kernfs/file.c:300 new_sync_write fs/read_write.c:508 (discriminator 4) vfs_write fs/read_write.c:594 ksys_write fs/read_write.c:648 do_syscall_64 arch/x86/entry/common.c:50 entry_SYSCALL_64_after_hwframe arch/x86/entry/entry_64.S:113 Add error check in devm_regmap_init_encx24j600 to avoid this situation. Fixes: 04fbfce7a222 ("net: Microchip encx24j600 driver") Reported-by: Hulk Robot Signed-off-by: Nanyong Sun Link: https://lore.kernel.org/r/20211012125901.3623144-1-sunnanyong@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/microchip/encx24j600-regmap.c | 10 ++++++++-- drivers/net/ethernet/microchip/encx24j600.c | 5 ++++- drivers/net/ethernet/microchip/encx24j600_hw.h | 4 ++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/microchip/encx24j600-regmap.c b/drivers/net/ethernet/microchip/encx24j600-regmap.c index 796e46a53926..81a8ccca7e5e 100644 --- a/drivers/net/ethernet/microchip/encx24j600-regmap.c +++ b/drivers/net/ethernet/microchip/encx24j600-regmap.c @@ -497,13 +497,19 @@ static struct regmap_bus phymap_encx24j600 = { .reg_read = regmap_encx24j600_phy_reg_read, }; -void devm_regmap_init_encx24j600(struct device *dev, - struct encx24j600_context *ctx) +int devm_regmap_init_encx24j600(struct device *dev, + struct encx24j600_context *ctx) { mutex_init(&ctx->mutex); regcfg.lock_arg = ctx; ctx->regmap = devm_regmap_init(dev, ®map_encx24j600, ctx, ®cfg); + if (IS_ERR(ctx->regmap)) + return PTR_ERR(ctx->regmap); ctx->phymap = devm_regmap_init(dev, &phymap_encx24j600, ctx, &phycfg); + if (IS_ERR(ctx->phymap)) + return PTR_ERR(ctx->phymap); + + return 0; } EXPORT_SYMBOL_GPL(devm_regmap_init_encx24j600); diff --git a/drivers/net/ethernet/microchip/encx24j600.c b/drivers/net/ethernet/microchip/encx24j600.c index ee921a99e439..0bc6b3176fbf 100644 --- a/drivers/net/ethernet/microchip/encx24j600.c +++ b/drivers/net/ethernet/microchip/encx24j600.c @@ -1023,10 +1023,13 @@ static int encx24j600_spi_probe(struct spi_device *spi) priv->speed = SPEED_100; priv->ctx.spi = spi; - devm_regmap_init_encx24j600(&spi->dev, &priv->ctx); ndev->irq = spi->irq; ndev->netdev_ops = &encx24j600_netdev_ops; + ret = devm_regmap_init_encx24j600(&spi->dev, &priv->ctx); + if (ret) + goto out_free; + mutex_init(&priv->lock); /* Reset device and check if it is connected */ diff --git a/drivers/net/ethernet/microchip/encx24j600_hw.h b/drivers/net/ethernet/microchip/encx24j600_hw.h index fac61a8fbd02..34c5a289898c 100644 --- a/drivers/net/ethernet/microchip/encx24j600_hw.h +++ b/drivers/net/ethernet/microchip/encx24j600_hw.h @@ -15,8 +15,8 @@ struct encx24j600_context { int bank; }; -void devm_regmap_init_encx24j600(struct device *dev, - struct encx24j600_context *ctx); +int devm_regmap_init_encx24j600(struct device *dev, + struct encx24j600_context *ctx); /* Single-byte instructions */ #define BANK_SELECT(bank) (0xC0 | ((bank & (BANK_MASK >> BANK_SHIFT)) << 1)) -- cgit From 7d5fda1c841f9f3930eed61b92d542137f93fc30 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 13 Oct 2021 16:51:12 -0400 Subject: tracing: Fix event probe removal from dynamic events When an event probe is to be removed via the API that created it via the dynamic events, an -ENOENT error is returned. This is because the removal of the event probe does not expect to see the event system and name that the event probe is attached to, even though that's part of the API to create it. As the removal of probes is to use the same API as they are created. In fact, the removal is not consistent with the kprobes and uprobes removal. Fix that by allowing various ways to remove the eprobe. The eprobe is created with: e:[GROUP/]NAME SYSTEM/EVENT [OPTIONS] Have it get removed by echoing in the following into dynamic_events: # Remove all eprobes with NAME echo '-:NAME' >> dynamic_events # Remove a specific eprobe echo '-:GROUP/NAME' >> dynamic_events echo '-:GROUP/NAME SYSTEM/EVENT' >> dynamic_events echo '-:NAME SYSTEM/EVENT' >> dynamic_events echo '-:GROUP/NAME SYSTEM/EVENT OPTIONS' >> dynamic_events echo '-:NAME SYSTEM/EVENT OPTIONS' >> dynamic_events Link: https://lkml.kernel.org/r/20211012081925.0e19cc4f@gandalf.local.home Link: https://lkml.kernel.org/r/20211013205533.630722129@goodmis.org Suggested-by: Masami Hiramatsu Acked-by: Masami Hiramatsu Fixes: 7491e2c442781 ("tracing: Add a probe that attaches to trace events") Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace_eprobe.c | 54 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c index 570d081929fb..c4a15aef36af 100644 --- a/kernel/trace/trace_eprobe.c +++ b/kernel/trace/trace_eprobe.c @@ -119,10 +119,58 @@ static bool eprobe_dyn_event_match(const char *system, const char *event, int argc, const char **argv, struct dyn_event *ev) { struct trace_eprobe *ep = to_trace_eprobe(ev); + const char *slash; - return strcmp(trace_probe_name(&ep->tp), event) == 0 && - (!system || strcmp(trace_probe_group_name(&ep->tp), system) == 0) && - trace_probe_match_command_args(&ep->tp, argc, argv); + /* + * We match the following: + * event only - match all eprobes with event name + * system and event only - match all system/event probes + * + * The below has the above satisfied with more arguments: + * + * attached system/event - If the arg has the system and event + * the probe is attached to, match + * probes with the attachment. + * + * If any more args are given, then it requires a full match. + */ + + /* + * If system exists, but this probe is not part of that system + * do not match. + */ + if (system && strcmp(trace_probe_group_name(&ep->tp), system) != 0) + return false; + + /* Must match the event name */ + if (strcmp(trace_probe_name(&ep->tp), event) != 0) + return false; + + /* No arguments match all */ + if (argc < 1) + return true; + + /* First argument is the system/event the probe is attached to */ + + slash = strchr(argv[0], '/'); + if (!slash) + slash = strchr(argv[0], '.'); + if (!slash) + return false; + + if (strncmp(ep->event_system, argv[0], slash - argv[0])) + return false; + if (strcmp(ep->event_name, slash + 1)) + return false; + + argc--; + argv++; + + /* If there are no other args, then match */ + if (argc < 1) + return true; + + return trace_probe_match_command_args(&ep->tp, argc, argv); } static struct dyn_event_operations eprobe_dyn_event_ops = { -- cgit From 0282b0f0126489af5b3993e52d1a05e6c7ebc4e8 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 13 Oct 2021 16:51:13 -0400 Subject: selftests/ftrace: Update test for more eprobe removal process The removal of eprobes was broken and missed in testing. Add various ways to remove eprobes that are considered acceptable to the testing process to catch when/if they break again. Link: https://lkml.kernel.org/r/20211013205533.836644549@goodmis.org Acked-by: Masami Hiramatsu Signed-off-by: Steven Rostedt (VMware) --- .../ftrace/test.d/dynevent/add_remove_eprobe.tc | 54 +++++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc index 5f5b2ba3e557..60c02b482be8 100644 --- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc +++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_eprobe.tc @@ -11,8 +11,8 @@ SYSTEM="syscalls" EVENT="sys_enter_openat" FIELD="filename" EPROBE="eprobe_open" - -echo "e:$EPROBE $SYSTEM/$EVENT file=+0(\$filename):ustring" >> dynamic_events +OPTIONS="file=+0(\$filename):ustring" +echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events grep -q "$EPROBE" dynamic_events test -d events/eprobes/$EPROBE @@ -37,4 +37,54 @@ echo "-:$EPROBE" >> dynamic_events ! grep -q "$EPROBE" dynamic_events ! test -d events/eprobes/$EPROBE +# test various ways to remove the probe (already tested with just event name) + +# With group name +echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events +grep -q "$EPROBE" dynamic_events +test -d events/eprobes/$EPROBE +echo "-:eprobes/$EPROBE" >> dynamic_events +! grep -q "$EPROBE" dynamic_events +! test -d events/eprobes/$EPROBE + +# With group name and system/event +echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events +grep -q "$EPROBE" dynamic_events +test -d events/eprobes/$EPROBE +echo "-:eprobes/$EPROBE $SYSTEM/$EVENT" >> dynamic_events +! grep -q "$EPROBE" dynamic_events +! test -d events/eprobes/$EPROBE + +# With just event name and system/event +echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events +grep -q "$EPROBE" dynamic_events +test -d events/eprobes/$EPROBE +echo "-:$EPROBE $SYSTEM/$EVENT" >> dynamic_events +! grep -q "$EPROBE" dynamic_events +! test -d events/eprobes/$EPROBE + +# With just event name and system/event and options +echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events +grep -q "$EPROBE" dynamic_events +test -d events/eprobes/$EPROBE +echo "-:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events +! grep -q "$EPROBE" dynamic_events +! test -d events/eprobes/$EPROBE + +# With group name and system/event and options +echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events +grep -q "$EPROBE" dynamic_events +test -d events/eprobes/$EPROBE +echo "-:eprobes/$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events +! grep -q "$EPROBE" dynamic_events +! test -d events/eprobes/$EPROBE + +# Finally make sure what is in the dynamic_events file clears it too +echo "e:$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events +LINE=`sed -e '/$EPROBE/s/^e/-/' < dynamic_events` +test -d events/eprobes/$EPROBE +echo "-:eprobes/$EPROBE $SYSTEM/$EVENT $OPTIONS" >> dynamic_events +! grep -q "$EPROBE" dynamic_events +! test -d events/eprobes/$EPROBE + clear_trace -- cgit From 1f922d9e374f0ca7d1b241666c792f403c6120aa Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Wed, 13 Oct 2021 03:19:09 +0300 Subject: Revert "net: procfs: add seq_puts() statement for dev_mcast" This reverts commit ec18e8455484370d633a718c6456ddbf6eceef21. It turns out that there are user space programs which got broken by that change. One example is the "ifstat" program shipped by Debian: https://packages.debian.org/source/bullseye/ifstat which, confusingly enough, seems to not have anything in common with the much more familiar (at least to me) ifstat program from iproute2: https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/misc/ifstat.c root@debian:~# ifstat ifstat: /proc/net/dev: unsupported format. This change modified the header (first two lines of text) in /proc/net/dev so that it looks like this: root@debian:~# cat /proc/net/dev Interface| Receive | Transmit | bytes packets errs drop fifo frame compressed multicast| bytes packets errs drop fifo colls carrier compressed lo: 97400 1204 0 0 0 0 0 0 97400 1204 0 0 0 0 0 0 bond0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 sit0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 eno2: 5002206 6651 0 0 0 0 0 0 105518642 1465023 0 0 0 0 0 0 swp0: 134531 2448 0 0 0 0 0 0 99599598 1464381 0 0 0 0 0 0 swp1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 swp2: 4867675 4203 0 0 0 0 0 0 58134 631 0 0 0 0 0 0 sw0p0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 sw0p1: 124739 2448 0 1422 0 0 0 0 93741184 1464369 0 0 0 0 0 0 sw0p2: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 sw2p0: 4850863 4203 0 0 0 0 0 0 54722 619 0 0 0 0 0 0 sw2p1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 sw2p2: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 sw2p3: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 br0: 10508 212 0 212 0 0 0 212 61369558 958857 0 0 0 0 0 0 whereas before it looked like this: root@debian:~# cat /proc/net/dev Inter-| Receive | Transmit face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed lo: 13160 164 0 0 0 0 0 0 13160 164 0 0 0 0 0 0 bond0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 sit0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 eno2: 30824 268 0 0 0 0 0 0 3332 37 0 0 0 0 0 0 swp0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 swp1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 swp2: 30824 268 0 0 0 0 0 0 2428 27 0 0 0 0 0 0 sw0p0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 sw0p1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 sw0p2: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 sw2p0: 29752 268 0 0 0 0 0 0 1564 17 0 0 0 0 0 0 sw2p1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 sw2p2: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 sw2p3: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 The reason why the ifstat shipped by Debian (v1.1, with a Debian patch upgrading it to 1.1-8.1 at the time of writing) is broken is because its "proc" driver/backend parses the header very literally: main/drivers.c#L825 if (!data->checked && strncmp(buf, "Inter-|", 7)) goto badproc; and there's no way in which the header can be changed such that programs parsing like that would not get broken. Even if we fix this ancient and very "lightly" maintained program to parse the text output of /proc/net/dev in a more sensible way, this story seems bound to repeat again with other programs, and modifying them all could cause more trouble than it's worth. On the other hand, the reverted patch had no other reason than an aesthetic one, so reverting it is the simplest way out. I don't know what other distributions would be affected; the fact that Debian doesn't ship the iproute2 version of the program (a different code base altogether, which uses netlink and not /proc/net/dev) is surprising in itself. Fixes: ec18e8455484 ("net: procfs: add seq_puts() statement for dev_mcast") Link: https://lore.kernel.org/netdev/20211009163511.vayjvtn3rrteglsu@skbuf/ Cc: Yajun Deng Cc: Matthieu Baerts Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20211013001909.3164185-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- net/core/net-procfs.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/net/core/net-procfs.c b/net/core/net-procfs.c index eab5fc88a002..d8b9dbabd4a4 100644 --- a/net/core/net-procfs.c +++ b/net/core/net-procfs.c @@ -77,8 +77,8 @@ static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) struct rtnl_link_stats64 temp; const struct rtnl_link_stats64 *stats = dev_get_stats(dev, &temp); - seq_printf(seq, "%9s: %16llu %12llu %4llu %6llu %4llu %5llu %10llu %9llu " - "%16llu %12llu %4llu %6llu %4llu %5llu %7llu %10llu\n", + seq_printf(seq, "%6s: %7llu %7llu %4llu %4llu %4llu %5llu %10llu %9llu " + "%8llu %7llu %4llu %4llu %4llu %5llu %7llu %10llu\n", dev->name, stats->rx_bytes, stats->rx_packets, stats->rx_errors, stats->rx_dropped + stats->rx_missed_errors, @@ -103,11 +103,11 @@ static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) static int dev_seq_show(struct seq_file *seq, void *v) { if (v == SEQ_START_TOKEN) - seq_puts(seq, "Interface| Receive " - " | Transmit\n" - " | bytes packets errs drop fifo frame " - "compressed multicast| bytes packets errs " - " drop fifo colls carrier compressed\n"); + seq_puts(seq, "Inter-| Receive " + " | Transmit\n" + " face |bytes packets errs drop fifo frame " + "compressed multicast|bytes packets errs " + "drop fifo colls carrier compressed\n"); else dev_seq_printf_stats(seq, v); return 0; @@ -259,14 +259,14 @@ static int ptype_seq_show(struct seq_file *seq, void *v) struct packet_type *pt = v; if (v == SEQ_START_TOKEN) - seq_puts(seq, "Type Device Function\n"); + seq_puts(seq, "Type Device Function\n"); else if (pt->dev == NULL || dev_net(pt->dev) == seq_file_net(seq)) { if (pt->type == htons(ETH_P_ALL)) seq_puts(seq, "ALL "); else seq_printf(seq, "%04x", ntohs(pt->type)); - seq_printf(seq, " %-9s %ps\n", + seq_printf(seq, " %-8s %ps\n", pt->dev ? pt->dev->name : "", pt->func); } @@ -327,14 +327,12 @@ static int dev_mc_seq_show(struct seq_file *seq, void *v) struct netdev_hw_addr *ha; struct net_device *dev = v; - if (v == SEQ_START_TOKEN) { - seq_puts(seq, "Ifindex Interface Refcount Global_use Address\n"); + if (v == SEQ_START_TOKEN) return 0; - } netif_addr_lock_bh(dev); netdev_for_each_mc_addr(ha, dev) { - seq_printf(seq, "%-7d %-9s %-8d %-10d %*phN\n", + seq_printf(seq, "%-4d %-15s %-5d %-5d %*phN\n", dev->ifindex, dev->name, ha->refcount, ha->global_use, (int)dev->addr_len, ha->addr); -- cgit From 0911ab31896f0e908540746414a77dd63912748d Mon Sep 17 00:00:00 2001 From: Ziyang Xuan Date: Wed, 13 Oct 2021 11:49:32 +0800 Subject: nfc: fix error handling of nfc_proto_register() When nfc proto id is using, nfc_proto_register() return -EBUSY error code, but forgot to unregister proto. Fix it by adding proto_unregister() in the error handling case. Fixes: c7fe3b52c128 ("NFC: add NFC socket family") Signed-off-by: Ziyang Xuan Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20211013034932.2833737-1-william.xuanziyang@huawei.com Signed-off-by: Jakub Kicinski --- net/nfc/af_nfc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/nfc/af_nfc.c b/net/nfc/af_nfc.c index 6024fad905ff..dda323e0a473 100644 --- a/net/nfc/af_nfc.c +++ b/net/nfc/af_nfc.c @@ -60,6 +60,9 @@ int nfc_proto_register(const struct nfc_protocol *nfc_proto) proto_tab[nfc_proto->id] = nfc_proto; write_unlock(&proto_tab_lock); + if (rc) + proto_unregister(nfc_proto->proto); + return rc; } EXPORT_SYMBOL(nfc_proto_register); -- cgit From 58e7dcc9ca29c14e44267a4d0ea61e3229124907 Mon Sep 17 00:00:00 2001 From: Ziyang Xuan Date: Wed, 13 Oct 2021 15:50:12 +0800 Subject: NFC: digital: fix possible memory leak in digital_tg_listen_mdaa() 'params' is allocated in digital_tg_listen_mdaa(), but not free when digital_send_cmd() failed, which will cause memory leak. Fix it by freeing 'params' if digital_send_cmd() return failed. Fixes: 1c7a4c24fbfd ("NFC Digital: Add target NFC-DEP support") Signed-off-by: Ziyang Xuan Reviewed-by: Krzysztof Kozlowski Signed-off-by: Jakub Kicinski --- net/nfc/digital_core.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index fefc03674f4f..d63d2e5dc60c 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c @@ -277,6 +277,7 @@ int digital_tg_configure_hw(struct nfc_digital_dev *ddev, int type, int param) static int digital_tg_listen_mdaa(struct nfc_digital_dev *ddev, u8 rf_tech) { struct digital_tg_mdaa_params *params; + int rc; params = kzalloc(sizeof(*params), GFP_KERNEL); if (!params) @@ -291,8 +292,12 @@ static int digital_tg_listen_mdaa(struct nfc_digital_dev *ddev, u8 rf_tech) get_random_bytes(params->nfcid2 + 2, NFC_NFCID2_MAXSIZE - 2); params->sc = DIGITAL_SENSF_FELICA_SC; - return digital_send_cmd(ddev, DIGITAL_CMD_TG_LISTEN_MDAA, NULL, params, - 500, digital_tg_recv_atr_req, NULL); + rc = digital_send_cmd(ddev, DIGITAL_CMD_TG_LISTEN_MDAA, NULL, params, + 500, digital_tg_recv_atr_req, NULL); + if (rc) + kfree(params); + + return rc; } static int digital_tg_listen_md(struct nfc_digital_dev *ddev, u8 rf_tech) -- cgit From 291c932fc3692e4d211a445ba8aa35663831bac7 Mon Sep 17 00:00:00 2001 From: Ziyang Xuan Date: Wed, 13 Oct 2021 15:50:32 +0800 Subject: NFC: digital: fix possible memory leak in digital_in_send_sdd_req() 'skb' is allocated in digital_in_send_sdd_req(), but not free when digital_in_send_cmd() failed, which will cause memory leak. Fix it by freeing 'skb' if digital_in_send_cmd() return failed. Fixes: 2c66daecc409 ("NFC Digital: Add NFC-A technology support") Signed-off-by: Ziyang Xuan Reviewed-by: Krzysztof Kozlowski Signed-off-by: Jakub Kicinski --- net/nfc/digital_technology.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c index 84d2345c75a3..3adf4589852a 100644 --- a/net/nfc/digital_technology.c +++ b/net/nfc/digital_technology.c @@ -465,8 +465,12 @@ static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, skb_put_u8(skb, sel_cmd); skb_put_u8(skb, DIGITAL_SDD_REQ_SEL_PAR); - return digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sdd_res, - target); + rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sdd_res, + target); + if (rc) + kfree_skb(skb); + + return rc; } static void digital_in_recv_sens_res(struct nfc_digital_dev *ddev, void *arg, -- cgit From 776c75010803849c1cc4f11031a2b3960ab05202 Mon Sep 17 00:00:00 2001 From: Wang Hai Date: Wed, 13 Oct 2021 14:16:31 +0800 Subject: ata: ahci_platform: fix null-ptr-deref in ahci_platform_enable_regulators() I got a null-ptr-deref report: KASAN: null-ptr-deref in range [0x0000000000000090-0x0000000000000097] ... RIP: 0010:regulator_enable+0x84/0x260 ... Call Trace: ahci_platform_enable_regulators+0xae/0x320 ahci_platform_enable_resources+0x1a/0x120 ahci_probe+0x4f/0x1b9 platform_probe+0x10b/0x280 ... entry_SYSCALL_64_after_hwframe+0x44/0xae If devm_regulator_get() in ahci_platform_get_resources() fails, hpriv->phy_regulator will point to NULL, when enabling or disabling it, null-ptr-deref will occur. ahci_probe() ahci_platform_get_resources() devm_regulator_get(, "phy") // failed, let phy_regulator = NULL ahci_platform_enable_resources() ahci_platform_enable_regulators() regulator_enable(hpriv->phy_regulator) // null-ptr-deref commit 962399bb7fbf ("ata: libahci_platform: Fix regulator_get_optional() misuse") replaces devm_regulator_get_optional() with devm_regulator_get(), but PHY regulator omits to delete "hpriv->phy_regulator = NULL;" like AHCI. Delete it like AHCI regulator to fix this bug. Fixes: commit 962399bb7fbf ("ata: libahci_platform: Fix regulator_get_optional() misuse") Reported-by: Hulk Robot Signed-off-by: Wang Hai Reviewed-by: Hans de Goede Signed-off-by: Damien Le Moal --- drivers/ata/libahci_platform.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c index b2f552088291..0910441321f7 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -440,10 +440,7 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, hpriv->phy_regulator = devm_regulator_get(dev, "phy"); if (IS_ERR(hpriv->phy_regulator)) { rc = PTR_ERR(hpriv->phy_regulator); - if (rc == -EPROBE_DEFER) - goto err_out; - rc = 0; - hpriv->phy_regulator = NULL; + goto err_out; } if (flags & AHCI_PLATFORM_GET_RESETS) { -- cgit From be5eb933542629ad6a7d4c92097b1b472b1612d0 Mon Sep 17 00:00:00 2001 From: Adam Manzanares Date: Wed, 13 Oct 2021 15:04:19 +0000 Subject: nvme: fix per-namespace chardev deletion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Decrease reference count of chardevice during char device deletion in order to fix a memory leak. Add a release callabck for the device associated chardev and move ida_simple_remove into the release function. Fixes: 2637baed7801 ("nvme: introduce generic per-namespace chardev") Reported-by: Yi Zhang Suggested-by: Sagi Grimberg Signed-off-by: Adam Manzanares Reviewed-by: Javier González Tested-by: Yi Zhang Signed-off-by: Christoph Hellwig --- drivers/nvme/host/core.c | 21 ++++++++++++--------- drivers/nvme/host/multipath.c | 2 -- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index e486845d2c7e..587385bc82b6 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -3548,10 +3548,15 @@ static int __nvme_check_ids(struct nvme_subsystem *subsys, return 0; } +static void nvme_cdev_rel(struct device *dev) +{ + ida_simple_remove(&nvme_ns_chr_minor_ida, MINOR(dev->devt)); +} + void nvme_cdev_del(struct cdev *cdev, struct device *cdev_device) { cdev_device_del(cdev, cdev_device); - ida_simple_remove(&nvme_ns_chr_minor_ida, MINOR(cdev_device->devt)); + put_device(cdev_device); } int nvme_cdev_add(struct cdev *cdev, struct device *cdev_device, @@ -3564,14 +3569,14 @@ int nvme_cdev_add(struct cdev *cdev, struct device *cdev_device, return minor; cdev_device->devt = MKDEV(MAJOR(nvme_ns_chr_devt), minor); cdev_device->class = nvme_ns_chr_class; + cdev_device->release = nvme_cdev_rel; device_initialize(cdev_device); cdev_init(cdev, fops); cdev->owner = owner; ret = cdev_device_add(cdev, cdev_device); - if (ret) { + if (ret) put_device(cdev_device); - ida_simple_remove(&nvme_ns_chr_minor_ida, minor); - } + return ret; } @@ -3603,11 +3608,9 @@ static int nvme_add_ns_cdev(struct nvme_ns *ns) ns->ctrl->instance, ns->head->instance); if (ret) return ret; - ret = nvme_cdev_add(&ns->cdev, &ns->cdev_device, &nvme_ns_chr_fops, - ns->ctrl->ops->module); - if (ret) - kfree_const(ns->cdev_device.kobj.name); - return ret; + + return nvme_cdev_add(&ns->cdev, &ns->cdev_device, &nvme_ns_chr_fops, + ns->ctrl->ops->module); } static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl, diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index e8ccdd398f78..fba06618c6c2 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -431,8 +431,6 @@ static int nvme_add_ns_head_cdev(struct nvme_ns_head *head) return ret; ret = nvme_cdev_add(&head->cdev, &head->cdev_device, &nvme_ns_head_chr_fops, THIS_MODULE); - if (ret) - kfree_const(head->cdev_device.kobj.name); return ret; } -- cgit From d9b7748ffc45250b4d7bcf22404383229bc495f5 Mon Sep 17 00:00:00 2001 From: Hans Potsch Date: Wed, 6 Oct 2021 14:13:32 +0200 Subject: EDAC/armada-xp: Fix output of uncorrectable error counter The number of correctable errors is displayed as uncorrectable errors because the "SBE" error count is passed to both calls of edac_mc_handle_error(). Pass the correct uncorrectable error count to the second edac_mc_handle_error() call when logging uncorrectable errors. [ bp: Massage commit message. ] Fixes: 7f6998a41257 ("ARM: 8888/1: EDAC: Add driver for the Marvell Armada XP SDRAM and L2 cache ECC") Signed-off-by: Hans Potsch Signed-off-by: Borislav Petkov Cc: Link: https://lkml.kernel.org/r/20211006121332.58788-1-hans.potsch@nokia.com --- drivers/edac/armada_xp_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/armada_xp_edac.c b/drivers/edac/armada_xp_edac.c index e3e757513d1b..b1f46a974b9e 100644 --- a/drivers/edac/armada_xp_edac.c +++ b/drivers/edac/armada_xp_edac.c @@ -178,7 +178,7 @@ static void axp_mc_check(struct mem_ctl_info *mci) "details unavailable (multiple errors)"); if (cnt_dbe) edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, - cnt_sbe, /* error count */ + cnt_dbe, /* error count */ 0, 0, 0, /* pfn, offset, syndrome */ -1, -1, -1, /* top, mid, low layer */ mci->ctl_name, -- cgit From 6098475d4cb48d821bdf453c61118c56e26294f0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 8 Oct 2021 14:31:57 +0100 Subject: spi: Fix deadlock when adding SPI controllers on SPI buses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we have a global spi_add_lock which we take when adding new devices so that we can check that we're not trying to reuse a chip select that's already controlled. This means that if the SPI device is itself a SPI controller and triggers the instantiation of further SPI devices we trigger a deadlock as we try to register and instantiate those devices while in the process of doing so for the parent controller and hence already holding the global spi_add_lock. Since we only care about concurrency within a single SPI bus move the lock to be per controller, avoiding the deadlock. This can be easily triggered in the case of spi-mux. Reported-by: Uwe Kleine-König Signed-off-by: Mark Brown --- drivers/spi/spi.c | 17 ++++++----------- include/linux/spi/spi.h | 3 +++ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index aea037c65985..412a10586233 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -478,12 +478,6 @@ static LIST_HEAD(spi_controller_list); */ static DEFINE_MUTEX(board_lock); -/* - * Prevents addition of devices with same chip select and - * addition of devices below an unregistering controller. - */ -static DEFINE_MUTEX(spi_add_lock); - /** * spi_alloc_device - Allocate a new SPI device * @ctlr: Controller to which device is connected @@ -636,9 +630,9 @@ int spi_add_device(struct spi_device *spi) * chipselect **BEFORE** we call setup(), else we'll trash * its configuration. Lock against concurrent add() calls. */ - mutex_lock(&spi_add_lock); + mutex_lock(&ctlr->add_lock); status = __spi_add_device(spi); - mutex_unlock(&spi_add_lock); + mutex_unlock(&ctlr->add_lock); return status; } EXPORT_SYMBOL_GPL(spi_add_device); @@ -658,7 +652,7 @@ static int spi_add_device_locked(struct spi_device *spi) /* Set the bus ID string */ spi_dev_set_name(spi); - WARN_ON(!mutex_is_locked(&spi_add_lock)); + WARN_ON(!mutex_is_locked(&ctlr->add_lock)); return __spi_add_device(spi); } @@ -2830,6 +2824,7 @@ int spi_register_controller(struct spi_controller *ctlr) spin_lock_init(&ctlr->bus_lock_spinlock); mutex_init(&ctlr->bus_lock_mutex); mutex_init(&ctlr->io_mutex); + mutex_init(&ctlr->add_lock); ctlr->bus_lock_flag = 0; init_completion(&ctlr->xfer_completion); if (!ctlr->max_dma_len) @@ -2966,7 +2961,7 @@ void spi_unregister_controller(struct spi_controller *ctlr) /* Prevent addition of new devices, unregister existing ones */ if (IS_ENABLED(CONFIG_SPI_DYNAMIC)) - mutex_lock(&spi_add_lock); + mutex_lock(&ctlr->add_lock); device_for_each_child(&ctlr->dev, NULL, __unregister); @@ -2997,7 +2992,7 @@ void spi_unregister_controller(struct spi_controller *ctlr) mutex_unlock(&board_lock); if (IS_ENABLED(CONFIG_SPI_DYNAMIC)) - mutex_unlock(&spi_add_lock); + mutex_unlock(&ctlr->add_lock); } EXPORT_SYMBOL_GPL(spi_unregister_controller); diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 8371bca13729..6b0b686f6f90 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -531,6 +531,9 @@ struct spi_controller { /* I/O mutex */ struct mutex io_mutex; + /* Used to avoid adding the same CS twice */ + struct mutex add_lock; + /* lock and mutex for SPI bus locking */ spinlock_t bus_lock_spinlock; struct mutex bus_lock_mutex; -- cgit From 16a8e2fbb2d49111004efc1c7342e083eafabeb0 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 13 Oct 2021 15:37:10 +0200 Subject: spi-mux: Fix false-positive lockdep splats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit io_mutex is taken by spi_setup() and spi-mux's .setup() callback calls spi_setup() which results in a nested lock of io_mutex. add_lock is taken by spi_add_device(). The device_add() call in there can result in calling spi-mux's .probe() callback which registers its own spi controller which in turn results in spi_add_device() being called again. To fix this initialize the controller's locks already in spi_alloc_controller() to give spi_mux_probe() a chance to set the lockdep subclass. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20211013133710.2679703-2-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi-mux.c | 7 +++++++ drivers/spi/spi.c | 12 ++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-mux.c b/drivers/spi/spi-mux.c index 9708b7827ff7..f5d32ec4634e 100644 --- a/drivers/spi/spi-mux.c +++ b/drivers/spi/spi-mux.c @@ -137,6 +137,13 @@ static int spi_mux_probe(struct spi_device *spi) priv = spi_controller_get_devdata(ctlr); priv->spi = spi; + /* + * Increase lockdep class as these lock are taken while the parent bus + * already holds their instance's lock. + */ + lockdep_set_subclass(&ctlr->io_mutex, 1); + lockdep_set_subclass(&ctlr->add_lock, 1); + priv->mux = devm_mux_control_get(&spi->dev, NULL); if (IS_ERR(priv->mux)) { ret = dev_err_probe(&spi->dev, PTR_ERR(priv->mux), diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 412a10586233..926b68aa45d3 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2547,6 +2547,12 @@ struct spi_controller *__spi_alloc_controller(struct device *dev, return NULL; device_initialize(&ctlr->dev); + INIT_LIST_HEAD(&ctlr->queue); + spin_lock_init(&ctlr->queue_lock); + spin_lock_init(&ctlr->bus_lock_spinlock); + mutex_init(&ctlr->bus_lock_mutex); + mutex_init(&ctlr->io_mutex); + mutex_init(&ctlr->add_lock); ctlr->bus_num = -1; ctlr->num_chipselect = 1; ctlr->slave = slave; @@ -2819,12 +2825,6 @@ int spi_register_controller(struct spi_controller *ctlr) return id; ctlr->bus_num = id; } - INIT_LIST_HEAD(&ctlr->queue); - spin_lock_init(&ctlr->queue_lock); - spin_lock_init(&ctlr->bus_lock_spinlock); - mutex_init(&ctlr->bus_lock_mutex); - mutex_init(&ctlr->io_mutex); - mutex_init(&ctlr->add_lock); ctlr->bus_lock_flag = 0; init_completion(&ctlr->xfer_completion); if (!ctlr->max_dma_len) -- cgit From 26d6574109838b8fa40a8261421693015bab0579 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 12 Oct 2021 22:40:56 -0500 Subject: MAINTAINERS: Update entry for the Stratix10 firmware Richard Gong is no longer at Intel, so update the MAINTAINER's entry for the Stratix10 firmware drivers. Signed-off-by: Dinh Nguyen Signed-off-by: Linus Torvalds --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index e0bca0de0df7..6b6f98483deb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9629,7 +9629,7 @@ F: include/uapi/linux/isst_if.h F: tools/power/x86/intel-speed-select/ INTEL STRATIX10 FIRMWARE DRIVERS -M: Richard Gong +M: Dinh Nguyen L: linux-kernel@vger.kernel.org S: Maintained F: Documentation/ABI/testing/sysfs-devices-platform-stratix10-rsu -- cgit From 40507e7aada8422c38aafa0c8a1a09e4623c712a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 13 Oct 2021 16:35:49 +0200 Subject: ethernet: s2io: fix setting mac address during resume After recent cleanups, gcc started warning about a suspicious memcpy() call during the s2io_io_resume() function: In function '__dev_addr_set', inlined from 'eth_hw_addr_set' at include/linux/etherdevice.h:318:2, inlined from 's2io_set_mac_addr' at drivers/net/ethernet/neterion/s2io.c:5205:2, inlined from 's2io_io_resume' at drivers/net/ethernet/neterion/s2io.c:8569:7: arch/x86/include/asm/string_32.h:182:25: error: '__builtin_memcpy' accessing 6 bytes at offsets 0 and 2 overlaps 4 bytes at offset 2 [-Werror=restrict] 182 | #define memcpy(t, f, n) __builtin_memcpy(t, f, n) | ^~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/netdevice.h:4648:9: note: in expansion of macro 'memcpy' 4648 | memcpy(dev->dev_addr, addr, len); | ^~~~~~ What apparently happened is that an old cleanup changed the calling conventions for s2io_set_mac_addr() from taking an ethernet address as a character array to taking a struct sockaddr, but one of the callers was not changed at the same time. Change it to instead call the low-level do_s2io_prog_unicast() function that still takes the old argument type. Fixes: 2fd376884558 ("S2io: Added support set_mac_address driver entry point") Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20211013143613.2049096-1-arnd@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/neterion/s2io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c index 09c0e839cca5..3b6b2e61139e 100644 --- a/drivers/net/ethernet/neterion/s2io.c +++ b/drivers/net/ethernet/neterion/s2io.c @@ -8566,7 +8566,7 @@ static void s2io_io_resume(struct pci_dev *pdev) return; } - if (s2io_set_mac_addr(netdev, netdev->dev_addr) == FAILURE) { + if (do_s2io_prog_unicast(netdev, netdev->dev_addr) == FAILURE) { s2io_card_down(sp); pr_err("Can't restore mac addr after reset.\n"); return; -- cgit From 332fdf951df8b870e3da86b122ae304e2aabe88c Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 12 Oct 2021 20:49:55 +0300 Subject: mlxsw: thermal: Fix out-of-bounds memory accesses Currently, mlxsw allows cooling states to be set above the maximum cooling state supported by the driver: # cat /sys/class/thermal/thermal_zone2/cdev0/type mlxsw_fan # cat /sys/class/thermal/thermal_zone2/cdev0/max_state 10 # echo 18 > /sys/class/thermal/thermal_zone2/cdev0/cur_state # echo $? 0 This results in out-of-bounds memory accesses when thermal state transition statistics are enabled (CONFIG_THERMAL_STATISTICS=y), as the transition table is accessed with a too large index (state) [1]. According to the thermal maintainer, it is the responsibility of the driver to reject such operations [2]. Therefore, return an error when the state to be set exceeds the maximum cooling state supported by the driver. To avoid dead code, as suggested by the thermal maintainer [3], partially revert commit a421ce088ac8 ("mlxsw: core: Extend cooling device with cooling levels") that tried to interpret these invalid cooling states (above the maximum) in a special way. The cooling levels array is not removed in order to prevent the fans going below 20% PWM, which would cause them to get stuck at 0% PWM. [1] BUG: KASAN: slab-out-of-bounds in thermal_cooling_device_stats_update+0x271/0x290 Read of size 4 at addr ffff8881052f7bf8 by task kworker/0:0/5 CPU: 0 PID: 5 Comm: kworker/0:0 Not tainted 5.15.0-rc3-custom-45935-gce1adf704b14 #122 Hardware name: Mellanox Technologies Ltd. "MSN2410-CB2FO"/"SA000874", BIOS 4.6.5 03/08/2016 Workqueue: events_freezable_power_ thermal_zone_device_check Call Trace: dump_stack_lvl+0x8b/0xb3 print_address_description.constprop.0+0x1f/0x140 kasan_report.cold+0x7f/0x11b thermal_cooling_device_stats_update+0x271/0x290 __thermal_cdev_update+0x15e/0x4e0 thermal_cdev_update+0x9f/0xe0 step_wise_throttle+0x770/0xee0 thermal_zone_device_update+0x3f6/0xdf0 process_one_work+0xa42/0x1770 worker_thread+0x62f/0x13e0 kthread+0x3ee/0x4e0 ret_from_fork+0x1f/0x30 Allocated by task 1: kasan_save_stack+0x1b/0x40 __kasan_kmalloc+0x7c/0x90 thermal_cooling_device_setup_sysfs+0x153/0x2c0 __thermal_cooling_device_register.part.0+0x25b/0x9c0 thermal_cooling_device_register+0xb3/0x100 mlxsw_thermal_init+0x5c5/0x7e0 __mlxsw_core_bus_device_register+0xcb3/0x19c0 mlxsw_core_bus_device_register+0x56/0xb0 mlxsw_pci_probe+0x54f/0x710 local_pci_probe+0xc6/0x170 pci_device_probe+0x2b2/0x4d0 really_probe+0x293/0xd10 __driver_probe_device+0x2af/0x440 driver_probe_device+0x51/0x1e0 __driver_attach+0x21b/0x530 bus_for_each_dev+0x14c/0x1d0 bus_add_driver+0x3ac/0x650 driver_register+0x241/0x3d0 mlxsw_sp_module_init+0xa2/0x174 do_one_initcall+0xee/0x5f0 kernel_init_freeable+0x45a/0x4de kernel_init+0x1f/0x210 ret_from_fork+0x1f/0x30 The buggy address belongs to the object at ffff8881052f7800 which belongs to the cache kmalloc-1k of size 1024 The buggy address is located 1016 bytes inside of 1024-byte region [ffff8881052f7800, ffff8881052f7c00) The buggy address belongs to the page: page:0000000052355272 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x1052f0 head:0000000052355272 order:3 compound_mapcount:0 compound_pincount:0 flags: 0x200000000010200(slab|head|node=0|zone=2) raw: 0200000000010200 ffffea0005034800 0000000300000003 ffff888100041dc0 raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff8881052f7a80: 00 00 00 00 00 00 04 fc fc fc fc fc fc fc fc fc ffff8881052f7b00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc >ffff8881052f7b80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ^ ffff8881052f7c00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ffff8881052f7c80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [2] https://lore.kernel.org/linux-pm/9aca37cb-1629-5c67-1895-1fdc45c0244e@linaro.org/ [3] https://lore.kernel.org/linux-pm/af9857f2-578e-de3a-e62b-6baff7e69fd4@linaro.org/ CC: Daniel Lezcano Fixes: a50c1e35650b ("mlxsw: core: Implement thermal zone") Fixes: a421ce088ac8 ("mlxsw: core: Extend cooling device with cooling levels") Signed-off-by: Ido Schimmel Tested-by: Vadim Pasternak Link: https://lore.kernel.org/r/20211012174955.472928-1-idosch@idosch.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 52 +++------------------- 1 file changed, 5 insertions(+), 47 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c index 0998dcc9cac0..b29824448aa8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c @@ -24,16 +24,8 @@ #define MLXSW_THERMAL_ZONE_MAX_NAME 16 #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 -/* Minimum and maximum fan allowed speed in percent: from 20% to 100%. Values - * MLXSW_THERMAL_MAX_STATE + x, where x is between 2 and 10 are used for - * setting fan speed dynamic minimum. For example, if value is set to 14 (40%) - * cooling levels vector will be set to 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10 to - * introduce PWM speed in percent: 40, 40, 40, 40, 40, 50, 60. 70, 80, 90, 100. - */ -#define MLXSW_THERMAL_SPEED_MIN (MLXSW_THERMAL_MAX_STATE + 2) -#define MLXSW_THERMAL_SPEED_MAX (MLXSW_THERMAL_MAX_STATE * 2) -#define MLXSW_THERMAL_SPEED_MIN_LEVEL 2 /* 20% */ /* External cooling devices, allowed for binding to mlxsw thermal zones. */ static char * const mlxsw_thermal_external_allowed_cdev[] = { @@ -646,49 +638,16 @@ static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev, struct mlxsw_thermal *thermal = cdev->devdata; struct device *dev = thermal->bus_info->dev; char mfsc_pl[MLXSW_REG_MFSC_LEN]; - unsigned long cur_state, i; int idx; - u8 duty; int err; + if (state > MLXSW_THERMAL_MAX_STATE) + return -EINVAL; + idx = mlxsw_get_cooling_device_idx(thermal, cdev); if (idx < 0) return idx; - /* Verify if this request is for changing allowed fan dynamical - * minimum. If it is - update cooling levels accordingly and update - * state, if current state is below the newly requested minimum state. - * For example, if current state is 5, and minimal state is to be - * changed from 4 to 6, thermal->cooling_levels[0 to 5] will be changed - * all from 4 to 6. And state 5 (thermal->cooling_levels[4]) should be - * overwritten. - */ - if (state >= MLXSW_THERMAL_SPEED_MIN && - state <= MLXSW_THERMAL_SPEED_MAX) { - state -= MLXSW_THERMAL_MAX_STATE; - for (i = 0; i <= MLXSW_THERMAL_MAX_STATE; i++) - thermal->cooling_levels[i] = max(state, i); - - mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0); - err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl); - if (err) - return err; - - duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl); - cur_state = mlxsw_duty_to_state(duty); - - /* If current fan state is lower than requested dynamical - * minimum, increase fan speed up to dynamical minimum. - */ - if (state < cur_state) - return 0; - - state = cur_state; - } - - if (state > MLXSW_THERMAL_MAX_STATE) - return -EINVAL; - /* Normalize the state to the valid speed range. */ state = thermal->cooling_levels[state]; mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state)); @@ -998,8 +957,7 @@ int mlxsw_thermal_init(struct mlxsw_core *core, /* Initialize cooling levels per PWM state. */ for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++) - thermal->cooling_levels[i] = max(MLXSW_THERMAL_SPEED_MIN_LEVEL, - i); + thermal->cooling_levels[i] = max(MLXSW_THERMAL_MIN_STATE, i); thermal->polling_delay = bus_info->low_frequency ? MLXSW_THERMAL_SLOW_POLL_INT : -- cgit From a2d859e3fc97e79d907761550dbc03ff1b36479c Mon Sep 17 00:00:00 2001 From: Eiichi Tsukata Date: Wed, 13 Oct 2021 17:27:29 -0300 Subject: sctp: account stream padding length for reconf chunk sctp_make_strreset_req() makes repeated calls to sctp_addto_chunk() which will automatically account for padding on each call. inreq and outreq are already 4 bytes aligned, but the payload is not and doing SCTP_PAD4(a + b) (which _sctp_make_chunk() did implicitly here) is different from SCTP_PAD4(a) + SCTP_PAD4(b) and not enough. It led to possible attempt to use more buffer than it was allocated and triggered a BUG_ON. Cc: Vlad Yasevich Cc: Neil Horman Cc: Greg KH Fixes: cc16f00f6529 ("sctp: add support for generating stream reconf ssn reset request chunk") Reported-by: Eiichi Tsukata Signed-off-by: Eiichi Tsukata Signed-off-by: Marcelo Ricardo Leitner Signed-off-by: Marcelo Ricardo Leitner Reviewed-by: Xin Long Link: https://lore.kernel.org/r/b97c1f8b0c7ff79ac4ed206fc2c49d3612e0850c.1634156849.git.mleitner@redhat.com Signed-off-by: Jakub Kicinski --- net/sctp/sm_make_chunk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index b8fa8f1a7277..c7503fd64915 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -3697,7 +3697,7 @@ struct sctp_chunk *sctp_make_strreset_req( outlen = (sizeof(outreq) + stream_len) * out; inlen = (sizeof(inreq) + stream_len) * in; - retval = sctp_make_reconf(asoc, outlen + inlen); + retval = sctp_make_reconf(asoc, SCTP_PAD4(outlen) + SCTP_PAD4(inlen)); if (!retval) return NULL; -- cgit From ea142b09a6399fb2c35c07198e3f0e2423273540 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Thu, 14 Oct 2021 19:02:14 +0800 Subject: MAINTAINERS: Update the devicetree documentation path of imx fec driver Change the devicetree documentation path to "Documentation/devicetree/bindings/net/fsl,fec.yaml" since 'fsl-fec.txt' has been converted to 'fsl,fec.yaml' already. Signed-off-by: Cai Huoqing Link: https://lore.kernel.org/r/20211014110214.3254-1-caihuoqing@baidu.com Signed-off-by: Jakub Kicinski --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 17f652b2f653..c4f2f3382e26 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7440,7 +7440,7 @@ FREESCALE IMX / MXC FEC DRIVER M: Joakim Zhang L: netdev@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/net/fsl-fec.txt +F: Documentation/devicetree/bindings/net/fsl,fec.yaml F: drivers/net/ethernet/freescale/fec.h F: drivers/net/ethernet/freescale/fec_main.c F: drivers/net/ethernet/freescale/fec_ptp.c -- cgit From 1fcd794518b7644169595c66b1bfe726d1f498ab Mon Sep 17 00:00:00 2001 From: Xin Long Date: Thu, 14 Oct 2021 05:50:50 -0400 Subject: icmp: fix icmp_ext_echo_iio parsing in icmp_build_probe In icmp_build_probe(), the icmp_ext_echo_iio parsing should be done step by step and skb_header_pointer() return value should always be checked, this patch fixes 3 places in there: - On case ICMP_EXT_ECHO_CTYPE_NAME, it should only copy ident.name from skb by skb_header_pointer(), its len is ident_len. Besides, the return value of skb_header_pointer() should always be checked. - On case ICMP_EXT_ECHO_CTYPE_INDEX, move ident_len check ahead of skb_header_pointer(), and also do the return value check for skb_header_pointer(). - On case ICMP_EXT_ECHO_CTYPE_ADDR, before accessing iio->ident.addr. ctype3_hdr.addrlen, skb_header_pointer() should be called first, then check its return value and ident_len. On subcases ICMP_AFI_IP and ICMP_AFI_IP6, also do check for ident. addr.ctype3_hdr.addrlen and skb_header_pointer()'s return value. On subcase ICMP_AFI_IP, the len for skb_header_pointer() should be "sizeof(iio->extobj_hdr) + sizeof(iio->ident.addr.ctype3_hdr) + sizeof(struct in_addr)" or "ident_len". v1->v2: - To make it more clear, call skb_header_pointer() once only for iio->indent's parsing as Jakub Suggested. v2->v3: - The extobj_hdr.length check against sizeof(_iio) should be done before calling skb_header_pointer(), as Eric noticed. Fixes: d329ea5bd884 ("icmp: add response to RFC 8335 PROBE messages") Reported-by: Dan Carpenter Signed-off-by: Xin Long Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/31628dd76657ea62f5cf78bb55da6b35240831f1.1634205050.git.lucien.xin@gmail.com Signed-off-by: Jakub Kicinski --- net/ipv4/icmp.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 8b30cadff708..b7e277d8a84d 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -1054,14 +1054,19 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr) iio = skb_header_pointer(skb, sizeof(_ext_hdr), sizeof(iio->extobj_hdr), &_iio); if (!ext_hdr || !iio) goto send_mal_query; - if (ntohs(iio->extobj_hdr.length) <= sizeof(iio->extobj_hdr)) + if (ntohs(iio->extobj_hdr.length) <= sizeof(iio->extobj_hdr) || + ntohs(iio->extobj_hdr.length) > sizeof(_iio)) goto send_mal_query; ident_len = ntohs(iio->extobj_hdr.length) - sizeof(iio->extobj_hdr); + iio = skb_header_pointer(skb, sizeof(_ext_hdr), + sizeof(iio->extobj_hdr) + ident_len, &_iio); + if (!iio) + goto send_mal_query; + status = 0; dev = NULL; switch (iio->extobj_hdr.class_type) { case ICMP_EXT_ECHO_CTYPE_NAME: - iio = skb_header_pointer(skb, sizeof(_ext_hdr), sizeof(_iio), &_iio); if (ident_len >= IFNAMSIZ) goto send_mal_query; memset(buff, 0, sizeof(buff)); @@ -1069,30 +1074,24 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr) dev = dev_get_by_name(net, buff); break; case ICMP_EXT_ECHO_CTYPE_INDEX: - iio = skb_header_pointer(skb, sizeof(_ext_hdr), sizeof(iio->extobj_hdr) + - sizeof(iio->ident.ifindex), &_iio); if (ident_len != sizeof(iio->ident.ifindex)) goto send_mal_query; dev = dev_get_by_index(net, ntohl(iio->ident.ifindex)); break; case ICMP_EXT_ECHO_CTYPE_ADDR: - if (ident_len != sizeof(iio->ident.addr.ctype3_hdr) + + if (ident_len < sizeof(iio->ident.addr.ctype3_hdr) || + ident_len != sizeof(iio->ident.addr.ctype3_hdr) + iio->ident.addr.ctype3_hdr.addrlen) goto send_mal_query; switch (ntohs(iio->ident.addr.ctype3_hdr.afi)) { case ICMP_AFI_IP: - iio = skb_header_pointer(skb, sizeof(_ext_hdr), sizeof(iio->extobj_hdr) + - sizeof(struct in_addr), &_iio); - if (ident_len != sizeof(iio->ident.addr.ctype3_hdr) + - sizeof(struct in_addr)) + if (iio->ident.addr.ctype3_hdr.addrlen != sizeof(struct in_addr)) goto send_mal_query; dev = ip_dev_find(net, iio->ident.addr.ip_addr.ipv4_addr); break; #if IS_ENABLED(CONFIG_IPV6) case ICMP_AFI_IP6: - iio = skb_header_pointer(skb, sizeof(_ext_hdr), sizeof(_iio), &_iio); - if (ident_len != sizeof(iio->ident.addr.ctype3_hdr) + - sizeof(struct in6_addr)) + if (iio->ident.addr.ctype3_hdr.addrlen != sizeof(struct in6_addr)) goto send_mal_query; dev = ipv6_stub->ipv6_dev_find(net, &iio->ident.addr.ip_addr.ipv6_addr, dev); dev_hold(dev); -- cgit From 14cfbb7a7856f190035f8e53045bdbfa648fae41 Mon Sep 17 00:00:00 2001 From: Hao Xu Date: Thu, 14 Oct 2021 22:04:00 +0800 Subject: io_uring: fix wrong condition to grab uring lock Grab uring lock when we are in io-worker rather than in the original or system-wq context since we already hold it in these two situation. Signed-off-by: Hao Xu Fixes: b66ceaf324b3 ("io_uring: move iopoll reissue into regular IO path") Link: https://lore.kernel.org/r/20211014140400.50235-1-haoxu@linux.alibaba.com Signed-off-by: Jens Axboe --- fs/io_uring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 6b9e70208782..e68d27829bb2 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2949,7 +2949,7 @@ static void kiocb_done(struct kiocb *kiocb, ssize_t ret, struct io_ring_ctx *ctx = req->ctx; req_set_fail(req); - if (issue_flags & IO_URING_F_NONBLOCK) { + if (!(issue_flags & IO_URING_F_NONBLOCK)) { mutex_lock(&ctx->uring_lock); __io_req_complete(req, issue_flags, ret, cflags); mutex_unlock(&ctx->uring_lock); -- cgit From 8e820f962345e6ce6f4677044209f23dde39d76d Mon Sep 17 00:00:00 2001 From: Alexey Bayduraev Date: Wed, 29 Sep 2021 12:14:45 +0300 Subject: perf report: Output non-zero offset for decompressed records Print offset of PERF_RECORD_COMPRESSED record instead of zero for decompressed records in raw trace dump (-D option of perf-report): 0x17cf08 [0x28]: event: 9 instead of: 0 [0x28]: event: 9 The fix is not critical, because currently file_pos for compressed events is used in perf_session__process_event only to show offsets in the raw dump. This patch was separated from patchset: https://lore.kernel.org/lkml/cover.1629186429.git.alexey.v.bayduraev@linux.intel.com/ and was already rewieved. Reviewed-by: Riccardo Mancini Signed-off-by: Alexey Bayduraev Tested-by: Riccardo Mancini Acked-by: Andi Kleen Acked-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Alexander Antonov Cc: Alexander Shishkin Cc: Alexei Budankov Cc: Ingo Molnar Cc: Peter Zijlstra Link: https://lore.kernel.org/r/20210929091445.18274-1-alexey.v.bayduraev@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 069c2cfdd3be..352f16076e01 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -2116,7 +2116,7 @@ fetch_decomp_event(u64 head, size_t mmap_size, char *buf, bool needs_swap) static int __perf_session__process_decomp_events(struct perf_session *session) { s64 skip; - u64 size, file_pos = 0; + u64 size; struct decomp *decomp = session->decomp_last; if (!decomp) @@ -2132,7 +2132,7 @@ static int __perf_session__process_decomp_events(struct perf_session *session) size = event->header.size; if (size < sizeof(struct perf_event_header) || - (skip = perf_session__process_event(session, event, file_pos)) < 0) { + (skip = perf_session__process_event(session, event, decomp->file_pos)) < 0) { pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", decomp->file_pos + decomp->head, event->header.size, event->header.type); return -EINVAL; -- cgit From f304c8d949f9adc2ef51304b63e49d5ea1c2d288 Mon Sep 17 00:00:00 2001 From: Shunsuke Nakamura Date: Wed, 6 Oct 2021 18:57:03 +0900 Subject: libperf test evsel: Fix build error on !x86 architectures In test_stat_user_read, following build error occurs except i386 and x86_64 architectures: tests/test-evsel.c:129:31: error: variable 'pc' set but not used [-Werror=unused-but-set-variable] struct perf_event_mmap_page *pc; Fix build error. Signed-off-by: Shunsuke Nakamura Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Ingo Molnar Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Link: https://lore.kernel.org/r/20211006095703.477826-1-nakamura.shun@fujitsu.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/perf/tests/test-evsel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/lib/perf/tests/test-evsel.c b/tools/lib/perf/tests/test-evsel.c index a184e4861627..9abd4c0bf6db 100644 --- a/tools/lib/perf/tests/test-evsel.c +++ b/tools/lib/perf/tests/test-evsel.c @@ -148,6 +148,7 @@ static int test_stat_user_read(int event) __T("failed to mmap evsel", err == 0); pc = perf_evsel__mmap_base(evsel, 0, 0); + __T("failed to get mmapped address", pc); #if defined(__i386__) || defined(__x86_64__) __T("userspace counter access not supported", pc->cap_user_rdpmc); -- cgit From 3ff6d64e68abc231955d216236615918797614ae Mon Sep 17 00:00:00 2001 From: Shunsuke Nakamura Date: Mon, 11 Oct 2021 17:37:04 +0900 Subject: libperf tests: Fix test_stat_cpu The `cpu` argument of perf_evsel__read() must specify the cpu index. perf_cpu_map__for_each_cpu() is for iterating the cpu number (not index) and is thus not appropriate for use with perf_evsel__read(). So, if there is an offline CPU, the cpu number specified in the argument may point out of range because the cpu number and the cpu index are different. Fix test_stat_cpu(). Testing it: # make tests -C tools/lib/perf/ make: Entering directory '/home/nakamura/kernel_src/linux-5.15-rc4_fix/tools/lib/perf' running static: - running tests/test-cpumap.c...OK - running tests/test-threadmap.c...OK - running tests/test-evlist.c...OK - running tests/test-evsel.c...OK running dynamic: - running tests/test-cpumap.c...OK - running tests/test-threadmap.c...OK - running tests/test-evlist.c...OK - running tests/test-evsel.c...OK make: Leaving directory '/home/nakamura/kernel_src/linux-5.15-rc4_fix/tools/lib/perf' Signed-off-by: Shunsuke Nakamura Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lore.kernel.org/lkml/20211011083704.4108720-1-nakamura.shun@fujitsu.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/perf/tests/test-evlist.c | 6 +++--- tools/lib/perf/tests/test-evsel.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/lib/perf/tests/test-evlist.c b/tools/lib/perf/tests/test-evlist.c index c67c83399170..ce91a582f0e4 100644 --- a/tools/lib/perf/tests/test-evlist.c +++ b/tools/lib/perf/tests/test-evlist.c @@ -40,7 +40,7 @@ static int test_stat_cpu(void) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK, }; - int err, cpu, tmp; + int err, idx; cpus = perf_cpu_map__new(NULL); __T("failed to create cpus", cpus); @@ -70,10 +70,10 @@ static int test_stat_cpu(void) perf_evlist__for_each_evsel(evlist, evsel) { cpus = perf_evsel__cpus(evsel); - perf_cpu_map__for_each_cpu(cpu, tmp, cpus) { + for (idx = 0; idx < perf_cpu_map__nr(cpus); idx++) { struct perf_counts_values counts = { .val = 0 }; - perf_evsel__read(evsel, cpu, 0, &counts); + perf_evsel__read(evsel, idx, 0, &counts); __T("failed to read value for evsel", counts.val != 0); } } diff --git a/tools/lib/perf/tests/test-evsel.c b/tools/lib/perf/tests/test-evsel.c index 9abd4c0bf6db..33ae9334861a 100644 --- a/tools/lib/perf/tests/test-evsel.c +++ b/tools/lib/perf/tests/test-evsel.c @@ -22,7 +22,7 @@ static int test_stat_cpu(void) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_CLOCK, }; - int err, cpu, tmp; + int err, idx; cpus = perf_cpu_map__new(NULL); __T("failed to create cpus", cpus); @@ -33,10 +33,10 @@ static int test_stat_cpu(void) err = perf_evsel__open(evsel, cpus, NULL); __T("failed to open evsel", err == 0); - perf_cpu_map__for_each_cpu(cpu, tmp, cpus) { + for (idx = 0; idx < perf_cpu_map__nr(cpus); idx++) { struct perf_counts_values counts = { .val = 0 }; - perf_evsel__read(evsel, cpu, 0, &counts); + perf_evsel__read(evsel, idx, 0, &counts); __T("failed to read value for evsel", counts.val != 0); } -- cgit From a1467faa10414ab3d91be7ef6d2b11272ec00e95 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 5 Oct 2021 12:06:18 +0200 Subject: ARM: imx: register reset controller from a platform driver Starting with commit 6b2117ad65f1 ("of: property: fw_devlink: Add support for "resets" and "pwms""), the imx-drm driver fails to load due to forever dormant devlinks to the reset-controller node. This node was never associated with a struct device. Add a platform device to allow fw_devnode to activate the devlinks. Fixes: 6b2117ad65f1 ("of: property: fw_devlink: Add support for "resets" and "pwms"") Signed-off-by: Philipp Zabel Tested-by: Fabio Estevam Reviewed-by: Saravana Kannan Signed-off-by: Shawn Guo --- arch/arm/mach-imx/src.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c index 95fd1fbb0826..59a8e8cc4469 100644 --- a/arch/arm/mach-imx/src.c +++ b/arch/arm/mach-imx/src.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -81,11 +82,6 @@ static const struct reset_control_ops imx_src_ops = { .reset = imx_src_reset_module, }; -static struct reset_controller_dev imx_reset_controller = { - .ops = &imx_src_ops, - .nr_resets = ARRAY_SIZE(sw_reset_bits), -}; - static void imx_gpcv2_set_m_core_pgc(bool enable, u32 offset) { writel_relaxed(enable, gpc_base + offset); @@ -177,10 +173,6 @@ void __init imx_src_init(void) src_base = of_iomap(np, 0); WARN_ON(!src_base); - imx_reset_controller.of_node = np; - if (IS_ENABLED(CONFIG_RESET_CONTROLLER)) - reset_controller_register(&imx_reset_controller); - /* * force warm reset sources to generate cold reset * for a more reliable restart @@ -214,3 +206,33 @@ void __init imx7_src_init(void) if (!gpc_base) return; } + +static const struct of_device_id imx_src_dt_ids[] = { + { .compatible = "fsl,imx51-src" }, + { /* sentinel */ } +}; + +static int imx_src_probe(struct platform_device *pdev) +{ + struct reset_controller_dev *rcdev; + + rcdev = devm_kzalloc(&pdev->dev, sizeof(*rcdev), GFP_KERNEL); + if (!rcdev) + return -ENOMEM; + + rcdev->ops = &imx_src_ops; + rcdev->dev = &pdev->dev; + rcdev->of_node = pdev->dev.of_node; + rcdev->nr_resets = ARRAY_SIZE(sw_reset_bits); + + return devm_reset_controller_register(&pdev->dev, rcdev); +} + +static struct platform_driver imx_src_driver = { + .driver = { + .name = "imx-src", + .of_match_table = imx_src_dt_ids, + }, + .probe = imx_src_probe, +}; +builtin_platform_driver(imx_src_driver); -- cgit From 97794170b696856483f74b47bfb6049780d2d3a0 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 5 Oct 2021 19:29:08 -0700 Subject: drm/edid: In connector_bad_edid() cap num_of_ext by num_blocks read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit e11f5bd8228f ("drm: Add support for DP 1.4 Compliance edid corruption test") the function connector_bad_edid() started assuming that the memory for the EDID passed to it was big enough to hold `edid[0x7e] + 1` blocks of data (1 extra for the base block). It completely ignored the fact that the function was passed `num_blocks` which indicated how much memory had been allocated for the EDID. Let's fix this by adding a bounds check. This is important for handling the case where there's an error in the first block of the EDID. In that case we will call connector_bad_edid() without having re-allocated memory based on `edid[0x7e]`. Fixes: e11f5bd8228f ("drm: Add support for DP 1.4 Compliance edid corruption test") Reported-by: Ville Syrjälä Signed-off-by: Douglas Anderson Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211005192905.v2.1.Ib059f9c23c2611cb5a9d760e7d0a700c1295928d@changeid Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 6325877c5fd6..ea9a79bc9583 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1834,11 +1834,20 @@ static void connector_bad_edid(struct drm_connector *connector, u8 *edid, int num_blocks) { int i; - u8 num_of_ext = edid[0x7e]; + u8 last_block; + + /* + * 0x7e in the EDID is the number of extension blocks. The EDID + * is 1 (base block) + num_ext_blocks big. That means we can think + * of 0x7e in the EDID of the _index_ of the last block in the + * combined chunk of memory. + */ + last_block = edid[0x7e]; /* Calculate real checksum for the last edid extension block data */ - connector->real_edid_checksum = - drm_edid_block_checksum(edid + num_of_ext * EDID_LENGTH); + if (last_block < num_blocks) + connector->real_edid_checksum = + drm_edid_block_checksum(edid + last_block * EDID_LENGTH); if (connector->bad_edid_counter++ && !drm_debug_enabled(DRM_UT_KMS)) return; -- cgit From b693e42921e0220c0d564c55c6cdc680b0f85390 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 5 Oct 2021 09:03:55 +0200 Subject: drm/fbdev: Clamp fbdev surface size if too large MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clamp the fbdev surface size of the available maximumi height to avoid failing to init console emulation. An example error is shown below. bad framebuffer height 2304, should be >= 768 && <= 768 [drm] Initialized simpledrm 1.0.0 20200625 for simple-framebuffer.0 on minor 0 simple-framebuffer simple-framebuffer.0: [drm] *ERROR* fbdev: Failed to setup generic emulation (ret=-22) This is especially a problem with drivers that have very small screen sizes and cannot over-allocate at all. v2: * reduce warning level (Ville) Signed-off-by: Thomas Zimmermann Fixes: 11e8f5fd223b ("drm: Add simpledrm driver") Reviewed-by: Ville Syrjälä Reviewed-by: Alex Deucher Reported-by: Amanoel Dawod Reported-by: Zoltán Kővágó Reported-by: Michael Stapelberg Cc: Daniel Vetter Cc: Maxime Ripard Cc: dri-devel@lists.freedesktop.org Cc: # v5.14+ Link: https://patchwork.freedesktop.org/patch/msgid/20211005070355.7680-1-tzimmermann@suse.de Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fb_helper.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 3ab078321045..8e7a124d6c5a 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1506,6 +1506,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, { struct drm_client_dev *client = &fb_helper->client; struct drm_device *dev = fb_helper->dev; + struct drm_mode_config *config = &dev->mode_config; int ret = 0; int crtc_count = 0; struct drm_connector_list_iter conn_iter; @@ -1663,6 +1664,11 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, /* Handle our overallocation */ sizes.surface_height *= drm_fbdev_overalloc; sizes.surface_height /= 100; + if (sizes.surface_height > config->max_height) { + drm_dbg_kms(dev, "Fbdev over-allocation too large; clamping height to %d\n", + config->max_height); + sizes.surface_height = config->max_height; + } /* push down into drivers */ ret = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes); -- cgit From b253c3026c29d4231099d3cf8d984d25787793af Mon Sep 17 00:00:00 2001 From: Dexuan Cui Date: Thu, 16 Sep 2021 12:36:44 -0700 Subject: drm/hyperv: Fix double mouse pointers Hyper-V supports a hardware cursor feature. It is not used by Linux VM, but the Hyper-V host still draws a point as an extra mouse pointer, which is unwanted, especially when Xorg is running. The hyperv_fb driver uses synthvid_send_ptr() to hide the unwanted pointer. When the hyperv_drm driver was developed, the function synthvid_send_ptr() was not copied from the hyperv_fb driver. Fix the issue by adding the function into hyperv_drm. Fixes: 76c56a5affeb ("drm/hyperv: Add DRM driver for hyperv synthetic video device") Signed-off-by: Dexuan Cui Reviewed-by: Haiyang Zhang Reviewed-by: Deepak Rawat Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20210916193644.45650-1-decui@microsoft.com Signed-off-by: Dave Airlie --- drivers/gpu/drm/hyperv/hyperv_drm.h | 1 + drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 1 + drivers/gpu/drm/hyperv/hyperv_drm_proto.c | 54 ++++++++++++++++++++++++++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/hyperv/hyperv_drm.h b/drivers/gpu/drm/hyperv/hyperv_drm.h index 886add4f9cd0..d2d8582b36df 100644 --- a/drivers/gpu/drm/hyperv/hyperv_drm.h +++ b/drivers/gpu/drm/hyperv/hyperv_drm.h @@ -46,6 +46,7 @@ int hyperv_mode_config_init(struct hyperv_drm_device *hv); int hyperv_update_vram_location(struct hv_device *hdev, phys_addr_t vram_pp); int hyperv_update_situation(struct hv_device *hdev, u8 active, u32 bpp, u32 w, u32 h, u32 pitch); +int hyperv_hide_hw_ptr(struct hv_device *hdev); int hyperv_update_dirt(struct hv_device *hdev, struct drm_rect *rect); int hyperv_connect_vsp(struct hv_device *hdev); diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c index 6dd4717d3e1e..8c97a20dfe23 100644 --- a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c +++ b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c @@ -101,6 +101,7 @@ static void hyperv_pipe_enable(struct drm_simple_display_pipe *pipe, struct hyperv_drm_device *hv = to_hv(pipe->crtc.dev); struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); + hyperv_hide_hw_ptr(hv->hdev); hyperv_update_situation(hv->hdev, 1, hv->screen_depth, crtc_state->mode.hdisplay, crtc_state->mode.vdisplay, diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_proto.c b/drivers/gpu/drm/hyperv/hyperv_drm_proto.c index 6d4bdccfbd1a..c0155c6271bf 100644 --- a/drivers/gpu/drm/hyperv/hyperv_drm_proto.c +++ b/drivers/gpu/drm/hyperv/hyperv_drm_proto.c @@ -299,6 +299,55 @@ int hyperv_update_situation(struct hv_device *hdev, u8 active, u32 bpp, return 0; } +/* + * Hyper-V supports a hardware cursor feature. It's not used by Linux VM, + * but the Hyper-V host still draws a point as an extra mouse pointer, + * which is unwanted, especially when Xorg is running. + * + * The hyperv_fb driver uses synthvid_send_ptr() to hide the unwanted + * pointer, by setting msg.ptr_pos.is_visible = 1 and setting the + * msg.ptr_shape.data. Note: setting msg.ptr_pos.is_visible to 0 doesn't + * work in tests. + * + * Copy synthvid_send_ptr() to hyperv_drm and rename it to + * hyperv_hide_hw_ptr(). Note: hyperv_hide_hw_ptr() is also called in the + * handler of the SYNTHVID_FEATURE_CHANGE event, otherwise the host still + * draws an extra unwanted mouse pointer after the VM Connection window is + * closed and reopened. + */ +int hyperv_hide_hw_ptr(struct hv_device *hdev) +{ + struct synthvid_msg msg; + + memset(&msg, 0, sizeof(struct synthvid_msg)); + msg.vid_hdr.type = SYNTHVID_POINTER_POSITION; + msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) + + sizeof(struct synthvid_pointer_position); + msg.ptr_pos.is_visible = 1; + msg.ptr_pos.video_output = 0; + msg.ptr_pos.image_x = 0; + msg.ptr_pos.image_y = 0; + hyperv_sendpacket(hdev, &msg); + + memset(&msg, 0, sizeof(struct synthvid_msg)); + msg.vid_hdr.type = SYNTHVID_POINTER_SHAPE; + msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) + + sizeof(struct synthvid_pointer_shape); + msg.ptr_shape.part_idx = SYNTHVID_CURSOR_COMPLETE; + msg.ptr_shape.is_argb = 1; + msg.ptr_shape.width = 1; + msg.ptr_shape.height = 1; + msg.ptr_shape.hot_x = 0; + msg.ptr_shape.hot_y = 0; + msg.ptr_shape.data[0] = 0; + msg.ptr_shape.data[1] = 1; + msg.ptr_shape.data[2] = 1; + msg.ptr_shape.data[3] = 1; + hyperv_sendpacket(hdev, &msg); + + return 0; +} + int hyperv_update_dirt(struct hv_device *hdev, struct drm_rect *rect) { struct hyperv_drm_device *hv = hv_get_drvdata(hdev); @@ -392,8 +441,11 @@ static void hyperv_receive_sub(struct hv_device *hdev) return; } - if (msg->vid_hdr.type == SYNTHVID_FEATURE_CHANGE) + if (msg->vid_hdr.type == SYNTHVID_FEATURE_CHANGE) { hv->dirt_needed = msg->feature_chg.is_dirt_needed; + if (hv->dirt_needed) + hyperv_hide_hw_ptr(hv->hdev); + } } static void hyperv_receive(void *ctx) -- cgit From d1d94b0129dccd226784633c60b7df90e8a051b5 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 7 Oct 2021 23:41:17 +0200 Subject: drm/nouveau/fifo: Reinstate the correct engine bit programming Commit 64f7c698bea9 ("drm/nouveau/fifo: add engine_id hook") replaced fifo/chang84.c g84_fifo_chan_engine() call with an indirect call of fifo/g84.c g84_fifo_engine_id(). The G84_FIFO_ENGN_* values returned from the later g84_fifo_engine_id() are incremented by 1 compared to the previous g84_fifo_chan_engine() return values. This is fine either way for most of the code, except this one line where an engine bit programmed into the hardware is derived from the return value. Decrement the return value accordingly, otherwise the wrong engine bit is programmed into the hardware and that leads to the following failure: nouveau 0000:01:00.0: gr: 00000030 [ILLEGAL_MTHD ILLEGAL_CLASS] ch 1 [003fbce000 DRM] subc 3 class 0000 mthd 085c data 00000420 On the following hardware: lspci -s 01:00.0 01:00.0 VGA compatible controller: NVIDIA Corporation GT216GLM [Quadro FX 880M] (rev a2) lspci -ns 01:00.0 01:00.0 0300: 10de:0a3c (rev a2) Fixes: 64f7c698bea9 ("drm/nouveau/fifo: add engine_id hook") Signed-off-by: Marek Vasut Cc: # 5.12+ Cc: Ben Skeggs Cc: Karol Herbst Cc: Lyude Paul Reviewed-by: Karol Herbst Reviewed-by: Ben Skeggs Signed-off-by: Karol Herbst Link: https://patchwork.freedesktop.org/patch/msgid/20211007214117.231472-1-marex@denx.de Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c index 353b77d9b3dc..3492c561f2cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c @@ -82,7 +82,7 @@ g84_fifo_chan_engine_fini(struct nvkm_fifo_chan *base, if (offset < 0) return 0; - engn = fifo->base.func->engine_id(&fifo->base, engine); + engn = fifo->base.func->engine_id(&fifo->base, engine) - 1; save = nvkm_mask(device, 0x002520, 0x0000003f, 1 << engn); nvkm_wr32(device, 0x0032fc, chan->base.inst->addr >> 12); done = nvkm_msec(device, 2000, -- cgit From 1a361b41c1a1c399399cd2a83e449c452d9d8115 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 11 Oct 2021 01:00:06 -0700 Subject: drm/r128: fix build for UML MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a build error on CONFIG_UML, which does not support (provide) wbinvd(). UML can use the generic mb() instead. ../drivers/gpu/drm/r128/ati_pcigart.c: In function ‘drm_ati_pcigart_init’: ../drivers/gpu/drm/r128/ati_pcigart.c:218:2: error: implicit declaration of function ‘wbinvd’ [-Werror=implicit-function-declaration] wbinvd(); ^~~~~~ Fixes: 68f5d3f3b654 ("um: add PCI over virtio emulation driver") Signed-off-by: Randy Dunlap Cc: David Airlie Cc: Daniel Vetter Cc: dri-devel@lists.freedesktop.org Cc: Jeff Dike Cc: Richard Weinberger Cc: Anton Ivanov Cc: linux-um@lists.infradead.org Cc: Sam Ravnborg Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20211011080006.31081-1-rdunlap@infradead.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/r128/ati_pcigart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/r128/ati_pcigart.c b/drivers/gpu/drm/r128/ati_pcigart.c index 0ecccf25a3c7..d2a0f5394fef 100644 --- a/drivers/gpu/drm/r128/ati_pcigart.c +++ b/drivers/gpu/drm/r128/ati_pcigart.c @@ -214,7 +214,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga } ret = 0; -#if defined(__i386__) || defined(__x86_64__) +#ifdef CONFIG_X86 wbinvd(); #else mb(); -- cgit From a14bc107edd0c108bda2245e50daa22f91c95d20 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Tue, 12 Oct 2021 13:52:42 +0200 Subject: drm/panel: olimex-lcd-olinuxino: select CRC32 Fix the following build/link error by adding a dependency on the CRC32 routines: ld: drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.o: in function `lcd_olinuxino_probe': panel-olimex-lcd-olinuxino.c:(.text+0x303): undefined reference to `crc32_le' Fixes: 17fd7a9d324fd ("drm/panel: Add support for Olimex LCD-OLinuXino panel") Cc: Arnd Bergmann Signed-off-by: Vegard Nossum Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20211012115242.10325-1-vegard.nossum@oracle.com Signed-off-by: Dave Airlie --- drivers/gpu/drm/panel/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index beb581b96ecd..418638e6e3b0 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -295,6 +295,7 @@ config DRM_PANEL_OLIMEX_LCD_OLINUXINO depends on OF depends on I2C depends on BACKLIGHT_CLASS_DEVICE + select CRC32 help The panel is used with different sizes LCDs, from 480x272 to 1280x800, and 24 bit per pixel. -- cgit From f42752729e2068a92c7d8b576d0dbbc9c1464149 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 14 Oct 2021 17:37:18 +0200 Subject: eeprom: 93xx46: fix MODULE_DEVICE_TABLE The newly added SPI device ID table does not work because the entry is incorrectly copied from the OF device table. During build testing, this shows as a compile failure when building it as a loadable module: drivers/misc/eeprom/eeprom_93xx46.c:424:1: error: redefinition of '__mod_of__eeprom_93xx46_of_table_device_table' MODULE_DEVICE_TABLE(of, eeprom_93xx46_of_table); Change the entry to refer to the correct symbol. Fixes: 137879f7ff23 ("eeprom: 93xx46: Add SPI device ID table") Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20211014153730.3821376-1-arnd@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/eeprom/eeprom_93xx46.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index 660ee924f8b1..1f15399e5cb4 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -421,7 +421,7 @@ static const struct spi_device_id eeprom_93xx46_spi_ids[] = { .driver_data = (kernel_ulong_t)µchip_93lc46b_data, }, {} }; -MODULE_DEVICE_TABLE(of, eeprom_93xx46_of_table); +MODULE_DEVICE_TABLE(spi, eeprom_93xx46_spi_ids); static int eeprom_93xx46_probe_dt(struct spi_device *spi) { -- cgit From 71920ea97d6d1d800ee8b51951dc3fda3f5dc698 Mon Sep 17 00:00:00 2001 From: Kan Liang Date: Wed, 6 Oct 2021 13:12:17 -0700 Subject: perf/x86/msr: Add Sapphire Rapids CPU support SMI_COUNT MSR is supported on Sapphire Rapids CPU. Signed-off-by: Kan Liang Signed-off-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/1633551137-192083-1-git-send-email-kan.liang@linux.intel.com --- arch/x86/events/msr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/events/msr.c b/arch/x86/events/msr.c index c853b28efa33..96c775abe31f 100644 --- a/arch/x86/events/msr.c +++ b/arch/x86/events/msr.c @@ -68,6 +68,7 @@ static bool test_intel(int idx, void *data) case INTEL_FAM6_BROADWELL_D: case INTEL_FAM6_BROADWELL_G: case INTEL_FAM6_BROADWELL_X: + case INTEL_FAM6_SAPPHIRERAPIDS_X: case INTEL_FAM6_ATOM_SILVERMONT: case INTEL_FAM6_ATOM_SILVERMONT_D: -- cgit From 9b4416c5095c20e110c82ae602c254099b83b72f Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 15 Oct 2021 23:01:48 +1100 Subject: KVM: PPC: Book3S HV: Fix stack handling in idle_kvm_start_guest() In commit 10d91611f426 ("powerpc/64s: Reimplement book3s idle code in C") kvm_start_guest() became idle_kvm_start_guest(). The old code allocated a stack frame on the emergency stack, but didn't use the frame to store anything, and also didn't store anything in its caller's frame. idle_kvm_start_guest() on the other hand is written more like a normal C function, it creates a frame on entry, and also stores CR/LR into its callers frame (per the ABI). The problem is that there is no caller frame on the emergency stack. The emergency stack for a given CPU is allocated with: paca_ptrs[i]->emergency_sp = alloc_stack(limit, i) + THREAD_SIZE; So emergency_sp actually points to the first address above the emergency stack allocation for a given CPU, we must not store above it without first decrementing it to create a frame. This is different to the regular kernel stack, paca->kstack, which is initialised to point at an initial frame that is ready to use. idle_kvm_start_guest() stores the backchain, CR and LR all of which write outside the allocation for the emergency stack. It then creates a stack frame and saves the non-volatile registers. Unfortunately the frame it creates is not large enough to fit the non-volatiles, and so the saving of the non-volatile registers also writes outside the emergency stack allocation. The end result is that we corrupt whatever is at 0-24 bytes, and 112-248 bytes above the emergency stack allocation. In practice this has gone unnoticed because the memory immediately above the emergency stack happens to be used for other stack allocations, either another CPUs mc_emergency_sp or an IRQ stack. See the order of calls to irqstack_early_init() and emergency_stack_init(). The low addresses of another stack are the top of that stack, and so are only used if that stack is under extreme pressue, which essentially never happens in practice - and if it did there's a high likelyhood we'd crash due to that stack overflowing. Still, we shouldn't be corrupting someone else's stack, and it is purely luck that we aren't corrupting something else. To fix it we save CR/LR into the caller's frame using the existing r1 on entry, we then create a SWITCH_FRAME_SIZE frame (which has space for pt_regs) on the emergency stack with the backchain pointing to the existing stack, and then finally we switch to the new frame on the emergency stack. Fixes: 10d91611f426 ("powerpc/64s: Reimplement book3s idle code in C") Cc: stable@vger.kernel.org # v5.2+ Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20211015133929.832061-1-mpe@ellerman.id.au --- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 90484425a1e6..ec57952b60b0 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -255,13 +255,15 @@ kvm_novcpu_exit: * r3 contains the SRR1 wakeup value, SRR1 is trashed. */ _GLOBAL(idle_kvm_start_guest) - ld r4,PACAEMERGSP(r13) mfcr r5 mflr r0 - std r1,0(r4) - std r5,8(r4) - std r0,16(r4) - subi r1,r4,STACK_FRAME_OVERHEAD + std r5, 8(r1) // Save CR in caller's frame + std r0, 16(r1) // Save LR in caller's frame + // Create frame on emergency stack + ld r4, PACAEMERGSP(r13) + stdu r1, -SWITCH_FRAME_SIZE(r4) + // Switch to new frame on emergency stack + mr r1, r4 SAVE_NVGPRS(r1) /* @@ -395,10 +397,9 @@ kvm_no_guest: /* set up r3 for return */ mfspr r3,SPRN_SRR1 REST_NVGPRS(r1) - addi r1, r1, STACK_FRAME_OVERHEAD - ld r0, 16(r1) - ld r5, 8(r1) - ld r1, 0(r1) + ld r1, 0(r1) // Switch back to caller stack + ld r0, 16(r1) // Reload LR + ld r5, 8(r1) // Reload CR mtlr r0 mtcr r5 blr -- cgit From cdeb5d7d890e14f3b70e8087e745c4a6a7d9f337 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 15 Oct 2021 23:02:08 +1100 Subject: KVM: PPC: Book3S HV: Make idle_kvm_start_guest() return 0 if it went to guest We call idle_kvm_start_guest() from power7_offline() if the thread has been requested to enter KVM. We pass it the SRR1 value that was returned from power7_idle_insn() which tells us what sort of wakeup we're processing. Depending on the SRR1 value we pass in, the KVM code might enter the guest, or it might return to us to do some host action if the wakeup requires it. If idle_kvm_start_guest() is able to handle the wakeup, and enter the guest it is supposed to indicate that by returning a zero SRR1 value to us. That was the behaviour prior to commit 10d91611f426 ("powerpc/64s: Reimplement book3s idle code in C"), however in that commit the handling of SRR1 was reworked, and the zeroing behaviour was lost. Returning from idle_kvm_start_guest() without zeroing the SRR1 value can confuse the host offline code, causing the guest to crash and other weirdness. Fixes: 10d91611f426 ("powerpc/64s: Reimplement book3s idle code in C") Cc: stable@vger.kernel.org # v5.2+ Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20211015133929.832061-2-mpe@ellerman.id.au --- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index ec57952b60b0..eb776d0c5d8e 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -264,6 +264,7 @@ _GLOBAL(idle_kvm_start_guest) stdu r1, -SWITCH_FRAME_SIZE(r4) // Switch to new frame on emergency stack mr r1, r4 + std r3, 32(r1) // Save SRR1 wakeup value SAVE_NVGPRS(r1) /* @@ -315,6 +316,10 @@ kvm_unsplit_wakeup: kvm_secondary_got_guest: + // About to go to guest, clear saved SRR1 + li r0, 0 + std r0, 32(r1) + /* Set HSTATE_DSCR(r13) to something sensible */ ld r6, PACA_DSCR_DEFAULT(r13) std r6, HSTATE_DSCR(r13) @@ -394,8 +399,8 @@ kvm_no_guest: mfspr r4, SPRN_LPCR rlwimi r4, r3, 0, LPCR_PECE0 | LPCR_PECE1 mtspr SPRN_LPCR, r4 - /* set up r3 for return */ - mfspr r3,SPRN_SRR1 + // Return SRR1 wakeup value, or 0 if we went into the guest + ld r3, 32(r1) REST_NVGPRS(r1) ld r1, 0(r1) // Switch back to caller stack ld r0, 16(r1) // Reload LR -- cgit From fbd63c08cdcca5fb1315aca3172b3c9c272cfb4f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 24 Sep 2021 00:35:42 +0000 Subject: csky: don't let sigreturn play with priveleged bits of status register csky restore_sigcontext() blindly overwrites regs->sr with the value it finds in sigcontext. Attacker can store whatever they want in there, which includes things like S-bit. Userland shouldn't be able to set that, or anything other than C flag (bit 0). Do the same thing other architectures with protected bits in flags register do - preserve everything that shouldn't be settable in user mode, picking the rest from the value saved is sigcontext. Signed-off-by: Al Viro Signed-off-by: Guo Ren Cc: stable@vger.kernel.org --- arch/csky/kernel/signal.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/csky/kernel/signal.c b/arch/csky/kernel/signal.c index bc4238b9f709..c7b763d2f526 100644 --- a/arch/csky/kernel/signal.c +++ b/arch/csky/kernel/signal.c @@ -52,10 +52,14 @@ static long restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) { int err = 0; + unsigned long sr = regs->sr; /* sc_pt_regs is structured the same as the start of pt_regs */ err |= __copy_from_user(regs, &sc->sc_pt_regs, sizeof(struct pt_regs)); + /* BIT(0) of regs->sr is Condition Code/Carry bit */ + regs->sr = (sr & ~1) | (regs->sr & 1); + /* Restore the floating-point state. */ err |= restore_fpu_state(sc); -- cgit From af89ebaa64de726ca0a39bbb0bf0c81a1f43ad50 Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Fri, 24 Sep 2021 15:33:38 +0800 Subject: csky: Fixup regs.sr broken in ptrace gpr_get() return the entire pt_regs (include sr) to userspace, if we don't restore the C bit in gpr_set, it may break the ALU result in that context. So the C flag bit is part of gpr context, that's why riscv totally remove the C bit in the ISA. That makes sr reg clear from userspace to supervisor privilege. Signed-off-by: Guo Ren Cc: Al Viro Cc: stable@vger.kernel.org --- arch/csky/kernel/ptrace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/csky/kernel/ptrace.c b/arch/csky/kernel/ptrace.c index 0105ac81b432..1a5f54e0d272 100644 --- a/arch/csky/kernel/ptrace.c +++ b/arch/csky/kernel/ptrace.c @@ -99,7 +99,8 @@ static int gpr_set(struct task_struct *target, if (ret) return ret; - regs.sr = task_pt_regs(target)->sr; + /* BIT(0) of regs.sr is Condition Code/Carry bit */ + regs.sr = (regs.sr & BIT(0)) | (task_pt_regs(target)->sr & ~BIT(0)); #ifdef CONFIG_CPU_HAS_HILO regs.dcsr = task_pt_regs(target)->dcsr; #endif -- cgit From aeba0b84dd07a9e6b362395f5ad47091249db13d Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 16 Sep 2021 21:38:36 -0700 Subject: csky: Select ARCH_WANT_FRAME_POINTERS only if compiler supports it Compiling csky:allmodconfig with an upstream C compiler results in the following error. csky-linux-gcc: error: unrecognized command-line option '-mbacktrace'; did you mean '-fbacktrace'? Select ARCH_WANT_FRAME_POINTERS only if gcc supports it to avoid the error. Signed-off-by: Guenter Roeck Signed-off-by: Guo Ren --- arch/csky/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig index 9d4d898df76b..58ca3ef02bab 100644 --- a/arch/csky/Kconfig +++ b/arch/csky/Kconfig @@ -8,7 +8,7 @@ config CSKY select ARCH_HAS_SYNC_DMA_FOR_DEVICE select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_QUEUED_RWLOCKS - select ARCH_WANT_FRAME_POINTERS if !CPU_CK610 + select ARCH_WANT_FRAME_POINTERS if !CPU_CK610 && $(cc-option,-mbacktrace) select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT select COMMON_CLK select CLKSRC_MMIO -- cgit From fb5d69a5cd7865a733c2c1f26e2e3b75f59ce00d Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 16 Sep 2021 21:38:37 -0700 Subject: csky: bitops: Remove duplicate __clear_bit define Building csky:allmodconfig results in the following build error. In file included from ./include/linux/bitops.h:33, from ./include/linux/log2.h:12, from kernel/bounds.c:13: ./arch/csky/include/asm/bitops.h:77: error: "__clear_bit" redefined Since commit 9248e52fec95 ("locking/atomic: simplify non-atomic wrappers"), __clear_bit is defined in include/asm-generic/bitops/non-atomic.h, and the define in the csky include file is no longer necessary or useful. Remove it. Fixes: 9248e52fec95 ("locking/atomic: simplify non-atomic wrappers") Signed-off-by: Guenter Roeck Signed-off-by: Guo Ren --- arch/csky/include/asm/bitops.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/csky/include/asm/bitops.h b/arch/csky/include/asm/bitops.h index 91818787d860..02b72a000767 100644 --- a/arch/csky/include/asm/bitops.h +++ b/arch/csky/include/asm/bitops.h @@ -74,7 +74,6 @@ static __always_inline unsigned long __fls(unsigned long x) * bug fix, why only could use atomic!!!! */ #include -#define __clear_bit(nr, vaddr) clear_bit(nr, vaddr) #include #include -- cgit From e21e52ad1e0126e2a5e2013084ac3f47cf1e887a Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 16 Sep 2021 21:38:38 -0700 Subject: csky: Make HAVE_TCM depend on !COMPILE_TEST Building csky:allmodconfig results in the following build errors. arch/csky/mm/tcm.c:9:2: error: #error "You should define ITCM_RAM_BASE" 9 | #error "You should define ITCM_RAM_BASE" | ^~~~~ arch/csky/mm/tcm.c:14:2: error: #error "You should define DTCM_RAM_BASE" 14 | #error "You should define DTCM_RAM_BASE" | ^~~~~ arch/csky/mm/tcm.c:18:2: error: #error "You should define correct DTCM_RAM_BASE" 18 | #error "You should define correct DTCM_RAM_BASE" This is seen with compile tests since those enable HAVE_TCM, but do not provide useful default values for ITCM_RAM_BASE or DTCM_RAM_BASE. Disable HAVE_TCM for commpile tests to avoid the error. Signed-off-by: Guenter Roeck Signed-off-by: Guo Ren --- arch/csky/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig index 58ca3ef02bab..823d3d5a9e11 100644 --- a/arch/csky/Kconfig +++ b/arch/csky/Kconfig @@ -241,6 +241,7 @@ endchoice menuconfig HAVE_TCM bool "Tightly-Coupled/Sram Memory" + depends on !COMPILE_TEST help The implementation are not only used by TCM (Tightly-Coupled Meory) but also used by sram on SOC bus. It follow existed linux tcm -- cgit From c3ca31ce0ea1e1ae34748ded54b6ccc319e7ed20 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Fri, 15 Oct 2021 10:43:35 -0700 Subject: ARC: fix potential build snafu In the big pgtable header split, I inadvertently introduced a couple of duplicate symbols. Fixes: fe6cb7b043b69cd9 ("ARC: mm: disintegrate pgtable.h into levels and flags") Signed-off-by: Vineet Gupta --- arch/arc/include/asm/pgtable.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h index 9320b04c04bf..4cf45a99fd79 100644 --- a/arch/arc/include/asm/pgtable.h +++ b/arch/arc/include/asm/pgtable.h @@ -26,11 +26,6 @@ extern char empty_zero_page[PAGE_SIZE]; extern pgd_t swapper_pg_dir[] __aligned(PAGE_SIZE); -/* Macro to mark a page protection as uncacheable */ -#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) & ~_PAGE_CACHEABLE)) - -extern pgd_t swapper_pg_dir[] __aligned(PAGE_SIZE); - /* to cope with aliasing VIPT cache */ #define HAVE_ARCH_UNMAPPED_AREA -- cgit From be358af1191b1b2fedebd8f3421cafdc8edacc7d Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 14 Oct 2021 14:35:07 -0400 Subject: nds32/ftrace: Fix Error: invalid operands (*UND* and *UND* sections) for `^' I received a build failure for a new patch I'm working on the nds32 architecture, and when I went to test it, I couldn't get to my build error, because it failed to build with a bunch of: Error: invalid operands (*UND* and *UND* sections) for `^' issues with various files. Those files were temporary asm files that looked like: kernel/.tmp_mc_fork.s I decided to look deeper, and found that the "mc" portion of that name stood for "mcount", and was created by the recordmcount.pl script. One that I wrote over a decade ago. Once I knew the source of the problem, I was able to investigate it further. The way the recordmcount.pl script works (BTW, there's a C version that simply modifies the ELF object) is by doing an "objdump" on the object file. Looks for all the calls to "mcount", and creates an offset of those locations from some global variable it can use (usually a global function name, found with <.*>:). Creates a asm file that is a table of references to these locations, using the found variable/function. Compiles it and links it back into the original object file. This asm file is called ".tmp_mc_.s". The problem here is that the objdump produced by the nds32 object file, contains things that look like: 0000159a <.L3^B1>: 159a: c6 00 beqz38 $r6, 159a <.L3^B1> 159a: R_NDS32_9_PCREL_RELA .text+0x159e 159c: 84 d2 movi55 $r6, #-14 159e: 80 06 mov55 $r0, $r6 15a0: ec 3c addi10.sp #0x3c Where ".L3^B1 is somehow selected as the "global" variable to index off of. Then the assembly file that holds the mcount locations looks like this: .section __mcount_loc,"a",@progbits .align 2 .long .L3^B1 + -5522 .long .L3^B1 + -5384 .long .L3^B1 + -5270 .long .L3^B1 + -5098 .long .L3^B1 + -4970 .long .L3^B1 + -4758 .long .L3^B1 + -4122 [...] And when it is compiled back to an object to link to the original object, the compile fails on the "^" symbol. Simple solution for now, is to have the perl script ignore using function symbols that have an "^" in the name. Link: https://lkml.kernel.org/r/20211014143507.4ad2c0f7@gandalf.local.home Cc: stable@vger.kernel.org Acked-by: Greentime Hu Fixes: fbf58a52ac088 ("nds32/ftrace: Add RECORD_MCOUNT support") Signed-off-by: Steven Rostedt (VMware) --- scripts/recordmcount.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl index 8f6b13ae46bf..7d631aaa0ae1 100755 --- a/scripts/recordmcount.pl +++ b/scripts/recordmcount.pl @@ -189,7 +189,7 @@ if ($arch =~ /(x86(_64)?)|(i386)/) { $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\S+)"; $weak_regex = "^[0-9a-fA-F]+\\s+([wW])\\s+(\\S+)"; $section_regex = "Disassembly of section\\s+(\\S+):"; -$function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:"; +$function_regex = "^([0-9a-fA-F]+)\\s+<([^^]*?)>:"; $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s(mcount|__fentry__)\$"; $section_type = '@progbits'; $mcount_adjust = 0; -- cgit From cc9c884dd7f4f036965e23f5445f838db316eb46 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 29 Sep 2021 09:12:37 +0200 Subject: block: call submit_bio_checks under q_usage_counter Ensure all bios check the current values of the queue under freeze protection, i.e. to make sure the zero capacity set by del_gendisk is actually seen before dispatching to the driver. Signed-off-by: Christoph Hellwig Link: https://lore.kernel.org/r/20210929071241.934472-2-hch@lst.de Tested-by: Yi Zhang Signed-off-by: Jens Axboe --- block/blk-core.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 5454db2fa263..c071f1a90b10 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -899,11 +899,18 @@ static blk_qc_t __submit_bio(struct bio *bio) struct gendisk *disk = bio->bi_bdev->bd_disk; blk_qc_t ret = BLK_QC_T_NONE; - if (blk_crypto_bio_prep(&bio)) { - if (!disk->fops->submit_bio) - return blk_mq_submit_bio(bio); + if (unlikely(bio_queue_enter(bio) != 0)) + return BLK_QC_T_NONE; + + if (!submit_bio_checks(bio) || !blk_crypto_bio_prep(&bio)) + goto queue_exit; + if (disk->fops->submit_bio) { ret = disk->fops->submit_bio(bio); + goto queue_exit; } + return blk_mq_submit_bio(bio); + +queue_exit: blk_queue_exit(disk->queue); return ret; } @@ -941,9 +948,6 @@ static blk_qc_t __submit_bio_noacct(struct bio *bio) struct request_queue *q = bio->bi_bdev->bd_disk->queue; struct bio_list lower, same; - if (unlikely(bio_queue_enter(bio) != 0)) - continue; - /* * Create a fresh bio_list for all subordinate requests. */ @@ -979,23 +983,12 @@ static blk_qc_t __submit_bio_noacct(struct bio *bio) static blk_qc_t __submit_bio_noacct_mq(struct bio *bio) { struct bio_list bio_list[2] = { }; - blk_qc_t ret = BLK_QC_T_NONE; + blk_qc_t ret; current->bio_list = bio_list; do { - struct gendisk *disk = bio->bi_bdev->bd_disk; - - if (unlikely(bio_queue_enter(bio) != 0)) - continue; - - if (!blk_crypto_bio_prep(&bio)) { - blk_queue_exit(disk->queue); - ret = BLK_QC_T_NONE; - continue; - } - - ret = blk_mq_submit_bio(bio); + ret = __submit_bio(bio); } while ((bio = bio_list_pop(&bio_list[0]))); current->bio_list = NULL; @@ -1013,9 +1006,6 @@ static blk_qc_t __submit_bio_noacct_mq(struct bio *bio) */ blk_qc_t submit_bio_noacct(struct bio *bio) { - if (!submit_bio_checks(bio)) - return BLK_QC_T_NONE; - /* * We only want one ->submit_bio to be active at a time, else stack * usage with stacked devices could be a problem. Use current->bio_list -- cgit From 1f14a0989073459c2be6b5c7b3fb7f9f3d7fa2af Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 29 Sep 2021 09:12:38 +0200 Subject: block: factor out a blk_try_enter_queue helper Factor out the code to try to get q_usage_counter without blocking into a separate helper. Both to improve code readability and to prepare for splitting bio_queue_enter from blk_queue_enter. Signed-off-by: Christoph Hellwig Tested-by: Darrick J. Wong Link: https://lore.kernel.org/r/20210929071241.934472-3-hch@lst.de Tested-by: Yi Zhang Signed-off-by: Jens Axboe --- block/blk-core.c | 60 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index c071f1a90b10..7e9eadacf2de 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -416,6 +416,30 @@ void blk_cleanup_queue(struct request_queue *q) } EXPORT_SYMBOL(blk_cleanup_queue); +static bool blk_try_enter_queue(struct request_queue *q, bool pm) +{ + rcu_read_lock(); + if (!percpu_ref_tryget_live(&q->q_usage_counter)) + goto fail; + + /* + * The code that increments the pm_only counter must ensure that the + * counter is globally visible before the queue is unfrozen. + */ + if (blk_queue_pm_only(q) && + (!pm || queue_rpm_status(q) == RPM_SUSPENDED)) + goto fail_put; + + rcu_read_unlock(); + return true; + +fail_put: + percpu_ref_put(&q->q_usage_counter); +fail: + rcu_read_unlock(); + return false; +} + /** * blk_queue_enter() - try to increase q->q_usage_counter * @q: request queue pointer @@ -425,40 +449,18 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags) { const bool pm = flags & BLK_MQ_REQ_PM; - while (true) { - bool success = false; - - rcu_read_lock(); - if (percpu_ref_tryget_live(&q->q_usage_counter)) { - /* - * The code that increments the pm_only counter is - * responsible for ensuring that that counter is - * globally visible before the queue is unfrozen. - */ - if ((pm && queue_rpm_status(q) != RPM_SUSPENDED) || - !blk_queue_pm_only(q)) { - success = true; - } else { - percpu_ref_put(&q->q_usage_counter); - } - } - rcu_read_unlock(); - - if (success) - return 0; - + while (!blk_try_enter_queue(q, pm)) { if (flags & BLK_MQ_REQ_NOWAIT) return -EBUSY; /* - * read pair of barrier in blk_freeze_queue_start(), - * we need to order reading __PERCPU_REF_DEAD flag of - * .q_usage_counter and reading .mq_freeze_depth or - * queue dying flag, otherwise the following wait may - * never return if the two reads are reordered. + * read pair of barrier in blk_freeze_queue_start(), we need to + * order reading __PERCPU_REF_DEAD flag of .q_usage_counter and + * reading .mq_freeze_depth or queue dying flag, otherwise the + * following wait may never return if the two reads are + * reordered. */ smp_rmb(); - wait_event(q->mq_freeze_wq, (!q->mq_freeze_depth && blk_pm_resume_queue(pm, q)) || @@ -466,6 +468,8 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags) if (blk_queue_dying(q)) return -ENODEV; } + + return 0; } static inline int bio_queue_enter(struct bio *bio) -- cgit From a6741536f44ae65491cfde6870ae518aabe1ca36 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 29 Sep 2021 09:12:39 +0200 Subject: block: split bio_queue_enter from blk_queue_enter To prepare for fixing a gendisk shutdown race, open code the blk_queue_enter logic in bio_queue_enter. This also removes the pointless flags translation. Signed-off-by: Christoph Hellwig Tested-by: Darrick J. Wong Link: https://lore.kernel.org/r/20210929071241.934472-4-hch@lst.de Tested-by: Yi Zhang Signed-off-by: Jens Axboe --- block/blk-core.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 7e9eadacf2de..43f5da707d8e 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -475,18 +475,35 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags) static inline int bio_queue_enter(struct bio *bio) { struct request_queue *q = bio->bi_bdev->bd_disk->queue; - bool nowait = bio->bi_opf & REQ_NOWAIT; - int ret; - ret = blk_queue_enter(q, nowait ? BLK_MQ_REQ_NOWAIT : 0); - if (unlikely(ret)) { - if (nowait && !blk_queue_dying(q)) + while (!blk_try_enter_queue(q, false)) { + if (bio->bi_opf & REQ_NOWAIT) { + if (blk_queue_dying(q)) + goto dead; bio_wouldblock_error(bio); - else - bio_io_error(bio); + return -EBUSY; + } + + /* + * read pair of barrier in blk_freeze_queue_start(), we need to + * order reading __PERCPU_REF_DEAD flag of .q_usage_counter and + * reading .mq_freeze_depth or queue dying flag, otherwise the + * following wait may never return if the two reads are + * reordered. + */ + smp_rmb(); + wait_event(q->mq_freeze_wq, + (!q->mq_freeze_depth && + blk_pm_resume_queue(false, q)) || + blk_queue_dying(q)); + if (blk_queue_dying(q)) + goto dead; } - return ret; + return 0; +dead: + bio_io_error(bio); + return -ENODEV; } void blk_queue_exit(struct request_queue *q) -- cgit From 8e141f9eb803e209714a80aa6ec073893f94c526 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 29 Sep 2021 09:12:40 +0200 Subject: block: drain file system I/O on del_gendisk Instead of delaying draining of file system I/O related items like the blk-qos queues, the integrity read workqueue and timeouts only when the request_queue is removed, do that when del_gendisk is called. This is important for SCSI where the upper level drivers that control the gendisk are separate entities, and the disk can be freed much earlier than the request_queue, or can even be unbound without tearing down the queue. Fixes: edb0872f44ec ("block: move the bdi from the request_queue to the gendisk") Reported-by: Ming Lei Signed-off-by: Christoph Hellwig Tested-by: Darrick J. Wong Link: https://lore.kernel.org/r/20210929071241.934472-5-hch@lst.de Tested-by: Yi Zhang Signed-off-by: Jens Axboe --- block/blk-core.c | 27 ++++++++++++--------------- block/blk.h | 1 + block/genhd.c | 21 +++++++++++++++++++++ include/linux/genhd.h | 1 + 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 43f5da707d8e..4d8f5fe91588 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -49,7 +49,6 @@ #include "blk-mq.h" #include "blk-mq-sched.h" #include "blk-pm.h" -#include "blk-rq-qos.h" struct dentry *blk_debugfs_root; @@ -337,23 +336,25 @@ void blk_put_queue(struct request_queue *q) } EXPORT_SYMBOL(blk_put_queue); -void blk_set_queue_dying(struct request_queue *q) +void blk_queue_start_drain(struct request_queue *q) { - blk_queue_flag_set(QUEUE_FLAG_DYING, q); - /* * When queue DYING flag is set, we need to block new req * entering queue, so we call blk_freeze_queue_start() to * prevent I/O from crossing blk_queue_enter(). */ blk_freeze_queue_start(q); - if (queue_is_mq(q)) blk_mq_wake_waiters(q); - /* Make blk_queue_enter() reexamine the DYING flag. */ wake_up_all(&q->mq_freeze_wq); } + +void blk_set_queue_dying(struct request_queue *q) +{ + blk_queue_flag_set(QUEUE_FLAG_DYING, q); + blk_queue_start_drain(q); +} EXPORT_SYMBOL_GPL(blk_set_queue_dying); /** @@ -385,13 +386,8 @@ void blk_cleanup_queue(struct request_queue *q) */ blk_freeze_queue(q); - rq_qos_exit(q); - blk_queue_flag_set(QUEUE_FLAG_DEAD, q); - /* for synchronous bio-based driver finish in-flight integrity i/o */ - blk_flush_integrity(); - blk_sync_queue(q); if (queue_is_mq(q)) blk_mq_exit_queue(q); @@ -474,11 +470,12 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags) static inline int bio_queue_enter(struct bio *bio) { - struct request_queue *q = bio->bi_bdev->bd_disk->queue; + struct gendisk *disk = bio->bi_bdev->bd_disk; + struct request_queue *q = disk->queue; while (!blk_try_enter_queue(q, false)) { if (bio->bi_opf & REQ_NOWAIT) { - if (blk_queue_dying(q)) + if (test_bit(GD_DEAD, &disk->state)) goto dead; bio_wouldblock_error(bio); return -EBUSY; @@ -495,8 +492,8 @@ static inline int bio_queue_enter(struct bio *bio) wait_event(q->mq_freeze_wq, (!q->mq_freeze_depth && blk_pm_resume_queue(false, q)) || - blk_queue_dying(q)); - if (blk_queue_dying(q)) + test_bit(GD_DEAD, &disk->state)); + if (test_bit(GD_DEAD, &disk->state)) goto dead; } diff --git a/block/blk.h b/block/blk.h index 7d2a0ba7ed21..e2ed2257709a 100644 --- a/block/blk.h +++ b/block/blk.h @@ -51,6 +51,7 @@ struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size, void blk_free_flush_queue(struct blk_flush_queue *q); void blk_freeze_queue(struct request_queue *q); +void blk_queue_start_drain(struct request_queue *q); #define BIO_INLINE_VECS 4 struct bio_vec *bvec_alloc(mempool_t *pool, unsigned short *nr_vecs, diff --git a/block/genhd.c b/block/genhd.c index 496e8458c357..1fe816be9bcd 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -26,6 +26,7 @@ #include #include "blk.h" +#include "blk-rq-qos.h" static struct kobject *block_depr; @@ -559,6 +560,8 @@ EXPORT_SYMBOL(device_add_disk); */ void del_gendisk(struct gendisk *disk) { + struct request_queue *q = disk->queue; + might_sleep(); if (WARN_ON_ONCE(!disk_live(disk) && !(disk->flags & GENHD_FL_HIDDEN))) @@ -575,8 +578,26 @@ void del_gendisk(struct gendisk *disk) fsync_bdev(disk->part0); __invalidate_device(disk->part0, true); + /* + * Fail any new I/O. + */ + set_bit(GD_DEAD, &disk->state); set_capacity(disk, 0); + /* + * Prevent new I/O from crossing bio_queue_enter(). + */ + blk_queue_start_drain(q); + blk_mq_freeze_queue_wait(q); + + rq_qos_exit(q); + blk_sync_queue(q); + blk_flush_integrity(); + /* + * Allow using passthrough request again after the queue is torn down. + */ + blk_mq_unfreeze_queue(q); + if (!(disk->flags & GENHD_FL_HIDDEN)) { sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi"); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index c68d83c87f83..0f5315c2b5a3 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -149,6 +149,7 @@ struct gendisk { unsigned long state; #define GD_NEED_PART_SCAN 0 #define GD_READ_ONLY 1 +#define GD_DEAD 2 struct mutex open_mutex; /* open/close mutex */ unsigned open_partitions; /* number of open partitions */ -- cgit From aec89dc5d421200b353d99a2bfff9e0967f67037 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 29 Sep 2021 09:12:41 +0200 Subject: block: keep q_usage_counter in atomic mode after del_gendisk Don't switch back to percpu mode to avoid the double RCU grace period when tearing down SCSI devices. After removing the disk only passthrough commands can be send anyway. Suggested-by: Ming Lei Signed-off-by: Christoph Hellwig Tested-by: Darrick J. Wong Link: https://lore.kernel.org/r/20210929071241.934472-6-hch@lst.de Tested-by: Yi Zhang Signed-off-by: Jens Axboe --- block/blk-mq.c | 9 ++++++++- block/blk.h | 1 + block/genhd.c | 3 ++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 108a352051be..bc026372de43 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -188,9 +188,11 @@ void blk_mq_freeze_queue(struct request_queue *q) } EXPORT_SYMBOL_GPL(blk_mq_freeze_queue); -void blk_mq_unfreeze_queue(struct request_queue *q) +void __blk_mq_unfreeze_queue(struct request_queue *q, bool force_atomic) { mutex_lock(&q->mq_freeze_lock); + if (force_atomic) + q->q_usage_counter.data->force_atomic = true; q->mq_freeze_depth--; WARN_ON_ONCE(q->mq_freeze_depth < 0); if (!q->mq_freeze_depth) { @@ -199,6 +201,11 @@ void blk_mq_unfreeze_queue(struct request_queue *q) } mutex_unlock(&q->mq_freeze_lock); } + +void blk_mq_unfreeze_queue(struct request_queue *q) +{ + __blk_mq_unfreeze_queue(q, false); +} EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue); /* diff --git a/block/blk.h b/block/blk.h index e2ed2257709a..6c3c00a8fe19 100644 --- a/block/blk.h +++ b/block/blk.h @@ -51,6 +51,7 @@ struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size, void blk_free_flush_queue(struct blk_flush_queue *q); void blk_freeze_queue(struct request_queue *q); +void __blk_mq_unfreeze_queue(struct request_queue *q, bool force_atomic); void blk_queue_start_drain(struct request_queue *q); #define BIO_INLINE_VECS 4 diff --git a/block/genhd.c b/block/genhd.c index 1fe816be9bcd..7a766cc613c7 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -596,7 +596,8 @@ void del_gendisk(struct gendisk *disk) /* * Allow using passthrough request again after the queue is torn down. */ - blk_mq_unfreeze_queue(q); + blk_queue_flag_clear(QUEUE_FLAG_INIT_DONE, q); + __blk_mq_unfreeze_queue(q, true); if (!(disk->flags & GENHD_FL_HIDDEN)) { sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi"); -- cgit From c41108049d143304faf06852c7181262b7b0d242 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 12 Oct 2021 11:33:01 +0200 Subject: kyber: avoid q->disk dereferences in trace points q->disk becomes invalid after the gendisk is removed. Work around this by caching the dev_t for the tracepoints. The real fix would be to properly tear down the I/O schedulers with the gendisk, but that is a much more invasive change. Signed-off-by: Christoph Hellwig Link: https://lore.kernel.org/r/20211012093301.GA27795@lst.de Tested-by: Yi Zhang Signed-off-by: Jens Axboe --- block/kyber-iosched.c | 10 ++++++---- include/trace/events/kyber.h | 19 +++++++++---------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/block/kyber-iosched.c b/block/kyber-iosched.c index 15a8be57203d..a0ffbabfac2c 100644 --- a/block/kyber-iosched.c +++ b/block/kyber-iosched.c @@ -151,6 +151,7 @@ struct kyber_ctx_queue { struct kyber_queue_data { struct request_queue *q; + dev_t dev; /* * Each scheduling domain has a limited number of in-flight requests @@ -257,7 +258,7 @@ static int calculate_percentile(struct kyber_queue_data *kqd, } memset(buckets, 0, sizeof(kqd->latency_buckets[sched_domain][type])); - trace_kyber_latency(kqd->q, kyber_domain_names[sched_domain], + trace_kyber_latency(kqd->dev, kyber_domain_names[sched_domain], kyber_latency_type_names[type], percentile, bucket + 1, 1 << KYBER_LATENCY_SHIFT, samples); @@ -270,7 +271,7 @@ static void kyber_resize_domain(struct kyber_queue_data *kqd, depth = clamp(depth, 1U, kyber_depth[sched_domain]); if (depth != kqd->domain_tokens[sched_domain].sb.depth) { sbitmap_queue_resize(&kqd->domain_tokens[sched_domain], depth); - trace_kyber_adjust(kqd->q, kyber_domain_names[sched_domain], + trace_kyber_adjust(kqd->dev, kyber_domain_names[sched_domain], depth); } } @@ -366,6 +367,7 @@ static struct kyber_queue_data *kyber_queue_data_alloc(struct request_queue *q) goto err; kqd->q = q; + kqd->dev = disk_devt(q->disk); kqd->cpu_latency = alloc_percpu_gfp(struct kyber_cpu_latency, GFP_KERNEL | __GFP_ZERO); @@ -774,7 +776,7 @@ kyber_dispatch_cur_domain(struct kyber_queue_data *kqd, list_del_init(&rq->queuelist); return rq; } else { - trace_kyber_throttled(kqd->q, + trace_kyber_throttled(kqd->dev, kyber_domain_names[khd->cur_domain]); } } else if (sbitmap_any_bit_set(&khd->kcq_map[khd->cur_domain])) { @@ -787,7 +789,7 @@ kyber_dispatch_cur_domain(struct kyber_queue_data *kqd, list_del_init(&rq->queuelist); return rq; } else { - trace_kyber_throttled(kqd->q, + trace_kyber_throttled(kqd->dev, kyber_domain_names[khd->cur_domain]); } } diff --git a/include/trace/events/kyber.h b/include/trace/events/kyber.h index 491098a0d8ed..bf7533f171ff 100644 --- a/include/trace/events/kyber.h +++ b/include/trace/events/kyber.h @@ -13,11 +13,11 @@ TRACE_EVENT(kyber_latency, - TP_PROTO(struct request_queue *q, const char *domain, const char *type, + TP_PROTO(dev_t dev, const char *domain, const char *type, unsigned int percentile, unsigned int numerator, unsigned int denominator, unsigned int samples), - TP_ARGS(q, domain, type, percentile, numerator, denominator, samples), + TP_ARGS(dev, domain, type, percentile, numerator, denominator, samples), TP_STRUCT__entry( __field( dev_t, dev ) @@ -30,7 +30,7 @@ TRACE_EVENT(kyber_latency, ), TP_fast_assign( - __entry->dev = disk_devt(q->disk); + __entry->dev = dev; strlcpy(__entry->domain, domain, sizeof(__entry->domain)); strlcpy(__entry->type, type, sizeof(__entry->type)); __entry->percentile = percentile; @@ -47,10 +47,9 @@ TRACE_EVENT(kyber_latency, TRACE_EVENT(kyber_adjust, - TP_PROTO(struct request_queue *q, const char *domain, - unsigned int depth), + TP_PROTO(dev_t dev, const char *domain, unsigned int depth), - TP_ARGS(q, domain, depth), + TP_ARGS(dev, domain, depth), TP_STRUCT__entry( __field( dev_t, dev ) @@ -59,7 +58,7 @@ TRACE_EVENT(kyber_adjust, ), TP_fast_assign( - __entry->dev = disk_devt(q->disk); + __entry->dev = dev; strlcpy(__entry->domain, domain, sizeof(__entry->domain)); __entry->depth = depth; ), @@ -71,9 +70,9 @@ TRACE_EVENT(kyber_adjust, TRACE_EVENT(kyber_throttled, - TP_PROTO(struct request_queue *q, const char *domain), + TP_PROTO(dev_t dev, const char *domain), - TP_ARGS(q, domain), + TP_ARGS(dev, domain), TP_STRUCT__entry( __field( dev_t, dev ) @@ -81,7 +80,7 @@ TRACE_EVENT(kyber_throttled, ), TP_fast_assign( - __entry->dev = disk_devt(q->disk); + __entry->dev = dev; strlcpy(__entry->domain, domain, sizeof(__entry->domain)); ), -- cgit From d997cc1715df7b6c3df798881fb9941acf0079f8 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 15 Oct 2021 21:19:33 -0700 Subject: Input: snvs_pwrkey - add clk handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On i.MX7S and i.MX8M* (but not i.MX6*) the pwrkey device has an associated clock. Accessing the registers requires that this clock is enabled. Binding the driver on at least i.MX7S and i.MX8MP while not having the clock enabled results in a complete hang of the machine. (This usually only happens if snvs_pwrkey is built as a module and the rtc-snvs driver isn't already bound because at bootup the required clk is on and only gets disabled when the clk framework disables unused clks late during boot.) This completes the fix in commit 135be16d3505 ("ARM: dts: imx7s: add snvs clock to pwrkey"). Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20211013062848.2667192-1-u.kleine-koenig@pengutronix.de Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/snvs_pwrkey.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c index 2f5e3ab5ed63..65286762b02a 100644 --- a/drivers/input/keyboard/snvs_pwrkey.c +++ b/drivers/input/keyboard/snvs_pwrkey.c @@ -3,6 +3,7 @@ // Driver for the IMX SNVS ON/OFF Power Key // Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved. +#include #include #include #include @@ -99,6 +100,11 @@ static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } +static void imx_snvs_pwrkey_disable_clk(void *data) +{ + clk_disable_unprepare(data); +} + static void imx_snvs_pwrkey_act(void *pdata) { struct pwrkey_drv_data *pd = pdata; @@ -111,6 +117,7 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev) struct pwrkey_drv_data *pdata; struct input_dev *input; struct device_node *np; + struct clk *clk; int error; u32 vid; @@ -134,6 +141,28 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "KEY_POWER without setting in dts\n"); } + clk = devm_clk_get_optional(&pdev->dev, NULL); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "Failed to get snvs clock (%pe)\n", clk); + return PTR_ERR(clk); + } + + error = clk_prepare_enable(clk); + if (error) { + dev_err(&pdev->dev, "Failed to enable snvs clock (%pe)\n", + ERR_PTR(error)); + return error; + } + + error = devm_add_action_or_reset(&pdev->dev, + imx_snvs_pwrkey_disable_clk, clk); + if (error) { + dev_err(&pdev->dev, + "Failed to register clock cleanup handler (%pe)\n", + ERR_PTR(error)); + return error; + } + pdata->wakeup = of_property_read_bool(np, "wakeup-source"); pdata->irq = platform_get_irq(pdev, 0); -- cgit From fe0a7e3d012738b0034b3c97ddb0e8bc0a3ff0e6 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Fri, 15 Oct 2021 21:12:06 -0700 Subject: Input: resistive-adc-touch - fix division by zero error on z1 == 0 For proper pressure calculation we need at least x and z1 to be non zero. Even worse, in case z1 we may run in to division by zero error. Fixes: 60b7db914ddd ("Input: resistive-adc-touch - rework mapping of channels") Signed-off-by: Oleksij Rempel Link: https://lore.kernel.org/r/20211007095727.29579-1-o.rempel@pengutronix.de Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/resistive-adc-touch.c | 29 ++++++++++++++----------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/input/touchscreen/resistive-adc-touch.c b/drivers/input/touchscreen/resistive-adc-touch.c index 744544a723b7..6f754a8d30b1 100644 --- a/drivers/input/touchscreen/resistive-adc-touch.c +++ b/drivers/input/touchscreen/resistive-adc-touch.c @@ -71,19 +71,22 @@ static int grts_cb(const void *data, void *private) unsigned int z2 = touch_info[st->ch_map[GRTS_CH_Z2]]; unsigned int Rt; - Rt = z2; - Rt -= z1; - Rt *= st->x_plate_ohms; - Rt = DIV_ROUND_CLOSEST(Rt, 16); - Rt *= x; - Rt /= z1; - Rt = DIV_ROUND_CLOSEST(Rt, 256); - /* - * On increased pressure the resistance (Rt) is decreasing - * so, convert values to make it looks as real pressure. - */ - if (Rt < GRTS_DEFAULT_PRESSURE_MAX) - press = GRTS_DEFAULT_PRESSURE_MAX - Rt; + if (likely(x && z1)) { + Rt = z2; + Rt -= z1; + Rt *= st->x_plate_ohms; + Rt = DIV_ROUND_CLOSEST(Rt, 16); + Rt *= x; + Rt /= z1; + Rt = DIV_ROUND_CLOSEST(Rt, 256); + /* + * On increased pressure the resistance (Rt) is + * decreasing so, convert values to make it looks as + * real pressure. + */ + if (Rt < GRTS_DEFAULT_PRESSURE_MAX) + press = GRTS_DEFAULT_PRESSURE_MAX - Rt; + } } if ((!x && !y) || (st->pressure && (press < st->pressure_min))) { -- cgit From 3378a07daa6cdd11e042797454c706d1c69f9ca6 Mon Sep 17 00:00:00 2001 From: Michael Cullen Date: Fri, 15 Oct 2021 13:17:50 -0700 Subject: Input: xpad - add support for another USB ID of Nacon GC-100 The Nacon GX100XF is already mapped, but it seems there is a Nacon GC-100 (identified as NC5136Wht PCGC-100WHITE though I believe other colours exist) with a different USB ID when in XInput mode. Signed-off-by: Michael Cullen Link: https://lore.kernel.org/r/20211015192051.5196-1-michael@michaelcullen.name Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 29de8412e416..4c914f75a902 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -334,6 +334,7 @@ static const struct xpad_device { { 0x24c6, 0x5b03, "Thrustmaster Ferrari 458 Racing Wheel", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5d04, "Razer Sabertooth", 0, XTYPE_XBOX360 }, { 0x24c6, 0xfafe, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, + { 0x3285, 0x0607, "Nacon GC-100", 0, XTYPE_XBOX360 }, { 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX }, { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } @@ -451,6 +452,7 @@ static const struct usb_device_id xpad_table[] = { XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA Controllers */ XPAD_XBOXONE_VENDOR(0x2e24), /* Hyperkin Duke X-Box One pad */ XPAD_XBOX360_VENDOR(0x2f24), /* GameSir Controllers */ + XPAD_XBOX360_VENDOR(0x3285), /* Nacon GC-100 */ { } }; -- cgit From a02dcde595f7cbd240ccd64de96034ad91cffc40 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Fri, 15 Oct 2021 13:13:06 -0700 Subject: Input: touchscreen - avoid bitwise vs logical OR warning A new warning in clang points out a few places in this driver where a bitwise OR is being used with boolean types: drivers/input/touchscreen.c:81:17: warning: use of bitwise '|' with boolean operands [-Wbitwise-instead-of-logical] data_present = touchscreen_get_prop_u32(dev, "touchscreen-min-x", ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This use of a bitwise OR is intentional, as bitwise operations do not short circuit, which allows all the calls to touchscreen_get_prop_u32() to happen so that the last parameter is initialized while coalescing the results of the calls to make a decision after they are all evaluated. To make this clearer to the compiler, use the '|=' operator to assign the result of each touchscreen_get_prop_u32() call to data_present, which keeps the meaning of the code the same but makes it obvious that every one of these calls is expected to happen. Signed-off-by: Nathan Chancellor Reported-by: Nick Desaulniers Reviewed-by: Nick Desaulniers Link: https://lore.kernel.org/r/20211014205757.3474635-1-nathan@kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/input/touchscreen.c b/drivers/input/touchscreen.c index dd18cb917c4d..4620e20d0190 100644 --- a/drivers/input/touchscreen.c +++ b/drivers/input/touchscreen.c @@ -80,27 +80,27 @@ void touchscreen_parse_properties(struct input_dev *input, bool multitouch, data_present = touchscreen_get_prop_u32(dev, "touchscreen-min-x", input_abs_get_min(input, axis_x), - &minimum) | - touchscreen_get_prop_u32(dev, "touchscreen-size-x", - input_abs_get_max(input, - axis_x) + 1, - &maximum) | - touchscreen_get_prop_u32(dev, "touchscreen-fuzz-x", - input_abs_get_fuzz(input, axis_x), - &fuzz); + &minimum); + data_present |= touchscreen_get_prop_u32(dev, "touchscreen-size-x", + input_abs_get_max(input, + axis_x) + 1, + &maximum); + data_present |= touchscreen_get_prop_u32(dev, "touchscreen-fuzz-x", + input_abs_get_fuzz(input, axis_x), + &fuzz); if (data_present) touchscreen_set_params(input, axis_x, minimum, maximum - 1, fuzz); data_present = touchscreen_get_prop_u32(dev, "touchscreen-min-y", input_abs_get_min(input, axis_y), - &minimum) | - touchscreen_get_prop_u32(dev, "touchscreen-size-y", - input_abs_get_max(input, - axis_y) + 1, - &maximum) | - touchscreen_get_prop_u32(dev, "touchscreen-fuzz-y", - input_abs_get_fuzz(input, axis_y), - &fuzz); + &minimum); + data_present |= touchscreen_get_prop_u32(dev, "touchscreen-size-y", + input_abs_get_max(input, + axis_y) + 1, + &maximum); + data_present |= touchscreen_get_prop_u32(dev, "touchscreen-fuzz-y", + input_abs_get_fuzz(input, axis_y), + &fuzz); if (data_present) touchscreen_set_params(input, axis_y, minimum, maximum - 1, fuzz); @@ -108,11 +108,11 @@ void touchscreen_parse_properties(struct input_dev *input, bool multitouch, data_present = touchscreen_get_prop_u32(dev, "touchscreen-max-pressure", input_abs_get_max(input, axis), - &maximum) | - touchscreen_get_prop_u32(dev, - "touchscreen-fuzz-pressure", - input_abs_get_fuzz(input, axis), - &fuzz); + &maximum); + data_present |= touchscreen_get_prop_u32(dev, + "touchscreen-fuzz-pressure", + input_abs_get_fuzz(input, axis), + &fuzz); if (data_present) touchscreen_set_params(input, axis, 0, maximum, fuzz); -- cgit From b2381acd3fd9bacd2c63f53b2c610c89959b31cc Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 15 Oct 2021 12:46:25 +0200 Subject: x86/fpu: Mask out the invalid MXCSR bits properly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a fix for the fix (yeah, /facepalm). The correct mask to use is not the negation of the MXCSR_MASK but the actual mask which contains the supported bits in the MXCSR register. Reported and debugged by Ville Syrjälä Fixes: d298b03506d3 ("x86/fpu: Restore the masking out of reserved MXCSR bits") Signed-off-by: Borislav Petkov Tested-by: Ville Syrjälä Tested-by: Ser Olmy Cc: Link: https://lore.kernel.org/r/YWgYIYXLriayyezv@intel.com --- arch/x86/kernel/fpu/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c index fa17a27390ab..831b25c5e705 100644 --- a/arch/x86/kernel/fpu/signal.c +++ b/arch/x86/kernel/fpu/signal.c @@ -385,7 +385,7 @@ static int __fpu_restore_sig(void __user *buf, void __user *buf_fx, return -EINVAL; } else { /* Mask invalid bits out for historical reasons (broken hardware). */ - fpu->state.fxsave.mxcsr &= ~mxcsr_feature_mask; + fpu->state.fxsave.mxcsr &= mxcsr_feature_mask; } /* Enforce XFEATURE_MASK_FPSSE when XSAVE is enabled */ -- cgit From f7bf35862477d6d4f8a9746c645a4380de984700 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Tue, 7 Sep 2021 19:18:00 +0900 Subject: brd: reduce the brd_devices_mutex scope As with commit 8b52d8be86d72308 ("loop: reorder loop_exit"), unregister_blkdev() needs to be called first in order to avoid calling brd_alloc() from brd_probe() after brd_del_one() from brd_exit(). Then, we can avoid holding global mutex during add_disk()/del_gendisk() as with commit 1c500ad706383f1a ("loop: reduce the loop_ctl_mutex scope"). Signed-off-by: Tetsuo Handa Reviewed-by: Christoph Hellwig Link: https://lore.kernel.org/r/e205f13d-18ff-a49c-0988-7de6ea5ff823@i-love.sakura.ne.jp Signed-off-by: Jens Axboe --- drivers/block/brd.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 58ec167aa018..530b31240203 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -373,10 +373,22 @@ static int brd_alloc(int i) struct gendisk *disk; char buf[DISK_NAME_LEN]; + mutex_lock(&brd_devices_mutex); + list_for_each_entry(brd, &brd_devices, brd_list) { + if (brd->brd_number == i) { + mutex_unlock(&brd_devices_mutex); + return -EEXIST; + } + } brd = kzalloc(sizeof(*brd), GFP_KERNEL); - if (!brd) + if (!brd) { + mutex_unlock(&brd_devices_mutex); return -ENOMEM; + } brd->brd_number = i; + list_add_tail(&brd->brd_list, &brd_devices); + mutex_unlock(&brd_devices_mutex); + spin_lock_init(&brd->brd_lock); INIT_RADIX_TREE(&brd->brd_pages, GFP_ATOMIC); @@ -411,37 +423,30 @@ static int brd_alloc(int i) blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue); blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, disk->queue); add_disk(disk); - list_add_tail(&brd->brd_list, &brd_devices); return 0; out_free_dev: + mutex_lock(&brd_devices_mutex); + list_del(&brd->brd_list); + mutex_unlock(&brd_devices_mutex); kfree(brd); return -ENOMEM; } static void brd_probe(dev_t dev) { - int i = MINOR(dev) / max_part; - struct brd_device *brd; - - mutex_lock(&brd_devices_mutex); - list_for_each_entry(brd, &brd_devices, brd_list) { - if (brd->brd_number == i) - goto out_unlock; - } - - brd_alloc(i); -out_unlock: - mutex_unlock(&brd_devices_mutex); + brd_alloc(MINOR(dev) / max_part); } static void brd_del_one(struct brd_device *brd) { - list_del(&brd->brd_list); del_gendisk(brd->brd_disk); blk_cleanup_disk(brd->brd_disk); brd_free_pages(brd); + mutex_lock(&brd_devices_mutex); + list_del(&brd->brd_list); + mutex_unlock(&brd_devices_mutex); kfree(brd); } @@ -491,25 +496,21 @@ static int __init brd_init(void) brd_debugfs_dir = debugfs_create_dir("ramdisk_pages", NULL); - mutex_lock(&brd_devices_mutex); for (i = 0; i < rd_nr; i++) { err = brd_alloc(i); if (err) goto out_free; } - mutex_unlock(&brd_devices_mutex); - pr_info("brd: module loaded\n"); return 0; out_free: + unregister_blkdev(RAMDISK_MAJOR, "ramdisk"); debugfs_remove_recursive(brd_debugfs_dir); list_for_each_entry_safe(brd, next, &brd_devices, brd_list) brd_del_one(brd); - mutex_unlock(&brd_devices_mutex); - unregister_blkdev(RAMDISK_MAJOR, "ramdisk"); pr_info("brd: module NOT loaded !!!\n"); return err; @@ -519,13 +520,12 @@ static void __exit brd_exit(void) { struct brd_device *brd, *next; + unregister_blkdev(RAMDISK_MAJOR, "ramdisk"); debugfs_remove_recursive(brd_debugfs_dir); list_for_each_entry_safe(brd, next, &brd_devices, brd_list) brd_del_one(brd); - unregister_blkdev(RAMDISK_MAJOR, "ramdisk"); - pr_info("brd: module unloaded\n"); } -- cgit From a20417611b98e12a724e5c828c472ea16990b71f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 14 Oct 2021 15:02:31 +0200 Subject: block: warn when putting the final reference on a registered disk Warn when the last reference on a live disk is put without calling del_gendisk first. There are some BDI related bug reports that look like a case of this, so make sure we have the proper instrumentation to catch it. Signed-off-by: Christoph Hellwig Link: https://lore.kernel.org/r/20211014130231.1468538-1-hch@lst.de Signed-off-by: Jens Axboe --- block/genhd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block/genhd.c b/block/genhd.c index 7a766cc613c7..b49858550fa6 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -1078,6 +1078,7 @@ static void disk_release(struct device *dev) struct gendisk *disk = dev_to_disk(dev); might_sleep(); + WARN_ON_ONCE(disk_live(disk)); disk_release_events(disk); kfree(disk->random); -- cgit From d29bd41428cfff9b582c248db14a47e2be8457a8 Mon Sep 17 00:00:00 2001 From: Paolo Valente Date: Fri, 15 Oct 2021 16:43:36 +0200 Subject: block, bfq: reset last_bfqq_created on group change Since commit 430a67f9d616 ("block, bfq: merge bursts of newly-created queues"), BFQ maintains a per-group pointer to the last bfq_queue created. If such a queue, say bfqq, happens to move to a different group, then bfqq is no more a valid last bfq_queue created for its previous group. That pointer must then be cleared. Not resetting such a pointer may also cause UAF, if bfqq happens to also be freed after being moved to a different group. This commit performs this missing reset. As such it fixes commit 430a67f9d616 ("block, bfq: merge bursts of newly-created queues"). Such a missing reset is most likely the cause of the crash reported in [1]. With some analysis, we found that this crash was due to the above UAF. And such UAF did go away with this commit applied [1]. Anyway, before this commit, that crash happened to be triggered in conjunction with commit 2d52c58b9c9b ("block, bfq: honor already-setup queue merges"). The latter was then reverted by commit ebc69e897e17 ("Revert "block, bfq: honor already-setup queue merges""). Yet commit 2d52c58b9c9b ("block, bfq: honor already-setup queue merges") contains no error related with the above UAF, and can then be restored. [1] https://bugzilla.kernel.org/show_bug.cgi?id=214503 Fixes: 430a67f9d616 ("block, bfq: merge bursts of newly-created queues") Tested-by: Grzegorz Kowal Signed-off-by: Paolo Valente Link: https://lore.kernel.org/r/20211015144336.45894-2-paolo.valente@linaro.org Signed-off-by: Jens Axboe --- block/bfq-cgroup.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c index e2f14508f2d6..85b8e1c3a762 100644 --- a/block/bfq-cgroup.c +++ b/block/bfq-cgroup.c @@ -666,6 +666,12 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq, bfq_put_idle_entity(bfq_entity_service_tree(entity), entity); bfqg_and_blkg_put(bfqq_group(bfqq)); + if (entity->parent && + entity->parent->last_bfqq_created == bfqq) + entity->parent->last_bfqq_created = NULL; + else if (bfqd->last_bfqq_created == bfqq) + bfqd->last_bfqq_created = NULL; + entity->parent = bfqg->my_entity; entity->sched_data = &bfqg->sched_data; /* pin down bfqg and its associated blkg */ -- cgit From 519d81956ee277b4419c723adfb154603c2565ba Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 17 Oct 2021 20:00:13 -1000 Subject: Linux 5.15-rc6 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4d0c0ed9236e..91297670da8e 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 5 PATCHLEVEL = 15 SUBLEVEL = 0 -EXTRAVERSION = -rc5 +EXTRAVERSION = -rc6 NAME = Opossums on Parade # *DOCUMENTATION* -- cgit