OSDN Git Service

cnss2: Export a platform API to force collect ramdump
authorGuisen Yang <guiseny@codeaurora.org>
Mon, 3 Dec 2018 23:29:44 +0000 (15:29 -0800)
committerGerrit - the friendly Code Review server <code-review@localhost>
Tue, 9 Apr 2019 02:43:57 +0000 (19:43 -0700)
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 <guiseny@codeaurora.org>
drivers/net/wireless/cnss2/main.c
drivers/net/wireless/cnss2/main.h
drivers/net/wireless/cnss2/pci.c
drivers/net/wireless/cnss2/pci.h
include/net/cnss2.h

index df65c97..4a75a29 100644 (file)
@@ -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);
index 28a2990..1b7c67b 100644 (file)
@@ -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);
index 5a27ad6..d0830fe 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/of.h>
 #include <linux/pm_runtime.h>
 #include <linux/memblock.h>
+#include <linux/completion.h>
 #include <soc/qcom/ramdump.h>
 
 #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",
index e47f14e..33c6276 100644 (file)
@@ -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 {
index 8563484..0b2c9d2 100644 (file)
@@ -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,