summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2018-01-13 03:50:14 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2018-01-13 03:50:13 -0800
commit879163d5997e9dbb89f086db857ab98f86ab680c (patch)
tree75201aec39bca675aa1af9b3fd2ca1cae56aa4fe
parentee6f57508906453501cb8c1ce0017e007bae4fbd (diff)
parentf43f0483211fd5389879a624c171973d8084f1e3 (diff)
Merge "soc: qcom: glink: Add sub system up notification in glink"
-rw-r--r--drivers/soc/qcom/glink.c36
-rw-r--r--drivers/soc/qcom/glink_private.h10
-rw-r--r--drivers/soc/qcom/glink_smem_native_xprt.c32
-rw-r--r--drivers/soc/qcom/glink_ssr.c13
-rw-r--r--drivers/soc/qcom/glink_xprt_if.h3
5 files changed, 81 insertions, 13 deletions
diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c
index f21e9c4c4f4e..813c97bb4a50 100644
--- a/drivers/soc/qcom/glink.c
+++ b/drivers/soc/qcom/glink.c
@@ -455,6 +455,42 @@ static void glink_put_ch_ctx(struct channel_ctx *ctx)
rwref_put(&ctx->ch_state_lhb2);
}
+
+/**
+ * glink_subsys_up() - Inform transport about remote subsystem up.
+ * @subsystem: The name of the subsystem
+ *
+ * Call into the transport using the subsys_up(if_ptr) function to allow it to
+ * initialize any necessary structures.
+ *
+ * Return: Standard error codes.
+ */
+int glink_subsys_up(const char *subsystem)
+{
+ int ret = 0;
+ bool transport_found = false;
+ struct glink_core_xprt_ctx *xprt_ctx = NULL;
+
+ mutex_lock(&transport_list_lock_lha0);
+ list_for_each_entry(xprt_ctx, &transport_list, list_node) {
+ if (!strcmp(subsystem, xprt_ctx->edge) &&
+ !xprt_is_fully_opened(xprt_ctx)) {
+ GLINK_INFO_XPRT(xprt_ctx, "%s: %s Subsystem up\n",
+ __func__, subsystem);
+ if (xprt_ctx->ops->subsys_up)
+ xprt_ctx->ops->subsys_up(xprt_ctx->ops);
+ transport_found = true;
+ }
+ }
+ mutex_unlock(&transport_list_lock_lha0);
+
+ if (!transport_found)
+ ret = -ENODEV;
+
+ return ret;
+}
+EXPORT_SYMBOL(glink_subsys_up);
+
/**
* glink_ssr() - Clean up locally for SSR by simulating remote close
* @subsystem: The name of the subsystem being restarted
diff --git a/drivers/soc/qcom/glink_private.h b/drivers/soc/qcom/glink_private.h
index e91ad30f73ab..c94ca7d57b2f 100644
--- a/drivers/soc/qcom/glink_private.h
+++ b/drivers/soc/qcom/glink_private.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, 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
@@ -817,6 +817,14 @@ uint32_t glink_ssr_get_seq_num(void);
*/
int glink_ssr(const char *subsystem);
+/*
+ * glink_subsys_up() - SSR sub system up function.
+ * @subsystem: Constant string for name of remote subsystem.
+ *
+ * Return: Standard error code.
+ */
+int glink_subsys_up(const char *subsystem);
+
/**
* notify for subsystem() - Notify other subsystems that a subsystem is being
* restarted
diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c
index a678e03235c0..4407dfbc45df 100644
--- a/drivers/soc/qcom/glink_smem_native_xprt.c
+++ b/drivers/soc/qcom/glink_smem_native_xprt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, 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
@@ -876,15 +876,6 @@ static void __rx_worker(struct edge_info *einfo, bool atomic_ctx)
rcu_id = srcu_read_lock(&einfo->use_ref);
- if (unlikely(!einfo->rx_fifo) && atomic_ctx) {
- if (!get_rx_fifo(einfo)) {
- srcu_read_unlock(&einfo->use_ref, rcu_id);
- return;
- }
- einfo->in_ssr = false;
- einfo->xprt_if.glink_core_if_ptr->link_up(&einfo->xprt_if);
- }
-
if (einfo->in_ssr) {
srcu_read_unlock(&einfo->use_ref, rcu_id);
return;
@@ -1487,6 +1478,24 @@ static void tx_cmd_ch_remote_close_ack(struct glink_transport_if *if_ptr,
}
/**
+ * subsys_up() - process a subsystem up notification
+ * @if_ptr: The transport which is up
+ *
+ */
+static void subsys_up(struct glink_transport_if *if_ptr)
+{
+ struct edge_info *einfo;
+
+ einfo = container_of(if_ptr, struct edge_info, xprt_if);
+ if (!einfo->rx_fifo) {
+ if (!get_rx_fifo(einfo))
+ return;
+ einfo->in_ssr = false;
+ einfo->xprt_if.glink_core_if_ptr->link_up(&einfo->xprt_if);
+ }
+}
+
+/**
* ssr() - process a subsystem restart notification of a transport
* @if_ptr: The transport to restart
*
@@ -2166,6 +2175,7 @@ static void init_xprt_if(struct edge_info *einfo)
einfo->xprt_if.tx_cmd_ch_remote_open_ack = tx_cmd_ch_remote_open_ack;
einfo->xprt_if.tx_cmd_ch_remote_close_ack = tx_cmd_ch_remote_close_ack;
einfo->xprt_if.ssr = ssr;
+ einfo->xprt_if.subsys_up = subsys_up;
einfo->xprt_if.allocate_rx_intent = allocate_rx_intent;
einfo->xprt_if.deallocate_rx_intent = deallocate_rx_intent;
einfo->xprt_if.tx_cmd_local_rx_intent = tx_cmd_local_rx_intent;
@@ -2437,6 +2447,7 @@ static int glink_smem_native_probe(struct platform_device *pdev)
rc);
goto request_irq_fail;
}
+ einfo->in_ssr = true;
rc = enable_irq_wake(irq_line);
if (rc < 0)
pr_err("%s: enable_irq_wake() failed on %d\n", __func__,
@@ -2941,6 +2952,7 @@ static int glink_mailbox_probe(struct platform_device *pdev)
cfg_p_addr = smem_virt_to_phys(mbox_cfg);
writel_relaxed(lower_32_bits(cfg_p_addr), mbox_loc);
writel_relaxed(upper_32_bits(cfg_p_addr), mbox_loc + 4);
+ einfo->in_ssr = true;
send_irq(einfo);
iounmap(mbox_size);
iounmap(mbox_loc);
diff --git a/drivers/soc/qcom/glink_ssr.c b/drivers/soc/qcom/glink_ssr.c
index fb003bd5d35b..fe7fb1e5b925 100644
--- a/drivers/soc/qcom/glink_ssr.c
+++ b/drivers/soc/qcom/glink_ssr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, 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
@@ -490,6 +490,17 @@ static int glink_ssr_restart_notifier_cb(struct notifier_block *this,
"Subsystem notification failed", ret);
return ret;
}
+ } else if (code == SUBSYS_AFTER_POWERUP) {
+ GLINK_SSR_LOG("<SSR> %s: %s: subsystem restart for %s\n",
+ __func__, "SUBSYS_AFTER_POWERUP",
+ notifier->subsystem);
+ ss_info = get_info_for_subsystem(notifier->subsystem);
+ if (ss_info == NULL) {
+ GLINK_SSR_ERR("<SSR> %s: ss_info is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ glink_subsys_up(ss_info->edge);
}
return NOTIFY_DONE;
}
diff --git a/drivers/soc/qcom/glink_xprt_if.h b/drivers/soc/qcom/glink_xprt_if.h
index 47c15807e379..1902152d91cb 100644
--- a/drivers/soc/qcom/glink_xprt_if.h
+++ b/drivers/soc/qcom/glink_xprt_if.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, 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
@@ -105,6 +105,7 @@ struct glink_transport_if {
void (*tx_cmd_ch_remote_close_ack)(struct glink_transport_if *if_ptr,
uint32_t rcid);
int (*ssr)(struct glink_transport_if *if_ptr);
+ void (*subsys_up)(struct glink_transport_if *if_ptr);
/* channel data */
int (*allocate_rx_intent)(struct glink_transport_if *if_ptr,