diff options
| -rw-r--r-- | drivers/net/wireless/cnss2/main.c | 37 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/main.h | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/pci.c | 24 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/pci.h | 1 | ||||
| -rw-r--r-- | include/net/cnss2.h | 1 |
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, |
