From 0ade8c4105985bc911b252ccf9f5665139829cbb Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Thu, 22 Apr 2021 14:44:52 +0530 Subject: [PATCH 01/67] ANDROID: ABI: update allowed list for QCOM Update the android/abi_gki_aarch64_qcom with rtc_add_group addition. No need to update the .xml file, as it is already updated with rtc_add_group symbol. Bug: 185539583 Change-Id: I581bcf83a02a4114a9e7a22397fb52934ea0c52b Signed-off-by: Mukesh Ojha --- android/abi_gki_aarch64_qcom | 1 + 1 file changed, 1 insertion(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index af413ee22491..930a3de22c5a 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -2022,6 +2022,7 @@ rpmsg_set_signals rpmsg_trysend rpmsg_unregister_device + rtc_add_group rtc_class_close rtc_class_open rtc_read_time From b6221e349592ef2fd7a1b78cb3cc64459e8dc9c2 Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Thu, 22 Apr 2021 13:19:19 -0700 Subject: [PATCH 02/67] Revert "ANDROID: Incremental fs: Fix selinux issues" This reverts commit 75c93eb4397b3fdbc7587e48fb8bb884775747c5. Reason for revert: rolling the three fixes into one with feature flag Bug: 174692664 Test: incfs_test passes Signed-off-by: Paul Lawrence Change-Id: I838bed85d6682aba44165a58c22e6a0e10c49d58 --- fs/incfs/vfs.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/fs/incfs/vfs.c b/fs/incfs/vfs.c index d7a750290953..915d8eb6f9b1 100644 --- a/fs/incfs/vfs.c +++ b/fs/incfs/vfs.c @@ -898,7 +898,7 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry, .dentry = dentry }; new_file = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE, - current_cred()); + mi->mi_owner); if (IS_ERR(new_file)) { error = PTR_ERR(new_file); @@ -1026,7 +1026,7 @@ static int dir_relative_path_resolve( if (dir_fd < 0) return dir_fd; - dir_f = dentry_open(base_path, O_RDONLY | O_NOATIME, current_cred()); + dir_f = dentry_open(base_path, O_RDONLY | O_NOATIME, mi->mi_owner); if (IS_ERR(dir_f)) { error = PTR_ERR(dir_f); @@ -1904,13 +1904,10 @@ static int file_open(struct inode *inode, struct file *file) struct file *backing_file = NULL; struct path backing_path = {}; int err = 0; - const struct cred *old_cred; get_incfs_backing_path(file->f_path.dentry, &backing_path); - old_cred = override_creds(mi->mi_owner); - backing_file = dentry_open(&backing_path, - O_RDWR | O_NOATIME | O_LARGEFILE, current_cred()); - revert_creds(old_cred); + backing_file = dentry_open( + &backing_path, O_RDWR | O_NOATIME | O_LARGEFILE, mi->mi_owner); path_put(&backing_path); if (IS_ERR(backing_file)) { From dbee4e7bc4e0816a6d84bd22ab6b9a0fbf2a4ab1 Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Thu, 22 Apr 2021 13:19:30 -0700 Subject: [PATCH 03/67] Revert "ANDROID: Incremental fs: Set credentials before reading/writing" This reverts commit 28688d32ed31a11f85ab649f344add1d92b739a2. Reason for revert: rolling the three fixes into one with feature flag Bug: 174692664 Test: incfs_test passes Signed-off-by: Paul Lawrence Change-Id: I85cb75b7acb5606659698a6d0e0918ffb731009d --- fs/incfs/data_mgmt.c | 29 +++++++++++++++-------------- fs/incfs/format.c | 33 +++++++++++---------------------- fs/incfs/format.h | 17 +++-------------- fs/incfs/vfs.c | 2 +- 4 files changed, 30 insertions(+), 51 deletions(-) diff --git a/fs/incfs/data_mgmt.c b/fs/incfs/data_mgmt.c index e0705be44fb2..386e4ced8b34 100644 --- a/fs/incfs/data_mgmt.c +++ b/fs/incfs/data_mgmt.c @@ -144,7 +144,7 @@ struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf) if (!S_ISREG(bf->f_inode->i_mode)) return ERR_PTR(-EBADF); - bfc = incfs_alloc_bfc(mi, bf); + bfc = incfs_alloc_bfc(bf); if (IS_ERR(bfc)) return ERR_CAST(bfc); @@ -388,8 +388,8 @@ static void log_block_read(struct mount_info *mi, incfs_uuid_t *id, schedule_delayed_work(&log->ml_wakeup_work, msecs_to_jiffies(16)); } -static int validate_hash_tree(struct backing_file_context *bfc, struct file *f, - int block_index, struct mem_range data, u8 *buf) +static int validate_hash_tree(struct file *bf, struct file *f, int block_index, + struct mem_range data, u8 *buf) { struct data_file *df = get_incfs_data_file(f); u8 stored_digest[INCFS_MAX_HASH_SIZE] = {}; @@ -446,7 +446,7 @@ static int validate_hash_tree(struct backing_file_context *bfc, struct file *f, if (page) put_page(page); - res = incfs_kread(bfc, buf, INCFS_DATA_FILE_BLOCK_SIZE, + res = incfs_kread(bf, buf, INCFS_DATA_FILE_BLOCK_SIZE, hash_block_offset[lvl] + sig->hash_offset); if (res < 0) return res; @@ -919,7 +919,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, ssize_t result; size_t bytes_to_read; struct mount_info *mi = NULL; - struct backing_file_context *bfc = NULL; + struct file *bf = NULL; struct data_file_block block = {}; struct data_file *df = get_incfs_data_file(f); @@ -930,7 +930,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, return -ERANGE; mi = df->df_mount_info; - bfc = df->df_backing_file_context; + bf = df->df_backing_file_context->bc_file; result = wait_for_data_block(df, index, timeout_ms, &block); if (result < 0) @@ -939,20 +939,20 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, pos = block.db_backing_file_data_offset; if (block.db_comp_alg == COMPRESSION_NONE) { bytes_to_read = min(dst.len, block.db_stored_size); - result = incfs_kread(bfc, dst.data, bytes_to_read, pos); + result = incfs_kread(bf, dst.data, bytes_to_read, pos); /* Some data was read, but not enough */ if (result >= 0 && result != bytes_to_read) result = -EIO; } else { bytes_to_read = min(tmp.len, block.db_stored_size); - result = incfs_kread(bfc, tmp.data, bytes_to_read, pos); + result = incfs_kread(bf, tmp.data, bytes_to_read, pos); if (result == bytes_to_read) { result = decompress(range(tmp.data, bytes_to_read), dst); if (result < 0) { const char *name = - bfc->bc_file->f_path.dentry->d_name.name; + bf->f_path.dentry->d_name.name; pr_warn_once("incfs: Decompression error. %s", name); @@ -964,7 +964,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, } if (result > 0) { - int err = validate_hash_tree(bfc, f, index, dst, tmp.data); + int err = validate_hash_tree(bf, f, index, dst, tmp.data); if (err < 0) result = err; @@ -1027,13 +1027,14 @@ int incfs_process_new_data_block(struct data_file *df, unlock: mutex_unlock(&segment->blockmap_mutex); if (error) - pr_debug("%d error: %d\n", block->block_index, error); + pr_debug("incfs: %s %d error: %d\n", __func__, + block->block_index, error); return error; } int incfs_read_file_signature(struct data_file *df, struct mem_range dst) { - struct backing_file_context *bfc = df->df_backing_file_context; + struct file *bf = df->df_backing_file_context->bc_file; struct incfs_df_signature *sig; int read_res = 0; @@ -1047,7 +1048,7 @@ int incfs_read_file_signature(struct data_file *df, struct mem_range dst) if (dst.len < sig->sig_size) return -E2BIG; - read_res = incfs_kread(bfc, dst.data, sig->sig_size, sig->sig_offset); + read_res = incfs_kread(bf, dst.data, sig->sig_size, sig->sig_offset); if (read_res < 0) return read_res; @@ -1173,7 +1174,7 @@ static int process_file_signature_md(struct incfs_file_signature *sg, goto out; } - read = incfs_kread(df->df_backing_file_context, buf, + read = incfs_kread(df->df_backing_file_context->bc_file, buf, signature->sig_size, signature->sig_offset); if (read < 0) { error = read; diff --git a/fs/incfs/format.c b/fs/incfs/format.c index 193cd8f23792..c56e559b6893 100644 --- a/fs/incfs/format.c +++ b/fs/incfs/format.c @@ -15,8 +15,7 @@ #include "format.h" #include "data_mgmt.h" -struct backing_file_context *incfs_alloc_bfc(struct mount_info *mi, - struct file *backing_file) +struct backing_file_context *incfs_alloc_bfc(struct file *backing_file) { struct backing_file_context *result = NULL; @@ -25,7 +24,6 @@ struct backing_file_context *incfs_alloc_bfc(struct mount_info *mi, return ERR_PTR(-ENOMEM); result->bc_file = get_file(backing_file); - result->bc_cred = mi->mi_owner; mutex_init(&result->bc_mutex); return result; } @@ -118,7 +116,7 @@ static int append_zeros(struct backing_file_context *bfc, size_t len) static int write_to_bf(struct backing_file_context *bfc, const void *buf, size_t count, loff_t pos) { - ssize_t res = incfs_kwrite(bfc, buf, count, pos); + ssize_t res = incfs_kwrite(bfc->bc_file, buf, count, pos); if (res < 0) return res; @@ -533,7 +531,8 @@ int incfs_read_blockmap_entries(struct backing_file_context *bfc, if (start_index < 0 || bm_base_off <= 0) return -ENODATA; - result = incfs_kread(bfc, entries, bytes_to_read, bm_entry_off); + result = incfs_kread(bfc->bc_file, entries, bytes_to_read, + bm_entry_off); if (result < 0) return result; return result / sizeof(*entries); @@ -550,7 +549,7 @@ int incfs_read_file_header(struct backing_file_context *bfc, return -EFAULT; LOCK_REQUIRED(bfc->bc_mutex); - bytes_read = incfs_kread(bfc, &fh, sizeof(fh), 0); + bytes_read = incfs_kread(bfc->bc_file, &fh, sizeof(fh), 0); if (bytes_read < 0) return bytes_read; @@ -604,8 +603,8 @@ int incfs_read_next_metadata_record(struct backing_file_context *bfc, return -EPERM; memset(&handler->md_buffer, 0, max_md_size); - bytes_read = incfs_kread(bfc, &handler->md_buffer, max_md_size, - handler->md_record_offset); + bytes_read = incfs_kread(bfc->bc_file, &handler->md_buffer, + max_md_size, handler->md_record_offset); if (bytes_read < 0) return bytes_read; if (bytes_read < sizeof(*md_hdr)) @@ -681,22 +680,12 @@ int incfs_read_next_metadata_record(struct backing_file_context *bfc, return res; } -ssize_t incfs_kread(struct backing_file_context *bfc, void *buf, size_t size, - loff_t pos) +ssize_t incfs_kread(struct file *f, void *buf, size_t size, loff_t pos) { - const struct cred *old_cred = override_creds(bfc->bc_cred); - int ret = kernel_read(bfc->bc_file, buf, size, &pos); - - revert_creds(old_cred); - return ret; + return kernel_read(f, buf, size, &pos); } -ssize_t incfs_kwrite(struct backing_file_context *bfc, const void *buf, - size_t size, loff_t pos) +ssize_t incfs_kwrite(struct file *f, const void *buf, size_t size, loff_t pos) { - const struct cred *old_cred = override_creds(bfc->bc_cred); - int ret = kernel_write(bfc->bc_file, buf, size, &pos); - - revert_creds(old_cred); - return ret; + return kernel_write(f, buf, size, &pos); } diff --git a/fs/incfs/format.h b/fs/incfs/format.h index a6d3aef6b358..1a83349bb2eb 100644 --- a/fs/incfs/format.h +++ b/fs/incfs/format.h @@ -256,13 +256,6 @@ struct backing_file_context { * 0 means there are no metadata records. */ loff_t bc_last_md_record_offset; - - /* - * Credentials to set before reads/writes - * Note that this is a pointer to the mount_info mi_owner field so - * there is no need to get/put the creds - */ - const struct cred *bc_cred; }; struct metadata_handler { @@ -290,9 +283,7 @@ struct metadata_handler { loff_t incfs_get_end_offset(struct file *f); /* Backing file context management */ -struct mount_info; -struct backing_file_context *incfs_alloc_bfc(struct mount_info *mi, - struct file *backing_file); +struct backing_file_context *incfs_alloc_bfc(struct file *backing_file); void incfs_free_bfc(struct backing_file_context *bfc); @@ -343,9 +334,7 @@ int incfs_read_blockmap_entries(struct backing_file_context *bfc, int incfs_read_next_metadata_record(struct backing_file_context *bfc, struct metadata_handler *handler); -ssize_t incfs_kread(struct backing_file_context *bfc, void *buf, size_t size, - loff_t pos); -ssize_t incfs_kwrite(struct backing_file_context *bfc, const void *buf, - size_t size, loff_t pos); +ssize_t incfs_kread(struct file *f, void *buf, size_t size, loff_t pos); +ssize_t incfs_kwrite(struct file *f, const void *buf, size_t size, loff_t pos); #endif /* _INCFS_FORMAT_H */ diff --git a/fs/incfs/vfs.c b/fs/incfs/vfs.c index 915d8eb6f9b1..582448ccdaef 100644 --- a/fs/incfs/vfs.c +++ b/fs/incfs/vfs.c @@ -905,7 +905,7 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry, goto out; } - bfc = incfs_alloc_bfc(mi, new_file); + bfc = incfs_alloc_bfc(new_file); fput(new_file); if (IS_ERR(bfc)) { error = PTR_ERR(bfc); From a035201d12cbb16c17cd94e86d43802c47dc11f2 Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Thu, 22 Apr 2021 13:19:39 -0700 Subject: [PATCH 04/67] Revert "ANDROID: Incremental fs: Fix memory leak on closing file" This reverts commit 152fd8f04491a5ccf26c1f1adfb1b228b3082d2c. Reason for revert: rolling the three fixes into one with feature flag Bug: 174692664 Test: incfs_test passes Signed-off-by: Paul Lawrence Change-Id: I9a2e6faa0c2293b691efca8e985390fd94bcf01a --- fs/incfs/data_mgmt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/incfs/data_mgmt.c b/fs/incfs/data_mgmt.c index 386e4ced8b34..074a733c7001 100644 --- a/fs/incfs/data_mgmt.c +++ b/fs/incfs/data_mgmt.c @@ -199,7 +199,6 @@ void incfs_free_data_file(struct data_file *df) for (i = 0; i < ARRAY_SIZE(df->df_segments); i++) data_file_segment_destroy(&df->df_segments[i]); incfs_free_bfc(df->df_backing_file_context); - kfree(df->df_signature); kfree(df); } From fad2655cb7287ba2c5ed5f344a8cfa66bb9f52f7 Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Wed, 3 Feb 2021 10:33:05 -0800 Subject: [PATCH 05/67] ANDROID: Incremental fs: Set credentials before reading/writing Use same selinux scheme as incfs v2 Fix memory leak Bug: 174692664 Test: incfs_test passes Signed-off-by: Paul Lawrence Change-Id: I6058ddad9d43ba01b2eabd7d3c576f2cc9b42292 --- fs/incfs/data_mgmt.c | 30 +++++++++++++++--------------- fs/incfs/format.c | 34 ++++++++++++++++++++++------------ fs/incfs/format.h | 17 ++++++++++++++--- fs/incfs/main.c | 10 ++++++++++ fs/incfs/vfs.c | 13 ++++++++----- 5 files changed, 69 insertions(+), 35 deletions(-) diff --git a/fs/incfs/data_mgmt.c b/fs/incfs/data_mgmt.c index 074a733c7001..e0705be44fb2 100644 --- a/fs/incfs/data_mgmt.c +++ b/fs/incfs/data_mgmt.c @@ -144,7 +144,7 @@ struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf) if (!S_ISREG(bf->f_inode->i_mode)) return ERR_PTR(-EBADF); - bfc = incfs_alloc_bfc(bf); + bfc = incfs_alloc_bfc(mi, bf); if (IS_ERR(bfc)) return ERR_CAST(bfc); @@ -199,6 +199,7 @@ void incfs_free_data_file(struct data_file *df) for (i = 0; i < ARRAY_SIZE(df->df_segments); i++) data_file_segment_destroy(&df->df_segments[i]); incfs_free_bfc(df->df_backing_file_context); + kfree(df->df_signature); kfree(df); } @@ -387,8 +388,8 @@ static void log_block_read(struct mount_info *mi, incfs_uuid_t *id, schedule_delayed_work(&log->ml_wakeup_work, msecs_to_jiffies(16)); } -static int validate_hash_tree(struct file *bf, struct file *f, int block_index, - struct mem_range data, u8 *buf) +static int validate_hash_tree(struct backing_file_context *bfc, struct file *f, + int block_index, struct mem_range data, u8 *buf) { struct data_file *df = get_incfs_data_file(f); u8 stored_digest[INCFS_MAX_HASH_SIZE] = {}; @@ -445,7 +446,7 @@ static int validate_hash_tree(struct file *bf, struct file *f, int block_index, if (page) put_page(page); - res = incfs_kread(bf, buf, INCFS_DATA_FILE_BLOCK_SIZE, + res = incfs_kread(bfc, buf, INCFS_DATA_FILE_BLOCK_SIZE, hash_block_offset[lvl] + sig->hash_offset); if (res < 0) return res; @@ -918,7 +919,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, ssize_t result; size_t bytes_to_read; struct mount_info *mi = NULL; - struct file *bf = NULL; + struct backing_file_context *bfc = NULL; struct data_file_block block = {}; struct data_file *df = get_incfs_data_file(f); @@ -929,7 +930,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, return -ERANGE; mi = df->df_mount_info; - bf = df->df_backing_file_context->bc_file; + bfc = df->df_backing_file_context; result = wait_for_data_block(df, index, timeout_ms, &block); if (result < 0) @@ -938,20 +939,20 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, pos = block.db_backing_file_data_offset; if (block.db_comp_alg == COMPRESSION_NONE) { bytes_to_read = min(dst.len, block.db_stored_size); - result = incfs_kread(bf, dst.data, bytes_to_read, pos); + result = incfs_kread(bfc, dst.data, bytes_to_read, pos); /* Some data was read, but not enough */ if (result >= 0 && result != bytes_to_read) result = -EIO; } else { bytes_to_read = min(tmp.len, block.db_stored_size); - result = incfs_kread(bf, tmp.data, bytes_to_read, pos); + result = incfs_kread(bfc, tmp.data, bytes_to_read, pos); if (result == bytes_to_read) { result = decompress(range(tmp.data, bytes_to_read), dst); if (result < 0) { const char *name = - bf->f_path.dentry->d_name.name; + bfc->bc_file->f_path.dentry->d_name.name; pr_warn_once("incfs: Decompression error. %s", name); @@ -963,7 +964,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, } if (result > 0) { - int err = validate_hash_tree(bf, f, index, dst, tmp.data); + int err = validate_hash_tree(bfc, f, index, dst, tmp.data); if (err < 0) result = err; @@ -1026,14 +1027,13 @@ int incfs_process_new_data_block(struct data_file *df, unlock: mutex_unlock(&segment->blockmap_mutex); if (error) - pr_debug("incfs: %s %d error: %d\n", __func__, - block->block_index, error); + pr_debug("%d error: %d\n", block->block_index, error); return error; } int incfs_read_file_signature(struct data_file *df, struct mem_range dst) { - struct file *bf = df->df_backing_file_context->bc_file; + struct backing_file_context *bfc = df->df_backing_file_context; struct incfs_df_signature *sig; int read_res = 0; @@ -1047,7 +1047,7 @@ int incfs_read_file_signature(struct data_file *df, struct mem_range dst) if (dst.len < sig->sig_size) return -E2BIG; - read_res = incfs_kread(bf, dst.data, sig->sig_size, sig->sig_offset); + read_res = incfs_kread(bfc, dst.data, sig->sig_size, sig->sig_offset); if (read_res < 0) return read_res; @@ -1173,7 +1173,7 @@ static int process_file_signature_md(struct incfs_file_signature *sg, goto out; } - read = incfs_kread(df->df_backing_file_context->bc_file, buf, + read = incfs_kread(df->df_backing_file_context, buf, signature->sig_size, signature->sig_offset); if (read < 0) { error = read; diff --git a/fs/incfs/format.c b/fs/incfs/format.c index c56e559b6893..d326415fc6de 100644 --- a/fs/incfs/format.c +++ b/fs/incfs/format.c @@ -15,7 +15,8 @@ #include "format.h" #include "data_mgmt.h" -struct backing_file_context *incfs_alloc_bfc(struct file *backing_file) +struct backing_file_context *incfs_alloc_bfc(struct mount_info *mi, + struct file *backing_file) { struct backing_file_context *result = NULL; @@ -24,6 +25,7 @@ struct backing_file_context *incfs_alloc_bfc(struct file *backing_file) return ERR_PTR(-ENOMEM); result->bc_file = get_file(backing_file); + result->bc_cred = mi->mi_owner; mutex_init(&result->bc_mutex); return result; } @@ -116,7 +118,7 @@ static int append_zeros(struct backing_file_context *bfc, size_t len) static int write_to_bf(struct backing_file_context *bfc, const void *buf, size_t count, loff_t pos) { - ssize_t res = incfs_kwrite(bfc->bc_file, buf, count, pos); + ssize_t res = incfs_kwrite(bfc, buf, count, pos); if (res < 0) return res; @@ -531,8 +533,7 @@ int incfs_read_blockmap_entries(struct backing_file_context *bfc, if (start_index < 0 || bm_base_off <= 0) return -ENODATA; - result = incfs_kread(bfc->bc_file, entries, bytes_to_read, - bm_entry_off); + result = incfs_kread(bfc, entries, bytes_to_read, bm_entry_off); if (result < 0) return result; return result / sizeof(*entries); @@ -548,8 +549,7 @@ int incfs_read_file_header(struct backing_file_context *bfc, if (!bfc || !first_md_off) return -EFAULT; - LOCK_REQUIRED(bfc->bc_mutex); - bytes_read = incfs_kread(bfc->bc_file, &fh, sizeof(fh), 0); + bytes_read = incfs_kread(bfc, &fh, sizeof(fh), 0); if (bytes_read < 0) return bytes_read; @@ -603,8 +603,8 @@ int incfs_read_next_metadata_record(struct backing_file_context *bfc, return -EPERM; memset(&handler->md_buffer, 0, max_md_size); - bytes_read = incfs_kread(bfc->bc_file, &handler->md_buffer, - max_md_size, handler->md_record_offset); + bytes_read = incfs_kread(bfc, &handler->md_buffer, max_md_size, + handler->md_record_offset); if (bytes_read < 0) return bytes_read; if (bytes_read < sizeof(*md_hdr)) @@ -680,12 +680,22 @@ int incfs_read_next_metadata_record(struct backing_file_context *bfc, return res; } -ssize_t incfs_kread(struct file *f, void *buf, size_t size, loff_t pos) +ssize_t incfs_kread(struct backing_file_context *bfc, void *buf, size_t size, + loff_t pos) { - return kernel_read(f, buf, size, &pos); + const struct cred *old_cred = override_creds(bfc->bc_cred); + int ret = kernel_read(bfc->bc_file, buf, size, &pos); + + revert_creds(old_cred); + return ret; } -ssize_t incfs_kwrite(struct file *f, const void *buf, size_t size, loff_t pos) +ssize_t incfs_kwrite(struct backing_file_context *bfc, const void *buf, + size_t size, loff_t pos) { - return kernel_write(f, buf, size, &pos); + const struct cred *old_cred = override_creds(bfc->bc_cred); + int ret = kernel_write(bfc->bc_file, buf, size, &pos); + + revert_creds(old_cred); + return ret; } diff --git a/fs/incfs/format.h b/fs/incfs/format.h index 1a83349bb2eb..a6d3aef6b358 100644 --- a/fs/incfs/format.h +++ b/fs/incfs/format.h @@ -256,6 +256,13 @@ struct backing_file_context { * 0 means there are no metadata records. */ loff_t bc_last_md_record_offset; + + /* + * Credentials to set before reads/writes + * Note that this is a pointer to the mount_info mi_owner field so + * there is no need to get/put the creds + */ + const struct cred *bc_cred; }; struct metadata_handler { @@ -283,7 +290,9 @@ struct metadata_handler { loff_t incfs_get_end_offset(struct file *f); /* Backing file context management */ -struct backing_file_context *incfs_alloc_bfc(struct file *backing_file); +struct mount_info; +struct backing_file_context *incfs_alloc_bfc(struct mount_info *mi, + struct file *backing_file); void incfs_free_bfc(struct backing_file_context *bfc); @@ -334,7 +343,9 @@ int incfs_read_blockmap_entries(struct backing_file_context *bfc, int incfs_read_next_metadata_record(struct backing_file_context *bfc, struct metadata_handler *handler); -ssize_t incfs_kread(struct file *f, void *buf, size_t size, loff_t pos); -ssize_t incfs_kwrite(struct file *f, const void *buf, size_t size, loff_t pos); +ssize_t incfs_kread(struct backing_file_context *bfc, void *buf, size_t size, + loff_t pos); +ssize_t incfs_kwrite(struct backing_file_context *bfc, const void *buf, + size_t size, loff_t pos); #endif /* _INCFS_FORMAT_H */ diff --git a/fs/incfs/main.c b/fs/incfs/main.c index 7c4ec4fa13d8..0fde230d5337 100644 --- a/fs/incfs/main.c +++ b/fs/incfs/main.c @@ -30,8 +30,18 @@ static ssize_t corefs_show(struct kobject *kobj, static struct kobj_attribute corefs_attr = __ATTR_RO(corefs); +static ssize_t mounter_context_for_backing_rw_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buff) +{ + return snprintf(buff, PAGE_SIZE, "supported\n"); +} + +static struct kobj_attribute mounter_context_for_backing_rw_attr = + __ATTR_RO(mounter_context_for_backing_rw); + static struct attribute *attributes[] = { &corefs_attr.attr, + &mounter_context_for_backing_rw_attr.attr, NULL, }; diff --git a/fs/incfs/vfs.c b/fs/incfs/vfs.c index 582448ccdaef..d7a750290953 100644 --- a/fs/incfs/vfs.c +++ b/fs/incfs/vfs.c @@ -898,14 +898,14 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry, .dentry = dentry }; new_file = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE, - mi->mi_owner); + current_cred()); if (IS_ERR(new_file)) { error = PTR_ERR(new_file); goto out; } - bfc = incfs_alloc_bfc(new_file); + bfc = incfs_alloc_bfc(mi, new_file); fput(new_file); if (IS_ERR(bfc)) { error = PTR_ERR(bfc); @@ -1026,7 +1026,7 @@ static int dir_relative_path_resolve( if (dir_fd < 0) return dir_fd; - dir_f = dentry_open(base_path, O_RDONLY | O_NOATIME, mi->mi_owner); + dir_f = dentry_open(base_path, O_RDONLY | O_NOATIME, current_cred()); if (IS_ERR(dir_f)) { error = PTR_ERR(dir_f); @@ -1904,10 +1904,13 @@ static int file_open(struct inode *inode, struct file *file) struct file *backing_file = NULL; struct path backing_path = {}; int err = 0; + const struct cred *old_cred; get_incfs_backing_path(file->f_path.dentry, &backing_path); - backing_file = dentry_open( - &backing_path, O_RDWR | O_NOATIME | O_LARGEFILE, mi->mi_owner); + old_cred = override_creds(mi->mi_owner); + backing_file = dentry_open(&backing_path, + O_RDWR | O_NOATIME | O_LARGEFILE, current_cred()); + revert_creds(old_cred); path_put(&backing_path); if (IS_ERR(backing_file)) { From dd2e0a80f1bea3d0ac99df4b3256682e4324df5f Mon Sep 17 00:00:00 2001 From: Jilai Wang Date: Fri, 23 Apr 2021 16:55:03 -0400 Subject: [PATCH 06/67] ANDROID: ABI: Update allowed list for QCOM Add the following symbols to QCOM allowed-list: -- bitmap_release_region -- bitmap_find_free_region Bug: 186222705 Change-Id: I6dc24587c6e7db35ecac16e6e68d889f79e7dae6 Signed-off-by: Jilai Wang --- android/abi_gki_aarch64.xml | 1140 +++++++++++++++++----------------- android/abi_gki_aarch64_qcom | 2 + 2 files changed, 572 insertions(+), 570 deletions(-) diff --git a/android/abi_gki_aarch64.xml b/android/abi_gki_aarch64.xml index c3d6fb4f3c40..c8cf7150a78c 100644 --- a/android/abi_gki_aarch64.xml +++ b/android/abi_gki_aarch64.xml @@ -8154,7 +8154,7 @@ - + @@ -11062,7 +11062,7 @@ - + @@ -20411,7 +20411,7 @@ - + @@ -23284,7 +23284,7 @@ - + @@ -23303,7 +23303,7 @@ - + @@ -23580,7 +23580,7 @@ - + @@ -23648,7 +23648,7 @@ - + @@ -23656,7 +23656,7 @@ - + @@ -25859,7 +25859,7 @@ - + @@ -26238,7 +26238,7 @@ - + @@ -26262,7 +26262,7 @@ - + @@ -26270,7 +26270,7 @@ - + @@ -26289,7 +26289,7 @@ - + @@ -26305,7 +26305,7 @@ - + @@ -26332,7 +26332,7 @@ - + @@ -26343,7 +26343,7 @@ - + @@ -28161,7 +28161,7 @@ - + @@ -28169,7 +28169,7 @@ - + @@ -28214,7 +28214,7 @@ - + @@ -28563,7 +28563,7 @@ - + @@ -30967,7 +30967,7 @@ - + @@ -31207,7 +31207,7 @@ - + @@ -31215,7 +31215,7 @@ - + @@ -31223,7 +31223,7 @@ - + @@ -31953,7 +31953,7 @@ - + @@ -32503,7 +32503,7 @@ - + @@ -32765,7 +32765,7 @@ - + @@ -51512,44 +51512,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -51850,6 +51812,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -108282,7 +108282,7 @@ - + @@ -108656,7 +108656,7 @@ - + @@ -108664,7 +108664,7 @@ - + @@ -108672,7 +108672,7 @@ - + @@ -108680,12 +108680,12 @@ - + - + @@ -111863,7 +111863,7 @@ - + @@ -111872,7 +111872,7 @@ - + @@ -111880,7 +111880,7 @@ - + @@ -111888,7 +111888,7 @@ - + @@ -111897,7 +111897,7 @@ - + @@ -111905,7 +111905,7 @@ - + @@ -112185,7 +112185,7 @@ - + @@ -112207,7 +112207,7 @@ - + @@ -112218,7 +112218,7 @@ - + @@ -112226,7 +112226,7 @@ - + @@ -112237,7 +112237,7 @@ - + @@ -112249,7 +112249,7 @@ - + @@ -112260,7 +112260,7 @@ - + @@ -112509,7 +112509,7 @@ - + @@ -112539,7 +112539,7 @@ - + @@ -112547,7 +112547,7 @@ - + @@ -112699,7 +112699,7 @@ - + @@ -112975,7 +112975,7 @@ - + @@ -113020,7 +113020,7 @@ - + @@ -113227,7 +113227,7 @@ - + @@ -113316,7 +113316,7 @@ - + @@ -113324,7 +113324,7 @@ - + @@ -113332,7 +113332,7 @@ - + @@ -113340,7 +113340,7 @@ - + @@ -113410,7 +113410,205 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -113598,7 +113796,7 @@ - + @@ -113677,7 +113875,7 @@ - + @@ -113726,7 +113924,7 @@ - + @@ -113902,204 +114100,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -114215,7 +114215,7 @@ - + @@ -114226,7 +114226,7 @@ - + @@ -114234,7 +114234,7 @@ - + @@ -114684,7 +114684,7 @@ - + @@ -165761,9 +165761,209 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -165899,7 +166099,18 @@ + + + + + + + + + + + @@ -166088,6 +166299,13 @@ + + + + + + + @@ -166095,6 +166313,10 @@ + + + + @@ -167614,7 +167836,7 @@ - + @@ -167622,7 +167844,7 @@ - + @@ -167630,7 +167852,7 @@ - + @@ -170267,7 +170489,7 @@ - + @@ -175900,9 +176122,15 @@ + + + + + + @@ -175956,7 +176184,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -176164,12 +176427,6 @@ - - - - - - @@ -176240,7 +176497,7 @@ - + @@ -176324,38 +176581,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -176370,7 +176595,7 @@ - + @@ -176432,9 +176657,6 @@ - - - @@ -177012,218 +177234,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -177307,17 +177318,6 @@ - - - - - - - - - - - diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 930a3de22c5a..d706370b2b5c 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -45,10 +45,12 @@ backlight_device_unregister bin2hex __bitmap_clear + bitmap_find_free_region bitmap_find_next_zero_area_off bitmap_free bitmap_parselist bitmap_print_to_pagebuf + bitmap_release_region __bitmap_set __bitmap_subset bitmap_zalloc From ff320df3e0e9915797a3e762f1cbfc0b034c1a9b Mon Sep 17 00:00:00 2001 From: Giuliano Procida Date: Thu, 22 Apr 2021 14:31:03 +0100 Subject: [PATCH 07/67] ANDROID: power: export pm_system_cancel_wakeup This symbol is needed by a QCOM driver. Bug: 186084429 Change-Id: I8001f14a6fded9b58a6dfba424dfa6ebb83543a5 Signed-off-by: Venkata Kakani Signed-off-by: Giuliano Procida --- drivers/base/power/wakeup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 911f1e85d44c..ffda3dad256a 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -922,6 +922,7 @@ void pm_system_cancel_wakeup(void) { atomic_dec_if_positive(&pm_abort_suspend); } +EXPORT_SYMBOL_GPL(pm_system_cancel_wakeup); void pm_wakeup_clear(bool reset) { From c8cd528e75550ac739bb0b774b9f84a895f20f4e Mon Sep 17 00:00:00 2001 From: Giuliano Procida Date: Thu, 22 Apr 2021 14:31:03 +0100 Subject: [PATCH 08/67] ANDROID: ABI: add pm_system_cancel_wakeup symbol Leaf changes summary: 1 artifact changed Changed leaf types summary: 0 leaf type changed Removed/Changed/Added functions summary: 0 Removed, 0 Changed, 1 Added function Removed/Changed/Added variables summary: 0 Removed, 0 Changed, 0 Added variable 1 Added function: [A] 'function void pm_system_cancel_wakeup()' Bug: 186084429 Change-Id: I5ec59917cb2a128b9d0605dd8b3cb8fa7e020af2 Signed-off-by: Venkata Kakani Signed-off-by: Giuliano Procida --- android/abi_gki_aarch64.xml | 518 ++++++++++++++++------------------- android/abi_gki_aarch64_qcom | 1 + 2 files changed, 237 insertions(+), 282 deletions(-) diff --git a/android/abi_gki_aarch64.xml b/android/abi_gki_aarch64.xml index c8cf7150a78c..ced999ef6ac8 100644 --- a/android/abi_gki_aarch64.xml +++ b/android/abi_gki_aarch64.xml @@ -3168,6 +3168,7 @@ + @@ -30028,7 +30029,7 @@ - + @@ -30763,20 +30764,7 @@ - - - - - - - - - - - - - - + @@ -31952,7 +31940,6 @@ - @@ -31964,7 +31951,7 @@ - + @@ -32330,17 +32317,6 @@ - - - - - - - - - - - @@ -32427,7 +32403,7 @@ - + @@ -58527,6 +58503,9 @@ + + + @@ -111594,20 +111573,7 @@ - - - - - - - - - - - - - - + @@ -165761,209 +165727,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -166099,18 +165865,7 @@ - - - - - - - - - - - @@ -166299,13 +166054,6 @@ - - - - - - - @@ -166313,10 +166061,6 @@ - - - - @@ -167182,18 +166926,6 @@ - - - - - - - - - - - - @@ -174208,7 +173940,7 @@ - + @@ -177234,7 +176966,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -177318,6 +177261,17 @@ + + + + + + + + + + + @@ -178752,7 +178706,7 @@ - + @@ -178781,7 +178735,7 @@ - + @@ -179373,7 +179327,7 @@ - + @@ -180333,7 +180287,7 @@ - + diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index d706370b2b5c..13187bc671f8 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -1804,6 +1804,7 @@ __pm_runtime_use_autosuspend __pm_stay_awake pm_stay_awake + pm_system_cancel_wakeup pm_system_wakeup pm_wakeup_dev_event pm_wakeup_ws_event From 48ffcbf0b9e7f0280bfb8c32c68da0aaf0fdfef6 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 25 Apr 2021 15:24:07 +0900 Subject: [PATCH 09/67] FROMGIT: kbuild: update config_data.gz only when the content of .config is changed If the timestamp of the .config file is updated, config_data.gz is regenerated, then vmlinux is re-linked. This occurs even if the content of the .config has not changed at all. This issue was mitigated by commit 67424f61f813 ("kconfig: do not write .config if the content is the same"); Kconfig does not update the .config when it ends up with the identical configuration. The issue is remaining when the .config is created by *_defconfig with some config fragment(s) applied on top. This is typical for powerpc and mips, where several *_defconfig targets are constructed by using merge_config.sh. One workaround is to have the copy of the .config. The filechk rule updates the copy, kernel/config_data, by checking the content instead of the timestamp. With this commit, the second run with the same configuration avoids the needless rebuilds. $ make ARCH=mips defconfig all [ snip ] $ make ARCH=mips defconfig all *** Default configuration is based on target '32r2el_defconfig' Using ./arch/mips/configs/generic_defconfig as base Merging arch/mips/configs/generic/32r2.config Merging arch/mips/configs/generic/el.config Merging ./arch/mips/configs/generic/board-boston.config Merging ./arch/mips/configs/generic/board-ni169445.config Merging ./arch/mips/configs/generic/board-ocelot.config Merging ./arch/mips/configs/generic/board-ranchu.config Merging ./arch/mips/configs/generic/board-sead-3.config Merging ./arch/mips/configs/generic/board-xilfpga.config # # configuration written to .config # SYNC include/config/auto.conf CALL scripts/checksyscalls.sh CALL scripts/atomic/check-atomics.sh CHK include/generated/compile.h CHK include/generated/autoksyms.h Reported-by: Elliot Berman Signed-off-by: Masahiro Yamada Bug: 179648610 (cherry picked from commit b33976d90d1ea7652fff662dcc2234f352346a33 https://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git kbuild) [eberman: Fixed minor conflicts in kernel/.gitignore] Change-Id: I8c93147c8d5a48d0f5e9abf855870b10c1a24efc Signed-off-by: Elliot Berman --- kernel/.gitignore | 1 + kernel/Makefile | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/.gitignore b/kernel/.gitignore index 34d1e77ee9df..16670321c138 100644 --- a/kernel/.gitignore +++ b/kernel/.gitignore @@ -1,6 +1,7 @@ # # Generated files # +config_data kheaders.md5 timeconst.h hz.bc diff --git a/kernel/Makefile b/kernel/Makefile index 08652a850458..9e02af6edfd3 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -128,10 +128,15 @@ KCOV_INSTRUMENT_stackleak.o := n $(obj)/configs.o: $(obj)/config_data.gz -targets += config_data.gz -$(obj)/config_data.gz: $(KCONFIG_CONFIG) FORCE +targets += config_data config_data.gz +$(obj)/config_data.gz: $(obj)/config_data FORCE $(call if_changed,gzip) +filechk_cat = cat $< + +$(obj)/config_data: $(KCONFIG_CONFIG) FORCE + $(call filechk,cat) + $(obj)/kheaders.o: $(obj)/kheaders_data.tar.xz quiet_cmd_genikh = CHK $(obj)/kheaders_data.tar.xz From 305c5f54869e206c5e82e8b8461e6779dd71e245 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 22 Apr 2020 02:01:54 +0000 Subject: [PATCH 10/67] UPSTREAM: mac80211_hwsim: use GFP_ATOMIC under spin lock A spin lock is taken here so we should use GFP_ATOMIC. Fixes: 5d44fe7c9808 ("mac80211_hwsim: add frame transmission support over virtio") Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20200422020154.112088-1-weiyongjun1@huawei.com Signed-off-by: Johannes Berg (cherry picked from commit 0379861217dc2dd46e3bc517010060065b0dd6fc) Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: I16c7f59f3e695ac6a6ffaa25217e3d7309827dca --- drivers/net/wireless/mac80211_hwsim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index a9fc831eba60..bc4618ae9c5f 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -4041,7 +4041,7 @@ static void hwsim_virtio_rx_work(struct work_struct *work) } vq = hwsim_vqs[HWSIM_VQ_RX]; sg_init_one(sg, skb->head, skb_end_offset(skb)); - err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_KERNEL); + err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_ATOMIC); if (WARN(err, "virtqueue_add_inbuf returned %d\n", err)) nlmsg_free(skb); else From 7db1c96c2d149e94e2380240364086a15a7c41e7 Mon Sep 17 00:00:00 2001 From: Alexander Lobakin Date: Wed, 17 Jun 2020 20:42:47 +0000 Subject: [PATCH 11/67] BACKPORT: net: ethtool: add missing NETIF_F_GSO_FRAGLIST feature string Commit 3b33583265ed ("net: Add fraglist GRO/GSO feature flags") missed an entry for NETIF_F_GSO_FRAGLIST in netdev_features_strings array. As a result, fraglist GSO feature is not shown in 'ethtool -k' output and can't be toggled on/off. The fix is trivial. Fixes: 3b33583265ed ("net: Add fraglist GRO/GSO feature flags") Signed-off-by: Alexander Lobakin Reviewed-by: Michal Kubecek Signed-off-by: David S. Miller (cherry picked from commit eddbf5d0204e550ee59de02bdc19fe90d4203dd6) [netdev_features_strings is in net/core/ethtool.c on this branch, so apply the change there] Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: I20b389538ac02fc63cf8fa59dfb9010296237056 --- net/core/ethtool.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index cd9bc67381b2..99ce0ccc66df 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -92,6 +92,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] [NETIF_F_GSO_SCTP_BIT] = "tx-sctp-segmentation", [NETIF_F_GSO_ESP_BIT] = "tx-esp-segmentation", [NETIF_F_GSO_UDP_L4_BIT] = "tx-udp-segmentation", + [NETIF_F_GSO_FRAGLIST_BIT] = "tx-gso-list", [NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc", [NETIF_F_SCTP_CRC_BIT] = "tx-checksum-sctp", From dee5558ec9dba4e38cf529db80c38a0e8e5f4da1 Mon Sep 17 00:00:00 2001 From: Yu Kuai Date: Tue, 10 Nov 2020 09:14:43 +0800 Subject: [PATCH 12/67] UPSTREAM: net: xfrm: fix memory leak in xfrm_user_policy() if xfrm_get_translator() failed, xfrm_user_policy() return without freeing 'data', which is allocated in memdup_sockptr(). Fixes: 96392ee5a13b ("xfrm/compat: Translate 32-bit user_policy from sockptr") Reported-by: Hulk Robot Signed-off-by: Yu Kuai Signed-off-by: Steffen Klassert (cherry picked from commit 48f486e13ffdb49fbb9b38c21d0e108ed60ab1a2) Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: If018bce68d0d23491f1c47299443f7011dce3e89 --- net/xfrm/xfrm_state.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 83a8cbf2a37a..8bb052bb137e 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -2381,8 +2381,10 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen if (in_compat_syscall()) { struct xfrm_translator *xtr = xfrm_get_translator(); - if (!xtr) + if (!xtr) { + kfree(data); return -EOPNOTSUPP; + } err = xtr->xlate_user_policy_sockptr(&data, optlen); xfrm_put_translator(xtr); From a9cedd30326a0fd7f7df3f4572f1132e67ad3447 Mon Sep 17 00:00:00 2001 From: Pujin Shi Date: Fri, 2 Oct 2020 14:35:38 +0800 Subject: [PATCH 13/67] BACKPORT: scsi: ufs: Fix missing brace warning for old compilers For older versions of gcc, the array = {0}; will cause warnings: drivers/scsi/ufs/ufshcd-crypto.c: In function 'ufshcd_crypto_keyslot_program': drivers/scsi/ufs/ufshcd-crypto.c:62:8: warning: missing braces around initializer [-Wmissing-braces] union ufs_crypto_cfg_entry cfg = { 0 }; ^ drivers/scsi/ufs/ufshcd-crypto.c:62:8: warning: (near initialization for 'cfg.reg_val') [-Wmissing-braces] drivers/scsi/ufs/ufshcd-crypto.c: In function 'ufshcd_clear_keyslot': drivers/scsi/ufs/ufshcd-crypto.c:103:8: warning: missing braces around initializer [-Wmissing-braces] union ufs_crypto_cfg_entry cfg = { 0 }; ^ 2 warnings generated Link: https://lore.kernel.org/r/20201002063538.1250-1-shipujin.t@gmail.com Fixes: 70297a8ac7a7 ("scsi: ufs: UFS crypto API") Reviewed-by: Eric Biggers Signed-off-by: Pujin Shi Signed-off-by: Martin K. Petersen (cherry picked from commit 6500251e590657066a227dce897a0392f302af24) [drop non-applicable change to ufshcd_crypto_keyslot_program] Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: I06c4eacc036cc5e9d80217a986cfe9427fb6e255 --- drivers/scsi/ufs/ufshcd-crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufshcd-crypto.c b/drivers/scsi/ufs/ufshcd-crypto.c index 43d105bc0e26..f667a946c740 100644 --- a/drivers/scsi/ufs/ufshcd-crypto.c +++ b/drivers/scsi/ufs/ufshcd-crypto.c @@ -159,7 +159,7 @@ out: static void ufshcd_clear_keyslot(struct ufs_hba *hba, int slot) { - union ufs_crypto_cfg_entry cfg = { 0 }; + union ufs_crypto_cfg_entry cfg = {}; int err; err = ufshcd_program_key(hba, &cfg, slot); From ee97d20c7e334274dd5d4d11dc1b85c26d7a5132 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Mon, 2 Nov 2020 16:14:47 +0000 Subject: [PATCH 14/67] UPSTREAM: xfrm/compat: Don't allocate memory with __GFP_ZERO 32-bit to 64-bit messages translator zerofies needed paddings in the translation, the rest is the actual payload. Don't allocate zero pages as they are not needed. Fixes: 5106f4a8acff ("xfrm/compat: Add 32=>64-bit messages translator") Signed-off-by: Dmitry Safonov Signed-off-by: Steffen Klassert (cherry picked from commit ad37f77fd3659e87fd9833a83692e0e4eba0f5cd) Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: Icefe6cd5ed03975f0f87cc1b126cfe55b36c35e5 --- net/xfrm/xfrm_compat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/xfrm/xfrm_compat.c b/net/xfrm/xfrm_compat.c index c1dee0696dfb..0e7476e05f3a 100644 --- a/net/xfrm/xfrm_compat.c +++ b/net/xfrm/xfrm_compat.c @@ -563,7 +563,7 @@ static struct nlmsghdr *xfrm_user_rcv_msg_compat(const struct nlmsghdr *h32, return NULL; len += NLMSG_HDRLEN; - h64 = kvmalloc(len, GFP_KERNEL | __GFP_ZERO); + h64 = kvmalloc(len, GFP_KERNEL); if (!h64) return ERR_PTR(-ENOMEM); From 957e971ed90cacdfdfc13c8a6e0def199735d9cb Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Mon, 2 Nov 2020 16:14:46 +0000 Subject: [PATCH 15/67] UPSTREAM: xfrm/compat: memset(0) 64-bit padding at right place 32-bit messages translated by xfrm_compat can have attributes attached. For all, but XFRMA_SA, XFRMA_POLICY the size of payload is the same in 32-bit UABI and 64-bit UABI. For XFRMA_SA (struct xfrm_usersa_info) and XFRMA_POLICY (struct xfrm_userpolicy_info) it's only tail-padding that is present in 64-bit payload, but not in 32-bit. The proper size for destination nlattr is already calculated by xfrm_user_rcv_calculate_len64() and allocated with kvmalloc(). xfrm_attr_cpy32() copies 32-bit copy_len into 64-bit attribute translated payload, zero-filling possible padding for SA/POLICY. Due to a typo, *pos already has 64-bit payload size, in a result next memset(0) is called on the memory after the translated attribute, not on the tail-padding of it. Fixes: 5106f4a8acff ("xfrm/compat: Add 32=>64-bit messages translator") Reported-by: syzbot+c43831072e7df506a646@syzkaller.appspotmail.com Signed-off-by: Dmitry Safonov Signed-off-by: Steffen Klassert (cherry picked from commit d1949d045fd67eab8a32a579a8c1ab1681330854) Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: Ic81e020da215c3fd093a76dc687abf5f86827283 --- net/xfrm/xfrm_compat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/xfrm/xfrm_compat.c b/net/xfrm/xfrm_compat.c index 0e7476e05f3a..48cbece14430 100644 --- a/net/xfrm/xfrm_compat.c +++ b/net/xfrm/xfrm_compat.c @@ -387,7 +387,7 @@ static int xfrm_attr_cpy32(void *dst, size_t *pos, const struct nlattr *src, memcpy(nla, src, nla_attr_size(copy_len)); nla->nla_len = nla_attr_size(payload); - *pos += nla_attr_size(payload); + *pos += nla_attr_size(copy_len); nlmsg->nlmsg_len += nla->nla_len; memset(dst + *pos, 0, payload - copy_len); From e6d3c97bac2566df51b64c4e07a02e3e18238c34 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Mon, 2 Nov 2020 16:14:45 +0000 Subject: [PATCH 16/67] UPSTREAM: xfrm/compat: Translate by copying XFRMA_UNSPEC attribute xfrm_xlate32() translates 64-bit message provided by kernel to be sent for 32-bit listener (acknowledge or monitor). Translator code doesn't expect XFRMA_UNSPEC attribute as it doesn't know its payload. Kernel never attaches such attribute, but a user can. I've searched if any opensource does it and the answer is no. Nothing on github and google finds only tfcproject that has such code commented-out. What will happen if a user sends a netlink message with XFRMA_UNSPEC attribute? Ipsec code ignores this attribute. But if there is a monitor-process or 32-bit user requested ack - kernel will try to translate such message and will hit WARN_ONCE() in xfrm_xlate64_attr(). Deal with XFRMA_UNSPEC by copying the attribute payload with xfrm_nla_cpy(). In result, the default switch-case in xfrm_xlate64_attr() becomes an unused code. Leave those 3 lines in case a new xfrm attribute will be added. Fixes: 5461fc0c8d9f ("xfrm/compat: Add 64=>32-bit messages translator") Reported-by: syzbot+a7e701c8385bd8543074@syzkaller.appspotmail.com Signed-off-by: Dmitry Safonov Signed-off-by: Steffen Klassert (cherry picked from commit dbd7ae5154d5fff7e84a9f3010bb06499017ef29) Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: I11e05ca491155a1dd28f8820ded7ada096595075 --- net/xfrm/xfrm_compat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/xfrm/xfrm_compat.c b/net/xfrm/xfrm_compat.c index 48cbece14430..aacbf250a25e 100644 --- a/net/xfrm/xfrm_compat.c +++ b/net/xfrm/xfrm_compat.c @@ -234,6 +234,7 @@ static int xfrm_xlate64_attr(struct sk_buff *dst, const struct nlattr *src) case XFRMA_PAD: /* Ignore */ return 0; + case XFRMA_UNSPEC: case XFRMA_ALG_AUTH: case XFRMA_ALG_CRYPT: case XFRMA_ALG_COMP: From 3f54d632a6049753185ea19a0200fb4e0eed3a43 Mon Sep 17 00:00:00 2001 From: Qinglang Miao Date: Tue, 10 Nov 2020 15:42:23 +0800 Subject: [PATCH 17/67] UPSTREAM: scsi: ufshcd: Fix missing destroy_workqueue() Add the missing destroy_workqueue() before return from ufshcd_init in the error handling case as well as in ufshcd_remove. Link: https://lore.kernel.org/r/20201110074223.41280-1-miaoqinglang@huawei.com Fixes: 4db7a2360597 ("scsi: ufs: Fix concurrency of error handler and other error recovery paths") Suggested-by: Avri Altman Reviewed-by: Asutosh Das Reviewed-by: Avri Altman Signed-off-by: Qinglang Miao Signed-off-by: Martin K. Petersen (cherry picked from commit 2e6f11a797a24d1e2141a214a6dd6dfbe709f55d) Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: I2db2a6c6fb22b1e780ec7e167940d7104aaae267 --- drivers/scsi/ufs/ufshcd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 88ea198697eb..4c12b3d3c9f4 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -9025,6 +9025,7 @@ void ufshcd_remove(struct ufs_hba *hba) ufs_bsg_remove(hba); ufs_sysfs_remove_nodes(hba->dev); scsi_remove_host(hba->host); + destroy_workqueue(hba->eh_wq); /* disable interrupts */ ufshcd_disable_intr(hba, hba->intr_mask); ufshcd_hba_stop(hba, true); @@ -9296,6 +9297,7 @@ out_remove_scsi_host: exit_gating: ufshcd_exit_clk_scaling(hba); ufshcd_exit_clk_gating(hba); + destroy_workqueue(hba->eh_wq); out_disable: hba->is_irq_enabled = false; ufshcd_hba_exit(hba); From be192b51bfdfb7bd223e7ca3354eb91641cc75cc Mon Sep 17 00:00:00 2001 From: Vincent Guittot Date: Thu, 29 Oct 2020 17:18:24 +0100 Subject: [PATCH 18/67] UPSTREAM: sched/fair: Prefer prev cpu in asymmetric wakeup path During fast wakeup path, scheduler always check whether local or prev cpus are good candidates for the task before looking for other cpus in the domain. With commit b7a331615d25 ("sched/fair: Add asymmetric CPU capacity wakeup scan") the heterogenous system gains a dedicated path but doesn't try to reuse prev cpu whenever possible. If the previous cpu is idle and belong to the LLC domain, we should check it 1st before looking for another cpu because it stays one of the best candidate and this also stabilizes task placement on the system. This change aligns asymmetric path behavior with symmetric one and reduces cases where the task migrates across all cpus of the sd_asym_cpucapacity domains at wakeup. This change does not impact normal EAS mode but only the overloaded case or when EAS is not used. - On hikey960 with performance governor (EAS disable) ./perf bench sched pipe -T -l 50000 mainline w/ patch ops/sec 149313(+/-0.28%) 182587(+/- 0.40) +22% - On hikey with performance governor ./perf bench sched pipe -T -l 50000 mainline w/ patch ops/sec 47721(+/-0.76%) 47899(+/- 0.56) +0.4% According to test on hikey, the patch doesn't impact symmetric system compared to current implementation (only tested on arm64) Also read the uclamped value of task's utilization at most twice instead instead each time we compare task's utilization with cpu's capacity. Fixes: b7a331615d25 ("sched/fair: Add asymmetric CPU capacity wakeup scan") Signed-off-by: Vincent Guittot Signed-off-by: Peter Zijlstra (Intel) Tested-by: Dietmar Eggemann Reviewed-by: Valentin Schneider Link: https://lkml.kernel.org/r/20201029161824.26389-1-vincent.guittot@linaro.org (cherry picked from commit b4c9c9f15649c98a5b45408919d1ff4fd7f5531c) Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: Icaba6ae29d5bd23f87ca5492b778869be9e0d9c9 --- kernel/sched/fair.c | 89 +++++++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index c319f4fac43e..ec1fccef1484 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -6085,21 +6085,21 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, int t static int select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target) { - unsigned long best_cap = 0; + unsigned long task_util, best_cap = 0; int cpu, best_cpu = -1; struct cpumask *cpus; - sync_entity_load_avg(&p->se); - cpus = this_cpu_cpumask_var_ptr(select_idle_mask); cpumask_and(cpus, sched_domain_span(sd), p->cpus_ptr); + task_util = uclamp_task_util(p); + for_each_cpu_wrap(cpu, cpus, target) { unsigned long cpu_cap = capacity_of(cpu); if (!available_idle_cpu(cpu) && !sched_idle_cpu(cpu)) continue; - if (task_fits_capacity(p, cpu_cap)) + if (fits_capacity(task_util, cpu_cap)) return cpu; if (cpu_cap > best_cap) { @@ -6111,14 +6111,60 @@ select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target) return best_cpu; } +static inline bool asym_fits_capacity(int task_util, int cpu) +{ + if (static_branch_unlikely(&sched_asym_cpucapacity)) + return fits_capacity(task_util, capacity_of(cpu)); + + return true; +} + /* * Try and locate an idle core/thread in the LLC cache domain. */ static int select_idle_sibling(struct task_struct *p, int prev, int target) { struct sched_domain *sd; + unsigned long task_util; int i, recent_used_cpu; + /* + * On asymmetric system, update task utilization because we will check + * that the task fits with cpu's capacity. + */ + if (static_branch_unlikely(&sched_asym_cpucapacity)) { + sync_entity_load_avg(&p->se); + task_util = uclamp_task_util(p); + } + + if ((available_idle_cpu(target) || sched_idle_cpu(target)) && + asym_fits_capacity(task_util, target)) + return target; + + /* + * If the previous CPU is cache affine and idle, don't be stupid: + */ + if (prev != target && cpus_share_cache(prev, target) && + (available_idle_cpu(prev) || sched_idle_cpu(prev)) && + asym_fits_capacity(task_util, prev)) + return prev; + + /* Check a recently used CPU as a potential idle candidate: */ + recent_used_cpu = p->recent_used_cpu; + if (recent_used_cpu != prev && + recent_used_cpu != target && + cpus_share_cache(recent_used_cpu, target) && + (available_idle_cpu(recent_used_cpu) || sched_idle_cpu(recent_used_cpu)) && + cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr) && + asym_fits_capacity(task_util, recent_used_cpu)) { + /* + * Replace recent_used_cpu with prev as it is a potential + * candidate for the next wake: + */ + p->recent_used_cpu = prev; + return recent_used_cpu; + } + /* * For asymmetric CPU capacity systems, our domain of interest is * sd_asym_cpucapacity rather than sd_llc. @@ -6133,37 +6179,10 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) * SD_ASYM_CPUCAPACITY. These should follow the usual symmetric * capacity path. */ - if (!sd) - goto symmetric; - - i = select_idle_capacity(p, sd, target); - return ((unsigned)i < nr_cpumask_bits) ? i : target; - } - -symmetric: - if (available_idle_cpu(target) || sched_idle_cpu(target)) - return target; - - /* - * If the previous CPU is cache affine and idle, don't be stupid: - */ - if (prev != target && cpus_share_cache(prev, target) && - (available_idle_cpu(prev) || sched_idle_cpu(prev))) - return prev; - - /* Check a recently used CPU as a potential idle candidate: */ - recent_used_cpu = p->recent_used_cpu; - if (recent_used_cpu != prev && - recent_used_cpu != target && - cpus_share_cache(recent_used_cpu, target) && - (available_idle_cpu(recent_used_cpu) || sched_idle_cpu(recent_used_cpu)) && - cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr)) { - /* - * Replace recent_used_cpu with prev as it is a potential - * candidate for the next wake: - */ - p->recent_used_cpu = prev; - return recent_used_cpu; + if (sd) { + i = select_idle_capacity(p, sd, target); + return ((unsigned)i < nr_cpumask_bits) ? i : target; + } } sd = rcu_dereference(per_cpu(sd_llc, target)); From d9d13f4b76a01fd80cc1d5b316b74db5f75fc77b Mon Sep 17 00:00:00 2001 From: Hyeongseok Kim Date: Thu, 12 Nov 2020 18:14:54 +0900 Subject: [PATCH 19/67] UPSTREAM: f2fs: fix double free of unicode map In case of retrying fill_super with skip_recovery, s_encoding for casefold would not be loaded again even though it's already been freed because it's not NULL. Set NULL after free to prevent double freeing when unmount. Fixes: eca4873ee1b6 ("f2fs: Use generic casefolding support") Signed-off-by: Hyeongseok Kim Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim (cherry picked from commit 89ff6005039a878afac87889fee748fa3f957c3a) Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: Ib29e84c8e77e710fd2f9649a56750d33fd620fba --- fs/f2fs/super.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 8b64af017733..3d63a89daa18 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -3844,6 +3844,7 @@ free_bio_info: #ifdef CONFIG_UNICODE utf8_unload(sb->s_encoding); + sb->s_encoding = NULL; #endif free_options: #ifdef CONFIG_QUOTA From b55ed54016717d09dd18c2fcb0cabb68443d9b5b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 8 Dec 2020 20:03:26 +0100 Subject: [PATCH 20/67] UPSTREAM: driver: core: Fix list corruption after device_del() The device_links_purge() function (called from device_del()) tries to remove the links.needs_suppliers list entry, but it's using list_del(), hence it doesn't initialize after the removal. This is OK for normal cases where device_del() is called via device_destroy(). However, it's not guaranteed that the device object will be really deleted soon after device_del(). In a minor case like HD-audio codec reconfiguration that re-initializes the device after device_del(), it may lead to a crash by the corrupted list entry. As a simple fix, replace list_del() with list_del_init() in order to make the list intact after the device_del() call. Fixes: e2ae9bcc4aaa ("driver core: Add support for linking devices during device addition") Cc: Reviewed-by: Rafael J. Wysocki Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20201208190326.27531-1-tiwai@suse.de Cc: Saravana Kannan Signed-off-by: Greg Kroah-Hartman (cherry picked from commit 66482f640755b31cb94371ff6cef17400cda6db5) Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: If1c0eb2511292b430eb275e72f7e4ccf55b4f96b --- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 0f9f3701bd89..0f6d3c4a2f3a 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1373,7 +1373,7 @@ static void device_links_purge(struct device *dev) return; mutex_lock(&wfs_lock); - list_del(&dev->links.needs_suppliers); + list_del_init(&dev->links.needs_suppliers); mutex_unlock(&wfs_lock); /* From 2e09274b7c603cf228c7d702a2020ff62cab30cc Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Tue, 8 Dec 2020 21:56:34 +0800 Subject: [PATCH 21/67] UPSTREAM: scsi: ufs: Re-enable WriteBooster after device reset UFS 3.1 specification mentions that the WriteBooster flags listed below will be set to their default values, i.e. disabled, after power cycle or any type of reset event. Thus we need to reset the flag variables kept in struct hba to align with the device status and ensure that WriteBooster-related functions are configured properly after device reset. Without this fix, WriteBooster will not be enabled successfully after by ufshcd_wb_ctrl() after device reset because hba->wb_enabled remains true. Flags required to be reset to default values: - fWriteBoosterEn: hba->wb_enabled - fWriteBoosterBufferFlushEn: hba->wb_buf_flush_enabled - fWriteBoosterBufferFlushDuringHibernate: No variable mapped Link: https://lore.kernel.org/r/20201208135635.15326-2-stanley.chu@mediatek.com Fixes: 3d17b9b5ab11 ("scsi: ufs: Add write booster feature support") Reviewed-by: Bean Huo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen (cherry picked from commit bd14bf0e4a084514aa62d24d2109e0f09a93822f) Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: I994290c3824cac50828e097cdfb4a93e9dcfeb36 --- drivers/scsi/ufs/ufshcd.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 13783dc5a0b4..c794fdc2fa10 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -1266,6 +1266,10 @@ static inline void ufshcd_vops_device_reset(struct ufs_hba *hba) if (hba->vops && hba->vops->device_reset) { hba->vops->device_reset(hba); ufshcd_set_ufs_dev_active(hba); + if (ufshcd_is_wb_allowed(hba)) { + hba->wb_enabled = false; + hba->wb_buf_flush_enabled = false; + } ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, 0); } } From e7e2f8329c29a7e17c35436b8dbdbb2118f1bfc4 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Tue, 22 Dec 2020 15:29:04 +0800 Subject: [PATCH 22/67] UPSTREAM: scsi: ufs: Fix possible power drain during system suspend Currently if device needs to do flush or BKOP operations, the device VCC power is kept during runtime-suspend period. However, if system suspend is happening while device is runtime-suspended, such power may not be disabled successfully. The reasons may be, 1. If current PM level is the same as SPM level, device will keep runtime-suspended by ufshcd_system_suspend(). 2. Flush recheck work may not be scheduled successfully during system suspend period. If it can wake up the system, this is also not the intention of the recheck work. To fix this issue, simply runtime-resume the device if the flush is allowed during runtime suspend period. Flush capability will be disabled while leaving runtime suspend, and also not be allowed in system suspend period. Link: https://lore.kernel.org/r/20201222072905.32221-2-stanley.chu@mediatek.com Fixes: 51dd905bd2f6 ("scsi: ufs: Fix WriteBooster flush during runtime suspend") Reviewed-by: Chaotian Jing Reviewed-by: Can Guo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen (cherry picked from commit 1d53864c3617f5235f891ca0fbe9347c4cd35d46) Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: I2c7738084d968fd3987d4876f04ea9c9b4318fb1 --- drivers/scsi/ufs/ufshcd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 4c12b3d3c9f4..1e387525b947 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -8850,7 +8850,8 @@ int ufshcd_system_suspend(struct ufs_hba *hba) if ((ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl) == hba->curr_dev_pwr_mode) && (ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) == - hba->uic_link_state)) + hba->uic_link_state) && + !hba->dev_info.b_rpm_dev_flush_capable) goto out; if (pm_runtime_suspended(hba->dev)) { From 550b2c0dce83a59994102f2910cb1e10ad00c9a0 Mon Sep 17 00:00:00 2001 From: Dongseok Yi Date: Fri, 8 Jan 2021 11:28:38 +0900 Subject: [PATCH 23/67] UPSTREAM: net: fix use-after-free when UDP GRO with shared fraglist skbs in fraglist could be shared by a BPF filter loaded at TC. If TC writes, it will call skb_ensure_writable -> pskb_expand_head to create a private linear section for the head_skb. And then call skb_clone_fraglist -> skb_get on each skb in the fraglist. skb_segment_list overwrites part of the skb linear section of each fragment itself. Even after skb_clone, the frag_skbs share their linear section with their clone in PF_PACKET. Both sk_receive_queue of PF_PACKET and PF_INET (or PF_INET6) can have a link for the same frag_skbs chain. If a new skb (not frags) is queued to one of the sk_receive_queue, multiple ptypes can see and release this. It causes use-after-free. [ 4443.426215] ------------[ cut here ]------------ [ 4443.426222] refcount_t: underflow; use-after-free. [ 4443.426291] WARNING: CPU: 7 PID: 28161 at lib/refcount.c:190 refcount_dec_and_test_checked+0xa4/0xc8 [ 4443.426726] pstate: 60400005 (nZCv daif +PAN -UAO) [ 4443.426732] pc : refcount_dec_and_test_checked+0xa4/0xc8 [ 4443.426737] lr : refcount_dec_and_test_checked+0xa0/0xc8 [ 4443.426808] Call trace: [ 4443.426813] refcount_dec_and_test_checked+0xa4/0xc8 [ 4443.426823] skb_release_data+0x144/0x264 [ 4443.426828] kfree_skb+0x58/0xc4 [ 4443.426832] skb_queue_purge+0x64/0x9c [ 4443.426844] packet_set_ring+0x5f0/0x820 [ 4443.426849] packet_setsockopt+0x5a4/0xcd0 [ 4443.426853] __sys_setsockopt+0x188/0x278 [ 4443.426858] __arm64_sys_setsockopt+0x28/0x38 [ 4443.426869] el0_svc_common+0xf0/0x1d0 [ 4443.426873] el0_svc_handler+0x74/0x98 [ 4443.426880] el0_svc+0x8/0xc Fixes: 3a1296a38d0c (net: Support GRO/GSO fraglist chaining.) Signed-off-by: Dongseok Yi Acked-by: Willem de Bruijn Acked-by: Daniel Borkmann Link: https://lore.kernel.org/r/1610072918-174177-1-git-send-email-dseok.yi@samsung.com Signed-off-by: Jakub Kicinski (cherry picked from commit 53475c5dd856212e91538a9501162e821cc1f791) Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: Ife87c4296ba12b39be4868b2c5e0ea6130f76d6d --- net/core/skbuff.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index b87b6334f689..edc9be5aa823 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3649,7 +3649,8 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb, unsigned int delta_truesize = 0; unsigned int delta_len = 0; struct sk_buff *tail = NULL; - struct sk_buff *nskb; + struct sk_buff *nskb, *tmp; + int err; skb_push(skb, -skb_network_offset(skb) + offset); @@ -3659,11 +3660,28 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb, nskb = list_skb; list_skb = list_skb->next; + err = 0; + if (skb_shared(nskb)) { + tmp = skb_clone(nskb, GFP_ATOMIC); + if (tmp) { + consume_skb(nskb); + nskb = tmp; + err = skb_unclone(nskb, GFP_ATOMIC); + } else { + err = -ENOMEM; + } + } + if (!tail) skb->next = nskb; else tail->next = nskb; + if (unlikely(err)) { + nskb->next = list_skb; + goto err_linearize; + } + tail = nskb; delta_len += nskb->len; From 24797c44c3baa41910d9df33e20b59bf8293f14e Mon Sep 17 00:00:00 2001 From: Dongseok Yi Date: Sat, 30 Jan 2021 08:13:27 +0900 Subject: [PATCH 24/67] UPSTREAM: udp: ipv4: manipulate network header of NATed UDP GRO fraglist UDP/IP header of UDP GROed frag_skbs are not updated even after NAT forwarding. Only the header of head_skb from ip_finish_output_gso -> skb_gso_segment is updated but following frag_skbs are not updated. A call path skb_mac_gso_segment -> inet_gso_segment -> udp4_ufo_fragment -> __udp_gso_segment -> __udp_gso_segment_list does not try to update UDP/IP header of the segment list but copy only the MAC header. Update port, addr and check of each skb of the segment list in __udp_gso_segment_list. It covers both SNAT and DNAT. Fixes: 9fd1ff5d2ac7 (udp: Support UDP fraglist GRO/GSO.) Signed-off-by: Dongseok Yi Acked-by: Steffen Klassert Link: https://lore.kernel.org/r/1611962007-80092-1-git-send-email-dseok.yi@samsung.com Signed-off-by: Jakub Kicinski (cherry picked from commit c3df39ac9b0e3747bf8233ea9ce4ed5ceb3199d3) Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: Ib6159d86309fc5ade95c67abd7eab6880accd12b --- include/net/udp.h | 2 +- net/ipv4/udp_offload.c | 69 +++++++++++++++++++++++++++++++++++++++--- net/ipv6/udp_offload.c | 2 +- 3 files changed, 66 insertions(+), 7 deletions(-) diff --git a/include/net/udp.h b/include/net/udp.h index e55d5f765807..9ab282cbff20 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -171,7 +171,7 @@ struct sk_buff *udp_gro_receive(struct list_head *head, struct sk_buff *skb, int udp_gro_complete(struct sk_buff *skb, int nhoff, udp_lookup_t lookup); struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, - netdev_features_t features); + netdev_features_t features, bool is_ipv6); static inline struct udphdr *udp_gro_udphdr(struct sk_buff *skb) { diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 9298b0ebc4ff..fd60e5cd1519 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -184,8 +184,67 @@ out_unlock: } EXPORT_SYMBOL(skb_udp_tunnel_segment); +static void __udpv4_gso_segment_csum(struct sk_buff *seg, + __be32 *oldip, __be32 *newip, + __be16 *oldport, __be16 *newport) +{ + struct udphdr *uh; + struct iphdr *iph; + + if (*oldip == *newip && *oldport == *newport) + return; + + uh = udp_hdr(seg); + iph = ip_hdr(seg); + + if (uh->check) { + inet_proto_csum_replace4(&uh->check, seg, *oldip, *newip, + true); + inet_proto_csum_replace2(&uh->check, seg, *oldport, *newport, + false); + if (!uh->check) + uh->check = CSUM_MANGLED_0; + } + *oldport = *newport; + + csum_replace4(&iph->check, *oldip, *newip); + *oldip = *newip; +} + +static struct sk_buff *__udpv4_gso_segment_list_csum(struct sk_buff *segs) +{ + struct sk_buff *seg; + struct udphdr *uh, *uh2; + struct iphdr *iph, *iph2; + + seg = segs; + uh = udp_hdr(seg); + iph = ip_hdr(seg); + + if ((udp_hdr(seg)->dest == udp_hdr(seg->next)->dest) && + (udp_hdr(seg)->source == udp_hdr(seg->next)->source) && + (ip_hdr(seg)->daddr == ip_hdr(seg->next)->daddr) && + (ip_hdr(seg)->saddr == ip_hdr(seg->next)->saddr)) + return segs; + + while ((seg = seg->next)) { + uh2 = udp_hdr(seg); + iph2 = ip_hdr(seg); + + __udpv4_gso_segment_csum(seg, + &iph2->saddr, &iph->saddr, + &uh2->source, &uh->source); + __udpv4_gso_segment_csum(seg, + &iph2->daddr, &iph->daddr, + &uh2->dest, &uh->dest); + } + + return segs; +} + static struct sk_buff *__udp_gso_segment_list(struct sk_buff *skb, - netdev_features_t features) + netdev_features_t features, + bool is_ipv6) { unsigned int mss = skb_shinfo(skb)->gso_size; @@ -195,11 +254,11 @@ static struct sk_buff *__udp_gso_segment_list(struct sk_buff *skb, udp_hdr(skb)->len = htons(sizeof(struct udphdr) + mss); - return skb; + return is_ipv6 ? skb : __udpv4_gso_segment_list_csum(skb); } struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, - netdev_features_t features) + netdev_features_t features, bool is_ipv6) { struct sock *sk = gso_skb->sk; unsigned int sum_truesize = 0; @@ -211,7 +270,7 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, __be16 newlen; if (skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST) - return __udp_gso_segment_list(gso_skb, features); + return __udp_gso_segment_list(gso_skb, features, is_ipv6); mss = skb_shinfo(gso_skb)->gso_size; if (gso_skb->len <= sizeof(*uh) + mss) @@ -325,7 +384,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, goto out; if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) - return __udp_gso_segment(skb, features); + return __udp_gso_segment(skb, features, false); mss = skb_shinfo(skb)->gso_size; if (unlikely(skb->len <= mss)) diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index 7a46bd33fa2f..6e06c90fa318 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c @@ -46,7 +46,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, goto out; if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) - return __udp_gso_segment(skb, features); + return __udp_gso_segment(skb, features, true); /* Do software UFO. Complete and fill in the UDP checksum as HW cannot * do checksum of UDP packets sent as multiple IP fragments. From 0475956802ab34d92a184ceee5949df268fc930c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2021 15:36:15 +0900 Subject: [PATCH 25/67] UPSTREAM: kbuild: do not include include/config/auto.conf from adjust_autoksyms.sh Commit cd195bc4775a ("kbuild: split adjust_autoksyms.sh in two parts") split out the code that needs include/config/auto.conf. This script no longer needs to include include/config/auto.conf. Fixes: cd195bc4775a ("kbuild: split adjust_autoksyms.sh in two parts") Signed-off-by: Masahiro Yamada (cherry picked from commit 12e9dea6c9766c7403417d00193940cea33ee81a) Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: I0781bd0198e4a3c8215830f4100ff1371e2d3e82 --- scripts/adjust_autoksyms.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/adjust_autoksyms.sh b/scripts/adjust_autoksyms.sh index 2b366d945ccb..d8f6f9c63043 100755 --- a/scripts/adjust_autoksyms.sh +++ b/scripts/adjust_autoksyms.sh @@ -34,9 +34,6 @@ case "$KBUILD_VERBOSE" in ;; esac -# We need access to CONFIG_ symbols -. include/config/auto.conf - # Generate a new symbol list file $CONFIG_SHELL $srctree/scripts/gen_autoksyms.sh "$new_ksyms_file" From 046c52c95b84f5efdf0cece1723136e862686f6b Mon Sep 17 00:00:00 2001 From: dongjian Date: Tue, 16 Mar 2021 20:15:15 +0800 Subject: [PATCH 26/67] UPSTREAM: scsi: ufs: ufs-mediatek: Correct operator & -> && The "lpm" and "->enabled" are all boolean. We should be using && rather than the bit operator. Link: https://lore.kernel.org/r/1615896915-148864-1-git-send-email-dj0227@163.com Fixes: 488edafb1120 ("scsi: ufs-mediatek: Introduce low-power mode for device power supply") Reviewed-by: Avri Altman Signed-off-by: dongjian Signed-off-by: Yue Hu Signed-off-by: Martin K. Petersen (cherry picked from commit 0fdc7d5d8f3719950478cca452cf7f0f1355be10) Bug: 187129171 Signed-off-by: Connor O'Brien Change-Id: I010318ede5b79f8b0443b3acf72a8736640ae3f8 --- drivers/scsi/ufs/ufs-mediatek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index e22f91695b04..6ac8f1e39796 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -582,7 +582,7 @@ static void ufs_mtk_vreg_set_lpm(struct ufs_hba *hba, bool lpm) if (!hba->vreg_info.vccq2 || !hba->vreg_info.vcc) return; - if (lpm & !hba->vreg_info.vcc->enabled) + if (lpm && !hba->vreg_info.vcc->enabled) regulator_set_mode(hba->vreg_info.vccq2->reg, REGULATOR_MODE_IDLE); else if (!lpm) From e3e60153a4c5838b0df44c30000c47cb8a3f957e Mon Sep 17 00:00:00 2001 From: Lecopzer Chen Date: Wed, 21 Apr 2021 16:23:48 +0800 Subject: [PATCH 27/67] BACKPORT: remoteproc: core: Remove casting to rproc_handle_resource_t There are four different callback functions that are used for the rproc_handle_resource_t callback that all have different second parameter types. rproc_handle_vdev -> struct fw_rsc_vdev rproc_handle_trace -> struct fw_rsc_trace rproc_handle_devmem -> struct fw_rsc_devmem rproc_handle_carveout -> struct fw_rsc_carveout These callbacks are cast to rproc_handle_resource_t so that there is no error about incompatible pointer types. Unfortunately, this is a Clang's Control-Flow Integrity checking violation, which verifies that the callback function's types match the prototypes exactly before jumping. [ 7.275750] Kernel panic - not syncing: CFI failure (target: rproc_handle_vdev+0x0/0x4) [ 7.283763] CPU: 2 PID: 1 Comm: init Tainted: G C O 5.4.70-03301-g527af2c96672 #17 [ 7.292463] Hardware name: NXP i.MX8MPlus EVK board (DT) [ 7.297779] Call trace: [ 7.300232] dump_backtrace.cfi_jt+0x0/0x4 [ 7.304337] show_stack+0x18/0x24 [ 7.307660] dump_stack+0xb8/0x114 [ 7.311069] panic+0x164/0x3d4 [ 7.314130] __ubsan_handle_cfi_check_fail_abort+0x0/0x14 [ 7.319533] perf_proc_update_handler+0x0/0xcc [ 7.323983] __cfi_check+0x63278/0x6a290 [ 7.327913] rproc_boot+0x3f8/0x738 [ 7.331404] rproc_add+0x68/0x110 [ 7.334738] imx_rproc_probe+0x5e4/0x708 [imx_rproc] [ 7.339711] platform_drv_probe+0xac/0xf0 [ 7.343726] really_probe+0x260/0x65c [ 7.347393] driver_probe_device+0x64/0x100 [ 7.351580] device_driver_attach+0x6c/0xac [ 7.355766] __driver_attach+0xdc/0x184 [ 7.359609] bus_for_each_dev+0x98/0x104 [ 7.363537] driver_attach+0x24/0x30 [ 7.367117] bus_add_driver+0x100/0x1e0 [ 7.370958] driver_register+0x78/0x114 [ 7.374800] __platform_driver_register+0x44/0x50 [ 7.379514] init_module+0x20/0xfe8 [imx_rproc] [ 7.384049] do_one_initcall+0x190/0x348 [ 7.387979] do_init_module+0x5c/0x210 [ 7.391731] load_module+0x2fbc/0x3590 [ 7.395485] __arm64_sys_finit_module+0xb8/0xec [ 7.400025] el0_svc_common+0xb4/0x19c [ 7.403777] el0_svc_handler+0x74/0x98 [ 7.407531] el0_svc+0x8/0xc [ 7.410419] SMP: stopping secondary CPUs [ 7.414648] Kernel Offset: disabled [ 7.418142] CPU features: 0x00010002,2000200c [ 7.422501] Memory Limit: none To fix this, change the second parameter of all functions to void * and use a local variable with the correct type so that everything works properly. With this, we can remove casting to rproc_handle_resource_t for these functions. Signed-off-by: Jindong Yue Reviewed-by: Peng Fan Reviewed-by: Sami Tolvanen Reviewed-by: Mathieu Poirier Link: https://lore.kernel.org/r/20210224055825.7417-1-jindong.yue@nxp.com Signed-off-by: Bjorn Andersson (cherry picked from commit 2bf2346159bc99cf0679e25be20f4daca60f3f5c) Bug: 187234877 Reported-by: Joy-mi Huang Signed-off-by: Lecopzer Chen Change-Id: Icc7adeaf98f779fc46a979ff7e9f2ab5f963f636 --- drivers/remoteproc/remoteproc_core.c | 29 +++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index ce92ae227aa1..a08568c85126 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -445,7 +445,7 @@ static void rproc_rvdev_release(struct device *dev) /** * rproc_handle_vdev() - handle a vdev fw resource * @rproc: the remote processor - * @rsc: the vring resource descriptor + * ptr: the vring resource descriptor * @avail: size of available data (for sanity checking the image) * * This resource entry requests the host to statically register a virtio @@ -469,9 +469,10 @@ static void rproc_rvdev_release(struct device *dev) * * Returns 0 on success, or an appropriate error code otherwise */ -static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc, +static int rproc_handle_vdev(struct rproc *rproc, void *ptr, int offset, int avail) { + struct fw_rsc_vdev *rsc = ptr; struct device *dev = &rproc->dev; struct rproc_vdev *rvdev; int i, ret; @@ -587,7 +588,7 @@ void rproc_vdev_release(struct kref *ref) /** * rproc_handle_trace() - handle a shared trace buffer resource * @rproc: the remote processor - * @rsc: the trace resource descriptor + * @ptr: the trace resource descriptor * @avail: size of available data (for sanity checking the image) * * In case the remote processor dumps trace logs into memory, @@ -600,9 +601,10 @@ void rproc_vdev_release(struct kref *ref) * * Returns 0 on success, or an appropriate error code otherwise */ -static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc, +static int rproc_handle_trace(struct rproc *rproc, void *ptr, int offset, int avail) { + struct fw_rsc_trace *rsc = ptr; struct rproc_debug_trace *trace; struct device *dev = &rproc->dev; char name[15]; @@ -652,7 +654,7 @@ static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc, /** * rproc_handle_devmem() - handle devmem resource entry * @rproc: remote processor handle - * @rsc: the devmem resource entry + * @ptr: the devmem resource entry * @avail: size of available data (for sanity checking the image) * * Remote processors commonly need to access certain on-chip peripherals. @@ -674,9 +676,10 @@ static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc, * and not allow firmwares to request access to physical addresses that * are outside those ranges. */ -static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc, +static int rproc_handle_devmem(struct rproc *rproc, void *ptr, int offset, int avail) { + struct fw_rsc_devmem *rsc = ptr; struct rproc_mem_entry *mapping; struct device *dev = &rproc->dev; int ret; @@ -853,7 +856,7 @@ static int rproc_release_carveout(struct rproc *rproc, /** * rproc_handle_carveout() - handle phys contig memory allocation requests * @rproc: rproc handle - * @rsc: the resource entry + * @ptr: the resource entry * @avail: size of available data (for image validation) * * This function will handle firmware requests for allocation of physically @@ -869,9 +872,9 @@ static int rproc_release_carveout(struct rproc *rproc, * pressure is important; it may have a substantial impact on performance. */ static int rproc_handle_carveout(struct rproc *rproc, - struct fw_rsc_carveout *rsc, - int offset, int avail) + void *ptr, int offset, int avail) { + struct fw_rsc_carveout *rsc = ptr; struct rproc_mem_entry *carveout; struct device *dev = &rproc->dev; @@ -1028,10 +1031,10 @@ EXPORT_SYMBOL(rproc_of_resm_mem_entry_init); * enum fw_resource_type. */ static rproc_handle_resource_t rproc_loading_handlers[RSC_LAST] = { - [RSC_CARVEOUT] = (rproc_handle_resource_t)rproc_handle_carveout, - [RSC_DEVMEM] = (rproc_handle_resource_t)rproc_handle_devmem, - [RSC_TRACE] = (rproc_handle_resource_t)rproc_handle_trace, - [RSC_VDEV] = (rproc_handle_resource_t)rproc_handle_vdev, + [RSC_CARVEOUT] = rproc_handle_carveout, + [RSC_DEVMEM] = rproc_handle_devmem, + [RSC_TRACE] = rproc_handle_trace, + [RSC_VDEV] = rproc_handle_vdev, }; /* handle firmware resource entries before booting the remote processor */ From 2d5e3ef63282a9539c0ea797e43ec672ea9fd1b7 Mon Sep 17 00:00:00 2001 From: "jy.ser" Date: Thu, 6 May 2021 14:26:54 +0900 Subject: [PATCH 28/67] ANDROID: ABI: update allowed list for galaxy Leaf changes summary: 2 artifacts changed Changed leaf types summary: 0 leaf type changed Removed/Changed/Added functions summary: 0 Removed, 0 Changed, 2 Added functions Removed/Changed/Added variables summary: 0 Removed, 0 Changed, 0 Added variable 2 Added functions: [A] 'function int gpiochip_irqchip_add_key(gpio_chip*, irq_chip*, unsigned int, void (irq_desc*)*, unsigned int, bool, lock_class_key*, lock_class_key*)' [A] 'function void gpiochip_set_nested_irqchip(gpio_chip*, irq_chip*, unsigned int)' Bug: 187366261 Signed-off-by: jy.ser Change-Id: I97e00013450cea1d47a18b9a135e5e8cff707d2c --- android/abi_gki_aarch64.xml | 227 +++++++++++++++++++++------------ android/abi_gki_aarch64_galaxy | 2 + 2 files changed, 150 insertions(+), 79 deletions(-) diff --git a/android/abi_gki_aarch64.xml b/android/abi_gki_aarch64.xml index ced999ef6ac8..5cf98b3e7288 100644 --- a/android/abi_gki_aarch64.xml +++ b/android/abi_gki_aarch64.xml @@ -1842,12 +1842,14 @@ + + @@ -28207,7 +28209,7 @@ - + @@ -30029,7 +30031,7 @@ - + @@ -30239,7 +30241,7 @@ - + @@ -30764,7 +30766,20 @@ - + + + + + + + + + + + + + + @@ -31940,6 +31955,7 @@ + @@ -31951,7 +31967,7 @@ - + @@ -32317,6 +32333,17 @@ + + + + + + + + + + + @@ -32403,7 +32430,7 @@ - + @@ -32487,7 +32514,7 @@ - + @@ -69088,6 +69115,12 @@ + + + + + + @@ -80794,7 +80827,7 @@ - + @@ -80866,7 +80899,7 @@ - + @@ -80939,7 +80972,7 @@ - + @@ -83186,7 +83219,7 @@ - + @@ -83258,7 +83291,7 @@ - + @@ -83303,7 +83336,7 @@ - + @@ -111573,7 +111606,20 @@ - + + + + + + + + + + + + + + @@ -119876,6 +119922,17 @@ + + + + + + + + + + + @@ -121974,57 +122031,57 @@ - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + @@ -165730,7 +165787,7 @@ - + @@ -165814,7 +165871,7 @@ - + @@ -166139,9 +166196,9 @@ - - - + + + @@ -166149,9 +166206,9 @@ - - - + + + @@ -166347,33 +166404,33 @@ - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + @@ -166926,6 +166983,18 @@ + + + + + + + + + + + + @@ -173940,7 +174009,7 @@ - + @@ -178706,7 +178775,7 @@ - + @@ -178735,7 +178804,7 @@ - + @@ -179327,7 +179396,7 @@ - + @@ -180287,7 +180356,7 @@ - + diff --git a/android/abi_gki_aarch64_galaxy b/android/abi_gki_aarch64_galaxy index bef65a0d87b9..b65bf734e98c 100644 --- a/android/abi_gki_aarch64_galaxy +++ b/android/abi_gki_aarch64_galaxy @@ -1103,9 +1103,11 @@ gpiochip_generic_free gpiochip_generic_request gpiochip_get_data + gpiochip_irqchip_add_key gpiochip_line_is_valid gpiochip_lock_as_irq gpiochip_remove + gpiochip_set_nested_irqchip gpiochip_unlock_as_irq gpiod_direction_input gpiod_direction_output From 0821bcfb48093fa544a1e727e98828340416f974 Mon Sep 17 00:00:00 2001 From: Lecopzer Chen Date: Mon, 14 Dec 2020 19:13:23 -0800 Subject: [PATCH 29/67] UPSTREAM: mm/cma.c: remove redundant cma_mutex lock The cma_mutex which protects alloc_contig_range() was first appeared in commit 7ee793a62fa8c ("cma: Remove potential deadlock situation"), at that time, there is no guarantee the behavior of concurrency inside alloc_contig_range(). After commit 2c7452a075d4db2dc ("mm/page_isolation.c: make start_isolate_page_range() fail if already isolated") > However, two subsystems (CMA and gigantic > huge pages for example) could attempt operations on the same range. If > this happens, one thread may 'undo' the work another thread is doing. > This can result in pageblocks being incorrectly left marked as > MIGRATE_ISOLATE and therefore not available for page allocation. The concurrency inside alloc_contig_range() was clarified. Now we can find that hugepage and virtio call alloc_contig_range() without any lock, thus cma_mutex is "redundant" in cma_alloc() now. Link: https://lkml.kernel.org/r/20201020102241.3729-1-lecopzer.chen@mediatek.com Signed-off-by: Lecopzer Chen Acked-by: David Hildenbrand Acked-by: Vlastimil Babka Cc: Matthias Brugger Cc: YJ Chiang Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds (cherry picked from commit a4efc174b382fcdb62e2d90d39e78a274a975e38) Signed-off-by: Lecopzer Chen Change-Id: I43755731ddb1a4ac9ac873a6e99c8c96d727ef77 --- mm/cma.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mm/cma.c b/mm/cma.c index e1bf400016b3..def0df5a32f8 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -39,7 +39,6 @@ struct cma cma_areas[MAX_CMA_AREAS]; unsigned cma_area_count; -static DEFINE_MUTEX(cma_mutex); phys_addr_t cma_get_base(const struct cma *cma) { @@ -455,10 +454,9 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align, mutex_unlock(&cma->lock); pfn = cma->base_pfn + (bitmap_no << cma->order_per_bit); - mutex_lock(&cma_mutex); ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA, GFP_KERNEL | (no_warn ? __GFP_NOWARN : 0)); - mutex_unlock(&cma_mutex); + if (ret == 0) { page = pfn_to_page(pfn); break; From c07e36bfc56c9d4c2ec896e09d243159552291c8 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 11 May 2021 07:29:32 +0000 Subject: [PATCH 30/67] ANDROID: db845c_gki.fragment: Add QCOM_TSENSE config to avoid thermal crashes This adds QCOM_TSENSE to the db845c_gki.fragment which is needed to avoid hard crashes seen on db845c (which crash into USB dump mode). This was causing some troube in our testing as we'd occasionally see hard crashes in certian CTS tests (also reproducible with a forkbomb). After lots of debugging we've narrowed down this config as the change which avoids the hard crashes. Thanks to: Vinod Koul and Bjorn Andersson for helping debug this issue! Bug: 146449535 Reported-by: YongQin Liu Signed-off-by: John Stultz Change-Id: I0752c85e44028e6272c14b59fa09d2baf2e18feb --- arch/arm64/configs/db845c_gki.fragment | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/db845c_gki.fragment b/arch/arm64/configs/db845c_gki.fragment index c8ca9a8110c6..2e69bf2494cb 100644 --- a/arch/arm64/configs/db845c_gki.fragment +++ b/arch/arm64/configs/db845c_gki.fragment @@ -12,6 +12,7 @@ CONFIG_PINCTRL_QCOM_SPMI_PMIC=m CONFIG_PINCTRL_SDM845=m CONFIG_POWER_RESET_QCOM_PON=m CONFIG_SYSCON_REBOOT_MODE=m +CONFIG_QCOM_TSENS=m CONFIG_QCOM_WDT=m CONFIG_PM8916_WATCHDOG=m CONFIG_MFD_SPMI_PMIC=m From 1c75846438c1378f7a74f2b20429ea0bd5881c46 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 11 May 2021 21:31:41 +0000 Subject: [PATCH 31/67] ANDROID: abi_gki_aarch64_db845c: Regenerate symbols list after enabling QCOM_TSENSE After enabling QCOM_TSENSE to avoid thermal crashes, we need to add some symbols to the symbol list. Generated with: BUILD_CONFIG=common/build.config.db845c build/build_abi.sh -s BUILD_CONFIG=common/build.config.gki.aarch64 build/build_abi.sh -u Leaf changes summary: 1 artifact changed Changed leaf types summary: 0 leaf type changed Removed/Changed/Added functions summary: 0 Removed, 0 Changed, 1 Added function Removed/Changed/Added variables summary: 0 Removed, 0 Changed, 0 Added variable 1 Added function: [A] 'function int thermal_zone_get_slope(thermal_zone_device*)' Bug: 146449535 Signed-off-by: John Stultz Change-Id: Ieea94a314c0f513bb8af447fe6673b2f40986748 --- android/abi_gki_aarch64.xml | 481 +++++++++++++++++---------------- android/abi_gki_aarch64_db845c | 14 +- 2 files changed, 252 insertions(+), 243 deletions(-) diff --git a/android/abi_gki_aarch64.xml b/android/abi_gki_aarch64.xml index 5cf98b3e7288..1440b007a403 100644 --- a/android/abi_gki_aarch64.xml +++ b/android/abi_gki_aarch64.xml @@ -4102,6 +4102,7 @@ + @@ -28209,7 +28210,7 @@ - + @@ -30241,7 +30242,7 @@ - + @@ -32514,7 +32515,7 @@ - + @@ -80827,7 +80828,7 @@ - + @@ -80899,7 +80900,7 @@ - + @@ -80972,7 +80973,7 @@ - + @@ -83219,7 +83220,7 @@ - + @@ -83291,7 +83292,7 @@ - + @@ -83336,7 +83337,7 @@ - + @@ -130129,6 +130130,10 @@ + + + + @@ -164709,13 +164714,13 @@ - - + + - - - + + + @@ -165784,10 +165789,210 @@ + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -165871,7 +166076,7 @@ - + @@ -165922,7 +166127,18 @@ + + + + + + + + + + + @@ -166111,6 +166327,13 @@ + + + + + + + @@ -166118,6 +166341,10 @@ + + + + @@ -177035,218 +177262,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -177330,17 +177346,6 @@ - - - - - - - - - - - diff --git a/android/abi_gki_aarch64_db845c b/android/abi_gki_aarch64_db845c index 671c62ec75aa..b77a5a8637cb 100644 --- a/android/abi_gki_aarch64_db845c +++ b/android/abi_gki_aarch64_db845c @@ -92,6 +92,7 @@ devm_phy_get devm_pinctrl_register devm_platform_ioremap_resource + devm_regmap_field_alloc __devm_regmap_init_mmio_clk devm_regulator_bulk_get devm_regulator_get @@ -213,6 +214,7 @@ irq_set_irq_wake irq_to_desc jiffies + jiffies_to_usecs kfree kfree_skb kimage_vaddr @@ -251,6 +253,8 @@ __netdev_alloc_skb netif_napi_add netif_napi_del + nvmem_cell_get + nvmem_cell_put nvmem_cell_read of_address_to_resource of_alias_get_id @@ -368,6 +372,7 @@ __register_rpmsg_driver regmap_bulk_read regmap_bulk_write + regmap_field_read regmap_read regmap_update_bits_base regmap_write @@ -1048,8 +1053,6 @@ no_llseek nsecs_to_jiffies ns_to_timespec - nvmem_cell_get - nvmem_cell_put of_device_is_available of_dma_configure of_drm_find_bridge @@ -1227,10 +1230,8 @@ of_irq_get # required by qcom_hwspinlock.ko - devm_regmap_field_alloc hwspin_lock_register hwspin_lock_unregister - regmap_field_read regmap_field_update_bits_base # required by qcom_q6v5.ko @@ -1252,7 +1253,6 @@ __memcpy_toio # required by qcom_spmi-regulator.ko - jiffies_to_usecs regulator_disable_regmap regulator_enable_regmap regulator_is_enabled_regmap @@ -1263,6 +1263,10 @@ rproc_get_by_child try_wait_for_completion +# required by qcom_tsens.ko + devm_thermal_zone_of_sensor_register + thermal_zone_get_slope + # required by qmi_helpers.ko init_net kernel_getsockname From 82038e31f36ab917f55966a419ffeebb1b9a2fc1 Mon Sep 17 00:00:00 2001 From: Alessio Balsini Date: Fri, 14 May 2021 10:38:40 +0100 Subject: [PATCH 32/67] ANDROID: FUSE OWNERS pointing to android-mainline OWNERS This was generated with: $ build/synchronize_owners common-mainline/ android-mainline \ common11-5.4 common12-5.10 common12-5.4 common-4.19-stable Test: none Bug: 188034287 Signed-off-by: Alessio Balsini Change-Id: Iaf020cae75ab47aa12e64bfdfbc8d76efd74880b --- fs/fuse/OWNERS | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fs/fuse/OWNERS diff --git a/fs/fuse/OWNERS b/fs/fuse/OWNERS new file mode 100644 index 000000000000..6c04da7a65d5 --- /dev/null +++ b/fs/fuse/OWNERS @@ -0,0 +1,2 @@ +# include OWNERS from the authoritative android-mainline branch +include kernel/common:android-mainline:/fs/fuse/OWNERS From 5f273643fce3d7a519f338b56c01bd7b61f05d80 Mon Sep 17 00:00:00 2001 From: Will McVicker Date: Sat, 5 Dec 2020 00:48:48 +0000 Subject: [PATCH 33/67] UPSTREAM: HID: make arrays usage and value to be the same commit ed9be64eefe26d7d8b0b5b9fa3ffdf425d87a01f upstream. The HID subsystem allows an "HID report field" to have a different number of "values" and "usages" when it is allocated. When a field struct is created, the size of the usage array is guaranteed to be at least as large as the values array, but it may be larger. This leads to a potential out-of-bounds write in __hidinput_change_resolution_multipliers() and an out-of-bounds read in hidinput_count_leds(). To fix this, let's make sure that both the usage and value arrays are the same size. Cc: stable@vger.kernel.org Signed-off-by: Will McVicker Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman Change-Id: I8a366703040f9701191a39f5bcb06829312b33c5 --- drivers/hid/hid-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index d2ecc9c45255..263eca119ff0 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -90,7 +90,7 @@ EXPORT_SYMBOL_GPL(hid_register_report); * Register a new field for this report. */ -static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) +static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages) { struct hid_field *field; @@ -101,7 +101,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned field = kzalloc((sizeof(struct hid_field) + usages * sizeof(struct hid_usage) + - values * sizeof(unsigned)), GFP_KERNEL); + usages * sizeof(unsigned)), GFP_KERNEL); if (!field) return NULL; @@ -300,7 +300,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign usages = max_t(unsigned, parser->local.usage_index, parser->global.report_count); - field = hid_register_field(report, usages, parser->global.report_count); + field = hid_register_field(report, usages); if (!field) return 0; From 7d99cf8c84a788dbe9b6652695c1e37e6830bee2 Mon Sep 17 00:00:00 2001 From: "hajun.sung" Date: Sat, 22 May 2021 18:26:46 +0900 Subject: [PATCH 34/67] ANDROID: GKI: Update abi_gki_aarch64_exynos Leaf changes summary: 1 artifact changed Changed leaf types summary: 0 leaf type changed Removed/Changed/Added functions summary: 0 Removed, 0 Changed, 1 Added function Removed/Changed/Added variables summary: 0 Removed, 0 Changed, 0 Added variable 1 Added function: [A] 'function char* stpcpy(char* restrict, const char* restrict)' Bug: 188891888 Signed-off-by: hajun.sung Change-Id: Ibac4b0eb23cbe3a40577e6b64c66b0825242aedb --- android/abi_gki_aarch64.xml | 482 +++++++++++++++++---------------- android/abi_gki_aarch64_exynos | 1 + 2 files changed, 246 insertions(+), 237 deletions(-) diff --git a/android/abi_gki_aarch64.xml b/android/abi_gki_aarch64.xml index 1440b007a403..2e8113c8c557 100644 --- a/android/abi_gki_aarch64.xml +++ b/android/abi_gki_aarch64.xml @@ -4002,6 +4002,7 @@ + @@ -17789,7 +17790,7 @@ - + @@ -20407,7 +20408,7 @@ - + @@ -30032,7 +30033,7 @@ - + @@ -31968,7 +31969,7 @@ - + @@ -32431,7 +32432,7 @@ - + @@ -148457,7 +148458,7 @@ - + @@ -164436,6 +164437,8 @@ + + @@ -164464,6 +164467,11 @@ + + + + + @@ -165789,209 +165797,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -166127,18 +165935,7 @@ - - - - - - - - - - - @@ -166327,13 +166124,6 @@ - - - - - - - @@ -166341,10 +166131,6 @@ - - - - @@ -167864,7 +167650,7 @@ - + @@ -167872,7 +167658,7 @@ - + @@ -167880,7 +167666,7 @@ - + @@ -174236,7 +174022,7 @@ - + @@ -177262,7 +177048,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -177346,6 +177343,17 @@ + + + + + + + + + + + @@ -178780,7 +178788,7 @@ - + @@ -178809,7 +178817,7 @@ - + @@ -179401,7 +179409,7 @@ - + @@ -180361,7 +180369,7 @@ - + @@ -191042,6 +191050,6 @@ diff --git a/android/abi_gki_aarch64_exynos b/android/abi_gki_aarch64_exynos index ac98ae3dd488..1f795dac9b27 100644 --- a/android/abi_gki_aarch64_exynos +++ b/android/abi_gki_aarch64_exynos @@ -1462,6 +1462,7 @@ static_key_initialized static_key_slow_dec static_key_slow_inc + stpcpy strcasecmp strcat strchr From 8546510ffe66c8d29b58f1330827fbf29827b128 Mon Sep 17 00:00:00 2001 From: Sarthak Garg Date: Fri, 28 May 2021 09:22:16 +0530 Subject: [PATCH 35/67] mmc: sdhci-msm: Reset SDIO cards during probe by toggling wlan_en pin Wlan cards are powered by external supply so mmc_power_cycle won't reset the card. The only way to reset the wlan cards is by toggling wlan_en pin. Moreover pinctrl sleep configuration don't get applied during reboot by default leading to wlan cards in some unknown state post reboot. Toggle wlan_en pin during probe to reset the card to proper state. Change-Id: I3065a9d3bf6cddd9f34adb51dd20932df4125f86 Signed-off-by: Sarthak Garg --- drivers/mmc/host/sdhci-msm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 99c9357c4b05..9b30ce9562b9 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "sdhci-pltfm.h" #include "cqhci.h" @@ -4379,6 +4380,13 @@ static int sdhci_msm_probe(struct platform_device *pdev) } } + /* Toggle wlan_en pin to reset SDIO card to correct state */ + if (host->mmc->pm_caps & MMC_PM_KEEP_POWER) { + pinctrl_pm_select_sleep_state(&pdev->dev); + mdelay(1); + pinctrl_pm_select_default_state(&pdev->dev); + } + /* Reset the vendor spec register to power on reset state */ writel_relaxed(CORE_VENDOR_SPEC_POR_VAL, host->ioaddr + msm_offset->core_vendor_spec); From df12e38f237feeb0a52d1efce7ed3869d441f9ce Mon Sep 17 00:00:00 2001 From: Zhenhua Huang Date: Thu, 27 May 2021 16:07:00 +0800 Subject: [PATCH 36/67] soc: qcom: mem-offline: online only valid memory blocks mem-offline driver onlines blocks between memory_limit to end of DDR, but for some cases when using large ram size, the range may not be contiguous. We online un-existed memory blocks in this case. Example - RAM Entry 0 : Base 0x0080000000 Size 0x0033E00000 RAM Entry 1 : Base 0x0200000000 Size 0x0200000000 RAM Entry 2 : Base 0x0800000000 Size 0x0100000000 RAM Entry 3 : Base 0x00C0000000 Size 0x0140000000 if offline-size is 5GB and total memory size is 18GB, we onlined also un-existed range [0x400000000,0x800000000] in mem_online_remaining_blocks(). To fix this, Do parsing the DT tree again and updated bitmap accordingly. Use this bitmap to online memory blocks. Change-Id: I5ea94a0ea9dca10e3a3311d6ea53a14302a41ae5 Signed-off-by: Zhenhua Huang --- drivers/soc/qcom/mem-offline.c | 68 ++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/drivers/soc/qcom/mem-offline.c b/drivers/soc/qcom/mem-offline.c index 99743264e4ea..296c84a2dd46 100644 --- a/drivers/soc/qcom/mem-offline.c +++ b/drivers/soc/qcom/mem-offline.c @@ -49,6 +49,7 @@ static bool is_rpm_controller; static bool has_pend_offline_req; static atomic_long_t totalram_pages_with_offline = ATOMIC_INIT(0); static struct workqueue_struct *migrate_wq; +static unsigned long movable_bitmap; #define MODULE_CLASS_NAME "mem-offline" #define MIGRATE_TIMEOUT_SEC (20) @@ -752,6 +753,63 @@ static int mem_event_callback(struct notifier_block *self, return NOTIFY_OK; } +static int update_movable_bitmap(void) +{ + struct device_node *node; + struct property *prop; + int len, num_cells, num_entries; + u64 base, size, end, section_size; + u64 movable_start, movable_end; + int nr_address_cells, nr_size_cells; + const __be32 *pos; + + node = of_find_node_by_name(of_root, "memory"); + if (!node) { + pr_err("mem-offine: memory node not found in DT\n"); + return -EINVAL; + } + + nr_address_cells = of_n_addr_cells(of_root); + nr_size_cells = of_n_size_cells(of_root); + + prop = of_find_property(node, "reg", &len); + + num_cells = len / sizeof(__be32); + num_entries = num_cells / (nr_address_cells + nr_size_cells); + + pos = prop->value; + + section_size = MIN_MEMORY_BLOCK_SIZE; + movable_start = memblock_end_of_DRAM(); + movable_end = bootloader_memory_limit - 1; + + while (num_entries--) { + u64 new_base, new_end; + u64 new_start_bitmap, bitmap_size; + + base = of_read_number(pos, nr_address_cells); + size = of_read_number(pos + nr_address_cells, nr_size_cells); + pos += nr_address_cells + nr_size_cells; + end = base + size; + + if (end <= movable_start) + continue; + + if (base < movable_start) + new_base = movable_start; + else + new_base = base; + new_end = end; + + new_start_bitmap = (new_base - movable_start) / section_size; + bitmap_size = (new_end - new_base) / section_size; + bitmap_set(&movable_bitmap, new_start_bitmap, bitmap_size); + } + + pr_debug("mem-offline: movable_bitmap is %lx\n", movable_bitmap); + return 0; +} + static int mem_online_remaining_blocks(void) { unsigned long memblock_end_pfn = __phys_to_pfn(memblock_end_of_DRAM()); @@ -760,6 +818,7 @@ static int mem_online_remaining_blocks(void) unsigned int nid; phys_addr_t phys_addr; int fail = 0; + int ret; block_size = memory_block_size_bytes(); sections_per_block = block_size / MIN_MEMORY_BLOCK_SIZE; @@ -771,8 +830,17 @@ static int mem_online_remaining_blocks(void) pr_info("mem-offline: System booted with no zone movable memory blocks. Cannot perform memory offlining\n"); return -EINVAL; } + + ret = update_movable_bitmap(); + if (ret < 0) + return -ENODEV; + for (memblock = start_section_nr; memblock <= end_section_nr; memblock += sections_per_block) { + + if (!test_bit(memblock - start_section_nr, &movable_bitmap)) + continue; + pfn = section_nr_to_pfn(memblock); phys_addr = __pfn_to_phys(pfn); From 5c364b0dafb3c33df8ec63073addce8e6ea3d26c Mon Sep 17 00:00:00 2001 From: Harshitha Sai Neelati Date: Sun, 30 May 2021 15:15:38 +0530 Subject: [PATCH 37/67] msm: kgsl: Allow access to QDSS only when coresight is enabled Allocate and map QDSS region only when coresight is enabled. Remove apb_pclk from the clock list when coresight is disabled. Change-Id: I9be6e1abeab26af3abe9196b87368ceba9a98d01 Signed-off-by: Harshitha Sai Neelati --- drivers/gpu/msm/adreno_a6xx_gmu.c | 17 +++++++++++++++-- drivers/gpu/msm/adreno_a6xx_rgmu.c | 17 +++++++++++++++-- drivers/gpu/msm/kgsl_iommu.c | 7 ++++--- drivers/gpu/msm/kgsl_pwrctrl.c | 3 +++ 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index 13f8ea7e2c0e..8c7d4f1d05a2 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -2632,7 +2632,7 @@ int a6xx_gmu_probe(struct kgsl_device *device, struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev); struct resource *res; - int ret; + int ret, i; gmu->pdev = pdev; @@ -2662,7 +2662,20 @@ int a6xx_gmu_probe(struct kgsl_device *device, ret = devm_clk_bulk_get_all(&pdev->dev, &gmu->clks); if (ret < 0) return ret; - + /* + * Voting for apb_pclk will enable power and clocks required for + * QDSS path to function. However, if CORESIGHT is not enabled, + * QDSS is essentially unusable. Hence, if QDSS cannot be used, + * don't vote for this clock. + */ + if (!IS_ENABLED(CONFIG_CORESIGHT)) { + for (i = 0; i < ret; i++) { + if (!strcmp(gmu->clks[i].id, "apb_pclk")) { + gmu->clks[i].clk = NULL; + break; + } + } + } gmu->num_clks = ret; /* Set up GMU IOMMU and shared memory with GMU */ diff --git a/drivers/gpu/msm/adreno_a6xx_rgmu.c b/drivers/gpu/msm/adreno_a6xx_rgmu.c index 0778956378d7..b16399af6af9 100644 --- a/drivers/gpu/msm/adreno_a6xx_rgmu.c +++ b/drivers/gpu/msm/adreno_a6xx_rgmu.c @@ -1248,12 +1248,25 @@ static int a6xx_rgmu_regulators_probe(struct a6xx_rgmu_device *rgmu) static int a6xx_rgmu_clocks_probe(struct a6xx_rgmu_device *rgmu, struct device_node *node) { - int ret; + int ret, i; ret = devm_clk_bulk_get_all(&rgmu->pdev->dev, &rgmu->clks); if (ret < 0) return ret; - + /* + * Voting for apb_pclk will enable power and clocks required for + * QDSS path to function. However, if CORESIGHT is not enabled, + * QDSS is essentially unusable. Hence, if QDSS cannot be used, + * don't vote for this clock. + */ + if (!IS_ENABLED(CONFIG_CORESIGHT)) { + for (i = 0; i < ret; i++) { + if (!strcmp(rgmu->clks[i].id, "apb_pclk")) { + rgmu->clks[i].clk = NULL; + break; + } + } + } rgmu->num_clks = ret; rgmu->gpu_clk = kgsl_of_clk_by_name(rgmu->clks, ret, "core"); diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 38f8100e5fc2..945f2a3838e0 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -2511,9 +2511,10 @@ int kgsl_iommu_probe(struct kgsl_device *device) */ kgsl_iommu_map_globals(mmu, mmu->defaultpagetable); kgsl_iommu_map_globals(mmu, mmu->lpac_pagetable); - - device->qdss_desc = kgsl_allocate_global_fixed(device, - "qcom,gpu-qdss-stm", "gpu-qdss"); + /* QDSS is supported only when CORESIGHT is enabled */ + if (IS_ENABLED(CONFIG_CORESIGHT)) + device->qdss_desc = kgsl_allocate_global_fixed(device, + "qcom,gpu-qdss-stm", "gpu-qdss"); device->qtimer_desc = kgsl_allocate_global_fixed(device, "qcom,gpu-timer", "gpu-qtimer"); diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 2831803a1817..6b9e43ec330d 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -1426,6 +1426,9 @@ static int _get_clocks(struct kgsl_device *device) for (i = 0; i < KGSL_MAX_CLKS; i++) { if (pwr->grp_clks[i] || strcmp(clocks[i], name)) continue; + /* apb_pclk should only be enabled if CORESIGHT is enabled */ + if (!strcmp(name, "apb_pclk") && !IS_ENABLED(CONFIG_CORESIGHT)) + continue; pwr->grp_clks[i] = devm_clk_get(dev, name); From 9aa8900a4ca5f8e497b0e479132d4053e125bc2b Mon Sep 17 00:00:00 2001 From: Lijuan Gao Date: Tue, 1 Jun 2021 10:41:35 +0800 Subject: [PATCH 38/67] defconfig: sdxnightjar: Enable Panic on for scheduler and RT throttling Enable Panic on for scheduler and RT throttling for sdxnightjar. Change-Id: Ie958aac9c329e2d8761a120349652e882cdb72ed Signed-off-by: Lijuan Gao --- arch/arm/configs/vendor/sdxnightjar-debug.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/vendor/sdxnightjar-debug.config b/arch/arm/configs/vendor/sdxnightjar-debug.config index 84d8a55ee6ea..82e13f7a4b1b 100644 --- a/arch/arm/configs/vendor/sdxnightjar-debug.config +++ b/arch/arm/configs/vendor/sdxnightjar-debug.config @@ -890,3 +890,5 @@ CONFIG_QTI_SYSTEM_PM_RPM=y CONFIG_HARDENED_USERCOPY=y CONFIG_STM_PROTO_BASIC=y CONFIG_QTI_ADC_TM=y +CONFIG_PANIC_ON_SCHED_BUG=y +CONFIG_PANIC_ON_RT_THROTTLING=y From 162bae29c8fae8abb04dba9fc5f116578d61f4fc Mon Sep 17 00:00:00 2001 From: lijuang Date: Fri, 30 Apr 2021 16:01:56 +0800 Subject: [PATCH 39/67] defconfig: sdxnightjar: disable unnecessary network driver Disable unused ethernet driver for sdxnightjar. Change-Id: Iabf645ec131e9c9c4a64cd93ad09d8c4e788a9a7 Signed-off-by: lijuang --- arch/arm/configs/vendor/sdxnightjar.config | 72 ++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/arch/arm/configs/vendor/sdxnightjar.config b/arch/arm/configs/vendor/sdxnightjar.config index 2b5b98783c9b..9a5eeb11a235 100644 --- a/arch/arm/configs/vendor/sdxnightjar.config +++ b/arch/arm/configs/vendor/sdxnightjar.config @@ -64,6 +64,62 @@ CONFIG_INTERCONNECT_TEST=y CONFIG_INTERCONNECT_QCOM=y CONFIG_DEBUG_FS=y CONFIG_ARCH_SDXNIGHTJAR=y +CONFIG_ETHERNET=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_AGERE is not set +# CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_ALTEON is not set +# CONFIG_ALTERA_TSE is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +CONFIG_NET_VENDOR_ATHEROS=y +# CONFIG_ATL2 is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_ALX is not set +# CONFIG_NET_VENDOR_AURORA is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_CADENCE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_GOOGLE is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_HP is not set +# CONFIG_NET_VENDOR_HUAWEI is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_JME is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MICROSEMI is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_FEALNX is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETERION is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_NI is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_ETHOC is not set +# CONFIG_NET_VENDOR_PACKET_ENGINES is not set +# CONFIG_NET_VENDOR_PENSANDO is not set +# CONFIG_NET_VENDOR_QLOGIC is not set CONFIG_PINCTRL_SDXNIGHTJAR=y # CONFIG_ARCH_SDXLEMUR is not set # CONFIG_PINCTRL_SDXLEMUR is not set @@ -926,3 +982,19 @@ CONFIG_PCIEPORTBUS=y CONFIG_PCIEAER=y CONFIG_PCI_QTI=y CONFIG_PCIEASPM_POWER_SUPERSAVE=y +# CONFIG_WLAN_VENDOR_ADMTEK is not set +# CONFIG_WLAN_VENDOR_ATH is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_CISCO is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_ST is not set +# CONFIG_WLAN_VENDOR_TI is not set +# CONFIG_WLAN_VENDOR_ZYDAS is not set +# CONFIG_WLAN_VENDOR_QUANTENNA is not set From a2261d88bad89e1522d1d66e4deacf88f085f2bd Mon Sep 17 00:00:00 2001 From: Mohammed Siddiq Date: Thu, 3 Jun 2021 20:23:53 +0530 Subject: [PATCH 40/67] cnss2: Properly send adsp power collapse enable/disable cmds Add code to properly handle sending adsp power collapse enable & disable cmds. Change-Id: I405b302180c0a6598592bf3dbad92976549d6d4b Signed-off-by: Mohammed Siddiq --- drivers/net/wireless/cnss2/main.c | 4 ++++ drivers/net/wireless/cnss2/main.h | 1 + drivers/net/wireless/cnss2/pci.c | 8 ++++++++ 3 files changed, 13 insertions(+) diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c index 2ab4c521c83c..9707beef230f 100644 --- a/drivers/net/wireless/cnss2/main.c +++ b/drivers/net/wireless/cnss2/main.c @@ -3053,6 +3053,10 @@ static void cnss_init_control_params(struct cnss_plat_data *plat_priv) plat_priv->ctrl_params.qmi_timeout = CNSS_QMI_TIMEOUT_DEFAULT; plat_priv->ctrl_params.bdf_type = CNSS_BDF_TYPE_DEFAULT; plat_priv->ctrl_params.time_sync_period = CNSS_TIME_SYNC_PERIOD_DEFAULT; + /* Set adsp_pc_enabled default value to true as ADSP pc is always + * enabled by default + */ + plat_priv->adsp_pc_enabled = true; } static void cnss_get_pm_domain_info(struct cnss_plat_data *plat_priv) diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h index 0c9ef48b3255..97115c84b1a8 100644 --- a/drivers/net/wireless/cnss2/main.h +++ b/drivers/net/wireless/cnss2/main.h @@ -505,6 +505,7 @@ struct cnss_plat_data { u32 is_converged_dt; struct device_node *dev_node; u64 feature_list; + bool adsp_pc_enabled; }; #ifdef CONFIG_ARCH_QCOM diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index e061547285df..624bd8470989 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -1802,6 +1802,13 @@ static int cnss_wlan_adsp_pc_enable(struct cnss_pci_data *pci_priv, struct pci_dev *pci_dev = pci_priv->pci_dev; int ret = 0; u32 pm_options = PM_OPTIONS_DEFAULT; + struct cnss_plat_data *plat_priv = pci_priv->plat_priv; + + if (plat_priv->adsp_pc_enabled == control) { + cnss_pr_dbg("ADSP power collapse already %s\n", + control ? "Enabled" : "Disabled"); + return 0; + } if (control) pm_options &= ~MSM_PCIE_CONFIG_NO_DRV_PC; @@ -1814,6 +1821,7 @@ static int cnss_wlan_adsp_pc_enable(struct cnss_pci_data *pci_priv, return ret; cnss_pr_dbg("%s ADSP power collapse\n", control ? "Enable" : "Disable"); + plat_priv->adsp_pc_enabled = control; return 0; } #else From a332b9453b80830aebf9caf89ee838298a1c6810 Mon Sep 17 00:00:00 2001 From: Mukesh Kumar Savaliya Date: Tue, 25 May 2021 09:57:49 +0530 Subject: [PATCH 41/67] spi: spi-msm-geni: Put device to suspend if PM status is active This change is to keep the device to autosuspend only if runtime PM status is not suspended. SPI driver resumes only if runtime PM is active, if framework calls unprepare_message/unprepare_hardware and if we try to keep driver to autosuspend, it may result into negative usage count. Also ensure for the PM calls, runtime is always enabled and if not, do not call PM. Change-Id: I8cf3f6deb776e282edce4b488e80c639d697374e Signed-off-by: Mukesh Kumar Savaliya --- drivers/spi/spi-msm-geni.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-msm-geni.c b/drivers/spi/spi-msm-geni.c index 5f350c02fc8a..954144323254 100644 --- a/drivers/spi/spi-msm-geni.c +++ b/drivers/spi/spi-msm-geni.c @@ -1106,7 +1106,8 @@ static int spi_geni_unprepare_message(struct spi_master *spi_mas, GENI_SE_ERR(mas->ipc, false, NULL, "suspend usage count mismatch:%d", count); - } else if (!pm_runtime_suspended(mas->dev)) { + } else if (!pm_runtime_status_suspended(mas->dev) && + pm_runtime_enabled(mas->dev)) { pm_runtime_mark_last_busy(mas->dev); pm_runtime_put_autosuspend(mas->dev); } @@ -1421,7 +1422,8 @@ static int spi_geni_unprepare_transfer_hardware(struct spi_master *spi) if (count < 0) GENI_SE_ERR(mas->ipc, false, NULL, "suspend usage count mismatch:%d", count); - } else { + } else if (!pm_runtime_status_suspended(mas->dev) && + pm_runtime_enabled(mas->dev)) { pm_runtime_mark_last_busy(mas->dev); pm_runtime_put_autosuspend(mas->dev); } From 235463e65a2a39c430f6b70a4bc771e3fcdf5c6a Mon Sep 17 00:00:00 2001 From: shiwgupt Date: Tue, 1 Jun 2021 14:45:34 +0530 Subject: [PATCH 42/67] dt-bindings: msm: Add bindings for flash type Add binding support for flash type. CRs-Fixed: 2938804 Change-Id: Ie4c7978d9baf34456300f39cd1d607c693420862 Signed-off-by: shiwgupt --- include/dt-bindings/msm/msm-camera.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/dt-bindings/msm/msm-camera.h b/include/dt-bindings/msm/msm-camera.h index a1eca27a755c..0a5aadce4eb7 100644 --- a/include/dt-bindings/msm/msm-camera.h +++ b/include/dt-bindings/msm/msm-camera.h @@ -94,4 +94,9 @@ #define CAM_CPAS_RT_OT_FUSE 9 #define CAM_CPAS_FUSE_FEATURE_MAX 10 +/* Flash type*/ +#define CAM_FLASH_TYPE_GPIO 0 +#define CAM_FLASH_TYPE_I2C 1 +#define CAM_FLASH_TYPE_PMIC 2 + #endif From 4f93b5add48d73f1236e9838908bc80f4f858e4c Mon Sep 17 00:00:00 2001 From: Madhuri Medasani Date: Sun, 6 Jun 2021 12:40:09 +0530 Subject: [PATCH 43/67] clk: qcom: debugcc: Update the CPU mux offset for BLAIR Correct the mux offset for CPU debug mux to be able to measure the CPU frequencies. Change-Id: I042d36cc94c08b80142c86f545102c24b00ea7e5 Signed-off-by: Madhuri Medasani --- drivers/clk/qcom/debugcc-blair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/debugcc-blair.c b/drivers/clk/qcom/debugcc-blair.c index 998f0d4ffebf..b8b55554678b 100644 --- a/drivers/clk/qcom/debugcc-blair.c +++ b/drivers/clk/qcom/debugcc-blair.c @@ -240,7 +240,7 @@ static const char *const gcc_debug_mux_parent_names[] = { }; static int gcc_debug_mux_sels[] = { - 0xBA, /* cpu_cc_debug_mux */ + 0xBF, /* cpu_cc_debug_mux */ 0x43, /* disp_cc_debug_mux */ 0x67, /* gcc_ahb2phy_csi_clk */ 0x68, /* gcc_ahb2phy_usb_clk */ From c039a777cc63097d2a074060acd369c895203acd Mon Sep 17 00:00:00 2001 From: Sahitya Tummala Date: Fri, 28 May 2021 19:37:59 +0530 Subject: [PATCH 44/67] Revert "aio: only use blk plugs for > 2 depth submissions" This reverts commit a79d40e9b0f309dcddc4e0bf5b64e51e28153e55. This is to fix the performance regression of storage tests observed with fio benchmark. Change-Id: I914bae800d6c7483639551d0ed7f6094b866fa12 Signed-off-by: Sahitya Tummala --- fs/aio.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 47bb7b5685ba..51dd01b578c5 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -71,12 +71,6 @@ struct aio_ring { struct io_event io_events[0]; }; /* 128 bytes + ring size */ -/* - * Plugging is meant to work with larger batches of IOs. If we don't - * have more than the below, then don't bother setting up a plug. - */ -#define AIO_PLUG_THRESHOLD 2 - #define AIO_RING_PAGES 8 struct kioctx_table { @@ -1932,8 +1926,7 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr, if (nr > ctx->nr_events) nr = ctx->nr_events; - if (nr > AIO_PLUG_THRESHOLD) - blk_start_plug(&plug); + blk_start_plug(&plug); for (i = 0; i < nr; i++) { struct iocb __user *user_iocb; @@ -1946,8 +1939,7 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr, if (ret) break; } - if (nr > AIO_PLUG_THRESHOLD) - blk_finish_plug(&plug); + blk_finish_plug(&plug); percpu_ref_put(&ctx->users); return i ? i : ret; @@ -1974,8 +1966,7 @@ COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id, if (nr > ctx->nr_events) nr = ctx->nr_events; - if (nr > AIO_PLUG_THRESHOLD) - blk_start_plug(&plug); + blk_start_plug(&plug); for (i = 0; i < nr; i++) { compat_uptr_t user_iocb; @@ -1988,8 +1979,7 @@ COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id, if (ret) break; } - if (nr > AIO_PLUG_THRESHOLD) - blk_finish_plug(&plug); + blk_finish_plug(&plug); percpu_ref_put(&ctx->users); return i ? i : ret; From afa85aa291e848cce802f2fe6903687479e970d2 Mon Sep 17 00:00:00 2001 From: Pradeep P V K Date: Mon, 17 May 2021 15:51:08 +0530 Subject: [PATCH 45/67] mtd: msm_qpic_nand: Enable one code word read along with PS read Enable one code word read support along with pagescope read feature support. Change-Id: Ib99a37140ec1bd929be34ebf21cd177df6493257 Signed-off-by: Pradeep P V K --- drivers/mtd/devices/msm_qpic_nand.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c index 7de758780067..e93965cd1ee8 100644 --- a/drivers/mtd/devices/msm_qpic_nand.c +++ b/drivers/mtd/devices/msm_qpic_nand.c @@ -2941,7 +2941,14 @@ static int msm_nand_read_partial_page(struct mtd_info *mtd, no_copy = false; ops->datbuf = no_copy ? actual_buf : bounce_buf; - if (info->nand_chip.caps & MSM_NAND_CAP_PAGE_SCOPE_READ) + + /* + * Do a Pagescope read only if PAGE_SCOPE_READ is enabled + * and request length is greater than codeword size or + * the page offset is not aligned to start of the page. + */ + if ((info->nand_chip.caps & MSM_NAND_CAP_PAGE_SCOPE_READ) && + ((len > ONE_CODEWORD_SIZE) || (offset != 0))) err = msm_nand_read_pagescope(mtd, aligned_from, ops); else { if ((len <= ONE_CODEWORD_SIZE) && (offset == 0)) From 5bcb9da72ba316472a45e0073367fbf768b69d5d Mon Sep 17 00:00:00 2001 From: Kavya Nunna Date: Wed, 7 Apr 2021 17:56:56 +0530 Subject: [PATCH 46/67] qpnp-regulator: Add support for pm6125 regulators Add support for HFSMPS, FTSMPS and other LDOs supported on PM6125. Change-Id: I2c9062876417915adeb9e739625adbbc58da8ff4 Signed-off-by: Kavya Nunna --- drivers/regulator/qpnp-regulator.c | 243 ++++++++++++++++++++++++++--- 1 file changed, 223 insertions(+), 20 deletions(-) diff --git a/drivers/regulator/qpnp-regulator.c b/drivers/regulator/qpnp-regulator.c index a78029d978da..b9cc97dd5d0d 100644 --- a/drivers/regulator/qpnp-regulator.c +++ b/drivers/regulator/qpnp-regulator.c @@ -53,6 +53,9 @@ enum qpnp_regulator_logical_type { QPNP_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS, QPNP_REGULATOR_LOGICAL_TYPE_ULT_LDO, QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS2, + QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3, + QPNP_REGULATOR_LOGICAL_TYPE_LDO_510, + QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS, }; enum qpnp_regulator_type { @@ -103,6 +106,17 @@ enum qpnp_regulator_subtype { QPNP_REGULATOR_SUBTYPE_ULT_HF_CTL2 = 0x0E, QPNP_REGULATOR_SUBTYPE_ULT_HF_CTL3 = 0x0F, QPNP_REGULATOR_SUBTYPE_ULT_HF_CTL4 = 0x10, + QPNP_REGULATOR_SUBTYPE_HFSMPS_510 = 0x0A, + QPNP_REGULATOR_SUBTYPE_FTSMPS_510 = 0x0B, + QPNP_REGULATOR_SUBTYPE_LV_P150_510 = 0x71, + QPNP_REGULATOR_SUBTYPE_LV_P300_510 = 0x72, + QPNP_REGULATOR_SUBTYPE_LV_P600_510 = 0x73, + QPNP_REGULATOR_SUBTYPE_N300_510 = 0x6A, + QPNP_REGULATOR_SUBTYPE_N600_510 = 0x6B, + QPNP_REGULATOR_SUBTYPE_N1200_510 = 0x6C, + QPNP_REGULATOR_SUBTYPE_MV_P50_510 = 0x7A, + QPNP_REGULATOR_SUBTYPE_MV_P150_510 = 0x7B, + QPNP_REGULATOR_SUBTYPE_MV_P600_510 = 0x7D, }; /* First common register layout used by older devices */ @@ -130,6 +144,11 @@ enum qpnp_common2_regulator_registers { QPNP_COMMON2_REG_STEP_CTRL = 0x61, }; +enum qpnp_common3_regulator_registers { + QPNP_COMMON3_REG_STEP_CTRL = 0x3C, +}; + + enum qpnp_ldo_registers { QPNP_LDO_REG_SOFT_START = 0x4C, }; @@ -191,6 +210,15 @@ enum qpnp_common2_control_register_index { #define QPNP_COMMON2_MODE_MASK 0x07 +/* Third common regulator mode register values */ +#define QPNP_COMMON3_MODE_BYPASS 2 +#define QPNP_COMMON3_MODE_RETENTION 3 +#define QPNP_COMMON3_MODE_LPM 4 +#define QPNP_COMMON3_MODE_AUTO 6 +#define QPNP_COMMON3_MODE_HPM 7 + +#define QPNP_COMMON3_MODE_MASK 0x07 + /* Common regulator pull down control register layout */ #define QPNP_COMMON_PULL_DOWN_ENABLE_MASK 0x80 @@ -251,6 +279,9 @@ enum qpnp_common2_control_register_index { #define QPNP_FTSMPS2_STEP_MARGIN_NUM 10 #define QPNP_FTSMPS2_STEP_MARGIN_DEN 11 +/* slew_rate has units of uV/us. */ +#define QPNP_COMMON3_FTSMPS3_SLEW_RATE_38p4 38400 + /* * This voltage in uV is returned by get_voltage functions when there is no way * to determine the current voltage level. It is needed because the regulator @@ -451,6 +482,26 @@ static struct qpnp_voltage_range ftsmps426_ranges[] = { VOLTAGE_RANGE(0, 0, 320000, 1352000, 1352000, 4000), }; +static struct qpnp_voltage_range pldo_510_ranges[] = { + VOLTAGE_RANGE(0, 1504000, 1504000, 2000000, 2000000, 8000), +}; + +static struct qpnp_voltage_range mv_pldo_510_ranges[] = { + VOLTAGE_RANGE(0, 1504000, 1504000, 3544000, 3544000, 8000), +}; + +static struct qpnp_voltage_range nldo_510_ranges[] = { + VOLTAGE_RANGE(0, 320000, 320000, 1304000, 1304000, 8000), +}; + +static struct qpnp_voltage_range hfsmps510_ranges[] = { + VOLTAGE_RANGE(0, 320000, 320000, 2040000, 2040000, 8000), +}; + +static struct qpnp_voltage_range ftsmps510_ranges[] = { + VOLTAGE_RANGE(0, 300000, 300000, 1372000, 1372000, 4000), +}; + static struct qpnp_voltage_set_points pldo_set_points = SET_POINTS(pldo_ranges); static struct qpnp_voltage_set_points nldo1_set_points = SET_POINTS(nldo1_ranges); @@ -479,6 +530,16 @@ static struct qpnp_voltage_set_points ult_pldo_set_points = SET_POINTS(ult_pldo_ranges); static struct qpnp_voltage_set_points ftsmps426_set_points = SET_POINTS(ftsmps426_ranges); +static struct qpnp_voltage_set_points pldo_510_set_points + = SET_POINTS(pldo_510_ranges); +static struct qpnp_voltage_set_points mv_pldo_510_set_points + = SET_POINTS(mv_pldo_510_ranges); +static struct qpnp_voltage_set_points nldo_510_set_points + = SET_POINTS(nldo_510_ranges); +static struct qpnp_voltage_set_points hfsmps510_set_points + = SET_POINTS(hfsmps510_ranges); +static struct qpnp_voltage_set_points ftsmps510_set_points + = SET_POINTS(ftsmps510_ranges); static struct qpnp_voltage_set_points none_set_points; static struct qpnp_voltage_set_points *all_set_points[] = { @@ -497,6 +558,11 @@ static struct qpnp_voltage_set_points *all_set_points[] = { &ult_nldo_set_points, &ult_pldo_set_points, &ftsmps426_set_points, + &pldo_510_set_points, + &mv_pldo_510_set_points, + &nldo_510_set_points, + &hfsmps510_set_points, + &ftsmps510_set_points, }; /* Determines which label to add to a debug print statement. */ @@ -1212,12 +1278,27 @@ static int qpnp_regulator_common2_set_mode(struct regulator_dev *rdev, * ensures that AUTO mode is re-asserted after switching away from * forced HPM if it was configured initially. */ - if (mode == REGULATOR_MODE_NORMAL) - val = QPNP_COMMON2_MODE_HPM; - else if (vreg->init_mode == QPNP_COMMON2_MODE_HPM) - val = QPNP_COMMON2_MODE_LPM; - else - val = vreg->init_mode; + if ((vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) || + (vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS) || + (vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_LDO_510)) { + if (mode == REGULATOR_MODE_NORMAL) + val = QPNP_COMMON3_MODE_HPM; + else if (vreg->init_mode == QPNP_COMMON3_MODE_HPM && + vreg->logical_type != + QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) + val = QPNP_COMMON3_MODE_LPM; + else if (vreg->init_mode == QPNP_COMMON3_MODE_HPM) + val = QPNP_COMMON3_MODE_RETENTION; + else + val = vreg->init_mode; + } else { + if (mode == REGULATOR_MODE_NORMAL) + val = QPNP_COMMON2_MODE_HPM; + else if (vreg->init_mode == QPNP_COMMON2_MODE_HPM) + val = QPNP_COMMON2_MODE_LPM; + else + val = vreg->init_mode; + } rc = qpnp_vreg_write_optimized(vreg, QPNP_COMMON2_REG_MODE, &val, &vreg->ctrl_reg[QPNP_COMMON2_IDX_MODE], 1); @@ -1335,6 +1416,18 @@ static const char * const qpnp_common2_mode_label[] = { [QPNP_COMMON2_MODE_HPM] = "HPM", }; +static const char * const qpnp_common3_mode_label[] = { + [0] = "RSV", + [1] = "RSV", + [2] = "RSV", + [QPNP_COMMON3_MODE_BYPASS] = "BYP", + [QPNP_COMMON3_MODE_RETENTION] = "RET", + [QPNP_COMMON3_MODE_LPM] = "LPM", + [QPNP_COMMON3_MODE_AUTO] = "AUTO", + [QPNP_COMMON3_MODE_HPM] = "HPM", +}; + + static void qpnp_vreg_show_state(struct regulator_dev *rdev, enum qpnp_regulator_action action) { @@ -1495,6 +1588,16 @@ static void qpnp_vreg_show_state(struct regulator_dev *rdev, action_label, vreg->rdesc.name, enable_label, uV, mode_label); break; + case QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS: + case QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3: + case QPNP_REGULATOR_LOGICAL_TYPE_LDO_510: + mode_reg = vreg->ctrl_reg[QPNP_COMMON_IDX_MODE]; + mode_label = qpnp_common3_mode_label[mode_reg + & QPNP_COMMON3_MODE_MASK]; + pr_info("%s %-11s: %s, v=%7d uV, mode=%s\n", + action_label, vreg->rdesc.name, enable_label, uV, + mode_label); + break; default: break; } @@ -1618,6 +1721,45 @@ static struct regulator_ops qpnp_ftsmps426_ops = { .enable_time = qpnp_regulator_common_enable_time, }; +static struct regulator_ops qpnp_hfsmps510_ops = { + .enable = qpnp_regulator_common_enable, + .disable = qpnp_regulator_common_disable, + .is_enabled = qpnp_regulator_common_is_enabled, + .set_voltage = qpnp_regulator_common2_set_voltage, + .get_voltage = qpnp_regulator_common2_get_voltage, + .list_voltage = qpnp_regulator_common_list_voltage, + .set_mode = qpnp_regulator_common2_set_mode, + .get_mode = qpnp_regulator_common2_get_mode, + .get_optimum_mode = qpnp_regulator_common_get_optimum_mode, + .enable_time = qpnp_regulator_common_enable_time, +}; + +static struct regulator_ops qpnp_ftsmps510_ops = { + .enable = qpnp_regulator_common_enable, + .disable = qpnp_regulator_common_disable, + .is_enabled = qpnp_regulator_common_is_enabled, + .set_voltage = qpnp_regulator_common2_set_voltage, + .get_voltage = qpnp_regulator_common2_get_voltage, + .list_voltage = qpnp_regulator_common_list_voltage, + .set_mode = qpnp_regulator_common2_set_mode, + .get_mode = qpnp_regulator_common2_get_mode, + .get_optimum_mode = qpnp_regulator_common_get_optimum_mode, + .enable_time = qpnp_regulator_common_enable_time, +}; + +static struct regulator_ops qpnp_ldo_510_ops = { + .enable = qpnp_regulator_common_enable, + .disable = qpnp_regulator_common_disable, + .is_enabled = qpnp_regulator_common_is_enabled, + .set_voltage = qpnp_regulator_common2_set_voltage, + .get_voltage = qpnp_regulator_common2_get_voltage, + .list_voltage = qpnp_regulator_common_list_voltage, + .set_mode = qpnp_regulator_common2_set_mode, + .get_mode = qpnp_regulator_common2_get_mode, + .get_optimum_mode = qpnp_regulator_common_get_optimum_mode, + .enable_time = qpnp_regulator_common_enable_time, +}; + /* Maximum possible digital major revision value */ #define INF 0xFF @@ -1679,8 +1821,27 @@ static const struct qpnp_regulator_mapping supported_regulators[] = { 10000), QPNP_VREG_MAP(ULT_LDO, P50, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 5000), - QPNP_VREG_MAP(FTS, FTS426, 0, INF, FTSMPS2, ftsmps426, ftsmps426, + QPNP_VREG_MAP(FTS, FTS426, 0, INF, FTSMPS2, ftsmps426, ftsmps426, 100000), + QPNP_VREG_MAP(LDO, LV_P150_510, 0, INF, LDO_510, ldo_510, pldo_510, + 10000), + QPNP_VREG_MAP(LDO, LV_P300_510, 0, INF, LDO_510, ldo_510, pldo_510, + 10000), + QPNP_VREG_MAP(LDO, LV_P600_510, 0, INF, LDO_510, ldo_510, pldo_510, + 10000), + QPNP_VREG_MAP(LDO, MV_P50_510, 0, INF, LDO_510, ldo_510, mv_pldo_510, + 10000), + QPNP_VREG_MAP(LDO, MV_P150_510, 0, INF, LDO_510, ldo_510, mv_pldo_510, + 10000), + QPNP_VREG_MAP(LDO, MV_P600_510, 0, INF, LDO_510, ldo_510, mv_pldo_510, + 10000), + QPNP_VREG_MAP(LDO, N300_510, 0, INF, LDO_510, ldo_510, nldo_510, 10000), + QPNP_VREG_MAP(LDO, N600_510, 0, INF, LDO_510, ldo_510, nldo_510, 10000), + QPNP_VREG_MAP(LDO, N1200_510, 0, INF, LDO_510, ldo_510, nldo_510, 10000), + QPNP_VREG_MAP(BUCK, HFSMPS_510, 0, INF, HFSMPS, hfsmps510, hfsmps510, + 100000), + QPNP_VREG_MAP(FTS, FTSMPS_510, 0, INF, FTSMPS3, ftsmps510, ftsmps510, + 100000), }; static int qpnp_regulator_match(struct qpnp_regulator *vreg) @@ -1792,10 +1953,18 @@ static int qpnp_regulator_ftsmps2_init_slew_rate(struct qpnp_regulator *vreg) int i, rc, delay; u8 reg = 0; - rc = qpnp_vreg_read(vreg, QPNP_COMMON2_REG_STEP_CTRL, ®, 1); - if (rc) { - vreg_err(vreg, "spmi read failed, rc=%d\n", rc); - return rc; + if (vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) { + rc = qpnp_vreg_read(vreg, QPNP_COMMON3_REG_STEP_CTRL, ®, 1); + if (rc) { + vreg_err(vreg, "spmi read failed, rc=%d\n", rc); + return rc; + } + } else { + rc = qpnp_vreg_read(vreg, QPNP_COMMON2_REG_STEP_CTRL, ®, 1); + if (rc) { + vreg_err(vreg, "spmi read failed, rc=%d\n", rc); + return rc; + } } /* @@ -1817,14 +1986,18 @@ static int qpnp_regulator_ftsmps2_init_slew_rate(struct qpnp_regulator *vreg) delay = (reg & QPNP_FTSMPS2_STEP_CTRL_DELAY_MASK) >> QPNP_FTSMPS2_STEP_CTRL_DELAY_SHIFT; - /* slew_rate has units of uV/us. */ - vreg->slew_rate = QPNP_FTSMPS2_CLOCK_RATE * range->step_uV; - vreg->slew_rate /= 1000 * (QPNP_FTSMPS2_STEP_DELAY << delay); - vreg->slew_rate = vreg->slew_rate * QPNP_FTSMPS2_STEP_MARGIN_NUM - / QPNP_FTSMPS2_STEP_MARGIN_DEN; + if (vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) { + vreg->slew_rate = QPNP_COMMON3_FTSMPS3_SLEW_RATE_38p4 >> delay; + } else { + /* slew_rate has units of uV/us. */ + vreg->slew_rate = QPNP_FTSMPS2_CLOCK_RATE * range->step_uV; + vreg->slew_rate /= 1000 * (QPNP_FTSMPS2_STEP_DELAY << delay); + vreg->slew_rate = vreg->slew_rate * QPNP_FTSMPS2_STEP_MARGIN_NUM + / QPNP_FTSMPS2_STEP_MARGIN_DEN; - /* Ensure that the slew rate is greater than 0. */ - vreg->slew_rate = max(vreg->slew_rate, 1); + /* Ensure that the slew rate is greater than 0. */ + vreg->slew_rate = max(vreg->slew_rate, 1); + } return rc; } @@ -1905,6 +2078,35 @@ static int qpnp_regulator_init_registers(struct qpnp_regulator *vreg, = QPNP_COMMON2_MODE_LPM; } + if (type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3 || + type == QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS || + type == QPNP_REGULATOR_LOGICAL_TYPE_LDO_510) { + if (pdata->hpm_enable == QPNP_REGULATOR_ENABLE) + ctrl_reg[QPNP_COMMON2_IDX_MODE] + = QPNP_COMMON3_MODE_HPM; + else if (pdata->auto_mode_enable == QPNP_REGULATOR_ENABLE + && type == QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS) + ctrl_reg[QPNP_COMMON2_IDX_MODE] + = QPNP_COMMON3_MODE_AUTO; + else if (pdata->hpm_enable == QPNP_REGULATOR_DISABLE + && ctrl_reg[QPNP_COMMON2_IDX_MODE] + == QPNP_COMMON3_MODE_HPM && + type != QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) + ctrl_reg[QPNP_COMMON2_IDX_MODE] + = QPNP_COMMON3_MODE_LPM; + else if (pdata->hpm_enable == QPNP_REGULATOR_DISABLE + && ctrl_reg[QPNP_COMMON2_IDX_MODE] + == QPNP_COMMON3_MODE_HPM) + ctrl_reg[QPNP_COMMON2_IDX_MODE] + = QPNP_COMMON3_MODE_RETENTION; + else if (pdata->auto_mode_enable == QPNP_REGULATOR_DISABLE + && ctrl_reg[QPNP_COMMON2_IDX_MODE] + == QPNP_COMMON2_MODE_AUTO && + type == QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS) + ctrl_reg[QPNP_COMMON2_IDX_MODE] + = QPNP_COMMON2_MODE_LPM; + } + /* Set up mode pin control. */ if ((type == QPNP_REGULATOR_LOGICAL_TYPE_SMPS || type == QPNP_REGULATOR_LOGICAL_TYPE_LDO) @@ -2068,8 +2270,9 @@ static int qpnp_regulator_init_registers(struct qpnp_regulator *vreg, } } - /* Calculate the slew rate for FTSMPS2 regulators. */ - if (type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS2) { + /* Calculate the slew rate for FTSMPS2 and FTSMPS3 regulators. */ + if (type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS2 || + type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) { rc = qpnp_regulator_ftsmps2_init_slew_rate(vreg); if (rc) { vreg_err(vreg, "failed to initialize step rate, rc=%d\n", From 587afd086ea19ce2f5c4afc1c14b85f9b70c8743 Mon Sep 17 00:00:00 2001 From: Madhuri Medasani Date: Tue, 8 Jun 2021 19:01:01 +0530 Subject: [PATCH 47/67] clk: qcom: debugcc: Update the MCCC mux offset for BLAIR Correct the mux offset for MCCC debug mux to be able to measure the its frequencies. Change-Id: Id4ff67c3e195fe1633f34b86cc322a03f83a83c0 Signed-off-by: Madhuri Medasani --- drivers/clk/qcom/debugcc-blair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/debugcc-blair.c b/drivers/clk/qcom/debugcc-blair.c index 998f0d4ffebf..15bffa7b80fe 100644 --- a/drivers/clk/qcom/debugcc-blair.c +++ b/drivers/clk/qcom/debugcc-blair.c @@ -349,7 +349,7 @@ static int gcc_debug_mux_sels[] = { 0x15B, /* gcc_video_venus_ctl_clk */ 0x3F, /* gcc_video_xo_clk */ 0xFB, /* gpu_cc_debug_mux */ - 0xA9, /* mc_cc_debug_mux */ + 0xAE, /* mc_cc_debug_mux */ 0x38, /* measure_only_gcc_camera_ahb_clk */ 0x40, /* measure_only_gcc_camera_xo_clk */ 0xBA, /* measure_only_gcc_cpuss_gnoc_clk */ From e27a837f09cc3187be7f04efc2003713632beb31 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Tue, 8 Jun 2021 19:30:02 +0530 Subject: [PATCH 48/67] soc: qcom: Add snapshot for Cx iPeak limit driver Add snapshot of common driver to limit Cx ipeak based on voting from various clients in multimedia. Change-Id: I800cc3a08783f9f33761e1a68a2c3072c7294bc0 Signed-off-by: Manaf Meethalavalappu Pallikunhi --- drivers/soc/qcom/Kconfig | 9 + drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/cx_ipeak.c | 545 ++++++++++++++++++++++++++++++++++++ include/soc/qcom/cx_ipeak.h | 55 ++++ 4 files changed, 610 insertions(+) create mode 100644 drivers/soc/qcom/cx_ipeak.c create mode 100644 include/soc/qcom/cx_ipeak.h diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 69e47acd8f51..dc81f16da5e0 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -1062,6 +1062,15 @@ config QCOM_WDT_CORE watchdog module must be loaded along with this for watchdog functionality. +config QCOM_CX_IPEAK + tristate "Common driver to handle Cx iPeak limitation" + help + Cx ipeak HW module is used to limit the current drawn by various + subsystem blocks on Cx power rail. Each client needs to set their + bit in tcsr register if it is going to cross its own threshold. + If all clients are going to cross their thresholds then Cx ipeak + hw module will raise an interrupt to cDSP block to throttle cDSP fmax. + config QCOM_SOC_WATCHDOG tristate "Qualcomm Technologies, Inc. Soc Watchdog" depends on QCOM_WDT_CORE diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index d6fbdcb8fb12..c2eb202f561a 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -120,6 +120,7 @@ obj-$(CONFIG_MSM_SLATECOM_INTERFACE) += slatecom_interface.o obj-$(CONFIG_QCOM_AOP_SET_DDR) += aop-set-ddr.o obj-$(CONFIG_CPU_V7) += idle-v7.o obj-$(CONFIG_DUMP_XBL_LOG) += dump_boot_log.o +obj-$(CONFIG_QCOM_CX_IPEAK) += cx_ipeak.o # GNSS driver obj-$(CONFIG_GNSS_SIRF) += gnsssirf/ obj-$(CONFIG_MSM_SEB) += slate_events_bridge.o diff --git a/drivers/soc/qcom/cx_ipeak.c b/drivers/soc/qcom/cx_ipeak.c new file mode 100644 index 000000000000..72d7ecac9b02 --- /dev/null +++ b/drivers/soc/qcom/cx_ipeak.c @@ -0,0 +1,545 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define TCSR_CXIP_LM_VOTE_FEATURE_ENABLE_OFFSET 0x10 + +/* v1 register set */ +#define TCSR_CXIP_LM_VOTE_BYPASS_OFFSET 0x4 +#define TCSR_CXIP_LM_VOTE_CLEAR_OFFSET 0x8 +#define TCSR_CXIP_LM_VOTE_SET_OFFSET 0xC +#define TCSR_CXIP_LM_TRS_OFFSET 0x24 + +/* v2 register set */ +#define TCSR_CXIP_LM_VOTE_CLIENTx_BYPASS_OFFSET 0x4 +#define TCSR_CXIP_LM_DANGER_OFFSET 0x24 + +#define CXIP_CLIENT_OFFSET 0x1000 +#define CXIP_CLIENT10_OFFSET 0x3000 +#define CXIP_VICTIM_OFFSET 0xB000 + +#define CXIP_POLL_TIMEOUT_US (50 * 1000) + +#define CXIP_VICTIMS 3 +#define VICTIM_ENTRIES 3 + +struct cx_ipeak_client; + +struct cx_ipeak_core_ops { + int (*update)(struct cx_ipeak_client *client, bool vote); + struct cx_ipeak_client* (*register_client)(int client_id); +}; + +static struct cx_ipeak_victims { + u32 client_id; + u32 victim_id; + u32 freq_limit; + void *data; + cx_ipeak_victim_fn victim_cb; + struct cx_ipeak_client *client; +} victim_list[CXIP_VICTIMS]; + +static struct cx_ipeak_device { + struct platform_device *pdev; + struct mutex vote_lock; + struct mutex throttle_lock; + void __iomem *tcsr_vptr; + struct cx_ipeak_core_ops *core_ops; + u32 victims_count; + int danger_intr_num; + int safe_intr_num; +} device_ipeak; + +struct cx_ipeak_client { + u32 vote_count; + unsigned int offset; + u32 client_id; + bool danger_assert; + struct cx_ipeak_device *dev; +}; + + +/** + * cx_ipeak_register() - allocate client structure and fill device private and + * offset details. + * @dev_node: device node of the client + * @client_name: property name of the client + * + * Allocate client memory and fill the structure with device private and bit + * + */ +struct cx_ipeak_client *cx_ipeak_register(struct device_node *dev_node, + const char *client_name) +{ + struct of_phandle_args cx_spec; + struct cx_ipeak_client *client = NULL; + int ret; + + ret = of_parse_phandle_with_args(dev_node, client_name, + "#size-cells", 0, &cx_spec); + if (ret) + return ERR_PTR(-EINVAL); + + if (!of_device_is_available(cx_spec.np)) + return NULL; + + if (device_ipeak.tcsr_vptr == NULL) + return ERR_PTR(-EPROBE_DEFER); + + if (cx_spec.args[0] > 31) + return ERR_PTR(-EINVAL); + + if (device_ipeak.core_ops) + client = device_ipeak.core_ops->register_client + (cx_spec.args[0]); + + client->client_id = cx_spec.args[0]; + + return client; +} +EXPORT_SYMBOL(cx_ipeak_register); + +static struct cx_ipeak_client *cx_ipeak_register_v1(int client_id) +{ + struct cx_ipeak_client *client; + unsigned int reg_enable, reg_bypass; + void __iomem *vptr = device_ipeak.tcsr_vptr; + + reg_enable = readl_relaxed(device_ipeak.tcsr_vptr + + TCSR_CXIP_LM_VOTE_FEATURE_ENABLE_OFFSET); + reg_bypass = readl_relaxed(vptr + + TCSR_CXIP_LM_VOTE_BYPASS_OFFSET) & + BIT(client_id); + if (!reg_enable || reg_bypass) + return NULL; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return ERR_PTR(-ENOMEM); + + client->offset = BIT(client_id); + client->dev = &device_ipeak; + + return client; +} + +static struct cx_ipeak_client *cx_ipeak_register_v2(int client_id) +{ + unsigned int reg_bypass, reg_enable; + struct cx_ipeak_client *client; + unsigned int client_offset = 0; + void __iomem *vptr = device_ipeak.tcsr_vptr; + int i; + + for (i = 0; i <= client_id; i++) + client_offset += CXIP_CLIENT_OFFSET; + + if (client_id >= 10) + client_offset += CXIP_CLIENT10_OFFSET; + + reg_enable = readl_relaxed(device_ipeak.tcsr_vptr + + TCSR_CXIP_LM_VOTE_FEATURE_ENABLE_OFFSET); + reg_bypass = readl_relaxed(vptr + client_offset + + TCSR_CXIP_LM_VOTE_CLIENTx_BYPASS_OFFSET) & + BIT(0); + + if (!reg_enable || reg_bypass) + return NULL; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return ERR_PTR(-ENOMEM); + + client->offset = client_offset; + client->dev = &device_ipeak; + + return client; +} + +/** + * cx_ipeak_victim_register - victim registration API to handle + * the cx ipeak hw interrupts (danger/safe) to throttle freq. + * @client: cx ipeak client + * @victim_cb: callback function of victim + * @data: data to be passed to victim while handling irq + */ +int cx_ipeak_victim_register(struct cx_ipeak_client *client, + cx_ipeak_victim_fn victim_cb, void *data) +{ + int i = 0; + + if (!victim_cb) + return -EINVAL; + + for (i = 0; i < device_ipeak.victims_count; i++) + if (client->client_id == victim_list[i].client_id) { + victim_list[i].victim_cb = victim_cb; + victim_list[i].data = data; + victim_list[i].client = client; + return 0; + } + + return -ENOENT; +} +EXPORT_SYMBOL(cx_ipeak_victim_register); + +/** + * cx_ipeak_victim_unregister - unregister victim client from + * cx_ipeak driver. + * @client: cx ipeak client + */ + +void cx_ipeak_victim_unregister(struct cx_ipeak_client *client) +{ + int i = 0; + + for (i = 0; i < device_ipeak.victims_count; i++) + if (client->client_id == victim_list[i].client_id) { + victim_list[i].victim_cb = NULL; + victim_list[i].data = NULL; + victim_list[i].client = NULL; + } +} +EXPORT_SYMBOL(cx_ipeak_victim_unregister); + +/** + * cx_ipeak_update() - Set/Clear client vote for Cx iPeak limit + * manager to throttle cDSP. + * @client: client handle. + * @vote: True to set the vote and False for reset. + * + * Receives vote from each client and decides whether to throttle cDSP or not. + * This function is NOP for the targets which does not support TCSR Cx iPeak. + */ +int cx_ipeak_update(struct cx_ipeak_client *client, bool vote) +{ + /* Check for client and device availability and proceed */ + if (!client) + return 0; + + if (!client->dev || !client->dev->core_ops || !client->dev->tcsr_vptr) + return -EINVAL; + + return client->dev->core_ops->update(client, vote); +} +EXPORT_SYMBOL(cx_ipeak_update); + +static int cx_ipeak_update_v1(struct cx_ipeak_client *client, bool vote) +{ + unsigned int reg_val; + int ret = 0; + + mutex_lock(&client->dev->vote_lock); + + if (vote) { + if (client->vote_count == 0) { + writel_relaxed(client->offset, + client->dev->tcsr_vptr + + TCSR_CXIP_LM_VOTE_SET_OFFSET); + /* + * Do a dummy read to give enough time for TRS register + * to become 1 when the last client votes. + */ + readl_relaxed(client->dev->tcsr_vptr + + TCSR_CXIP_LM_TRS_OFFSET); + + ret = readl_poll_timeout(client->dev->tcsr_vptr + + TCSR_CXIP_LM_TRS_OFFSET, + reg_val, !reg_val, 0, + CXIP_POLL_TIMEOUT_US); + if (ret) { + writel_relaxed(client->offset, + client->dev->tcsr_vptr + + TCSR_CXIP_LM_VOTE_CLEAR_OFFSET); + goto done; + } + } + client->vote_count++; + } else { + if (client->vote_count > 0) { + client->vote_count--; + if (client->vote_count == 0) { + writel_relaxed(client->offset, + client->dev->tcsr_vptr + + TCSR_CXIP_LM_VOTE_CLEAR_OFFSET); + } + } else + ret = -EINVAL; + } + +done: + mutex_unlock(&client->dev->vote_lock); + return ret; +} + +static int cx_ipeak_update_v2(struct cx_ipeak_client *client, bool vote) +{ + u32 reg_val; + int ret = 0; + + mutex_lock(&client->dev->vote_lock); + + if (vote) { + if (client->vote_count == 0) { + writel_relaxed(BIT(0), + client->dev->tcsr_vptr + + client->offset); + + ret = readl_poll_timeout( + client->dev->tcsr_vptr + + TCSR_CXIP_LM_DANGER_OFFSET, + reg_val, !reg_val || + client->danger_assert, + 0, CXIP_POLL_TIMEOUT_US); + /* + * If poll exits due to danger assert condition return + * error to client to avoid voting. + */ + if (client->danger_assert) + ret = -ETIMEDOUT; + + if (ret) { + writel_relaxed(0, + client->dev->tcsr_vptr + + client->offset); + goto done; + } + } + client->vote_count++; + } else { + if (client->vote_count > 0) { + client->vote_count--; + if (client->vote_count == 0) { + writel_relaxed(0, + client->dev->tcsr_vptr + + client->offset); + } + } else { + ret = -EINVAL; + } + } + +done: + mutex_unlock(&client->dev->vote_lock); + return ret; +} + +static irqreturn_t cx_ipeak_irq_soft_handler(int irq, void *data) +{ + int i; + irqreturn_t ret = IRQ_NONE; + + mutex_lock(&device_ipeak.throttle_lock); + + for (i = 0; i < device_ipeak.victims_count; i++) { + cx_ipeak_victim_fn victim_cb = victim_list[i].victim_cb; + struct cx_ipeak_client *victim_client = victim_list[i].client; + + if (!victim_cb || !victim_client) + continue; + + if (irq == device_ipeak.danger_intr_num) { + + victim_client->danger_assert = true; + + /* + * To set frequency limit at victim client + * side in danger interrupt case + */ + + ret = victim_cb(victim_list[i].data, + victim_list[i].freq_limit); + + if (ret) { + dev_err(&device_ipeak.pdev->dev, + "Unable to throttle client:%d freq:%d\n", + victim_list[i].client_id, + victim_list[i].freq_limit); + victim_client->danger_assert = false; + ret = IRQ_HANDLED; + goto done; + } + + writel_relaxed(1, (device_ipeak.tcsr_vptr + + CXIP_VICTIM_OFFSET + + ((victim_list[i].victim_id)* + CXIP_CLIENT_OFFSET))); + + ret = IRQ_HANDLED; + } else if (irq == device_ipeak.safe_intr_num) { + victim_client->danger_assert = false; + /* + * To remove frequency limit at victim client + * side in safe interrupt case + */ + ret = victim_cb(victim_list[i].data, 0); + + if (ret) + dev_err(&device_ipeak.pdev->dev, "Unable to remove freq limit client:%d\n", + victim_list[i].client_id); + + writel_relaxed(0, (device_ipeak.tcsr_vptr + + CXIP_VICTIM_OFFSET + + ((victim_list[i].victim_id)* + CXIP_CLIENT_OFFSET))); + ret = IRQ_HANDLED; + } + } +done: + mutex_unlock(&device_ipeak.throttle_lock); + return ret; +} + +int cx_ipeak_request_irq(struct platform_device *pdev, const char *name, + irq_handler_t handler, irq_handler_t thread_fn, void *data) +{ + int ret, num = platform_get_irq_byname(pdev, name); + + if (num < 0) + return num; + + ret = devm_request_threaded_irq(&pdev->dev, num, handler, thread_fn, + IRQF_ONESHOT | IRQF_TRIGGER_RISING, name, data); + + if (ret) + dev_err(&pdev->dev, "Unable to get interrupt %s: %d\n", + name, ret); + + return ret ? ret : num; +} + +/** + * cx_ipeak_unregister() - unregister client + * @client: client address to free + * + * Free the client memory + */ +void cx_ipeak_unregister(struct cx_ipeak_client *client) +{ + kfree(client); +} +EXPORT_SYMBOL(cx_ipeak_unregister); + +struct cx_ipeak_core_ops core_ops_v1 = { + .update = cx_ipeak_update_v1, + .register_client = cx_ipeak_register_v1, +}; + +struct cx_ipeak_core_ops core_ops_v2 = { + .update = cx_ipeak_update_v2, + .register_client = cx_ipeak_register_v2, +}; + +static int cx_ipeak_probe(struct platform_device *pdev) +{ + struct resource *res; + int i, ret, count; + u32 victim_en; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + device_ipeak.tcsr_vptr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(device_ipeak.tcsr_vptr)) + return PTR_ERR(device_ipeak.tcsr_vptr); + + if (of_device_is_compatible(pdev->dev.of_node, "qcom,cx-ipeak-v1")) + device_ipeak.core_ops = &core_ops_v1; + else if (of_device_is_compatible(pdev->dev.of_node, + "qcom,cx-ipeak-v2")) + device_ipeak.core_ops = &core_ops_v2; + else + device_ipeak.core_ops = NULL; + + victim_en = of_property_read_bool(pdev->dev.of_node, + "victims_table"); + + if (victim_en) { + count = of_property_count_u32_elems(pdev->dev.of_node, + "victims_table"); + + if (((count%VICTIM_ENTRIES) != 0) || + ((count/VICTIM_ENTRIES) > CXIP_VICTIMS)) + return -EINVAL; + + for (i = 0; i < (count/VICTIM_ENTRIES); i++) { + ret = of_property_read_u32_index(pdev->dev.of_node, + "victims_table", i*VICTIM_ENTRIES, + &victim_list[i].client_id); + + if (ret) + return ret; + + ret = of_property_read_u32_index(pdev->dev.of_node, + "victims_table", (i*VICTIM_ENTRIES) + 1, + &victim_list[i].victim_id); + + if (ret) + return ret; + + ret = of_property_read_u32_index(pdev->dev.of_node, + "victims_table", (i*VICTIM_ENTRIES) + 2, + &victim_list[i].freq_limit); + + if (ret) + return ret; + + device_ipeak.victims_count++; + } + + device_ipeak.danger_intr_num = cx_ipeak_request_irq(pdev, + "cx_ipeak_danger", NULL, + cx_ipeak_irq_soft_handler, NULL); + + if (device_ipeak.danger_intr_num < 0) + return device_ipeak.danger_intr_num; + + device_ipeak.safe_intr_num = cx_ipeak_request_irq(pdev, + "cx_ipeak_safe", NULL, + cx_ipeak_irq_soft_handler, NULL); + + if (device_ipeak.safe_intr_num < 0) + return device_ipeak.safe_intr_num; + + } + + device_ipeak.pdev = pdev; + mutex_init(&device_ipeak.vote_lock); + mutex_init(&device_ipeak.throttle_lock); + return 0; +} + +static const struct of_device_id cx_ipeak_match_table[] = { + { .compatible = "qcom,cx-ipeak-v1"}, + { .compatible = "qcom,cx-ipeak-v2"}, + {} +}; + +static struct platform_driver cx_ipeak_platform_driver = { + .probe = cx_ipeak_probe, + .driver = { + .name = "cx_ipeak", + .of_match_table = cx_ipeak_match_table, + .suppress_bind_attrs = true, + } +}; + +static int __init cx_ipeak_init(void) +{ + return platform_driver_register(&cx_ipeak_platform_driver); +} + +arch_initcall(cx_ipeak_init); + +MODULE_LICENSE("GPL v2"); diff --git a/include/soc/qcom/cx_ipeak.h b/include/soc/qcom/cx_ipeak.h new file mode 100644 index 000000000000..e07ac81fe127 --- /dev/null +++ b/include/soc/qcom/cx_ipeak.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018, 2021 The Linux Foundation. All rights reserved. + */ + +#ifndef __SOC_COM_CX_IPEAK_H +#define __SOC_COM_CX_IPEAK_H + +typedef int (*cx_ipeak_victim_fn)(void *data, u32 freq_limit); + +struct device_node; +struct cx_ipeak_client; + +#if IS_ENABLED(CONFIG_QCOM_CX_IPEAK) + +struct cx_ipeak_client *cx_ipeak_register(struct device_node *dev_node, + const char *client_name); +void cx_ipeak_unregister(struct cx_ipeak_client *client); +int cx_ipeak_update(struct cx_ipeak_client *ipeak_client, bool vote); +int cx_ipeak_victim_register(struct cx_ipeak_client *client, + cx_ipeak_victim_fn victim_cb, void *data); +void cx_ipeak_victim_unregister(struct cx_ipeak_client *client); + +#else + +static inline struct cx_ipeak_client *cx_ipeak_register( + struct device_node *dev_node, + const char *client_name) +{ + return NULL; +} + +static inline void cx_ipeak_unregister(struct cx_ipeak_client *client) +{ +} + +static inline int cx_ipeak_update(struct cx_ipeak_client *ipeak_client, + bool vote) +{ + return 0; +} + +static inline int cx_ipeak_victim_register(struct cx_ipeak_client *client, + cx_ipeak_victim_fn victim_cb, void *data) +{ + return 0; +} + +static inline void cx_ipeak_victim_unregister(struct cx_ipeak_client *client) +{ +} + +#endif + +#endif /*__SOC_COM_CX_IPEAK_H*/ From eaac003b93c9da26305ab8b5d308732104398ac6 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Tue, 8 Jun 2021 19:34:57 +0530 Subject: [PATCH 49/67] arm64: defconfig: holi-gki: enable Cx iPeak limit driver Enable common driver to limit Cx ipeak based on voting from various clients in multimedia. Change-Id: I6504279f76bb215e24434aa4078bf073a1e83b9f Signed-off-by: Manaf Meethalavalappu Pallikunhi --- arch/arm64/configs/vendor/holi_GKI.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/holi_GKI.config b/arch/arm64/configs/vendor/holi_GKI.config index 7634f6b449a3..4c2a7b55c0c3 100644 --- a/arch/arm64/configs/vendor/holi_GKI.config +++ b/arch/arm64/configs/vendor/holi_GKI.config @@ -239,3 +239,4 @@ CONFIG_SM_GCC_BLAIR=m CONFIG_SM_GPUCC_BLAIR=m CONFIG_SM_DISPCC_BLAIR=m CONFIG_SM_DEBUGCC_BLAIR=m +CONFIG_QCOM_CX_IPEAK=m From 0d537dd2cd4bcc0c3d03b5e17577275a4bb3ee16 Mon Sep 17 00:00:00 2001 From: Naman Padhiar Date: Wed, 12 May 2021 17:09:09 +0530 Subject: [PATCH 50/67] icnss2: Make SOC_WAKE workqueue as high priority ICNSS2 process SOC_WAKE requests serially by putting the in a workqueue. Create this workqueue as high priority queue. Change-Id: I9920f744bc56655c4ab52273fae3242300237a37 Signed-off-by: Naman Padhiar --- drivers/soc/qcom/icnss2/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/icnss2/main.c b/drivers/soc/qcom/icnss2/main.c index 0959b5184ddb..05c4c0499ae9 100644 --- a/drivers/soc/qcom/icnss2/main.c +++ b/drivers/soc/qcom/icnss2/main.c @@ -3901,7 +3901,7 @@ static int icnss_probe(struct platform_device *pdev) INIT_LIST_HEAD(&priv->event_list); priv->soc_wake_wq = alloc_workqueue("icnss_soc_wake_event", - WQ_UNBOUND, 1); + WQ_UNBOUND|WQ_HIGHPRI, 1); if (!priv->soc_wake_wq) { icnss_pr_err("Soc wake Workqueue creation failed\n"); ret = -EFAULT; From 71edb4e7994d5f0db6486a6ae20a2bc99fbb772c Mon Sep 17 00:00:00 2001 From: Pradeep P V K Date: Tue, 1 Jun 2021 11:49:05 +0530 Subject: [PATCH 51/67] block: Enable BFQ io scheduler as default Enable BFQ IO-Scheduler as a default scheduler for systems adapting to block multiqueue design. Change-Id: I12ff8c0495a53f1fc1f1a95c39ed03d927c1821b Signed-off-by: Pradeep P V K --- block/elevator.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/block/elevator.c b/block/elevator.c index 076ba7308e65..9340e2388c62 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -630,7 +630,10 @@ static struct elevator_type *elevator_get_default(struct request_queue *q) { if (q->nr_hw_queues != 1) return NULL; - +#if defined(CONFIG_SDC_QTI) || defined(CONFIG_SCSI_UFSHCD_QTI) + if (IS_ENABLED(CONFIG_IOSCHED_BFQ)) + return elevator_get(q, "bfq", false); +#endif return elevator_get(q, "mq-deadline", false); } From 9f8482a379581b43d03c36c01747b0b8a0593d8f Mon Sep 17 00:00:00 2001 From: Yue Ma Date: Tue, 30 Jun 2020 12:22:18 -0700 Subject: [PATCH 52/67] cnss2: Export if DRV is supported through platform capability Add CNSS_HAS_DRV_SUPPORT to platform capability to indicate if PCIe DRV is supported or not. Change-Id: Id114467d060946dda43bb00fe8856cea2c18e738 Signed-off-by: Yue Ma Signed-off-by: Mohammed Siddiq --- drivers/net/wireless/cnss2/pci.c | 4 ++++ include/net/cnss2.h | 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 624bd8470989..55fb99a8d6de 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -2986,6 +2986,7 @@ int cnss_pci_unregister_driver_hdlr(struct cnss_pci_data *pci_priv) static bool cnss_pci_is_drv_supported(struct cnss_pci_data *pci_priv) { struct pci_dev *root_port = pci_find_pcie_root_port(pci_priv->pci_dev); + struct cnss_plat_data *plat_priv = pci_priv->plat_priv; struct device_node *root_of_node; bool drv_supported = false; @@ -3005,6 +3006,9 @@ static bool cnss_pci_is_drv_supported(struct cnss_pci_data *pci_priv) drv_supported ? "supported" : "not supported"); pci_priv->drv_supported = drv_supported; + if (drv_supported) + plat_priv->cap.cap_flag |= CNSS_HAS_DRV_SUPPORT; + return drv_supported; } diff --git a/include/net/cnss2.h b/include/net/cnss2.h index cbcfac90f960..2cbfd3136d82 100644 --- a/include/net/cnss2.h +++ b/include/net/cnss2.h @@ -29,6 +29,7 @@ enum cnss_bus_width_type { enum cnss_platform_cap_flag { CNSS_HAS_EXTERNAL_SWREG = 0x01, CNSS_HAS_UART_ACCESS = 0x02, + CNSS_HAS_DRV_SUPPORT = 0x04, }; struct cnss_platform_cap { From 32ce17873bfef56c612f58bbfab84ea33eb268a6 Mon Sep 17 00:00:00 2001 From: Puranam V G Tejaswi Date: Fri, 28 May 2021 12:48:30 +0530 Subject: [PATCH 53/67] msm: kgsl: Add support for enhanced memory accounting Update the vm_stat counter NR_UNRECLAIMABLE_PAGES to account for the total memory allocated. Update the rss_stat counter MM_UNRECLAIMABLE to account for the memory allocated and memory imported per process. Change-Id: I0a40bf215fedbe421cce8d5fc41e2580fefb6523 Signed-off-by: Puranam V G Tejaswi --- drivers/gpu/msm/kgsl.c | 29 ++++++++++++++++++--- drivers/gpu/msm/kgsl_pool.c | 10 ++++++++ drivers/gpu/msm/kgsl_sharedmem.c | 44 +++++++++++++++++++++++++++----- 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 1b344cd066db..04d1a0523a11 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -335,6 +335,27 @@ static void kgsl_destroy_ion(struct kgsl_dma_buf_meta *meta) } #endif +static void kgsl_process_sub_stats(struct kgsl_process_private *priv, + unsigned int type, uint64_t size) +{ +#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES + struct task_struct *task; + struct mm_struct *mm; + + task = get_pid_task(priv->pid, PIDTYPE_PID); + if (task) { + mm = get_task_mm(task); + if (mm) { + add_mm_counter(mm, MM_UNRECLAIMABLE, + -(size >> PAGE_SHIFT)); + mmput(mm); + } + put_task_struct(task); + } +#endif + atomic64_sub(size, &priv->stats[type].cur); +} + void kgsl_mem_entry_destroy(struct kref *kref) { @@ -349,7 +370,7 @@ kgsl_mem_entry_destroy(struct kref *kref) /* pull out the memtype before the flags get cleared */ memtype = kgsl_memdesc_usermem_type(&entry->memdesc); - atomic64_sub(entry->memdesc.size, &entry->priv->stats[memtype].cur); + kgsl_process_sub_stats(entry->priv, memtype, entry->memdesc.size); /* Detach from process list */ kgsl_mem_entry_detach_process(entry); @@ -2753,10 +2774,12 @@ static void kgsl_process_add_stats(struct kgsl_process_private *priv, if (ret > priv->stats[type].max) priv->stats[type].max = ret; + +#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES + add_mm_counter(current->mm, MM_UNRECLAIMABLE, (size >> PAGE_SHIFT)); +#endif } - - long kgsl_ioctl_gpuobj_import(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { diff --git a/drivers/gpu/msm/kgsl_pool.c b/drivers/gpu/msm/kgsl_pool.c index cace5bb18027..d633aed832de 100644 --- a/drivers/gpu/msm/kgsl_pool.c +++ b/drivers/gpu/msm/kgsl_pool.c @@ -450,6 +450,11 @@ done: pcount++; } +#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES + mod_node_page_state(page_pgdat(page), NR_UNRECLAIMABLE_PAGES, + (1 << order)); +#endif + return pcount; eagain: @@ -521,6 +526,11 @@ static void kgsl_pool_free_page(struct page *page) page_order = compound_order(page); +#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES + mod_node_page_state(page_pgdat(page), NR_UNRECLAIMABLE_PAGES, + -(1 << page_order)); +#endif + if (!kgsl_pool_max_pages || (kgsl_pool_size_total() < kgsl_pool_max_pages)) { pool = _kgsl_get_pool_from_order(page_order); diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index 3343ce49fc89..8bb7bd4aadc7 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -952,6 +952,11 @@ static void kgsl_contiguous_free(struct kgsl_memdesc *memdesc) atomic_long_sub(memdesc->size, &kgsl_driver.stats.coherent); +#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES + mod_node_page_state(page_pgdat(phys_to_page(memdesc->physaddr)), + NR_UNRECLAIMABLE_PAGES, -(memdesc->size >> PAGE_SHIFT)); +#endif + _kgsl_contiguous_free(memdesc); } @@ -961,6 +966,7 @@ static void kgsl_free_secure_system_pages(struct kgsl_memdesc *memdesc) int i; struct scatterlist *sg; int ret = unlock_sgt(memdesc->sgt); + int order = get_order(PAGE_SIZE); if (ret) { /* @@ -979,7 +985,11 @@ static void kgsl_free_secure_system_pages(struct kgsl_memdesc *memdesc) for_each_sg(memdesc->sgt->sgl, sg, memdesc->sgt->nents, i) { struct page *page = sg_page(sg); - __free_pages(page, get_order(PAGE_SIZE)); + __free_pages(page, order); +#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES + mod_node_page_state(page_pgdat(page), NR_UNRECLAIMABLE_PAGES, + -(1 << order)); +#endif } sg_free_table(memdesc->sgt); @@ -1032,15 +1042,20 @@ static void kgsl_free_pool_pages(struct kgsl_memdesc *memdesc) static void kgsl_free_system_pages(struct kgsl_memdesc *memdesc) { - int i; + int i, order = get_order(PAGE_SIZE); kgsl_paged_unmap_kernel(memdesc); WARN_ON(memdesc->hostptr); atomic_long_sub(memdesc->size, &kgsl_driver.stats.page_alloc); - for (i = 0; i < memdesc->page_count; i++) - __free_pages(memdesc->pages[i], get_order(PAGE_SIZE)); + for (i = 0; i < memdesc->page_count; i++) { + __free_pages(memdesc->pages[i], order); +#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES + mod_node_page_state(page_pgdat(memdesc->pages[i]), + NR_UNRECLAIMABLE_PAGES, -(1 << order)); +#endif + } memdesc->page_count = 0; kvfree(memdesc->pages); @@ -1087,6 +1102,7 @@ static int kgsl_system_alloc_pages(u64 size, struct page ***pages, struct scatterlist sg; struct page **local; int i, npages = size >> PAGE_SHIFT; + int order = get_order(PAGE_SIZE); local = kvcalloc(npages, sizeof(*pages), GFP_KERNEL); if (!local) @@ -1098,8 +1114,13 @@ static int kgsl_system_alloc_pages(u64 size, struct page ***pages, local[i] = alloc_pages(gfp, get_order(PAGE_SIZE)); if (!local[i]) { - for (i = i - 1; i >= 0; i--) - __free_pages(local[i], get_order(PAGE_SIZE)); + for (i = i - 1; i >= 0; i--) { +#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES + mod_node_page_state(page_pgdat(local[i]), + NR_UNRECLAIMABLE_PAGES, -(1 << order)); +#endif + __free_pages(local[i], order); + } kvfree(local); return -ENOMEM; } @@ -1110,6 +1131,10 @@ static int kgsl_system_alloc_pages(u64 size, struct page ***pages, sg_dma_address(&sg) = page_to_phys(local[i]); dma_sync_sg_for_device(dev, &sg, 1, DMA_BIDIRECTIONAL); +#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES + mod_node_page_state(page_pgdat(local[i]), NR_UNRECLAIMABLE_PAGES, + (1 << order)); +#endif } *pages = local; @@ -1256,9 +1281,14 @@ static int kgsl_alloc_contiguous(struct kgsl_device *device, memdesc->ops = &kgsl_contiguous_ops; ret = _kgsl_alloc_contiguous(&device->pdev->dev, memdesc, size, 0); - if (!ret) + if (!ret) { KGSL_STATS_ADD(size, &kgsl_driver.stats.coherent, &kgsl_driver.stats.coherent_max); +#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES + mod_node_page_state(page_pgdat(phys_to_page(memdesc->physaddr)), + NR_UNRECLAIMABLE_PAGES, (size >> PAGE_SHIFT)); +#endif + } return ret; } From ae323e18fc5d39af500349f9952f34b435bc3ecd Mon Sep 17 00:00:00 2001 From: Jeya R Date: Tue, 8 Jun 2021 15:27:25 +0530 Subject: [PATCH 54/67] defconfig: msm: enable remote debugger driver Add remote debugger device configuration. The Remote Debugger driver allows a debugger running on a host PC to communicate with a remote stub running on peripheral subsystems. Change-Id: I4a96cd5ee354d9be0b2f77eaf3330b6529154aa6 Acked-by: Devender Kaushik Signed-off-by: Jeya R --- arch/arm/configs/vendor/monaco.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/vendor/monaco.config b/arch/arm/configs/vendor/monaco.config index cf10179279a0..f3ba1baa2f05 100644 --- a/arch/arm/configs/vendor/monaco.config +++ b/arch/arm/configs/vendor/monaco.config @@ -430,6 +430,7 @@ CONFIG_INCREMENTAL_FS=y CONFIG_QFMT_V2=y # CONFIG_QFMT_V1 is not set CONFIG_MSM_ADSPRPC=y +CONFIG_MSM_RDBG=m CONFIG_QSEECOM=y CONFIG_USB_CONFIGFS_F_ACC=y CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y From fcf3a13fb7a99f8684f3a818364cf18d991dc815 Mon Sep 17 00:00:00 2001 From: Naman Padhiar Date: Mon, 7 Jun 2021 18:56:32 +0530 Subject: [PATCH 55/67] icnss2: Avoid sending MODE_OFF if MODE_ON is not set Avoid sending MODE_OFF QMI request to FW if MODE_ON is not send previously. Change-Id: I143baac9de884773b1f3c376030d5252bae5fa15 Signed-off-by: Naman Padhiar --- drivers/soc/qcom/icnss2/qmi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/soc/qcom/icnss2/qmi.c b/drivers/soc/qcom/icnss2/qmi.c index 54f1d9d7bbda..95b58adcf92e 100644 --- a/drivers/soc/qcom/icnss2/qmi.c +++ b/drivers/soc/qcom/icnss2/qmi.c @@ -1350,6 +1350,10 @@ int wlfw_wlan_mode_send_sync_msg(struct icnss_priv *priv, mode == QMI_WLFW_OFF_V01) return 0; + if (!test_bit(ICNSS_MODE_ON, &priv->state) && + mode == QMI_WLFW_OFF_V01) + return 0; + icnss_pr_dbg("Sending Mode request, state: 0x%lx, mode: %d\n", priv->state, mode); From 87d7af180e23eca158d638cb62c9488a0f35e77e Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Mon, 24 May 2021 17:06:50 +0530 Subject: [PATCH 56/67] clk: qcom: gdsc-regulator: Dump consumers of GDSC Dump GDSC consumers and consumer votes in clock dump API's. Change-Id: I35b179155756e0aa68da59525888c460d348ff0d Signed-off-by: Jagadeesh Kona --- drivers/clk/qcom/gdsc-regulator.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/gdsc-regulator.c b/drivers/clk/qcom/gdsc-regulator.c index d3794fbe283d..5cc91f0e5001 100644 --- a/drivers/clk/qcom/gdsc-regulator.c +++ b/drivers/clk/qcom/gdsc-regulator.c @@ -661,7 +661,10 @@ static struct regmap_config gdsc_regmap_config = { void gdsc_debug_print_regs(struct regulator *regulator) { - struct gdsc *sc = rdev_get_drvdata(regulator->rdev); + struct regulator_dev *rdev = regulator->rdev; + struct gdsc *sc = rdev_get_drvdata(rdev); + struct regulator *reg; + const char *supply_name; uint32_t regvals[3] = {0}; int ret; @@ -670,6 +673,23 @@ void gdsc_debug_print_regs(struct regulator *regulator) return; } + ww_mutex_lock(&rdev->mutex, NULL); + + if (rdev->open_count) + pr_info("%-32s EN\n", "Device-Supply"); + + list_for_each_entry(reg, &rdev->consumer_list, list) { + if (reg->supply_name) + supply_name = reg->supply_name; + else + supply_name = "(null)-(null)"; + + pr_info("%-32s %c\n", supply_name, + (reg->enable_count ? 'Y' : 'N')); + } + + ww_mutex_unlock(&rdev->mutex); + ret = regmap_bulk_read(sc->regmap, REG_OFFSET, regvals, gdsc_regmap_config.max_register ? 3 : 1); if (ret) { From b048e61d9cd732dabe33c39c0cdf2266b46f85b0 Mon Sep 17 00:00:00 2001 From: Lingutla Chandrasekhar Date: Tue, 1 Jun 2021 16:58:40 +0530 Subject: [PATCH 57/67] sched: walt: Improve the scheduler This change is for general scheduler improvements. Change-Id: Ia2854ae8701151761fe0780b6451133ab09a050b Signed-off-by: Lingutla Chandrasekhar --- kernel/sched/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index b3e2892c3c39..5ee5789c14fb 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3870,6 +3870,9 @@ void scheduler_tick(void) if (curr->sched_class == &fair_sched_class) check_for_migration(rq, curr); + if (idle_cpu(cpu) && is_reserved(cpu)) + clear_reserved(cpu); + trace_android_vh_scheduler_tick(rq); } From e646feb1986ecfe0b43ee6d804aba35f8cf90e53 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Date: Wed, 10 Mar 2021 18:29:45 +0530 Subject: [PATCH 58/67] msm: kgsl: Add APIs to provide GPU stats Add APIs which provide per GPU freq active and total time, number of GPU frequency corners and number of frames processed by GPU. Change-Id: If42e76a435a4766a3de0b9b028d48b6c1759e466 Signed-off-by: Deepak Kumar --- drivers/gpu/msm/adreno_a6xx_gmu.c | 5 +++ drivers/gpu/msm/adreno_a6xx_hwsched.c | 6 +++- drivers/gpu/msm/adreno_a6xx_rgmu.c | 3 ++ drivers/gpu/msm/adreno_dispatch.c | 6 ++++ drivers/gpu/msm/kgsl.c | 19 ++++++++++ drivers/gpu/msm/kgsl.h | 2 +- drivers/gpu/msm/kgsl_compat.h | 4 +-- drivers/gpu/msm/kgsl_device.h | 2 ++ drivers/gpu/msm/kgsl_pwrctrl.c | 41 +++++++++++++++++++++ drivers/gpu/msm/kgsl_pwrctrl.h | 4 +++ drivers/gpu/msm/kgsl_pwrscale.c | 4 +++ include/linux/msm_kgsl.h | 52 +++++++++++++++++++++++++++ 12 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 include/linux/msm_kgsl.h diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index 8c7d4f1d05a2..acd6a97cb66c 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -2948,6 +2948,8 @@ static int a6xx_boot(struct adreno_device *adreno_dev) kgsl_pwrscale_wake(device); set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags); + + device->pwrctrl.last_stat_updated = ktime_get(); device->state = KGSL_STATE_ACTIVE; trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE); @@ -3016,6 +3018,7 @@ static int a6xx_first_boot(struct adreno_device *adreno_dev) set_bit(GMU_PRIV_FIRST_BOOT_DONE, &gmu->flags); set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags); + device->pwrctrl.last_stat_updated = ktime_get(); device->state = KGSL_STATE_ACTIVE; trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE); @@ -3277,6 +3280,8 @@ static void a6xx_gmu_touch_wakeup(struct adreno_device *adreno_dev) kgsl_pwrscale_wake(device); set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags); + + device->pwrctrl.last_stat_updated = ktime_get(); device->state = KGSL_STATE_ACTIVE; trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE); diff --git a/drivers/gpu/msm/adreno_a6xx_hwsched.c b/drivers/gpu/msm/adreno_a6xx_hwsched.c index 433454a70619..4d8e7897e8cb 100644 --- a/drivers/gpu/msm/adreno_a6xx_hwsched.c +++ b/drivers/gpu/msm/adreno_a6xx_hwsched.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #include @@ -500,6 +500,7 @@ static void a6xx_hwsched_touch_wakeup(struct adreno_device *adreno_dev) set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags); + device->pwrctrl.last_stat_updated = ktime_get(); device->state = KGSL_STATE_ACTIVE; trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE); @@ -541,6 +542,8 @@ static int a6xx_hwsched_boot(struct adreno_device *adreno_dev) kgsl_pwrscale_wake(device); set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags); + + device->pwrctrl.last_stat_updated = ktime_get(); device->state = KGSL_STATE_ACTIVE; trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE); @@ -589,6 +592,7 @@ static int a6xx_hwsched_first_boot(struct adreno_device *adreno_dev) set_bit(GMU_PRIV_FIRST_BOOT_DONE, &gmu->flags); set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags); + device->pwrctrl.last_stat_updated = ktime_get(); device->state = KGSL_STATE_ACTIVE; trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE); diff --git a/drivers/gpu/msm/adreno_a6xx_rgmu.c b/drivers/gpu/msm/adreno_a6xx_rgmu.c index b16399af6af9..4e82413092e9 100644 --- a/drivers/gpu/msm/adreno_a6xx_rgmu.c +++ b/drivers/gpu/msm/adreno_a6xx_rgmu.c @@ -896,6 +896,7 @@ static int a6xx_boot(struct adreno_device *adreno_dev) set_bit(RGMU_PRIV_GPU_STARTED, &rgmu->flags); + device->pwrctrl.last_stat_updated = ktime_get(); device->state = KGSL_STATE_ACTIVE; trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE); @@ -934,6 +935,7 @@ static void a6xx_rgmu_touch_wakeup(struct adreno_device *adreno_dev) set_bit(RGMU_PRIV_GPU_STARTED, &rgmu->flags); + device->pwrctrl.last_stat_updated = ktime_get(); device->state = KGSL_STATE_ACTIVE; trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE); @@ -1002,6 +1004,7 @@ static int a6xx_first_boot(struct adreno_device *adreno_dev) set_bit(RGMU_PRIV_FIRST_BOOT_DONE, &rgmu->flags); set_bit(RGMU_PRIV_GPU_STARTED, &rgmu->flags); + device->pwrctrl.last_stat_updated = ktime_get(); device->state = KGSL_STATE_ACTIVE; trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE); diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index 7ae90d71130d..5177e74acc10 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -304,6 +304,9 @@ static void _retire_timestamp(struct kgsl_drawobj *drawobj) context->id, drawobj->timestamp, !!(drawobj->flags & KGSL_DRAWOBJ_END_OF_FRAME)); + if (drawobj->flags & KGSL_DRAWOBJ_END_OF_FRAME) + atomic64_inc(&context->proc_priv->frame_count); + /* * For A3xx we still get the rptr from the CP_RB_RPTR instead of * rptr scratch out address. At this point GPU clocks turned off. @@ -2355,6 +2358,9 @@ static void retire_cmdobj(struct adreno_device *adreno_dev, context->id, drawobj->timestamp, !!(drawobj->flags & KGSL_DRAWOBJ_END_OF_FRAME)); + if (drawobj->flags & KGSL_DRAWOBJ_END_OF_FRAME) + atomic64_inc(&context->proc_priv->frame_count); + /* * For A3xx we still get the rptr from the CP_RB_RPTR instead of * rptr scratch out address. At this point GPU clocks turned off. diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 1b344cd066db..97ee1d058efa 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -1043,6 +1044,24 @@ done: return private; } +int kgsl_gpu_frame_count(pid_t pid, u64 *frame_count) +{ + struct kgsl_process_private *p; + + if (!frame_count) + return -EINVAL; + + p = kgsl_process_private_find(pid); + if (!p) + return -ENOENT; + + *frame_count = atomic64_read(&p->frame_count); + kgsl_process_private_put(p); + + return 0; +} +EXPORT_SYMBOL(kgsl_gpu_frame_count); + static int kgsl_close_device(struct kgsl_device *device) { int result = 0; diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index 9e4bf99e7163..fc2cb005722c 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -5,12 +5,12 @@ #ifndef __KGSL_H #define __KGSL_H +#include #include #include #include #include #include -#include #include #include "kgsl_gmu_core.h" diff --git a/drivers/gpu/msm/kgsl_compat.h b/drivers/gpu/msm/kgsl_compat.h index a62c3b40d798..85e1871de6ac 100644 --- a/drivers/gpu/msm/kgsl_compat.h +++ b/drivers/gpu/msm/kgsl_compat.h @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2013-2017,2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017,2019,2021 The Linux Foundation. All rights reserved. */ #ifndef __KGSL_COMPAT_H #define __KGSL_COMPAT_H +#include #include -#include #ifdef CONFIG_COMPAT diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index e3271ccbe327..3d3cfdab5128 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -437,6 +437,7 @@ struct kgsl_context { * @fd_count: Counter for the number of FDs for this process * @ctxt_count: Count for the number of contexts for this process * @ctxt_count_lock: Spinlock to protect ctxt_count + * @frame_count: Count for the number of frames processed */ struct kgsl_process_private { unsigned long priv; @@ -460,6 +461,7 @@ struct kgsl_process_private { int fd_count; atomic_t ctxt_count; spinlock_t ctxt_count_lock; + atomic64_t frame_count; }; /** diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 6b9e43ec330d..7003d76d933f 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -1878,6 +1879,7 @@ static int _wake(struct kgsl_device *device) kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, KGSL_STATE_ACTIVE); device->ftbl->deassert_gbif_halt(device); + pwr->last_stat_updated = ktime_get(); /* * No need to turn on/off irq here as it no longer affects * power collapse @@ -2258,3 +2260,42 @@ int kgsl_pwrctrl_set_default_gpu_pwrlevel(struct kgsl_device *device) /* Request adjusted DCVS level */ return device->ftbl->gpu_clock_set(device, pwr->active_pwrlevel); } + +int kgsl_gpu_num_freqs(void) +{ + struct kgsl_device *device = kgsl_get_device(0); + + if (!device) + return -ENODEV; + + return device->pwrctrl.num_pwrlevels; +} +EXPORT_SYMBOL(kgsl_gpu_num_freqs); + +int kgsl_gpu_stat(struct kgsl_gpu_freq_stat *stats, u32 numfreq) +{ + struct kgsl_device *device = kgsl_get_device(0); + struct kgsl_pwrctrl *pwr; + int i; + + if (!device) + return -ENODEV; + + pwr = &device->pwrctrl; + + if (!stats || (numfreq < pwr->num_pwrlevels)) + return -EINVAL; + + mutex_lock(&device->mutex); + kgsl_pwrscale_update_stats(device); + + for (i = 0; i < pwr->num_pwrlevels; i++) { + stats[i].freq = pwr->pwrlevels[i].gpu_freq; + stats[i].active_time = pwr->clock_times[i]; + stats[i].idle_time = pwr->time_in_pwrlevel[i] - pwr->clock_times[i]; + } + mutex_unlock(&device->mutex); + + return 0; +} +EXPORT_SYMBOL(kgsl_gpu_stat); diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index 9b040126c57b..2786c8745bb1 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -175,6 +175,10 @@ struct kgsl_pwrctrl { u32 minbw_timeout; /** @ddr_qos_devfreq: Devfreq device for setting DDR qos policy */ struct devfreq *ddr_qos_devfreq; + /** @time_in_pwrlevel: Each pwrlevel active duration in usec */ + u64 time_in_pwrlevel[KGSL_MAX_PWRLEVELS]; + /** @last_stat_updated: The last time stats were updated */ + ktime_t last_stat_updated; }; int kgsl_pwrctrl_init(struct kgsl_device *device); diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c index 870f090c769e..45d6e99a66cb 100644 --- a/drivers/gpu/msm/kgsl_pwrscale.c +++ b/drivers/gpu/msm/kgsl_pwrscale.c @@ -122,6 +122,7 @@ void kgsl_pwrscale_update_stats(struct kgsl_device *device) if (device->state == KGSL_STATE_ACTIVE) { struct kgsl_power_stats stats; + ktime_t cur_time = ktime_get(); device->ftbl->power_stats(device, &stats); device->pwrscale.accum_stats.busy_time += stats.busy_time; @@ -129,6 +130,9 @@ void kgsl_pwrscale_update_stats(struct kgsl_device *device) device->pwrscale.accum_stats.ram_wait += stats.ram_wait; pwrctrl->clock_times[pwrctrl->active_pwrlevel] += stats.busy_time; + pwrctrl->time_in_pwrlevel[pwrctrl->active_pwrlevel] += + ktime_us_delta(cur_time, pwrctrl->last_stat_updated); + pwrctrl->last_stat_updated = cur_time; } } diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h new file mode 100644 index 000000000000..e5950b135dda --- /dev/null +++ b/include/linux/msm_kgsl.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ +#ifndef _MSM_KGSL_H +#define _MSM_KGSL_H + +/** + * struct kgsl_gpu_freq_stat - Per GPU freq stat struct + * @freq: GPU frequency in Hz + * @active_time: GPU busy time in usecs + * @idle_time: GPU idle time in usec + */ +struct kgsl_gpu_freq_stat { + u32 freq; + u64 active_time; + u64 idle_time; +}; + +/** + * kgsl_gpu_num_freqs - Get number of available GPU frequencies + * + * Return: number of available frequencies on success or negative error + * on failure + */ +int kgsl_gpu_num_freqs(void); + +/** + * kgsl_gpu_stat - Get per GPU freq stats + * @stats: Array of struct kgsl_gpu_freq_stat to hold stats + * @numfreq: Number of entries in @stats + * + * This function will populate @stats with per freq stats. + * Number of entries in @stats array must be greater or + * equal to value returned by function kgsl_gpu_num_freqs + * + * Return: 0 on success or negative error on failure + */ +int kgsl_gpu_stat(struct kgsl_gpu_freq_stat *stats, u32 numfreq); + +/** + * kgsl_gpu_frame_count - Get number of frames already processed by GPU + * @pid: pid of the process for which frame count is required + * @frame_count: pointer to a u64 to store frame count + * + * Return: zero on success and number of frames processed corresponding + * to @pid in @frame_count or negative error on failure + */ +int kgsl_gpu_frame_count(pid_t pid, u64 *frame_count); + +#endif /* _MSM_KGSL_H */ + From 5cc0d092640b031b309b18cd5890ab0180f887d6 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Fri, 28 May 2021 09:05:20 -0700 Subject: [PATCH 59/67] clk: qcom: clk-cpu-sdxlemur: Don't limit the max register The lucid_5lpe PLL has multiple registers past 0x3C, including the ALPHA_VAL and SSC registers. Since we currently set max_register to 0x3C, this causes read failures on ALPHA_VAL in in alpha_pll_lucid_recalc_rate(). This function ignores the regmap_read() return codes, which results in the frac variable being uninitialized. The CPU PLL doesn't currently use fractional operation, so it should always be zero in HW. But the uninitialized frac variable causes random, small increases to the calculated frequency. Specifying max_register is optional, so just remove it and allow the full range we define in devicetree. Change-Id: I3549c249f2dfbad5c056de584864b0e1a3eeb912 Signed-off-by: Mike Tipton --- drivers/clk/qcom/clk-cpu-sdxlemur.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/qcom/clk-cpu-sdxlemur.c b/drivers/clk/qcom/clk-cpu-sdxlemur.c index 5c1e5d7f7c44..04ab88561051 100644 --- a/drivers/clk/qcom/clk-cpu-sdxlemur.c +++ b/drivers/clk/qcom/clk-cpu-sdxlemur.c @@ -361,7 +361,6 @@ static struct regmap_config cpu_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = 0x3C, .fast_io = true, }; From f65f53d3bd359bb1c142d9f14e11ef7e958403a9 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Fri, 28 May 2021 13:31:18 -0700 Subject: [PATCH 60/67] clk: qcom: clk-alpha-pll: Add clk_alpha_pll_lucid_5lpe_sdx_cpu_ops The lucid_5lpe PLL used for the CPU on SDX targets uses a custom mechanism to assert the latch. Add ops that can be used for this. Change-Id: I24f8e3db2b908e34e4d0560841f1f5fdcfd215af Signed-off-by: Mike Tipton --- drivers/clk/qcom/clk-alpha-pll.c | 80 ++++++++++++++++++++++++++++++++ drivers/clk/qcom/clk-alpha-pll.h | 3 +- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index f81ef5d61313..e40f344609f8 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -276,6 +276,12 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); #define LUCID_EVO_PLL_L_VAL_MASK GENMASK(15, 0) #define LUCID_EVO_PLL_CAL_L_VAL_MASK GENMASK(31, 16) +/* + * The lucid_5lpe CPU PLL on SDX targets overloaded this field. Reading it + * returns PCAL_DONE and writing it asserts the latch. + */ +#define LUCID_5LPE_SDX_CPU_LATCH_INPUT LUCID_5LPE_PCAL_DONE + /* ZONDA PLL specific offsets */ #define ZONDA_PLL_OUT_MASK 0xF #define ZONDA_STAY_IN_CFA BIT(16) @@ -3190,6 +3196,61 @@ static int alpha_pll_lucid_5lpe_set_rate(struct clk_hw *hw, unsigned long rate, return 0; } +static int alpha_pll_lucid_5lpe_sdx_cpu_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long prate) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + unsigned long rrate; + u32 regval, l; + u64 a; + int ret; + + rrate = alpha_pll_round_rate(rate, prate, &l, &a, ALPHA_REG_16BIT_WIDTH); + + /* + * Due to a limited number of bits for fractional rate programming, the + * rounded up rate could be marginally higher than the requested rate. + */ + if (rrate > (rate + PLL_OUT_RATE_MARGIN) || rrate < rate) { + pr_err("Call set rate on the PLL with rounded rates!\n"); + return -EINVAL; + } + + regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); + regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); + + /* Latch the PLL input */ + ret = regmap_write_bits(pll->clkr.regmap, PLL_MODE(pll), + LUCID_5LPE_SDX_CPU_LATCH_INPUT, + LUCID_5LPE_SDX_CPU_LATCH_INPUT); + if (ret) + return ret; + + /* Wait for 2 reference cycles before checking the ACK bit. */ + udelay(1); + regmap_read(pll->clkr.regmap, PLL_MODE(pll), ®val); + if (!(regval & LUCID_5LPE_ALPHA_PLL_ACK_LATCH)) { + WARN_CLK(&pll->clkr.hw, 1, + "PLL latch failed. Output may be unstable!\n"); + return -EINVAL; + } + + /* Return the latch input to 0 */ + ret = regmap_write_bits(pll->clkr.regmap, PLL_MODE(pll), + LUCID_5LPE_SDX_CPU_LATCH_INPUT, 0); + if (ret) + return ret; + + if (clk_hw_is_enabled(hw)) { + ret = wait_for_pll_enable_lock(pll); + if (ret) + return ret; + } + + return 0; +} + static int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { @@ -3331,6 +3392,25 @@ const struct clk_ops clk_alpha_pll_lucid_5lpe_ops = { }; EXPORT_SYMBOL(clk_alpha_pll_lucid_5lpe_ops); +const struct clk_ops clk_alpha_pll_lucid_5lpe_sdx_cpu_ops = { + .prepare = alpha_pll_lucid_5lpe_prepare, + .unprepare = clk_unprepare_regmap, + .pre_rate_change = clk_pre_change_regmap, + .post_rate_change = clk_post_change_regmap, + .enable = alpha_pll_lucid_5lpe_enable, + .disable = alpha_pll_lucid_5lpe_disable, + .is_enabled = alpha_pll_lucid_is_enabled, + .recalc_rate = alpha_pll_lucid_recalc_rate, + .round_rate = clk_alpha_pll_round_rate, + .set_rate = alpha_pll_lucid_5lpe_sdx_cpu_set_rate, + .debug_init = clk_common_debug_init, + .init = clk_lucid_pll_init, +#ifdef CONFIG_COMMON_CLK_QCOM_DEBUG + .list_rate_vdd_level = clk_list_rate_vdd_level, +#endif +}; +EXPORT_SYMBOL(clk_alpha_pll_lucid_5lpe_sdx_cpu_ops); + const struct clk_ops clk_alpha_pll_fixed_lucid_ops = { .prepare = clk_prepare_regmap, .unprepare = clk_unprepare_regmap, diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index d5791e9cc4bf..d5f1ab60d6d1 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2016, 2018-2020 The Linux Foundation. + * Copyright (c) 2015-2016, 2018-2021 The Linux Foundation. * All rights reserved. */ @@ -173,6 +173,7 @@ extern const struct clk_ops clk_alpha_pll_postdiv_zonda_ops; extern const struct clk_ops clk_alpha_pll_zonda_5lpe_ops; extern const struct clk_ops clk_alpha_pll_lucid_5lpe_ops; +extern const struct clk_ops clk_alpha_pll_lucid_5lpe_sdx_cpu_ops; extern const struct clk_ops clk_alpha_pll_fixed_lucid_5lpe_ops; extern const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops; extern const struct clk_ops clk_alpha_pll_slew_ops; From 162fb9a267898f58cf3c5eb45b318fc0f18be76a Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Fri, 28 May 2021 13:32:37 -0700 Subject: [PATCH 61/67] clk: qcom: clk-cpu-sdxlemur: Use correct PLL ops The SDXLEMUR CPU PLL uses a non-standard sequence for latching new configurations. Using the standard lucid_5lpe ops for this PLL means the latch won't be asserted and the PLL will run at the original frequency from before the update. Change-Id: Ia1cb8b7fd116e17a937b961e5907082097e27bfd Signed-off-by: Mike Tipton --- drivers/clk/qcom/clk-cpu-sdxlemur.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/clk-cpu-sdxlemur.c b/drivers/clk/qcom/clk-cpu-sdxlemur.c index 04ab88561051..b2daf0519ccd 100644 --- a/drivers/clk/qcom/clk-cpu-sdxlemur.c +++ b/drivers/clk/qcom/clk-cpu-sdxlemur.c @@ -306,7 +306,7 @@ static struct clk_alpha_pll apcs_cpu_pll = { .fw_name = "bi_tcxo_ao", }, .num_parents = 1, - .ops = &clk_alpha_pll_lucid_5lpe_ops, + .ops = &clk_alpha_pll_lucid_5lpe_sdx_cpu_ops, }, .vdd_data = { .vdd_class = &vdd_pll, From 914e88ee4e6f2c08ad37b4fb74b67cd5a94cbe9b Mon Sep 17 00:00:00 2001 From: Paul Zhang Date: Thu, 29 Apr 2021 15:55:10 +0800 Subject: [PATCH 62/67] cnss: clean interface per PCI driver update PCI RC driver is removing EP shadow support to restore EP's config space. So update cnss driver accordingly. Change-Id: I562de4b338dcf2204d73b9d5fafebf9e597c7b42 Signed-off-by: Paul Zhang --- drivers/net/wireless/cnss/cnss_pci.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/cnss/cnss_pci.c b/drivers/net/wireless/cnss/cnss_pci.c index bef8ef6ee5b0..16e290819962 100644 --- a/drivers/net/wireless/cnss/cnss_pci.c +++ b/drivers/net/wireless/cnss/cnss_pci.c @@ -79,9 +79,9 @@ #define WLAN_BOOTSTRAP_GPIO_NAME "wlan-bootstrap-gpio" #define PM_OPTIONS 0 #define PM_OPTIONS_SUSPEND_LINK_DOWN \ - (MSM_PCIE_CONFIG_NO_CFG_RESTORE | MSM_PCIE_CONFIG_LINKDOWN) + (PM_OPTIONS | MSM_PCIE_CONFIG_LINKDOWN) #define PM_OPTIONS_RESUME_LINK_DOWN \ - (MSM_PCIE_CONFIG_NO_CFG_RESTORE) + (PM_OPTIONS) #define SOC_SWREG_VOLT_MAX 1200000 #define SOC_SWREG_VOLT_MIN 1200000 @@ -231,6 +231,7 @@ static struct cnss_data { bool pci_register_again; bool notify_modem_status; struct pci_saved_state *saved_state; + struct pci_saved_state *default_state; u16 revision_id; bool recovery_in_progress; atomic_t fw_available; @@ -1518,7 +1519,7 @@ int cnss_pci_load_and_free_saved_state(struct pci_dev *dev, int cnss_msm_pcie_shadow_control(struct pci_dev *dev, bool enable) { - return msm_pcie_shadow_control(dev, enable); + return 0; } int cnss_msm_pcie_deregister_event(struct msm_pcie_register_event *reg) @@ -1528,7 +1529,12 @@ int cnss_msm_pcie_deregister_event(struct msm_pcie_register_event *reg) int cnss_msm_pcie_recover_config(struct pci_dev *dev) { - return msm_pcie_recover_config(dev); + if (penv->saved_state) + cnss_pci_load_and_free_saved_state(dev, &penv->saved_state); + else + pci_load_saved_state(dev, penv->default_state); + + pci_restore_state(dev); } int cnss_msm_pcie_register_event(struct msm_pcie_register_event *reg) @@ -1661,6 +1667,8 @@ static int cnss_wlan_pci_probe(struct pci_dev *pdev, if (penv->pcie_link_state) { pci_save_state(pdev); penv->saved_state = cnss_pci_store_saved_state(pdev); + /* Save default config space */ + penv->default_state = cnss_pci_store_saved_state(pdev); ret = cnss_msm_pcie_pm_control(MSM_PCIE_SUSPEND, cnss_get_pci_dev_bus_number(pdev), @@ -1734,6 +1742,9 @@ static void cnss_wlan_pci_remove(struct pci_dev *pdev) if (!penv) return; + if (penv->default_state) + pci_load_and_free_saved_state(penv->pdev, &penv->default_state); + dev = &penv->pldev->dev; cnss_pcie_reset_platform_ops(dev); device_remove_file(dev, &dev_attr_wlan_setup); From 7304a7bf8d9f33b46b8933a4968c907fc4115b20 Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Thu, 3 Jun 2021 14:55:10 +0530 Subject: [PATCH 63/67] serial: msm_geni_serial: Avoid unclocked access from start_tx During system suspend/resume testing, when console is in suspended state and clocks are OFF. Seems UART console used to dump some info on console and leading to NOC fault. To fix this issue add defensive check in msm_geni_serial_start_tx() api. Change-Id: I27edd7814e28946449afe256f72f7cb1c868822e Signed-off-by: Chandana Kishori Chiluveru --- drivers/tty/serial/msm_geni_serial.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index c5559fbc0ca9..d22339a25c30 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -1225,6 +1225,13 @@ static void msm_geni_serial_start_tx(struct uart_port *uport) unsigned int geni_ios; static unsigned int ios_log_limit; + /* when start_tx is called with UART clocks OFF return. */ + if (uart_console(uport) && msm_port->is_clock_off) { + IPC_LOG_MSG(msm_port->console_log, + "%s. Console in suspend state\n", __func__); + return; + } + if (!uart_console(uport) && !pm_runtime_active(uport->dev)) { IPC_LOG_MSG(msm_port->ipc_log_misc, "%s.Putting in async RPM vote\n", __func__); @@ -3562,6 +3569,7 @@ static int msm_geni_serial_sys_suspend(struct device *dev) if (uart_console(uport) || port->pm_auto_suspend_disable) { uart_suspend_port((struct uart_driver *)uport->private_data, uport); + IPC_LOG_MSG(port->console_log, "%s\n", __func__); } else { struct uart_state *state = uport->state; struct tty_port *tty_port = &state->port; @@ -3593,6 +3601,7 @@ static int msm_geni_serial_sys_resume(struct device *dev) port->pm_auto_suspend_disable) { uart_resume_port((struct uart_driver *)uport->private_data, uport); + IPC_LOG_MSG(port->console_log, "%s\n", __func__); } return 0; } From 01b9c27d1c45b7018fd1a958201b366b59ddae1f Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Tue, 2 Mar 2021 19:09:33 +0530 Subject: [PATCH 64/67] serial: msm_geni_serial: Log UART RFR and IRQ enable status in IPC Add geni_ios changes to log RFR line status in GENI_IOS register. Also set GENI FORCE_DEFAULT after performing TX/RX Abort Sequence. Change-Id: I995e5cd864cd1f54dd295b82d887c8df3452e706 Signed-off-by: Chandana Kishori Chiluveru --- drivers/tty/serial/msm_geni_serial.c | 59 ++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index c5559fbc0ca9..0fe0582eba9b 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -30,6 +30,7 @@ /* UART specific GENI registers */ #define SE_UART_LOOPBACK_CFG (0x22C) +#define SE_GENI_CFG_REG80 (0x240) #define SE_UART_TX_TRANS_CFG (0x25C) #define SE_UART_TX_WORD_LEN (0x268) #define SE_UART_TX_STOP_BIT_LEN (0x26C) @@ -258,6 +259,7 @@ static int msm_geni_serial_runtime_resume(struct device *dev); static int msm_geni_serial_runtime_suspend(struct device *dev); static int msm_geni_serial_get_ver_info(struct uart_port *uport); static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport); +static void msm_geni_serial_allow_rx(struct msm_geni_serial_port *port); static int uart_line_id; #define GET_DEV_PORT(uport) \ @@ -308,6 +310,7 @@ static void msm_geni_update_uart_error_code(struct msm_geni_serial_port *port, static void msm_geni_serial_enable_interrupts(struct uart_port *uport) { unsigned int geni_m_irq_en, geni_s_irq_en; + unsigned int geni_dma_tx_irq_en, geni_dma_rx_irq_en; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); geni_m_irq_en = geni_read_reg_nolog(uport->membase, @@ -326,12 +329,28 @@ static void msm_geni_serial_enable_interrupts(struct uart_port *uport) geni_write_reg_nolog(DMA_RX_IRQ_BITS, uport->membase, SE_DMA_RX_IRQ_EN_SET); } + + if (!uart_console(uport)) { + geni_m_irq_en = geni_read_reg_nolog(uport->membase, + SE_GENI_M_IRQ_EN); + geni_s_irq_en = geni_read_reg_nolog(uport->membase, + SE_GENI_S_IRQ_EN); + geni_dma_tx_irq_en = geni_read_reg_nolog(uport->membase, + SE_DMA_TX_IRQ_EN); + geni_dma_rx_irq_en = geni_read_reg_nolog(uport->membase, + SE_DMA_RX_IRQ_EN); + IPC_LOG_MSG(port->ipc_log_misc, + "%s: M_IRQ_EN:0x%x S_IRQ_EN:0x%x TX_IRQ_EN:0x%x RX_IRQ_EN:0x%x\n", + __func__, geni_m_irq_en, geni_s_irq_en, + geni_dma_tx_irq_en, geni_dma_rx_irq_en); + } } /* Try disabling interrupts in order to do polling in an atomic contexts. */ static bool msm_serial_try_disable_interrupts(struct uart_port *uport) { unsigned int geni_m_irq_en, geni_s_irq_en; + unsigned int geni_dma_tx_irq_en, geni_dma_rx_irq_en; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); /* @@ -356,6 +375,21 @@ static bool msm_serial_try_disable_interrupts(struct uart_port *uport) SE_DMA_RX_IRQ_EN_CLR); } + if (!uart_console(uport)) { + geni_m_irq_en = geni_read_reg_nolog(uport->membase, + SE_GENI_M_IRQ_EN); + geni_s_irq_en = geni_read_reg_nolog(uport->membase, + SE_GENI_S_IRQ_EN); + geni_dma_tx_irq_en = geni_read_reg_nolog(uport->membase, + SE_DMA_TX_IRQ_EN); + geni_dma_rx_irq_en = geni_read_reg_nolog(uport->membase, + SE_DMA_RX_IRQ_EN); + IPC_LOG_MSG(port->ipc_log_misc, + "%s: M_IRQ_EN:0x%x S_IRQ_EN:0x%x TX_IRQ_EN:0x%x RX_IRQ_EN:0x%x\n", + __func__, geni_m_irq_en, geni_s_irq_en, + geni_dma_tx_irq_en, geni_dma_rx_irq_en); + } + return true; } @@ -375,6 +409,8 @@ static bool geni_wait_for_cmd_done(struct uart_port *uport, bool is_irq_masked) * We need to do polling if spinlock is taken * by framework as we cannot rely on ISR. */ + if (!uart_console(uport)) + IPC_LOG_MSG(msm_port->ipc_log_misc, "%s polling:%d\n", __func__, is_irq_masked); if (is_irq_masked) { /* * Polling is done for 1000 iterrations with @@ -1028,6 +1064,9 @@ static void msm_geni_serial_console_write(struct console *co, const char *s, "%s: tx abort failed 0x%x\n", __func__, geni_read_reg_nolog(uport->membase, SE_GENI_STATUS)); + msm_geni_serial_allow_rx(port); + geni_write_reg(FORCE_DEFAULT, uport->membase, + GENI_FORCE_DEFAULT_REG); } msm_geni_serial_enable_interrupts(uport); @@ -1181,6 +1220,9 @@ static int msm_geni_serial_prep_dma_tx(struct uart_port *uport) SE_GENI_STATUS)); msm_geni_update_uart_error_code(msm_port, UART_ERROR_TX_ABORT_FAIL); } + msm_geni_serial_allow_rx(msm_port); + geni_write_reg(FORCE_DEFAULT, uport->membase, + GENI_FORCE_DEFAULT_REG); } if (msm_port->xfer_mode == SE_DMA) { @@ -1328,6 +1370,9 @@ static void stop_tx_sequencer(struct uart_port *uport) geni_read_reg_nolog(uport->membase, SE_GENI_STATUS)); msm_geni_update_uart_error_code(port, UART_ERROR_TX_ABORT_FAIL); } + msm_geni_serial_allow_rx(port); + geni_write_reg(FORCE_DEFAULT, uport->membase, + GENI_FORCE_DEFAULT_REG); } if (port->xfer_mode == SE_DMA) { @@ -1608,6 +1653,9 @@ static int stop_rx_sequencer(struct uart_port *uport) geni_se_dump_dbg_regs(&port->serial_rsc, uport->membase, port->ipc_log_misc); } + msm_geni_serial_allow_rx(port); + geni_write_reg(FORCE_DEFAULT, uport->membase, + GENI_FORCE_DEFAULT_REG); if (port->xfer_mode == SE_DMA) { port->s_cmd_done = false; @@ -2168,9 +2216,9 @@ static void msm_geni_serial_handle_isr(struct uart_port *uport, if (m_irq_status || s_irq_status || dma_tx_status || dma_rx_status) IPC_LOG_MSG(msm_port->ipc_log_irqstatus, - "%s: sirq:0x%x mirq:0x%x dma_txirq:0x%x dma_rxirq:0x%x\n", + "%s: sirq:0x%x mirq:0x%x dma_txirq:0x%x dma_rxirq:0x%x is_irq_masked:%d\n", __func__, s_irq_status, m_irq_status, - dma_tx_status, dma_rx_status); + dma_tx_status, dma_rx_status, is_irq_masked); m_cmd_done = handle_tx_dma_xfer(m_irq_status, uport); s_cmd_done = handle_rx_dma_xfer(s_irq_status, uport); } @@ -2351,6 +2399,8 @@ static int msm_geni_serial_port_setup(struct uart_port *uport) SE_GENI_RX_PACKING_CFG0); geni_write_reg_nolog(cfg1, uport->membase, SE_GENI_RX_PACKING_CFG1); + geni_write_reg_nolog(0x431c, uport->membase, + SE_GENI_CFG_REG80); if (!msm_port->rx_fifo) { ret = -ENOMEM; goto exit_portsetup; @@ -2618,7 +2668,10 @@ static void msm_geni_serial_set_termios(struct uart_port *uport, } if (!uart_console(uport)) { - int ret = msm_geni_serial_power_on(uport); + int ret; + + IPC_LOG_MSG(port->ipc_log_misc, "%s: start\n", __func__); + ret = msm_geni_serial_power_on(uport); if (ret) { IPC_LOG_MSG(port->ipc_log_misc, From 3fd58de5e5eb5c56971002b401f819614e138231 Mon Sep 17 00:00:00 2001 From: Bavyasritha Alahari Date: Mon, 31 May 2021 20:08:52 +0530 Subject: [PATCH 65/67] soc: qcom: Add symon_subsystem_stats driver support Sysmon subsystem driver exposes API to query various SoC level Q6 load, power statistics from the shared memory exported by the remote processor. Change-Id: I84da55d0f72a0c9d0c4a90a78d8589079aa9b93e Signed-off-by: Bavyasritha Alahari --- arch/arm64/configs/vendor/lahaina_GKI.config | 1 + drivers/soc/qcom/Kconfig | 10 +++ drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/sysmon_subsystem_stats.c | 89 +++++++++++++++++++ .../linux/soc/qcom/sysmon_subsystem_stats.h | 62 +++++++++++++ 5 files changed, 163 insertions(+) create mode 100644 drivers/soc/qcom/sysmon_subsystem_stats.c create mode 100644 include/linux/soc/qcom/sysmon_subsystem_stats.h diff --git a/arch/arm64/configs/vendor/lahaina_GKI.config b/arch/arm64/configs/vendor/lahaina_GKI.config index 45d69f8c4c37..1d1ab64c11df 100644 --- a/arch/arm64/configs/vendor/lahaina_GKI.config +++ b/arch/arm64/configs/vendor/lahaina_GKI.config @@ -198,6 +198,7 @@ CONFIG_VIDEOBUF2_VMALLOC=m CONFIG_SLIMBUS_MSM_NGD=m CONFIG_QRTR_HAVEN=m CONFIG_QCOM_CDSP_RM=m +CONFIG_QCOM_SYSMON_SUBSYSTEM_STATS=m CONFIG_QCOM_PDC=m CONFIG_HEADER_TEST=y CONFIG_HEADERS_INSTALL=y diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index dc81f16da5e0..89f4f2b7ee52 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -1050,6 +1050,16 @@ config CDSPRM_VTCM_DYNAMIC_DEBUG enabled, the vtcm partition details are sent to the CDSP via rpmsg channel. +config QCOM_SYSMON_SUBSYSTEM_STATS + tristate "Qualcomm Technologies SysMon DSP subsystem stats" + depends on QCOM_SMEM + help + sysMon subsystem stats driver exposes API to query DSP + subsystem's load and power statistics stored in SMEM. + SMEM region for each DSP subsystem is updated periodically + by the respective subsystem. Power stats gets updated after + DSP clock change event. + config QCOM_WDT_CORE tristate "Qualcomm Technologies, Inc. Watchdog Support" depends on ARCH_QCOM diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index c2eb202f561a..9e3889984ba3 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -109,6 +109,7 @@ endif obj-$(CONFIG_QTI_SYS_PM_VX) += sys_pm_vx.o obj-$(CONFIG_ICNSS2) += icnss2/ obj-$(CONFIG_QTI_PLH_SCMI_CLIENT) += plh_scmi.o +obj-$(CONFIG_QCOM_SYSMON_SUBSYSTEM_STATS) += sysmon_subsystem_stats.o obj-$(CONFIG_QTI_HW_MEMLAT_SCMI_CLIENT) += memlat_scmi.o obj-$(CONFIG_QTI_HW_MEMLAT) += rimps_memlat.o obj-$(CONFIG_QTI_HW_MEMLAT_LOG) += rimps_log.o diff --git a/drivers/soc/qcom/sysmon_subsystem_stats.c b/drivers/soc/qcom/sysmon_subsystem_stats.c new file mode 100644 index 000000000000..14ff0b7b650d --- /dev/null +++ b/drivers/soc/qcom/sysmon_subsystem_stats.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#define SYSMON_SMEM_ID 634 +#define SYSMON_POWER_STATS_VERSIONID 0x1 +#define SYSMON_POWER_STATS_FEATUREID 0x3 + +/** + * sysmon_stats_query_power_residency() - * API to query requested + * DSP subsystem power residency.On success, returns power residency + * statistics in the given sysmon_smem_power_stats structure. + */ +int sysmon_stats_query_power_residency(enum dsp_id_t dsp_id, + struct sysmon_smem_power_stats *sysmon_power_stats) +{ + u32 featureId; + int err = 0; + int feature, size_rcvd; + size_t size; + char *smem_pointer = NULL; + int size_of_u32 = sizeof(u32); + + if (!sysmon_power_stats || !dsp_id) { + pr_err("%s: Null pointer received/invalid dsp ID\n", __func__); + return -EINVAL; + } + + smem_pointer = qcom_smem_get(dsp_id, SYSMON_SMEM_ID, &size); + + if (IS_ERR_OR_NULL(smem_pointer) || !size) { + pr_err("Failed to fetch data from SMEM for ID %d: %d\n", + dsp_id, PTR_ERR(smem_pointer)); + return -ENOMEM; + } + + featureId = *(unsigned int *)smem_pointer; + + feature = featureId >> 28; + size_rcvd = (featureId >> 16) & 0xFFF; + + while (size != 0) { + switch (feature) { + + case SYSMON_POWER_STATS_FEATUREID: + + if (!IS_ERR_OR_NULL(smem_pointer + size_of_u32)) { + memcpy(sysmon_power_stats, (smem_pointer + size_of_u32), + sizeof(struct sysmon_smem_power_stats)); + size = 0; + } else { + pr_err("%s: Requested feature not found\n", __func__); + size = 0; + return -ENOMEM; + } + break; + default: + + if (!IS_ERR_OR_NULL(smem_pointer + size_rcvd) + && (size > size_rcvd)) { + + featureId = *(unsigned int *)(smem_pointer + size_rcvd); + + smem_pointer += size_rcvd; + size = size - size_rcvd; + + feature = featureId >> 28; + size_rcvd = (featureId >> 16) & 0xFFF; + } else { + pr_err("%s: Requested feature not found\n", __func__); + size = 0; + return -ENOMEM; + } + break; + } + } + return err; +} +EXPORT_SYMBOL(sysmon_stats_query_power_residency); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Sysmon subsystem Stats driver"); diff --git a/include/linux/soc/qcom/sysmon_subsystem_stats.h b/include/linux/soc/qcom/sysmon_subsystem_stats.h new file mode 100644 index 000000000000..7e8840ef1e9a --- /dev/null +++ b/include/linux/soc/qcom/sysmon_subsystem_stats.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +/* + * This header is for sysmon subsystem stats query API's in drivers. + */ + +#ifndef __QCOM_SYSMON_SUBSYSTEM_STATS_H__ +#define __QCOM_SYSMON_SUBSYSTEM_STATS_H__ + +/* + * @struct sysmon_smem_power_stats_t + * @brief Structure type to hold DSP power statistics. + */ +struct sysmon_smem_power_stats { + u32 clk_arr[8]; + /**< Core clock frequency(KHz) array */ + + u32 active_time[8]; + /**< Active time(seconds) array corresponding to core clock array */ + + u32 pc_time; + /**< DSP LPM(Low Power Mode) time(seconds) */ + + u32 lpi_time; + /**< DSP LPI(Low Power Island Mode) time(seconds) */ +}; + +/* + * @enum dsp_id_t + * @brief Enum to hold SMEM HOST ID for DSP subsystems. + */ +enum dsp_id_t { + ADSP = 2, + SLPI, + CDSP = 5 +}; + +/** + * API to query requested DSP subsystem power residency. + * On success, returns power residency statistics in the given + * sysmon_smem_power_stats structure. + * @arg: DSP_ID +.* 2 - ADSP + * 3 - SLPI + * 5 - CDSP + *sysmon_smem_power_stats + * u32 clk_arr[8]; + * u32 active_time[8]; + * u32 pc_time; + * u32 lpi_time; + *@return SUCCESS (0) if Query is succssful + * FAILURE (Non-zero) if Query could not be processed. + * + */ + +int sysmon_stats_query_power_residency(enum dsp_id_t dsp_id, + struct sysmon_smem_power_stats *sysmon_power_stats); + +#endif From 33686b66f11aa880f72fe4b7077f6d8fc52ee767 Mon Sep 17 00:00:00 2001 From: Kiran Gunda Date: Thu, 3 Jun 2021 21:09:51 +0530 Subject: [PATCH 66/67] input: qcom-hv-haptics: Add support for non-hboost haptics Some PMICs such as PM5100 does not have the HBOOST peripheral for haptics input supply. Add a new compatible string to avoid accessing the non-existent HBOOST peripheral and also make the necessary configurations required for hpwr supply. Change-Id: I84301115706ee59984f7b051bc467d1537bbad29 Signed-off-by: Kiran Gunda --- drivers/input/misc/qcom-hv-haptics.c | 239 ++++++++++++++++++++++----- 1 file changed, 195 insertions(+), 44 deletions(-) diff --git a/drivers/input/misc/qcom-hv-haptics.c b/drivers/input/misc/qcom-hv-haptics.c index f72e47b70426..734af9d8adb9 100644 --- a/drivers/input/misc/qcom-hv-haptics.c +++ b/drivers/input/misc/qcom-hv-haptics.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -173,10 +174,20 @@ #define CAL_RC_CLK_AUTO_VAL 1 #define CAL_RC_CLK_MANUAL_VAL 2 +/* These registers are only applicable for PM5100 */ +#define HAP_CFG_HPWR_INTF_CTL_REG 0x80 +#define INTF_CTL_MASK GENMASK(1, 0) +#define INTF_CTL_BOB 1 +#define INTF_CTL_BHARGER 2 + +#define HAP_CFG_VHPWR_REG 0x84 +#define VHPWR_STEP_MV 32 + /* version register definitions for HAPTICS_PATTERN module */ #define HAP_PTN_REVISION2_REG 0x01 #define HAP_PTN_V1 0x1 #define HAP_PTN_V2 0x2 +#define HAP_PTN_V3 0x3 /* status register definition for HAPTICS_PATTERN module */ #define HAP_PTN_FIFO_READY_STS_REG 0x08 @@ -267,10 +278,6 @@ #define F_LRA_VARIATION_HZ 5 #define NON_HBOOST_MAX_VMAX_MV 4000 -#define MAX_FIFO_SAMPLES(chip) \ - ((chip)->ptn_revision == HAP_PTN_V1 ? 104 : 640) -#define FIFO_EMPTY_THRESHOLD(chip) \ - ((chip)->ptn_revision == HAP_PTN_V1 ? 48 : 280) #define is_between(val, min, max) \ (((min) <= (max)) && ((min) <= (val)) && ((val) <= (max))) #define HAP_BOOST_CLAMP_5V_REG_OFFSET(chip) \ @@ -346,6 +353,11 @@ enum custom_effect_param { CUSTOM_DATA_LEN, }; +enum pmic_type { + PM8350B, + PM5100, +}; + static const char * const src_str[] = { "FIFO", "DIRECT_PLAY", @@ -495,7 +507,9 @@ struct haptics_chip { u32 hbst_addr_base; u8 cfg_revision; u8 ptn_revision; + u8 hpwr_intf_ctl; u16 hbst_revision; + enum pmic_type pmic_type; bool fifo_empty_irq_en; bool swr_slave_enabled; bool clamp_at_5v; @@ -507,6 +521,86 @@ struct haptics_reg_info { u8 val; }; +static inline int get_max_fifo_samples(struct haptics_chip *chip) +{ + int val = 0; + + switch (chip->ptn_revision) { + case HAP_PTN_V1: + val = 104; + break; + case HAP_PTN_V2: + val = 640; + break; + case HAP_PTN_V3: + val = 1024; + break; + default: + pr_err("Invalid pattern revision\n"); + break; + } + + return val; +} + +static int get_fifo_empty_threshold(struct haptics_chip *chip) +{ + int val = 0; + + switch (chip->ptn_revision) { + case HAP_PTN_V1: + val = 48; + break; + case HAP_PTN_V2: + val = 280; + break; + case HAP_PTN_V3: + val = 288; + break; + default: + pr_err("Invalid pattern revision\n"); + break; + } + + return val; +} + +static int get_fifo_threshold_per_bit(struct haptics_chip *chip) +{ + int val = -EINVAL; + + switch (chip->ptn_revision) { + case HAP_PTN_V1: + val = 4; + break; + case HAP_PTN_V2: + val = 40; + break; + case HAP_PTN_V3: + val = 32; + break; + default: + pr_err("Invalid pattern revision\n"); + break; + } + + return val; +} + +static bool is_haptics_external_powered(struct haptics_chip *chip) +{ + /* SW based explicit vote */ + if (chip->hpwr_vreg) + return true; + + /* Implicit voting by HW */ + if (chip->pmic_type == PM5100) + return true; + + /* Powered by HBOOST */ + return false; +} + static int haptics_read(struct haptics_chip *chip, u16 base, u8 offset, u8 *val, u32 length) { @@ -890,7 +984,7 @@ static int haptics_get_closeloop_lra_period_v2( rc_clk_cal = ((val[0] & CAL_RC_CLK_MASK) >> CAL_RC_CLK_SHIFT); /* read auto resonance calibration result */ - if (in_boot) { + if (in_boot && (chip->pmic_type == PM8350B)) { if (chip->hap_cfg_nvmem == NULL) { dev_dbg(chip->dev, "nvmem device for hap_cfg is not defined\n"); return -EINVAL; @@ -1164,6 +1258,9 @@ static int haptics_boost_vreg_enable(struct haptics_chip *chip, bool en) int rc; u8 val; + if (is_haptics_external_powered(chip)) + return 0; + if (chip->hap_cfg_nvmem == NULL) { dev_dbg(chip->dev, "nvmem device for hap_cfg is not defined\n"); return 0; @@ -1208,6 +1305,9 @@ static bool is_boost_vreg_enabled_in_open_loop(struct haptics_chip *chip) int rc; u8 val; + if (is_haptics_external_powered(chip)) + return false; + rc = haptics_read(chip, chip->hbst_addr_base, HAP_BOOST_HW_CTRL_FOLLOW_REG, &val, 1); if (!rc && !(val & FOLLOW_HW_EN_BIT)) { @@ -1229,6 +1329,8 @@ static int haptics_wait_hboost_ready(struct haptics_chip *chip) int i, rc; u8 val; + if (is_haptics_external_powered(chip)) + return 0; /* * Wait ~20ms until hBoost is ready, otherwise * bail out and return -EBUSY @@ -1325,7 +1427,7 @@ static int haptics_open_loop_drive_config(struct haptics_chip *chip, bool en) u8 val; if ((is_boost_vreg_enabled_in_open_loop(chip) || - chip->hpwr_vreg != NULL) && en) { + is_haptics_external_powered(chip)) && en) { /* Force VREG_RDY */ rc = haptics_masked_write(chip, chip->cfg_addr_base, HAP_CFG_VSET_CFG_REG, FORCE_VREG_RDY_BIT, @@ -1357,7 +1459,7 @@ static int haptics_open_loop_drive_config(struct haptics_chip *chip, bool en) dev_dbg(chip->dev, "Toggle CAL_EN in open-loop-VREG playing\n"); } - } else if (chip->hpwr_vreg == NULL) { + } else if (!is_haptics_external_powered(chip)) { rc = haptics_masked_write(chip, chip->cfg_addr_base, HAP_CFG_VSET_CFG_REG, FORCE_VREG_RDY_BIT, 0); @@ -1619,16 +1721,16 @@ static int haptics_get_available_fifo_memory(struct haptics_chip *chip) if (rc < 0) return rc; - if (fill > MAX_FIFO_SAMPLES(chip)) { + if (fill > get_max_fifo_samples(chip)) { dev_err(chip->dev, "Filled FIFO number %d exceed the max %d\n", - fill, MAX_FIFO_SAMPLES(chip)); + fill, get_max_fifo_samples(chip)); return -EINVAL; - } else if (fill == MAX_FIFO_SAMPLES(chip)) { + } else if (fill == get_max_fifo_samples(chip)) { dev_err(chip->dev, "no FIFO space available\n"); return -EBUSY; } - available = MAX_FIFO_SAMPLES(chip) - fill; + available = get_max_fifo_samples(chip) - fill; return available; } @@ -1717,12 +1819,16 @@ static int haptics_set_fifo_empty_threshold(struct haptics_chip *chip, u8 reg, thresh_per_bit; int rc; + rc = get_fifo_threshold_per_bit(chip); + if (rc < 0) + return rc; + + thresh_per_bit = rc; + reg = (chip->ptn_revision == HAP_PTN_V1) ? HAP_PTN_V1_FIFO_EMPTY_CFG_REG : HAP_PTN_V2_FIFO_EMPTY_CFG_REG; - thresh_per_bit = (chip->ptn_revision == HAP_PTN_V1) ? - HAP_PTN_V1_FIFO_THRESH_LSB : HAP_PTN_V2_FIFO_THRESH_LSB; - rc = haptics_masked_write(chip, chip->ptn_addr_base, - reg, EMPTY_THRESH_MASK, thresh / thresh_per_bit); + rc = haptics_masked_write(chip, chip->ptn_addr_base, reg, + EMPTY_THRESH_MASK, (thresh / thresh_per_bit)); if (rc < 0) dev_err(chip->dev, "Set FIFO empty threshold failed, rc=%d\n", rc); @@ -1782,7 +1888,7 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo) if (chip->ptn_revision == HAP_PTN_V1 && fifo->period_per_s > F_8KHZ && - fifo->num_s > MAX_FIFO_SAMPLES(chip)) { + fifo->num_s > get_max_fifo_samples(chip)) { dev_err(chip->dev, "PM8350B v1 doesn't support playing long FIFO pattern higher than 8 KHz play rate\n"); return -EINVAL; } @@ -1808,7 +1914,7 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo) * more than MAX_FIFO_SAMPLES samples, the rest will be * written if any FIFO memory is available after playing. */ - num = min_t(u32, fifo->num_s, MAX_FIFO_SAMPLES(chip)); + num = min_t(u32, fifo->num_s, get_max_fifo_samples(chip)); available = haptics_get_available_fifo_memory(chip); if (available < 0) return available; @@ -1861,7 +1967,7 @@ static int haptics_load_constant_effect(struct haptics_chip *chip, u8 amplitude) play->effect = NULL; /* Fix Vmax to (hpwr_vreg_mv - hdrm_mv) in non-HBOOST regulator case */ - if (chip->hpwr_vreg) { + if (is_haptics_external_powered(chip)) { rc = haptics_get_vmax_headroom_mv(chip, &hdrm_mv); if (rc < 0) goto unlock; @@ -2199,7 +2305,7 @@ static u8 get_direct_play_max_amplitude(struct haptics_chip *chip) u32 amplitude = DIRECT_PLAY_MAX_AMPLITUDE, hdrm_mv; int rc; - if (chip->hpwr_vreg) { + if (is_haptics_external_powered(chip)) { rc = haptics_get_vmax_headroom_mv(chip, &hdrm_mv); if (rc < 0) return 0; @@ -2477,12 +2583,15 @@ static int haptics_hw_init(struct haptics_chip *chip) if (rc < 0) return rc; - rc = haptics_read(chip, chip->hbst_addr_base, - HAP_BOOST_CLAMP_5V_REG_OFFSET(chip), val, 1); - if (rc < 0) - return rc; + if (!is_haptics_external_powered(chip)) { + rc = haptics_read(chip, chip->hbst_addr_base, + HAP_BOOST_CLAMP_5V_REG_OFFSET(chip), val, 1); + if (rc < 0) + return rc; + + chip->clamp_at_5v = val[0] & CLAMP_5V_BIT; + } - chip->clamp_at_5v = val[0] & CLAMP_5V_BIT; /* Config VMAX */ rc = haptics_set_vmax_mv(chip, config->vmax_mv); if (rc < 0) @@ -2506,8 +2615,29 @@ static int haptics_hw_init(struct haptics_chip *chip) if (rc < 0) return rc; - /* Force VREG_RDY if non-HBoost is used for powering haptics */ - if (chip->hpwr_vreg) { + if ((chip->pmic_type == PM5100) && !chip->hpwr_vreg) { + /* Indicates if HPWR is BOB or Bharger */ + rc = haptics_read(chip, chip->cfg_addr_base, + HAP_CFG_HPWR_INTF_CTL_REG, val, 1); + if (rc < 0) + return rc; + + chip->hpwr_intf_ctl = val[0] & INTF_CTL_MASK; + + /* Read HPWR voltage to adjust the VMAX */ + if (chip->hpwr_voltage_mv == 0 && + chip->hpwr_intf_ctl == INTF_CTL_BOB) { + rc = haptics_read(chip, chip->cfg_addr_base, + HAP_CFG_VHPWR_REG, val, 1); + if (rc < 0) + return rc; + + chip->hpwr_voltage_mv = val[0] * VHPWR_STEP_MV; + } + } + + if (is_haptics_external_powered(chip)) { + /* Force VREG_RDY if non-HBoost is used for powering haptics */ rc = haptics_masked_write(chip, chip->cfg_addr_base, HAP_CFG_VSET_CFG_REG, FORCE_VREG_RDY_BIT, FORCE_VREG_RDY_BIT); @@ -2597,9 +2727,9 @@ static irqreturn_t fifo_empty_irq_handler(int irq, void *data) * memory, defer the stop into erase() function. */ num = haptics_get_available_fifo_memory(chip); - if (num != MAX_FIFO_SAMPLES(chip)) { + if (num != get_max_fifo_samples(chip)) { dev_dbg(chip->dev, "%d FIFO samples still in playing\n", - MAX_FIFO_SAMPLES(chip) - num); + get_max_fifo_samples(chip) - num); goto unlock; } @@ -3686,14 +3816,21 @@ static int haptics_get_revision(struct haptics_chip *chip) return rc; chip->ptn_revision = val[0]; - rc = haptics_read(chip, chip->hbst_addr_base, - HAP_BOOST_REVISION1, val, 2); - if (rc < 0) - return rc; - chip->hbst_revision = (val[1] << 8) | val[0]; - dev_dbg(chip->dev, "haptics revision: HAP_CFG %#x, HAP_PTN %#x, HAP_HBST %#x\n", - chip->cfg_revision, chip->ptn_revision, chip->hbst_revision); + if (is_haptics_external_powered(chip)) { + dev_dbg(chip->dev, "haptics revision: HAP_CFG %#x, HAP_PTN %#x\n", + chip->cfg_revision, chip->ptn_revision); + } else { + rc = haptics_read(chip, chip->hbst_addr_base, + HAP_BOOST_REVISION1, val, 2); + if (rc < 0) + return rc; + + chip->hbst_revision = (val[1] << 8) | val[0]; + dev_dbg(chip->dev, "haptics revision: HAP_CFG %#x, HAP_PTN %#x, HAP_HBST %#x\n", + chip->cfg_revision, chip->ptn_revision, chip->hbst_revision); + } + return 0; } @@ -3791,13 +3928,14 @@ static int haptics_parse_dt(struct haptics_chip *chip) chip->ptn_addr_base = be32_to_cpu(*addr); addr = of_get_address(node, 2, NULL, NULL); - if (!addr) { + if (!addr && !is_haptics_external_powered(chip)) { dev_err(chip->dev, "Read HAPTICS_HBOOST address failed\n"); rc = -EINVAL; goto free_pbs; + } else if (addr != NULL) { + chip->hbst_addr_base = be32_to_cpu(*addr); } - chip->hbst_addr_base = be32_to_cpu(*addr); rc = haptics_get_revision(chip); if (rc < 0) { dev_err(chip->dev, "Get revision failed, rc=%d\n", rc); @@ -3820,12 +3958,12 @@ static int haptics_parse_dt(struct haptics_chip *chip) goto free_pbs; } - config->fifo_empty_thresh = FIFO_EMPTY_THRESHOLD(chip); + config->fifo_empty_thresh = get_fifo_empty_threshold(chip); of_property_read_u32(node, "qcom,fifo-empty-threshold", &config->fifo_empty_thresh); - if (config->fifo_empty_thresh >= MAX_FIFO_SAMPLES(chip)) { + if (config->fifo_empty_thresh >= get_max_fifo_samples(chip)) { dev_err(chip->dev, "FIFO empty threshold (%d) should be less than %d\n", - config->fifo_empty_thresh, MAX_FIFO_SAMPLES(chip)); + config->fifo_empty_thresh, get_max_fifo_samples(chip)); rc = -EINVAL; goto free_pbs; } @@ -4044,7 +4182,7 @@ static u32 get_lra_impedance_capable_max(struct haptics_chip *chip) if (chip->clamp_at_5v) mohms = MAX_IMPEDANCE_MOHM / 2; - if (chip->hpwr_vreg) + if (is_haptics_external_powered(chip)) mohms = (chip->hpwr_voltage_mv * 1000) / MIN_ISC_MA; dev_dbg(chip->dev, "LRA impedance capable max: %u mohms\n", mohms); @@ -4210,7 +4348,7 @@ static int haptics_detect_lra_frequency(struct haptics_chip *chip) goto restore; /* Fix Vmax to (hpwr_vreg_mv - hdrm_mv) in non-HBOOST regulator case */ - if (chip->hpwr_vreg) + if (is_haptics_external_powered(chip)) vmax_mv = chip->hpwr_voltage_mv - LRA_CALIBRATION_VMAX_HDRM_MV; rc = haptics_set_vmax_mv(chip, vmax_mv); @@ -4401,6 +4539,9 @@ static int haptics_probe(struct platform_device *pdev) return -ENXIO; } + chip->pmic_type = + (enum pmic_type)(uintptr_t)of_device_get_match_data(chip->dev); + rc = haptics_parse_dt(chip); if (rc < 0) { dev_err(chip->dev, "Parse device-tree failed, rc = %d\n", rc); @@ -4572,8 +4713,18 @@ static const struct dev_pm_ops haptics_pm_ops = { }; static const struct of_device_id haptics_match_table[] = { - { .compatible = "qcom,hv-haptics" }, - { .compatible = "qcom,pm8350b-haptics" }, + { + .compatible = "qcom,hv-haptics", + .data = (void *)PM8350B, + }, + { + .compatible = "qcom,pm8350b-haptics", + .data = (void *)PM8350B, + }, + { + .compatible = "qcom,pm5100-haptics", + .data = (void *)PM5100, + }, {}, }; From 1d1b0056f9b53eb65dbbaf5a9a7b2040bc5d76bb Mon Sep 17 00:00:00 2001 From: Sandeep Singh Date: Mon, 7 Jun 2021 15:41:19 +0530 Subject: [PATCH 67/67] icnss2: Add support to vote for SMPS This change will add support to vote for SMPS node if regulator handle is provided in DTS source. Change-Id: I7519b6c2b93c85a4f4bf7e26ca0b72ef03df094b Signed-off-by: Sandeep Singh --- drivers/soc/qcom/icnss2/power.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/icnss2/power.c b/drivers/soc/qcom/icnss2/power.c index fe19f1f90315..86b33c5a5ad9 100644 --- a/drivers/soc/qcom/icnss2/power.c +++ b/drivers/soc/qcom/icnss2/power.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #include #include @@ -26,6 +26,7 @@ static struct icnss_vreg_cfg icnss_adrestea_vreg_list[] = { {"vdd-1.3-rfa", 1304000, 1304000, 0, 0, 0, false, true}, {"vdd-3.3-ch1", 3312000, 3312000, 0, 0, 0, false, true}, {"vdd-3.3-ch0", 3312000, 3312000, 0, 0, 0, false, true}, + {"vdd-smps", 984000, 984000, 0, 0, 0, false, true}, }; static struct icnss_clk_cfg icnss_clk_list[] = {