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

This commit is contained in:
Linux Build Service Account 2017-06-07 20:57:59 -07:00 committed by Gerrit - the friendly Code Review server
commit 0899f88b10
5 changed files with 63 additions and 6 deletions

View file

@ -17,6 +17,8 @@ Optional properties:
by pil. Absence of this property indicates that by pil. Absence of this property indicates that
subsystem loading through pil voting is disabled for subsystem loading through pil voting is disabled for
that subsystem. that subsystem.
-qcom,dynamic-wakeup-source: Boolean property to indicate that G-Link
transport supports dynamic wakeup source
Example: Example:
qcom,ipc_router_modem_xprt { qcom,ipc_router_modem_xprt {

View file

@ -1,4 +1,4 @@
/* 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 * 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 * 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_version: IPC Router header version supported by this XPRT.
* @xprt_option: XPRT specific options to be handled by IPC Router. * @xprt_option: XPRT specific options to be handled by IPC Router.
* @disable_pil_loading: Disable PIL Loading of the subsystem. * @disable_pil_loading: Disable PIL Loading of the subsystem.
* @dynamic_wakeup_source: Dynamic wakeup source for this subsystem.
*/ */
struct ipc_router_glink_xprt { struct ipc_router_glink_xprt {
struct list_head list; struct list_head list;
@ -91,6 +92,7 @@ struct ipc_router_glink_xprt {
uint32_t cur_lo_intents_cnt; uint32_t cur_lo_intents_cnt;
uint32_t cur_md_intents_cnt; uint32_t cur_md_intents_cnt;
uint32_t cur_hi_intents_cnt; uint32_t cur_hi_intents_cnt;
bool dynamic_wakeup_source;
}; };
struct ipc_router_glink_xprt_work { 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. * @link_id: Network Cluster ID to which this XPRT belongs to.
* @xprt_version: IPC Router header version supported by this XPRT. * @xprt_version: IPC Router header version supported by this XPRT.
* @disable_pil_loading:Disable PIL Loading of the subsystem. * @disable_pil_loading:Disable PIL Loading of the subsystem.
* @dynamic_wakeup_source: Dynamic wakeup source for this subsystem.
*/ */
struct ipc_router_glink_xprt_config { struct ipc_router_glink_xprt_config {
char ch_name[GLINK_NAME_SIZE]; char ch_name[GLINK_NAME_SIZE];
@ -138,6 +141,7 @@ struct ipc_router_glink_xprt_config {
unsigned xprt_version; unsigned xprt_version;
unsigned xprt_option; unsigned xprt_option;
bool disable_pil_loading; bool disable_pil_loading;
bool dynamic_wakeup_source;
}; };
#define MODULE_NAME "ipc_router_glink_xprt" #define MODULE_NAME "ipc_router_glink_xprt"
@ -292,6 +296,14 @@ static void glink_xprt_sft_close_done(struct msm_ipc_router_xprt *xprt)
complete_all(&glink_xprtp->sft_close_complete); 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) static struct rr_packet *glink_xprt_copy_data(struct read_work *rx_work)
{ {
void *buf, *pbuf, *dest_buf; void *buf, *pbuf, *dest_buf;
@ -705,6 +717,8 @@ static int ipc_router_glink_config_init(
glink_xprtp->xprt_option = glink_xprt_config->xprt_option; glink_xprtp->xprt_option = glink_xprt_config->xprt_option;
glink_xprtp->disable_pil_loading = glink_xprtp->disable_pil_loading =
glink_xprt_config->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) if (!glink_xprtp->disable_pil_loading)
strlcpy(glink_xprtp->pil_edge, glink_xprt_config->pil_edge, strlcpy(glink_xprtp->pil_edge, glink_xprt_config->pil_edge,
@ -727,6 +741,7 @@ static int ipc_router_glink_config_init(
glink_xprtp->xprt.write = ipc_router_glink_xprt_write; glink_xprtp->xprt.write = ipc_router_glink_xprt_write;
glink_xprtp->xprt.close = ipc_router_glink_xprt_close; glink_xprtp->xprt.close = ipc_router_glink_xprt_close;
glink_xprtp->xprt.sft_close_done = glink_xprt_sft_close_done; 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; glink_xprtp->xprt.priv = NULL;
init_rwsem(&glink_xprtp->ss_reset_rwlock); init_rwsem(&glink_xprtp->ss_reset_rwlock);
@ -821,6 +836,10 @@ static int parse_devicetree(struct device_node *node,
scnprintf(glink_xprt_config->ipc_rtr_xprt_name, IPC_RTR_XPRT_NAME_LEN, scnprintf(glink_xprt_config->ipc_rtr_xprt_name, IPC_RTR_XPRT_NAME_LEN,
"%s_%s", edge, ch_name); "%s_%s", edge, ch_name);
key = "qcom,dynamic-wakeup-source";
glink_xprt_config->dynamic_wakeup_source =
of_property_read_bool(node, key);
return 0; return 0;
error: error:

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2015,2017 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * 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); 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 #else
struct msm_ipc_port *msm_ipc_router_create_port( 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; return -ENODEV;
} }
void msm_ipc_router_set_ws_allowed(bool flag) { }
#endif #endif
#endif #endif

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2015,2017 The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * 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. * @pkt_fragment_q: Queue of SKBs containing payload.
* @length: Length of data in the chain of SKBs * @length: Length of data in the chain of SKBs
* @ref: Reference count for the packet. * @ref: Reference count for the packet.
* @ws_need: Flag to check wakeup soruce need
*/ */
struct rr_packet { struct rr_packet {
struct list_head list; struct list_head list;
@ -108,6 +109,7 @@ struct rr_packet {
struct sk_buff_head *pkt_fragment_q; struct sk_buff_head *pkt_fragment_q;
uint32_t length; uint32_t length;
struct kref ref; struct kref ref;
bool ws_need;
}; };
/** /**
@ -125,6 +127,7 @@ struct rr_packet {
* @close: Method to close the XPRT. * @close: Method to close the XPRT.
* @sft_close_done: Method to indicate to the XPRT that handling of reset * @sft_close_done: Method to indicate to the XPRT that handling of reset
* event is complete. * event is complete.
* @get_ws_info: Method to get the wakeup soruce inforamtion of the XPRT
*/ */
struct msm_ipc_router_xprt { struct msm_ipc_router_xprt {
char *name; char *name;
@ -143,6 +146,7 @@ struct msm_ipc_router_xprt {
struct msm_ipc_router_xprt *xprt); struct msm_ipc_router_xprt *xprt);
int (*close)(struct msm_ipc_router_xprt *xprt); int (*close)(struct msm_ipc_router_xprt *xprt);
void (*sft_close_done)(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, void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt,

View file

@ -1,4 +1,4 @@
/* 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 * 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 * it under the terms of the GNU General Public License version 2 and
@ -149,6 +149,7 @@ struct msm_ipc_router_xprt_info {
void *log_ctx; void *log_ctx;
struct kref ref; struct kref ref;
struct completion ref_complete; struct completion ref_complete;
bool dynamic_ws;
}; };
#define RT_HASH_SIZE 4 #define RT_HASH_SIZE 4
@ -216,6 +217,13 @@ enum {
UP, 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) static void init_routing_table(void)
{ {
int i; int i;
@ -581,6 +589,7 @@ struct rr_packet *clone_pkt(struct rr_packet *pkt)
} }
cloned_pkt->pkt_fragment_q = pkt_fragment_q; cloned_pkt->pkt_fragment_q = pkt_fragment_q;
cloned_pkt->length = pkt->length; cloned_pkt->length = pkt->length;
cloned_pkt->ws_need = pkt->ws_need;
return cloned_pkt; return cloned_pkt;
fail_clone: fail_clone:
@ -1164,7 +1173,8 @@ static int post_pkt_to_port(struct msm_ipc_port *port_ptr,
} }
mutex_lock(&port_ptr->port_rx_q_lock_lhc3); mutex_lock(&port_ptr->port_rx_q_lock_lhc3);
__pm_stay_awake(port_ptr->port_rx_ws); if (pkt->ws_need)
__pm_stay_awake(port_ptr->port_rx_ws);
list_add_tail(&temp_pkt->list, &port_ptr->port_rx_q); list_add_tail(&temp_pkt->list, &port_ptr->port_rx_q);
wake_up(&port_ptr->port_rx_wait_q); wake_up(&port_ptr->port_rx_wait_q);
notify = port_ptr->notify; notify = port_ptr->notify;
@ -4064,6 +4074,9 @@ static int msm_ipc_router_add_xprt(struct msm_ipc_router_xprt *xprt)
INIT_LIST_HEAD(&xprt_info->list); INIT_LIST_HEAD(&xprt_info->list);
kref_init(&xprt_info->ref); kref_init(&xprt_info->ref);
init_completion(&xprt_info->ref_complete); 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); xprt_info->workqueue = create_singlethread_workqueue(xprt->name);
if (!xprt_info->workqueue) { if (!xprt_info->workqueue) {
@ -4218,9 +4231,18 @@ void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt,
if (!pkt) if (!pkt)
return; return;
pkt->ws_need = false;
mutex_lock(&xprt_info->rx_lock_lhb2); mutex_lock(&xprt_info->rx_lock_lhb2);
list_add_tail(&pkt->list, &xprt_info->pkt_list); list_add_tail(&pkt->list, &xprt_info->pkt_list);
__pm_stay_awake(&xprt_info->ws); 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); mutex_unlock(&xprt_info->rx_lock_lhb2);
queue_work(xprt_info->workqueue, &xprt_info->read_data); queue_work(xprt_info->workqueue, &xprt_info->read_data);
} }