diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c index 43fb44687f..1b900a2717 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c @@ -2235,6 +2235,81 @@ static ssize_t ipa_debugfs_print_drop_stats(struct file *file, return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes); } +static ssize_t ipa_debugfs_enable_disable_drop_stats(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + unsigned long missing; + unsigned int pipe_num = 0; + bool enable_pipe = true; + u32 pipe_bitmask = ipa3_ctx->hw_stats.drop.init.enabled_bitmask; + char seprator = ','; + int i, j; + bool is_pipe = false; + ssize_t ret; + + mutex_lock(&ipa3_ctx->lock); + if (sizeof(dbg_buff) < count + 1) { + ret = -EFAULT; + goto bail; + } + + missing = copy_from_user(dbg_buff, ubuf, count); + if (missing) { + ret = -EFAULT; + goto bail; + } + dbg_buff[count] = '\0'; + IPADBG("data is %s", dbg_buff); + + i = 0; + while (dbg_buff[i] != ' ' && i < count) + i++; + j = i; + i++; + if (i < count) { + if (dbg_buff[i] == '0') { + enable_pipe = false; + IPADBG("Drop stats will be disabled for pipes:"); + } + } + + for (i = 0; i < j; i++) { + if (dbg_buff[i] >= '0' && dbg_buff[i] <= '9') { + pipe_num = (pipe_num * 10) + (dbg_buff[i] - '0'); + is_pipe = true; + } + if (dbg_buff[i] == seprator) { + if (pipe_num >= 0 && pipe_num < ipa3_ctx->ipa_num_pipes + && ipa3_get_client_by_pipe(pipe_num) < + IPA_CLIENT_MAX) { + IPADBG("pipe number %u\n", pipe_num); + if (enable_pipe) + pipe_bitmask = pipe_bitmask | + (1 << pipe_num); + else + pipe_bitmask = pipe_bitmask & + (~(1 << pipe_num)); + } + pipe_num = 0; + is_pipe = false; + } + } + if (is_pipe && pipe_num >= 0 && pipe_num < ipa3_ctx->ipa_num_pipes && + ipa3_get_client_by_pipe(pipe_num) < IPA_CLIENT_MAX) { + IPADBG("pipe number %u\n", pipe_num); + if (enable_pipe) + pipe_bitmask = pipe_bitmask | (1 << pipe_num); + else + pipe_bitmask = pipe_bitmask & (~(1 << pipe_num)); + } + + ipa_init_drop_stats(pipe_bitmask); + ret = count; +bail: + mutex_unlock(&ipa3_ctx->lock); + return ret; +} + static const struct file_operations ipa3_quota_ops = { .read = ipa_debugfs_print_quota_stats, .write = ipa_debugfs_reset_quota_stats, @@ -2255,10 +2330,14 @@ static const struct file_operations ipa3_drop_ops = { .write = ipa_debugfs_reset_drop_stats, }; +static const struct file_operations ipa3_enable_drop_ops = { + .write = ipa_debugfs_enable_disable_drop_stats, +}; int ipa_debugfs_init_stats(struct dentry *parent) { const mode_t read_write_mode = 0664; + const mode_t write_mode = 0220; struct dentry *file; struct dentry *dent; @@ -2285,6 +2364,13 @@ int ipa_debugfs_init_stats(struct dentry *parent) goto fail; } + file = debugfs_create_file("enable_drop_stats", write_mode, dent, NULL, + &ipa3_enable_drop_ops); + if (IS_ERR_OR_NULL(file)) { + IPAERR("fail to create file %s\n", "enable_drop_stats"); + goto fail; + } + file = debugfs_create_file("tethering", read_write_mode, dent, NULL, &ipa3_tethering_ops); if (IS_ERR_OR_NULL(file)) {