diff --git a/drivers/net/wireless/cnss/cnss_pci.c b/drivers/net/wireless/cnss/cnss_pci.c index 2e01ae9528f2..8e9d9e4a08cf 100644 --- a/drivers/net/wireless/cnss/cnss_pci.c +++ b/drivers/net/wireless/cnss/cnss_pci.c @@ -1752,12 +1752,12 @@ static ssize_t fw_image_setup_store(struct device *dev, static DEVICE_ATTR(fw_image_setup, S_IRUSR | S_IWUSR, fw_image_setup_show, fw_image_setup_store); -void recovery_work_handler(struct work_struct *recovery) +void cnss_pci_recovery_work_handler(struct work_struct *recovery) { cnss_device_self_recovery(); } -DECLARE_WORK(recovery_work, recovery_work_handler); +DECLARE_WORK(recovery_work, cnss_pci_recovery_work_handler); void cnss_schedule_recovery_work(void) { @@ -2189,6 +2189,32 @@ void cnss_release_pm_sem(void) } EXPORT_SYMBOL(cnss_release_pm_sem); +void cnss_pci_schedule_recovery_work(void) +{ + schedule_work(&recovery_work); +} +EXPORT_SYMBOL(cnss_pci_schedule_recovery_work); + +void *cnss_pci_get_virt_ramdump_mem(unsigned long *size) +{ + if (!penv || !penv->pldev) + return NULL; + + *size = penv->ramdump_size; + + return penv->ramdump_addr; +} +EXPORT_SYMBOL(cnss_pci_get_virt_ramdump_mem); + +void cnss_pci_device_crashed(void) +{ + if (penv && penv->subsys) { + subsys_set_crash_status(penv->subsys, true); + subsystem_restart_dev(penv->subsys); + } +} +EXPORT_SYMBOL(cnss_pci_device_crashed); + int cnss_get_ramdump_mem(unsigned long *address, unsigned long *size) { if (!penv || !penv->pldev) @@ -2364,6 +2390,32 @@ err_wlan_vreg_on: return ret; } +void cnss_pci_device_self_recovery(void) +{ + if (!penv) + return; + + if (penv->recovery_in_progress) { + pr_err("cnss: Recovery already in progress\n"); + return; + } + + if (penv->driver_status == CNSS_LOAD_UNLOAD) { + pr_err("cnss: load unload in progress\n"); + return; + } + + penv->recovery_count++; + penv->recovery_in_progress = true; + cnss_pm_wake_lock(&penv->ws); + cnss_shutdown(NULL, false); + msleep(WLAN_RECOVERY_DELAY); + cnss_powerup(NULL); + cnss_pm_wake_lock_release(&penv->ws); + penv->recovery_in_progress = false; +} +EXPORT_SYMBOL(cnss_pci_device_self_recovery); + static int cnss_ramdump(int enable, const struct subsys_desc *subsys) { struct ramdump_segment segment; diff --git a/drivers/net/wireless/cnss/cnss_sdio.c b/drivers/net/wireless/cnss/cnss_sdio.c index 7cdd2a033caf..86ca4b512108 100644 --- a/drivers/net/wireless/cnss/cnss_sdio.c +++ b/drivers/net/wireless/cnss/cnss_sdio.c @@ -467,6 +467,39 @@ static void cnss_ramdump_cleanup(void) ssr_info->ramdump_dev = NULL; } +void *cnss_sdio_get_virt_ramdump_mem(unsigned long *size) +{ + if (!cnss_pdata || !cnss_pdata->pdev) + return NULL; + + *size = cnss_pdata->ssr_info.ramdump_size; + + return cnss_pdata->ssr_info.ramdump_addr; +} +EXPORT_SYMBOL(cnss_sdio_get_virt_ramdump_mem); + +void cnss_sdio_device_self_recovery(void) +{ + cnss_sdio_shutdown(NULL, false); + msleep(WLAN_RECOVERY_DELAY); + cnss_sdio_powerup(NULL); +} +EXPORT_SYMBOL(cnss_sdio_device_self_recovery); + +void cnss_sdio_device_crashed(void) +{ + struct cnss_ssr_info *ssr_info; + + if (!cnss_pdata) + return; + ssr_info = &cnss_pdata->ssr_info; + if (ssr_info->subsys) { + subsys_set_crash_status(ssr_info->subsys, true); + subsystem_restart_dev(ssr_info->subsys); + } +} +EXPORT_SYMBOL(cnss_sdio_device_crashed); + int cnss_get_ramdump_mem(unsigned long *address, unsigned long *size) { struct cnss_ssr_info *ssr_info; @@ -501,12 +534,18 @@ void cnss_device_self_recovery(void) } EXPORT_SYMBOL(cnss_device_self_recovery); -static void recovery_work_handler(struct work_struct *recovery) +static void cnss_sdio_recovery_work_handler(struct work_struct *recovery) { cnss_device_self_recovery(); } -DECLARE_WORK(recovery_work, recovery_work_handler); +DECLARE_WORK(recovery_work, cnss_sdio_recovery_work_handler); + +void cnss_sdio_schedule_recovery_work(void) +{ + schedule_work(&recovery_work); +} +EXPORT_SYMBOL(cnss_sdio_schedule_recovery_work); void cnss_schedule_recovery_work(void) { diff --git a/include/net/cnss.h b/include/net/cnss.h index 71b8d9a27f46..ff8469fc78e7 100644 --- a/include/net/cnss.h +++ b/include/net/cnss.h @@ -195,11 +195,24 @@ extern int cnss_get_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 *ch_count, u16 buf_len); extern int cnss_wlan_set_dfs_nol(const void *info, u16 info_len); extern int cnss_wlan_get_dfs_nol(void *info, u16 info_len); + extern void cnss_device_crashed(void); +extern void cnss_sdio_device_crashed(void); +extern void cnss_pci_device_crashed(void); + extern void cnss_device_self_recovery(void); +extern void cnss_pci_device_self_recovery(void); +extern void cnss_sdio_device_self_recovery(void); + extern int cnss_get_ramdump_mem(unsigned long *address, unsigned long *size); + extern void *cnss_get_virt_ramdump_mem(unsigned long *size); +extern void *cnss_pci_get_virt_ramdump_mem(unsigned long *size); +extern void *cnss_sdio_get_virt_ramdump_mem(unsigned long *size); + extern void cnss_schedule_recovery_work(void); +extern void cnss_sdio_schedule_recovery_work(void); +extern void cnss_pci_schedule_recovery_work(void); enum { CNSS_RESET_SOC = 0,