From 9ec08ea59b839ac61ee6fcd9f073e713d35fe3e8 Mon Sep 17 00:00:00 2001 From: Guisen Yang Date: Mon, 3 Dec 2018 15:29:44 -0800 Subject: [PATCH] cnss2: Export a platform API to force collect ramdump Add an API to force collect ramdump in platform driver. This API will be called from WLAN driver to collect ramdump before calling kernel panic. CRs-Fixed: 2351811 Change-Id: Ic88769beec4f7f8303fc2c0803012789e02c9f4f Signed-off-by: Guisen Yang --- drivers/net/wireless/cnss2/main.c | 37 +++++++++++++++++++++++++++++++++++++ drivers/net/wireless/cnss2/main.h | 2 ++ drivers/net/wireless/cnss2/pci.c | 24 ++++++++++++++++++++++++ drivers/net/wireless/cnss2/pci.h | 1 + include/net/cnss2.h | 1 + 5 files changed, 65 insertions(+) diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c index df65c97b3257..4a75a293dfbd 100644 --- a/drivers/net/wireless/cnss2/main.c +++ b/drivers/net/wireless/cnss2/main.c @@ -1179,6 +1179,41 @@ int cnss_force_fw_assert(struct device *dev) } EXPORT_SYMBOL(cnss_force_fw_assert); +int cnss_force_collect_rddm(struct device *dev) +{ + struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); + int ret = 0; + + if (!plat_priv) { + cnss_pr_err("plat_priv is NULL\n"); + return -ENODEV; + } + + if (plat_priv->device_id == QCA6174_DEVICE_ID) { + cnss_pr_info("Force collect rddm is not supported\n"); + return -EOPNOTSUPP; + } + + if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) { + cnss_pr_info("Recovery is already in progress, ignore forced collect rddm\n"); + return 0; + } + + cnss_driver_event_post(plat_priv, + CNSS_DRIVER_EVENT_FORCE_FW_ASSERT, + 0, NULL); + + reinit_completion(&plat_priv->rddm_complete); + ret = wait_for_completion_timeout + (&plat_priv->rddm_complete, + msecs_to_jiffies(CNSS_RDDM_TIMEOUT_MS)); + if (!ret) + ret = -ETIMEDOUT; + + return ret; +} +EXPORT_SYMBOL(cnss_force_collect_rddm); + static int cnss_wlfw_server_arrive_hdlr(struct cnss_plat_data *plat_priv) { int ret; @@ -1928,6 +1963,7 @@ static int cnss_probe(struct platform_device *plat_dev) ret); init_completion(&plat_priv->power_up_complete); + init_completion(&plat_priv->rddm_complete); mutex_init(&plat_priv->dev_lock); cnss_pr_info("Platform driver probed successfully.\n"); @@ -1967,6 +2003,7 @@ static int cnss_remove(struct platform_device *plat_dev) { struct cnss_plat_data *plat_priv = platform_get_drvdata(plat_dev); + complete_all(&plat_priv->rddm_complete); complete_all(&plat_priv->power_up_complete); device_init_wakeup(&plat_dev->dev, false); unregister_pm_notifier(&cnss_pm_notifier); diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h index 28a2990ed831..1b7c67b90795 100644 --- a/drivers/net/wireless/cnss2/main.h +++ b/drivers/net/wireless/cnss2/main.h @@ -24,6 +24,7 @@ #include "qmi.h" #define MAX_NO_OF_MAC_ADDR 4 +#define CNSS_RDDM_TIMEOUT_MS 20000 #define CNSS_EVENT_SYNC BIT(0) #define CNSS_EVENT_UNINTERRUPTIBLE BIT(1) @@ -225,6 +226,7 @@ struct cnss_plat_data { u8 *diag_reg_read_buf; void *caldb_mem; bool cal_done; + struct completion rddm_complete; }; struct cnss_plat_data *cnss_get_plat_priv(struct platform_device *plat_dev); diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 5a27ad6cf047..d0830fec3701 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "main.h" @@ -573,6 +574,11 @@ static void cnss_qca6290_crash_shutdown(struct cnss_pci_data *pci_priv) return; } + if (test_bit(CNSS_MHI_RDDM_DONE, &plat_priv->driver_state)) { + cnss_pr_dbg("RDDM already collected, return\n"); + return; + } + cnss_pci_collect_dump_info(pci_priv); } @@ -1511,8 +1517,15 @@ int cnss_pci_force_fw_assert_hdlr(struct cnss_pci_data *pci_priv) if (!plat_priv) return -ENODEV; + if (test_bit(CNSS_MHI_RDDM_DONE, &pci_priv->mhi_state)) { + cnss_pr_err("RDDM already collected 0x%lx, return\n", + pci_priv->mhi_state); + return 0; + } + ret = cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_TRIGGER_RDDM); + if (ret) { cnss_pr_err("Failed to trigger RDDM, err = %d\n", ret); cnss_schedule_recovery(&pci_priv->pci_dev->dev, @@ -1912,6 +1925,8 @@ static char *cnss_mhi_state_to_str(enum cnss_mhi_state mhi_state) return "RDDM_KERNEL_PANIC"; case CNSS_MHI_NOTIFY_LINK_ERROR: return "NOTIFY_LINK_ERROR"; + case CNSS_MHI_RDDM_DONE: + return "RDDM_DONE"; default: return "UNKNOWN"; } @@ -1974,6 +1989,9 @@ void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv) if (dump_data->nentries > 0) plat_priv->ramdump_info_v2.dump_data_valid = true; + + cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_RDDM_DONE); + complete(&plat_priv->rddm_complete); } void cnss_pci_clear_dump_info(struct cnss_pci_data *pci_priv) @@ -2118,6 +2136,7 @@ static int cnss_pci_check_mhi_state_bit(struct cnss_pci_data *pci_priv, case CNSS_MHI_RDDM: case CNSS_MHI_RDDM_KERNEL_PANIC: case CNSS_MHI_NOTIFY_LINK_ERROR: + case CNSS_MHI_RDDM_DONE: return 0; default: cnss_pr_err("Unhandled MHI state: %s(%d)\n", @@ -2146,6 +2165,7 @@ static void cnss_pci_set_mhi_state_bit(struct cnss_pci_data *pci_priv, break; case CNSS_MHI_POWER_OFF: clear_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state); + clear_bit(CNSS_MHI_RDDM_DONE, &pci_priv->mhi_state); break; case CNSS_MHI_SUSPEND: set_bit(CNSS_MHI_SUSPEND, &pci_priv->mhi_state); @@ -2158,6 +2178,9 @@ static void cnss_pci_set_mhi_state_bit(struct cnss_pci_data *pci_priv, case CNSS_MHI_RDDM_KERNEL_PANIC: case CNSS_MHI_NOTIFY_LINK_ERROR: break; + case CNSS_MHI_RDDM_DONE: + set_bit(CNSS_MHI_RDDM_DONE, &pci_priv->mhi_state); + break; default: cnss_pr_err("Unhandled MHI state (%d)\n", mhi_state); } @@ -2188,6 +2211,7 @@ int cnss_pci_set_mhi_state(struct cnss_pci_data *pci_priv, cnss_pr_dbg("Setting MHI state: %s(%d)\n", cnss_mhi_state_to_str(mhi_state), mhi_state); + ret = mhi_pm_control_device(&pci_priv->mhi_dev, mhi_dev_state); if (ret) { cnss_pr_err("Failed to set MHI state: %s(%d)\n", diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h index e47f14e8a325..33c6276744c3 100644 --- a/drivers/net/wireless/cnss2/pci.h +++ b/drivers/net/wireless/cnss2/pci.h @@ -42,6 +42,7 @@ enum cnss_mhi_state { CNSS_MHI_RDDM, CNSS_MHI_RDDM_KERNEL_PANIC, CNSS_MHI_NOTIFY_LINK_ERROR, + CNSS_MHI_RDDM_DONE, }; struct cnss_msi_user { diff --git a/include/net/cnss2.h b/include/net/cnss2.h index 85634842834e..0b2c9d272fac 100644 --- a/include/net/cnss2.h +++ b/include/net/cnss2.h @@ -189,6 +189,7 @@ extern void cnss_schedule_recovery(struct device *dev, extern int cnss_self_recovery(struct device *dev, enum cnss_recovery_reason reason); extern int cnss_force_fw_assert(struct device *dev); +extern int cnss_force_collect_rddm(struct device *dev); extern void *cnss_get_virt_ramdump_mem(struct device *dev, unsigned long *size); extern int cnss_get_fw_files_for_target(struct device *dev, struct cnss_fw_files *pfw_files, -- 2.11.0