summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/arm/msm/msm_ipc_router_glink_xprt.txt2
-rw-r--r--drivers/soc/qcom/ipc_router_glink_xprt.c21
-rw-r--r--include/linux/ipc_router.h12
-rw-r--r--include/linux/ipc_router_xprt.h6
-rw-r--r--net/ipc_router/ipc_router_core.c28
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);
}