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

Commit 74ff856e authored by Arun Kumar Neelakantam's avatar Arun Kumar Neelakantam
Browse files

net: ipc_router: Add dynamic enable/disable wakeup source feature



By default IPC Router core uses edge and port specific wakeup sources
which are blocking system suspend in special use cases like streaming
non wakeup sensors data at high speed.

Add dynamic wakeup source enable/disable functionality to acquire the
wakeup source only during the APPS suspend stage.

CRs-Fixed: 2057391
Change-Id: I2a5ea4e2c31432a9dd195c702ef7001b26eed33d
Signed-off-by: default avatarArun Kumar Neelakantam <aneela@codeaurora.org>
parent 50b1d5bf
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@ Optional properties:
			by pil. Absence of this property indicates that
			subsystem loading through pil voting is disabled for
			that subsystem.
-qcom,dynamic-wakeup-source:	Boolean property to indicate that G-Link
				transport supports dynamic wakeup source

Example:
	qcom,ipc_router_modem_xprt {
+20 −1
Original line number Diff line number Diff line
/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -70,6 +70,7 @@ if (ipc_router_glink_xprt_debug_mask) \
 * @xprt_version: IPC Router header version supported by this XPRT.
 * @xprt_option: XPRT specific options to be handled by IPC Router.
 * @disable_pil_loading: Disable PIL Loading of the subsystem.
 * @dynamic_wakeup_source: Dynamic wakeup source for this subsystem.
 */
struct ipc_router_glink_xprt {
	struct list_head list;
@@ -91,6 +92,7 @@ struct ipc_router_glink_xprt {
	uint32_t cur_lo_intents_cnt;
	uint32_t cur_md_intents_cnt;
	uint32_t cur_hi_intents_cnt;
	bool dynamic_wakeup_source;
};

struct ipc_router_glink_xprt_work {
@@ -127,6 +129,7 @@ static void glink_xprt_close_event(struct work_struct *work);
 * @link_id:		Network Cluster ID to which this XPRT belongs to.
 * @xprt_version:	IPC Router header version supported by this XPRT.
 * @disable_pil_loading:Disable PIL Loading of the subsystem.
 * @dynamic_wakeup_source: Dynamic wakeup source for this subsystem.
 */
struct ipc_router_glink_xprt_config {
	char ch_name[GLINK_NAME_SIZE];
@@ -138,6 +141,7 @@ struct ipc_router_glink_xprt_config {
	unsigned int xprt_version;
	unsigned int xprt_option;
	bool disable_pil_loading;
	bool dynamic_wakeup_source;
};

#define MODULE_NAME "ipc_router_glink_xprt"
@@ -294,6 +298,14 @@ static void glink_xprt_sft_close_done(struct msm_ipc_router_xprt *xprt)
	complete_all(&glink_xprtp->sft_close_complete);
}

static bool ipc_router_glink_xprt_get_ws_info(struct msm_ipc_router_xprt *xprt)
{
	struct ipc_router_glink_xprt *glink_xprtp =
		container_of(xprt, struct ipc_router_glink_xprt, xprt);

	return glink_xprtp->dynamic_wakeup_source;
}

static struct rr_packet *glink_xprt_copy_data(struct read_work *rx_work)
{
	void *buf, *pbuf, *dest_buf;
@@ -706,6 +718,8 @@ static int ipc_router_glink_config_init(
	glink_xprtp->xprt_option = glink_xprt_config->xprt_option;
	glink_xprtp->disable_pil_loading =
				glink_xprt_config->disable_pil_loading;
	glink_xprtp->dynamic_wakeup_source =
				glink_xprt_config->dynamic_wakeup_source;

	if (!glink_xprtp->disable_pil_loading)
		strlcpy(glink_xprtp->pil_edge, glink_xprt_config->pil_edge,
@@ -728,6 +742,7 @@ static int ipc_router_glink_config_init(
	glink_xprtp->xprt.write = ipc_router_glink_xprt_write;
	glink_xprtp->xprt.close = ipc_router_glink_xprt_close;
	glink_xprtp->xprt.sft_close_done = glink_xprt_sft_close_done;
	glink_xprtp->xprt.get_ws_info = ipc_router_glink_xprt_get_ws_info;
	glink_xprtp->xprt.priv = NULL;

	init_rwsem(&glink_xprtp->ss_reset_rwlock);
@@ -822,6 +837,10 @@ static int parse_devicetree(struct device_node *node,
	scnprintf(glink_xprt_config->ipc_rtr_xprt_name, IPC_RTR_XPRT_NAME_LEN,
		  "%s_%s", edge, ch_name);

	key = "qcom,dynamic-wakeup-source";
	glink_xprt_config->dynamic_wakeup_source =
					of_property_read_bool(node, key);

	return 0;

error:
+11 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -269,6 +269,14 @@ int register_ipcrtr_af_init_notifier(struct notifier_block *nb);
 */
int unregister_ipcrtr_af_init_notifier(struct notifier_block *nb);

/**
 * msm_ipc_router_set_ws_allowed() - To Enable/disable the wakeup source allowed
 *					flag
 * @flag: Flag to set/clear the wakeup soruce allowed
 *
 */
void msm_ipc_router_set_ws_allowed(bool flag);

#else

struct msm_ipc_port *msm_ipc_router_create_port(
@@ -341,6 +349,8 @@ int unregister_ipcrtr_af_init_notifier(struct notifier_block *nb)
	return -ENODEV;
}

void msm_ipc_router_set_ws_allowed(bool flag) { }

#endif

#endif
+5 −1
Original line number Diff line number Diff line
/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -100,6 +100,7 @@ struct rr_opt_hdr {
 * @pkt_fragment_q: Queue of SKBs containing payload.
 * @length: Length of data in the chain of SKBs
 * @ref: Reference count for the packet.
 * @ws_need: Flag to check wakeup soruce need
 */
struct rr_packet {
	struct list_head list;
@@ -108,6 +109,7 @@ struct rr_packet {
	struct sk_buff_head *pkt_fragment_q;
	uint32_t length;
	struct kref ref;
	bool ws_need;
};

/**
@@ -125,6 +127,7 @@ struct rr_packet {
 * @close: Method to close the XPRT.
 * @sft_close_done: Method to indicate to the XPRT that handling of reset
 *                  event is complete.
 * @get_ws_info: Method to get the wakeup soruce inforamtion of the XPRT
 */
struct msm_ipc_router_xprt {
	char *name;
@@ -143,6 +146,7 @@ struct msm_ipc_router_xprt {
		     struct msm_ipc_router_xprt *xprt);
	int (*close)(struct msm_ipc_router_xprt *xprt);
	void (*sft_close_done)(struct msm_ipc_router_xprt *xprt);
	bool (*get_ws_info)(struct msm_ipc_router_xprt *xprt);
};

void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt,
+25 −3
Original line number Diff line number Diff line
/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -148,6 +148,7 @@ struct msm_ipc_router_xprt_info {
	void *log_ctx;
	struct kref ref;
	struct completion ref_complete;
	bool dynamic_ws;
};

#define RT_HASH_SIZE 4
@@ -215,6 +216,13 @@ enum {
	UP,
};

static bool is_wakeup_source_allowed;

void msm_ipc_router_set_ws_allowed(bool flag)
{
	is_wakeup_source_allowed = flag;
}

static void init_routing_table(void)
{
	int i;
@@ -580,6 +588,7 @@ struct rr_packet *clone_pkt(struct rr_packet *pkt)
	}
	cloned_pkt->pkt_fragment_q = pkt_fragment_q;
	cloned_pkt->length = pkt->length;
	cloned_pkt->ws_need = pkt->ws_need;
	return cloned_pkt;

fail_clone:
@@ -1162,6 +1171,7 @@ static int post_pkt_to_port(struct msm_ipc_port *port_ptr,
	}

	mutex_lock(&port_ptr->port_rx_q_lock_lhc3);
	if (pkt->ws_need)
		__pm_stay_awake(port_ptr->port_rx_ws);
	list_add_tail(&temp_pkt->list, &port_ptr->port_rx_q);
	wake_up(&port_ptr->port_rx_wait_q);
@@ -4043,6 +4053,9 @@ static int msm_ipc_router_add_xprt(struct msm_ipc_router_xprt *xprt)
	INIT_LIST_HEAD(&xprt_info->list);
	kref_init(&xprt_info->ref);
	init_completion(&xprt_info->ref_complete);
	xprt_info->dynamic_ws = 0;
	if (xprt->get_ws_info)
		xprt_info->dynamic_ws = xprt->get_ws_info(xprt);

	xprt_info->workqueue = create_singlethread_workqueue(xprt->name);
	if (!xprt_info->workqueue) {
@@ -4193,9 +4206,18 @@ void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt,
	if (!pkt)
		return;

	pkt->ws_need = false;
	mutex_lock(&xprt_info->rx_lock_lhb2);
	list_add_tail(&pkt->list, &xprt_info->pkt_list);
	if (!xprt_info->dynamic_ws) {
		__pm_stay_awake(&xprt_info->ws);
		pkt->ws_need = true;
	} else {
		if (is_wakeup_source_allowed) {
			__pm_stay_awake(&xprt_info->ws);
			pkt->ws_need = true;
		}
	}
	mutex_unlock(&xprt_info->rx_lock_lhb2);
	queue_work(xprt_info->workqueue, &xprt_info->read_data);
}