summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/cnss2/main.c37
-rw-r--r--drivers/net/wireless/cnss2/main.h2
-rw-r--r--drivers/net/wireless/cnss2/pci.c24
-rw-r--r--drivers/net/wireless/cnss2/pci.h1
-rw-r--r--include/net/cnss2.h1
5 files changed, 65 insertions, 0 deletions
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 <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",
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,