summaryrefslogtreecommitdiff
path: root/drivers/soc/qcom/icnss.c
diff options
context:
space:
mode:
authorYuanyuan Liu <yuanliu@codeaurora.org>2016-10-04 10:32:58 -0700
committerYuanyuan Liu <yuanliu@codeaurora.org>2016-11-11 09:13:27 -0800
commit5090370f0363ba2b07dfcbf906981770ab6893dd (patch)
tree307e223738072fc539aff316395b82a5c7f74525 /drivers/soc/qcom/icnss.c
parentb67bb93f565e831efbcdea58a6751737064d3fc6 (diff)
icnss: Collect ramdump from MSA memory space
Collect ramdump from MSA memory space when Modem SSR happens. WLAN FW runs on modem and stores some data on APPS MSA memory space. In order to collect full data of FW during Modem SSR, ICNSS platform listens for Modem SSR notification and collects MSA ramdump. CRs-Fixed: 1088608 Change-Id: I9c014261f5e25b3ec4585747d324ea2cb6ab18fb Signed-off-by: Yuanyuan Liu <yuanliu@codeaurora.org>
Diffstat (limited to 'drivers/soc/qcom/icnss.c')
-rw-r--r--drivers/soc/qcom/icnss.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index feeed645fc47..a40c75990bfb 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -45,6 +45,7 @@
#include <soc/qcom/service-locator.h>
#include <soc/qcom/service-notifier.h>
#include <soc/qcom/socinfo.h>
+#include <soc/qcom/ramdump.h>
#include "wlan_firmware_service_v01.h"
@@ -463,6 +464,7 @@ static struct icnss_priv {
struct qpnp_vadc_chip *vadc_dev;
uint64_t vph_pwr;
atomic_t pm_count;
+ struct ramdump_device *msa0_dump_dev;
} *penv;
static void icnss_hw_write_reg(void *base, u32 offset, u32 val)
@@ -2657,8 +2659,6 @@ static int icnss_driver_event_pd_service_down(struct icnss_priv *priv,
out:
ret = icnss_hw_power_off(priv);
- icnss_remove_msa_permissions(priv);
-
kfree(data);
return ret;
@@ -2763,6 +2763,16 @@ static int icnss_qmi_wlfw_clnt_svc_event_notify(struct notifier_block *this,
return ret;
}
+static int icnss_msa0_ramdump(struct icnss_priv *priv)
+{
+ struct ramdump_segment segment;
+
+ memset(&segment, 0, sizeof(segment));
+ segment.v_address = priv->msa_va;
+ segment.size = priv->msa_mem_size;
+ return do_ramdump(priv->msa0_dump_dev, &segment, 1);
+}
+
static struct notifier_block wlfw_clnt_nb = {
.notifier_call = icnss_qmi_wlfw_clnt_svc_event_notify,
};
@@ -2778,9 +2788,19 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb,
icnss_pr_dbg("Modem-Notify: event %lu\n", code);
+ if (code == SUBSYS_AFTER_SHUTDOWN) {
+ icnss_remove_msa_permissions(priv);
+ icnss_pr_info("Collecting msa0 segment dump\n");
+ icnss_msa0_ramdump(priv);
+ return NOTIFY_OK;
+ }
+
if (code != SUBSYS_BEFORE_SHUTDOWN)
return NOTIFY_OK;
+ if (test_bit(ICNSS_PDR_ENABLED, &priv->state))
+ return NOTIFY_OK;
+
icnss_pr_info("Modem went down, state: %lx\n", priv->state);
event_data = kzalloc(sizeof(*data), GFP_KERNEL);
@@ -2936,8 +2956,6 @@ static int icnss_get_service_location_notify(struct notifier_block *nb,
set_bit(ICNSS_PDR_ENABLED, &priv->state);
- icnss_modem_ssr_unregister_notifier(priv);
-
icnss_pr_dbg("PD restart enabled, state: 0x%lx\n", priv->state);
return NOTIFY_OK;
@@ -3000,6 +3018,11 @@ static int icnss_enable_recovery(struct icnss_priv *priv)
goto enable_pdr;
}
+ priv->msa0_dump_dev = create_ramdump_device("wcss_msa0",
+ &priv->pdev->dev);
+ if (!priv->msa0_dump_dev)
+ return -ENOMEM;
+
icnss_modem_ssr_register_notifier(priv);
if (test_bit(SSR_ONLY, &quirks)) {
icnss_pr_dbg("PDR disabled through module parameter\n");
@@ -4511,6 +4534,8 @@ static int icnss_remove(struct platform_device *pdev)
icnss_modem_ssr_unregister_notifier(penv);
+ destroy_ramdump_device(penv->msa0_dump_dev);
+
icnss_pdr_unregister_notifier(penv);
qmi_svc_event_notifier_unregister(WLFW_SERVICE_ID_V01,
@@ -4522,6 +4547,8 @@ static int icnss_remove(struct platform_device *pdev)
icnss_hw_power_off(penv);
+ icnss_remove_msa_permissions(penv);
+
dev_set_drvdata(&pdev->dev, NULL);
return 0;