diff options
-rw-r--r-- | Documentation/devicetree/bindings/arm/msm/msm_ipc_router_glink_xprt.txt | 2 | ||||
-rw-r--r-- | drivers/soc/qcom/ipc_router_glink_xprt.c | 21 | ||||
-rw-r--r-- | include/linux/ipc_router.h | 12 | ||||
-rw-r--r-- | include/linux/ipc_router_xprt.h | 6 | ||||
-rw-r--r-- | net/ipc_router/ipc_router_core.c | 28 |
5 files changed, 63 insertions, 6 deletions
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_glink_xprt.txt b/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_glink_xprt.txt index 9e1d230432cf..c5d052cd6039 100644 --- a/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_glink_xprt.txt +++ b/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_glink_xprt.txt @@ -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 { diff --git a/drivers/soc/qcom/ipc_router_glink_xprt.c b/drivers/soc/qcom/ipc_router_glink_xprt.c index 1f36dd0ba07e..7dd1683881fb 100644 --- a/drivers/soc/qcom/ipc_router_glink_xprt.c +++ b/drivers/soc/qcom/ipc_router_glink_xprt.c @@ -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 * 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 xprt_version; unsigned xprt_option; bool disable_pil_loading; + bool dynamic_wakeup_source; }; #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); } +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; @@ -705,6 +717,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, @@ -727,6 +741,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); @@ -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, "%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: diff --git a/include/linux/ipc_router.h b/include/linux/ipc_router.h index b17f684a9895..04a06df66d4b 100644 --- a/include/linux/ipc_router.h +++ b/include/linux/ipc_router.h @@ -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 * 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 diff --git a/include/linux/ipc_router_xprt.h b/include/linux/ipc_router_xprt.h index 276c79ff1591..ac6c1e4db8a4 100644 --- a/include/linux/ipc_router_xprt.h +++ b/include/linux/ipc_router_xprt.h @@ -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 * 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, diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c index d23799a5b260..f08aef9509bb 100644 --- a/net/ipc_router/ipc_router_core.c +++ b/net/ipc_router/ipc_router_core.c @@ -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 * 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; struct kref ref; struct completion ref_complete; + bool dynamic_ws; }; #define RT_HASH_SIZE 4 @@ -216,6 +217,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; @@ -581,6 +589,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: @@ -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); - __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); wake_up(&port_ptr->port_rx_wait_q); 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); 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) { @@ -4218,9 +4231,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); - __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); queue_work(xprt_info->workqueue, &xprt_info->read_data); } |