From d630f1d6aa02aad44f9e4a058ab30b1084165d2b Mon Sep 17 00:00:00 2001 From: Utkarsh Saxena Date: Thu, 14 Jul 2016 23:20:15 +0530 Subject: [PATCH] msm: ipa: add support for configuring polling interval/sleep time Using 1 millisecond Rx polling sleep makes the cpu wake up too often, results in more power consumption. Using 3 milliseconds is helping on MSM8940 in terms of both power and performance. Give provision to change the polling time via device tree entry and use 3 milliseconds for MSM8940. And also give provision to modify the rx polling timeout via debugfs entry for testing purposes. Change-Id: I88de436b29c3000dcebeec4da607dff42d0609fe Acked-by: Mohammad Javid Signed-off-by: Utkarsh Saxena --- .../devicetree/bindings/platform/msm/ipa.txt | 4 + drivers/platform/msm/ipa/ipa_v2/ipa.c | 42 ++++++ drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c | 124 ++++++++++++++++++ drivers/platform/msm/ipa/ipa_v2/ipa_dp.c | 8 +- drivers/platform/msm/ipa/ipa_v2/ipa_i.h | 8 ++ drivers/platform/msm/ipa/ipa_v2/ipa_utils.c | 29 ++++ 6 files changed, 210 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/platform/msm/ipa.txt b/Documentation/devicetree/bindings/platform/msm/ipa.txt index 222b4fe66697..31ffd2a47282 100644 --- a/Documentation/devicetree/bindings/platform/msm/ipa.txt +++ b/Documentation/devicetree/bindings/platform/msm/ipa.txt @@ -76,6 +76,10 @@ memory allocation over a PCIe bridge - qcom,tethered-flow-control: Boolean context flag to indicate whether apps based flow control is needed for tethered call. +- qcom,rx-polling-sleep-ms: Receive Polling Timeout in millisecond, + default is 1 millisecond. +- qcom,ipa-polling-iteration: IPA Polling Iteration Count,default is 40. + IPA pipe sub nodes (A2 static pipes configurations): -label: two labels are supported, a2-to-ipa and ipa-to-a2 which diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c index 1f9fd7a38a37..aacad8cd90ce 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c @@ -65,6 +65,10 @@ #define IPA2_ACTIVE_CLIENT_LOG_TYPE_RESOURCE 2 #define IPA2_ACTIVE_CLIENT_LOG_TYPE_SPECIAL 3 +#define MAX_POLLING_ITERATION 40 +#define MIN_POLLING_ITERATION 1 +#define ONE_MSEC 1 + #define IPA_AGGR_STR_IN_BYTES(str) \ (strnlen((str), IPA_AGGR_MAX_STR_LENGTH - 1) + 1) @@ -3613,6 +3617,19 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p, ipa_ctx->use_dma_zone = resource_p->use_dma_zone; ipa_ctx->tethered_flow_control = resource_p->tethered_flow_control; + /* Setting up IPA RX Polling Timeout Seconds */ + ipa_rx_timeout_min_max_calc(&ipa_ctx->ipa_rx_min_timeout_usec, + &ipa_ctx->ipa_rx_max_timeout_usec, + resource_p->ipa_rx_polling_sleep_msec); + + /* Setting up ipa polling iteration */ + if ((resource_p->ipa_polling_iteration >= MIN_POLLING_ITERATION) + && (resource_p->ipa_polling_iteration <= MAX_POLLING_ITERATION)) + ipa_ctx->ipa_polling_iteration = + resource_p->ipa_polling_iteration; + else + ipa_ctx->ipa_polling_iteration = MAX_POLLING_ITERATION; + /* default aggregation parameters */ ipa_ctx->aggregation_type = IPA_MBIM_16; ipa_ctx->aggregation_byte_limit = 1; @@ -4268,6 +4285,31 @@ static int get_ipa_dts_configuration(struct platform_device *pdev, if (result) ipa_drv_res->ee = 0; + /* Get IPA RX Polling Timeout Seconds */ + result = of_property_read_u32(pdev->dev.of_node, + "qcom,rx-polling-sleep-ms", + &ipa_drv_res->ipa_rx_polling_sleep_msec); + + if (result) { + ipa_drv_res->ipa_rx_polling_sleep_msec = ONE_MSEC; + IPADBG("using default polling timeout of 1MSec\n"); + } else { + IPADBG(": found ipa_drv_res->ipa_rx_polling_sleep_sec = %d", + ipa_drv_res->ipa_rx_polling_sleep_msec); + } + + /* Get IPA Polling Iteration */ + result = of_property_read_u32(pdev->dev.of_node, + "qcom,ipa-polling-iteration", + &ipa_drv_res->ipa_polling_iteration); + if (result) { + ipa_drv_res->ipa_polling_iteration = MAX_POLLING_ITERATION; + IPADBG("using default polling iteration\n"); + } else { + IPADBG(": found ipa_drv_res->ipa_polling_iteration = %d", + ipa_drv_res->ipa_polling_iteration); + } + return 0; } diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c index 566cb4d03c51..ca3c6d0a1c1a 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c @@ -25,6 +25,12 @@ * IPA2_ACTIVE_CLIENTS_LOG_BUFFER_SIZE_LINES) \ + IPA_MAX_MSG_LEN) +#define RX_MIN_POLL_CNT "Rx Min Poll Count" +#define RX_MAX_POLL_CNT "Rx Max Poll Count" +#define MAX_COUNT_LENGTH 6 +#define MAX_POLLING_ITERATION 40 +#define MIN_POLLING_ITERATION 1 + #define IPA_DUMP_STATUS_FIELD(f) \ pr_err(#f "=0x%x\n", status->f) @@ -110,6 +116,9 @@ static struct dentry *dfile_ip4_nat; static struct dentry *dfile_rm_stats; static struct dentry *dfile_status_stats; static struct dentry *dfile_active_clients; +static struct dentry *dfile_ipa_rx_poll_timeout; +static struct dentry *dfile_ipa_poll_iteration; + static char dbg_buff[IPA_MAX_MSG_LEN]; static char *active_clients_buf; static s8 ep_reg_idx; @@ -1597,6 +1606,97 @@ static ssize_t ipa2_clear_active_clients_log(struct file *file, return count; } +static ssize_t ipa_read_rx_polling_timeout(struct file *file, + char __user *ubuf, size_t count, loff_t *ppos) +{ + int min_cnt; + int max_cnt; + + if (active_clients_buf == NULL) { + IPAERR("Active Clients buffer is not allocated"); + return 0; + } + memset(active_clients_buf, 0, IPA_DBG_ACTIVE_CLIENTS_BUF_SIZE); + min_cnt = scnprintf(active_clients_buf, + IPA_DBG_ACTIVE_CLIENTS_BUF_SIZE, + "Rx Min Poll count = %u\n", + ipa_ctx->ipa_rx_min_timeout_usec); + + max_cnt = scnprintf(active_clients_buf + min_cnt, + IPA_DBG_ACTIVE_CLIENTS_BUF_SIZE, + "Rx Max Poll count = %u\n", + ipa_ctx->ipa_rx_max_timeout_usec); + + return simple_read_from_buffer(ubuf, count, ppos, active_clients_buf, + min_cnt + max_cnt); +} + +static ssize_t ipa_write_rx_polling_timeout(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + s8 polltime = 0; + + if (sizeof(dbg_buff) < count + 1) + return -EFAULT; + + if (copy_from_user(dbg_buff, ubuf, count)) + return -EFAULT; + + dbg_buff[count] = '\0'; + + if (kstrtos8(dbg_buff, 0, &polltime)) + return -EFAULT; + + ipa_rx_timeout_min_max_calc(&ipa_ctx->ipa_rx_min_timeout_usec, + &ipa_ctx->ipa_rx_max_timeout_usec, polltime); + return count; +} + +static ssize_t ipa_read_polling_iteration(struct file *file, + char __user *ubuf, size_t count, loff_t *ppos) +{ + int cnt; + + if (active_clients_buf == NULL) { + IPAERR("Active Clients buffer is not allocated"); + return 0; + } + + memset(active_clients_buf, 0, IPA_DBG_ACTIVE_CLIENTS_BUF_SIZE); + + cnt = scnprintf(active_clients_buf, IPA_DBG_ACTIVE_CLIENTS_BUF_SIZE, + "Polling Iteration count = %u\n", + ipa_ctx->ipa_polling_iteration); + + return simple_read_from_buffer(ubuf, count, ppos, active_clients_buf, + cnt); +} + +static ssize_t ipa_write_polling_iteration(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + s8 iteration_cnt = 0; + + if (sizeof(dbg_buff) < count + 1) + return -EFAULT; + + if (copy_from_user(dbg_buff, ubuf, count)) + return -EFAULT; + + dbg_buff[count] = '\0'; + + if (kstrtos8(dbg_buff, 0, &iteration_cnt)) + return -EFAULT; + + if ((iteration_cnt >= MIN_POLLING_ITERATION) && + (iteration_cnt <= MAX_POLLING_ITERATION)) + ipa_ctx->ipa_polling_iteration = iteration_cnt; + else + ipa_ctx->ipa_polling_iteration = MAX_POLLING_ITERATION; + + return count; +} + const struct file_operations ipa_gen_reg_ops = { .read = ipa_read_gen_reg, }; @@ -1671,6 +1771,16 @@ const struct file_operations ipa2_active_clients = { .write = ipa2_clear_active_clients_log, }; +const struct file_operations ipa_rx_poll_time_ops = { + .read = ipa_read_rx_polling_timeout, + .write = ipa_write_rx_polling_timeout, +}; + +const struct file_operations ipa_poll_iteration_ops = { + .read = ipa_read_polling_iteration, + .write = ipa_write_polling_iteration, +}; + void ipa_debugfs_init(void) { const mode_t read_only_mode = S_IRUSR | S_IRGRP | S_IROTH; @@ -1832,6 +1942,20 @@ void ipa_debugfs_init(void) goto fail; } + dfile_ipa_rx_poll_timeout = debugfs_create_file("ipa_rx_poll_time", + read_write_mode, dent, 0, &ipa_rx_poll_time_ops); + if (!dfile_ipa_rx_poll_timeout || IS_ERR(dfile_ipa_rx_poll_timeout)) { + IPAERR("fail to create file for debug_fs rx poll timeout\n"); + goto fail; + } + + dfile_ipa_poll_iteration = debugfs_create_file("ipa_poll_iteration", + read_write_mode, dent, 0, &ipa_poll_iteration_ops); + if (!dfile_ipa_poll_iteration || IS_ERR(dfile_ipa_poll_iteration)) { + IPAERR("fail to create file for debug_fs poll iteration\n"); + goto fail; + } + file = debugfs_create_u32("enable_clock_scaling", read_write_mode, dent, &ipa_ctx->enable_clock_scaling); if (!file) { diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c index 1c93ac16d419..50caeb9a19ee 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c @@ -20,8 +20,6 @@ #define IPA_LAST_DESC_CNT 0xFFFF #define POLLING_INACTIVITY_RX 40 -#define POLLING_MIN_SLEEP_RX 1010 -#define POLLING_MAX_SLEEP_RX 1050 #define POLLING_INACTIVITY_TX 40 #define POLLING_MIN_SLEEP_TX 400 #define POLLING_MAX_SLEEP_TX 500 @@ -1045,8 +1043,8 @@ static void ipa_handle_rx(struct ipa_sys_context *sys) if (cnt == 0) { inactive_cycles++; trace_idle_sleep_enter(sys->ep->client); - usleep_range(POLLING_MIN_SLEEP_RX, - POLLING_MAX_SLEEP_RX); + usleep_range(ipa_ctx->ipa_rx_min_timeout_usec, + ipa_ctx->ipa_rx_max_timeout_usec); trace_idle_sleep_exit(sys->ep->client); } else { inactive_cycles = 0; @@ -1059,7 +1057,7 @@ static void ipa_handle_rx(struct ipa_sys_context *sys) if (sys->len == 0) break; - } while (inactive_cycles <= POLLING_INACTIVITY_RX); + } while (inactive_cycles <= ipa_ctx->ipa_polling_iteration); trace_poll_to_intr(sys->ep->client); ipa_rx_switch_to_intr_mode(sys); diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h index f94418efc927..0a0b23815ce3 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h @@ -1244,6 +1244,9 @@ struct ipa_context { /* M-release support to know client pipes */ struct ipacm_client_info ipacm_client[IPA_MAX_NUM_PIPES]; bool tethered_flow_control; + u32 ipa_rx_min_timeout_usec; + u32 ipa_rx_max_timeout_usec; + u32 ipa_polling_iteration; }; /** @@ -1295,6 +1298,8 @@ struct ipa_plat_drv_res { bool skip_uc_pipe_reset; bool use_dma_zone; bool tethered_flow_control; + u32 ipa_rx_polling_sleep_msec; + u32 ipa_polling_iteration; }; struct ipa_mem_partition { @@ -1730,6 +1735,9 @@ void ipa_debugfs_init(void); void ipa_debugfs_remove(void); void ipa_dump_buff_internal(void *base, dma_addr_t phy_base, u32 size); + +void ipa_rx_timeout_min_max_calc(u32 *min, u32 *max, s8 time); + #ifdef IPA_DEBUG #define IPA_DUMP_BUFF(base, phy_base, size) \ ipa_dump_buff_internal(base, phy_base, size) diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c index 0dd10743a01e..69052eb289bb 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c @@ -43,6 +43,11 @@ #define IPA_AGGR_GRAN_MAX (32) #define IPA_EOT_COAL_GRAN_MIN (1) #define IPA_EOT_COAL_GRAN_MAX (16) +#define MSEC 1000 +#define MIN_RX_POLL_TIME 1 +#define MAX_RX_POLL_TIME 5 +#define UPPER_CUTOFF 50 +#define LOWER_CUTOFF 10 #define IPA_DEFAULT_SYS_YELLOW_WM 32 @@ -3622,6 +3627,30 @@ void ipa_dump_buff_internal(void *base, dma_addr_t phy_base, u32 size) IPADBG("END\n"); } +/** + * void ipa_rx_timeout_min_max_calc() - calc min max timeout time of rx polling + * @time: time fom dtsi entry or from debugfs file system + * @min: rx polling min timeout + * @max: rx polling max timeout + * Maximum time could be of 10Msec allowed. + */ +void ipa_rx_timeout_min_max_calc(u32 *min, u32 *max, s8 time) +{ + if ((time >= MIN_RX_POLL_TIME) && + (time <= MAX_RX_POLL_TIME)) { + *min = (time * MSEC) + LOWER_CUTOFF; + *max = (time * MSEC) + UPPER_CUTOFF; + } else { + /* Setting up the default min max time */ + IPADBG("Setting up default rx polling timeout\n"); + *min = (MIN_RX_POLL_TIME * MSEC) + + LOWER_CUTOFF; + *max = (MIN_RX_POLL_TIME * MSEC) + + UPPER_CUTOFF; + } + IPADBG("Rx polling timeout Min = %u len = %u\n", *min, *max); +} + /** * ipa_pipe_mem_init() - initialize the pipe memory * @start_ofst: start offset