Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 48ea28e8 authored by Utkarsh Saxena's avatar Utkarsh Saxena
Browse files

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: default avatarMohammad Javid <mjavid@qti.qualcomm.com>
Signed-off-by: default avatarUtkarsh Saxena <usaxena@codeaurora.org>
parent 558d13ea
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -74,6 +74,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
+42 −0
Original line number Diff line number Diff line
@@ -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)

@@ -3698,6 +3702,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;
@@ -4353,6 +4370,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;
}

+124 −0
Original line number Diff line number Diff line
@@ -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) {
+3 −5
Original line number Diff line number Diff line
@@ -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
@@ -1020,8 +1018,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;
@@ -1034,7 +1032,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);
+8 −0
Original line number Diff line number Diff line
@@ -1237,6 +1237,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;
};

/**
@@ -1288,6 +1291,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 {
@@ -1732,6 +1737,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)
Loading