mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 12:58:12 -04:00
cnss2: Add support to remove WLAN recovery from SSR framework
WLAN driver and device can work independently from any other sub systems so add the support to avoid using MSM SSR framework for recovery. This can give more flexibility to enable recovery for non-MSM platforms. Change-Id: I0365163deee1ab213c6326b44761788a5f7a6a0d Signed-off-by: Yue Ma <yuem@codeaurora.org>
This commit is contained in:
parent
63a58ef9b3
commit
c4e9e0ada3
6 changed files with 174 additions and 30 deletions
|
|
@ -250,6 +250,21 @@ void cnss_bus_collect_dump_info(struct cnss_plat_data *plat_priv, bool in_panic)
|
|||
}
|
||||
}
|
||||
|
||||
void cnss_bus_device_crashed(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
return;
|
||||
|
||||
switch (plat_priv->bus_type) {
|
||||
case CNSS_BUS_PCI:
|
||||
return cnss_pci_device_crashed(plat_priv->bus_priv);
|
||||
default:
|
||||
cnss_pr_err("Unsupported bus type: %d\n",
|
||||
plat_priv->bus_type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int cnss_bus_call_driver_probe(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
if (!plat_priv)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ int cnss_bus_qmi_send_put(struct cnss_plat_data *plat_priv);
|
|||
void cnss_bus_fw_boot_timeout_hdlr(struct timer_list *t);
|
||||
void cnss_bus_collect_dump_info(struct cnss_plat_data *plat_priv,
|
||||
bool in_panic);
|
||||
void cnss_bus_device_crashed(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_call_driver_probe(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_call_driver_remove(struct cnss_plat_data *plat_priv);
|
||||
int cnss_bus_dev_powerup(struct cnss_plat_data *plat_priv);
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@
|
|||
#include <linux/suspend.h>
|
||||
#include <linux/timer.h>
|
||||
#include <soc/qcom/minidump.h>
|
||||
#include <soc/qcom/ramdump.h>
|
||||
#include <soc/qcom/subsystem_notif.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "bus.h"
|
||||
|
|
@ -26,7 +24,7 @@
|
|||
#define CNSS_DUMP_NAME "CNSS_WLAN"
|
||||
#define CNSS_DUMP_DESC_SIZE 0x1000
|
||||
#define CNSS_DUMP_SEG_VER 0x1
|
||||
#define WLAN_RECOVERY_DELAY 1000
|
||||
#define RECOVERY_DELAY_MS 100
|
||||
#define FILE_SYSTEM_READY 1
|
||||
#define FW_READY_TIMEOUT 20000
|
||||
#define FW_ASSERT_TIMEOUT 5000
|
||||
|
|
@ -765,7 +763,7 @@ static void cnss_put_resources(struct cnss_plat_data *plat_priv)
|
|||
cnss_put_vreg_type(plat_priv, CNSS_VREG_PRIM);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESOC
|
||||
#if IS_ENABLED(CONFIG_ESOC) && IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART)
|
||||
static int cnss_modem_notifier_nb(struct notifier_block *nb,
|
||||
unsigned long code,
|
||||
void *ss_handle)
|
||||
|
|
@ -873,6 +871,7 @@ static inline int cnss_register_esoc(struct cnss_plat_data *plat_priv)
|
|||
static inline void cnss_unregister_esoc(struct cnss_plat_data *plat_priv) {}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART)
|
||||
static int cnss_subsys_powerup(const struct subsys_desc *subsys_desc)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv;
|
||||
|
|
@ -965,6 +964,36 @@ static int cnss_subsys_ramdump(int enable,
|
|||
return cnss_bus_dev_ramdump(plat_priv);
|
||||
}
|
||||
|
||||
static void cnss_recovery_work_handler(struct work_struct *work)
|
||||
{
|
||||
}
|
||||
#else
|
||||
static void cnss_recovery_work_handler(struct work_struct *work)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv =
|
||||
container_of(work, struct cnss_plat_data, recovery_work);
|
||||
|
||||
if (!plat_priv->recovery_enabled)
|
||||
panic("subsys-restart: Resetting the SoC wlan crashed\n");
|
||||
|
||||
cnss_bus_dev_shutdown(plat_priv);
|
||||
msleep(RECOVERY_DELAY_MS);
|
||||
cnss_bus_dev_powerup(plat_priv);
|
||||
}
|
||||
|
||||
void cnss_device_crashed(struct device *dev)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
|
||||
|
||||
if (!plat_priv)
|
||||
return;
|
||||
|
||||
set_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
|
||||
schedule_work(&plat_priv->recovery_work);
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_device_crashed);
|
||||
#endif /* CONFIG_MSM_SUBSYSTEM_RESTART */
|
||||
|
||||
void *cnss_get_virt_ramdump_mem(struct device *dev, unsigned long *size)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
|
||||
|
|
@ -999,9 +1028,6 @@ static const char *cnss_recovery_reason_to_str(enum cnss_recovery_reason reason)
|
|||
static int cnss_do_recovery(struct cnss_plat_data *plat_priv,
|
||||
enum cnss_recovery_reason reason)
|
||||
{
|
||||
struct cnss_subsys_info *subsys_info =
|
||||
&plat_priv->subsys_info;
|
||||
|
||||
plat_priv->recovery_count++;
|
||||
|
||||
if (plat_priv->device_id == QCA6174_DEVICE_ID)
|
||||
|
|
@ -1034,11 +1060,7 @@ static int cnss_do_recovery(struct cnss_plat_data *plat_priv,
|
|||
break;
|
||||
}
|
||||
|
||||
if (!subsys_info->subsys_device)
|
||||
return 0;
|
||||
|
||||
subsys_set_crash_status(subsys_info->subsys_device, true);
|
||||
subsystem_restart_dev(subsys_info->subsys_device);
|
||||
cnss_bus_device_crashed(plat_priv);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
@ -1609,6 +1631,7 @@ int cnss_va_to_pa(struct device *dev, size_t size, void *va, dma_addr_t dma,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART)
|
||||
int cnss_register_subsys(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
@ -1660,6 +1683,70 @@ void cnss_unregister_subsys(struct cnss_plat_data *plat_priv)
|
|||
subsys_unregister(subsys_info->subsys_device);
|
||||
}
|
||||
|
||||
static void *cnss_create_ramdump_device(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
struct cnss_subsys_info *subsys_info = &plat_priv->subsys_info;
|
||||
|
||||
return create_ramdump_device(subsys_info->subsys_desc.name,
|
||||
subsys_info->subsys_desc.dev);
|
||||
}
|
||||
|
||||
static void cnss_destroy_ramdump_device(struct cnss_plat_data *plat_priv,
|
||||
void *ramdump_dev)
|
||||
{
|
||||
destroy_ramdump_device(ramdump_dev);
|
||||
}
|
||||
#else
|
||||
static int cnss_panic_handler(struct notifier_block *nb, unsigned long action,
|
||||
void *data)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv =
|
||||
container_of(nb, struct cnss_plat_data, panic_nb);
|
||||
|
||||
cnss_bus_dev_crash_shutdown(plat_priv);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
int cnss_register_subsys(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
plat_priv->panic_nb.notifier_call = cnss_panic_handler;
|
||||
ret = atomic_notifier_chain_register(&panic_notifier_list,
|
||||
&plat_priv->panic_nb);
|
||||
if (ret) {
|
||||
cnss_pr_err("Failed to register panic handler\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cnss_unregister_subsys(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = atomic_notifier_chain_unregister(&panic_notifier_list,
|
||||
&plat_priv->panic_nb);
|
||||
if (ret)
|
||||
cnss_pr_err("Failed to unregister panic handler\n");
|
||||
}
|
||||
|
||||
static void *cnss_create_ramdump_device(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
return &plat_priv->plat_dev->dev;
|
||||
}
|
||||
|
||||
static void cnss_destroy_ramdump_device(struct cnss_plat_data *plat_priv,
|
||||
void *ramdump_dev)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_MSM_SUBSYSTEM_RESTART */
|
||||
|
||||
static int cnss_init_dump_entry(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
struct cnss_ramdump_info *ramdump_info;
|
||||
|
|
@ -1683,12 +1770,10 @@ static int cnss_register_ramdump_v1(struct cnss_plat_data *plat_priv)
|
|||
{
|
||||
int ret = 0;
|
||||
struct device *dev;
|
||||
struct cnss_subsys_info *subsys_info;
|
||||
struct cnss_ramdump_info *ramdump_info;
|
||||
u32 ramdump_size = 0;
|
||||
|
||||
dev = &plat_priv->plat_dev->dev;
|
||||
subsys_info = &plat_priv->subsys_info;
|
||||
ramdump_info = &plat_priv->ramdump_info;
|
||||
|
||||
if (of_property_read_u32(dev->of_node, "qcom,wlan-ramdump-dynamic",
|
||||
|
|
@ -1716,9 +1801,7 @@ static int cnss_register_ramdump_v1(struct cnss_plat_data *plat_priv)
|
|||
goto free_ramdump;
|
||||
}
|
||||
|
||||
ramdump_info->ramdump_dev =
|
||||
create_ramdump_device(subsys_info->subsys_desc.name,
|
||||
subsys_info->subsys_desc.dev);
|
||||
ramdump_info->ramdump_dev = cnss_create_ramdump_device(plat_priv);
|
||||
if (!ramdump_info->ramdump_dev) {
|
||||
cnss_pr_err("Failed to create ramdump device!");
|
||||
ret = -ENOMEM;
|
||||
|
|
@ -1742,7 +1825,8 @@ static void cnss_unregister_ramdump_v1(struct cnss_plat_data *plat_priv)
|
|||
ramdump_info = &plat_priv->ramdump_info;
|
||||
|
||||
if (ramdump_info->ramdump_dev)
|
||||
destroy_ramdump_device(ramdump_info->ramdump_dev);
|
||||
cnss_destroy_ramdump_device(plat_priv,
|
||||
ramdump_info->ramdump_dev);
|
||||
|
||||
if (ramdump_info->ramdump_va)
|
||||
dma_free_coherent(dev, ramdump_info->ramdump_size,
|
||||
|
|
@ -1774,14 +1858,12 @@ static int cnss_ignore_dump_data_reg_fail(int ret)
|
|||
static int cnss_register_ramdump_v2(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cnss_subsys_info *subsys_info;
|
||||
struct cnss_ramdump_info_v2 *info_v2;
|
||||
struct cnss_dump_data *dump_data;
|
||||
struct msm_dump_entry dump_entry;
|
||||
struct device *dev = &plat_priv->plat_dev->dev;
|
||||
u32 ramdump_size = 0;
|
||||
|
||||
subsys_info = &plat_priv->subsys_info;
|
||||
info_v2 = &plat_priv->ramdump_info_v2;
|
||||
dump_data = &info_v2->dump_data;
|
||||
|
||||
|
|
@ -1813,9 +1895,7 @@ static int cnss_register_ramdump_v2(struct cnss_plat_data *plat_priv)
|
|||
goto free_ramdump;
|
||||
}
|
||||
|
||||
info_v2->ramdump_dev =
|
||||
create_ramdump_device(subsys_info->subsys_desc.name,
|
||||
subsys_info->subsys_desc.dev);
|
||||
info_v2->ramdump_dev = cnss_create_ramdump_device(plat_priv);
|
||||
if (!info_v2->ramdump_dev) {
|
||||
cnss_pr_err("Failed to create ramdump device!\n");
|
||||
ret = -ENOMEM;
|
||||
|
|
@ -1837,7 +1917,7 @@ static void cnss_unregister_ramdump_v2(struct cnss_plat_data *plat_priv)
|
|||
info_v2 = &plat_priv->ramdump_info_v2;
|
||||
|
||||
if (info_v2->ramdump_dev)
|
||||
destroy_ramdump_device(info_v2->ramdump_dev);
|
||||
cnss_destroy_ramdump_device(plat_priv, info_v2->ramdump_dev);
|
||||
|
||||
kfree(info_v2->dump_data_vaddr);
|
||||
info_v2->dump_data_vaddr = NULL;
|
||||
|
|
@ -2031,6 +2111,32 @@ static void cnss_unregister_bus_scale(struct cnss_plat_data *plat_priv)
|
|||
kfree(bus_bw_info->cfg_table);
|
||||
}
|
||||
|
||||
static ssize_t recovery_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv = dev_get_drvdata(dev);
|
||||
unsigned int recovery = 0;
|
||||
|
||||
if (!plat_priv)
|
||||
return -ENODEV;
|
||||
|
||||
if (sscanf(buf, "%du", &recovery) != 1) {
|
||||
cnss_pr_err("Invalid recovery sysfs command\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (recovery)
|
||||
plat_priv->recovery_enabled = true;
|
||||
else
|
||||
plat_priv->recovery_enabled = false;
|
||||
|
||||
cnss_pr_dbg("%s WLAN recovery, count is %zu\n",
|
||||
plat_priv->recovery_enabled ? "Enable" : "Disable", count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t shutdown_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
|
|
@ -2094,10 +2200,12 @@ static ssize_t fs_ready_store(struct device *dev,
|
|||
|
||||
static DEVICE_ATTR_WO(fs_ready);
|
||||
static DEVICE_ATTR_WO(shutdown);
|
||||
static DEVICE_ATTR_WO(recovery);
|
||||
|
||||
static struct attribute *cnss_attrs[] = {
|
||||
&dev_attr_fs_ready.attr,
|
||||
&dev_attr_shutdown.attr,
|
||||
&dev_attr_recovery.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
@ -2223,6 +2331,7 @@ static int cnss_misc_init(struct cnss_plat_data *plat_priv)
|
|||
cnss_pr_err("Failed to init platform device wakeup source, err = %d\n",
|
||||
ret);
|
||||
|
||||
INIT_WORK(&plat_priv->recovery_work, cnss_recovery_work_handler);
|
||||
init_completion(&plat_priv->power_up_complete);
|
||||
init_completion(&plat_priv->cal_complete);
|
||||
init_completion(&plat_priv->rddm_complete);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#define _CNSS_MAIN_H
|
||||
|
||||
#include <asm/arch_timer.h>
|
||||
#ifdef CONFIG_ESOC
|
||||
#if IS_ENABLED(CONFIG_ESOC)
|
||||
#include <linux/esoc_client.h>
|
||||
#endif
|
||||
#include <linux/etherdevice.h>
|
||||
|
|
@ -14,7 +14,11 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <net/cnss2.h>
|
||||
#include <soc/qcom/memory_dump.h>
|
||||
#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART)
|
||||
#include <soc/qcom/ramdump.h>
|
||||
#include <soc/qcom/subsystem_notif.h>
|
||||
#include <soc/qcom/subsystem_restart.h>
|
||||
#endif
|
||||
|
||||
#include "qmi.h"
|
||||
|
||||
|
|
@ -83,14 +87,16 @@ struct cnss_pinctrl_info {
|
|||
struct pinctrl_state *wlan_en_sleep;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART)
|
||||
struct cnss_subsys_info {
|
||||
struct subsys_device *subsys_device;
|
||||
struct subsys_desc subsys_desc;
|
||||
void *subsys_handle;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct cnss_ramdump_info {
|
||||
struct ramdump_device *ramdump_dev;
|
||||
void *ramdump_dev;
|
||||
unsigned long ramdump_size;
|
||||
void *ramdump_va;
|
||||
phys_addr_t ramdump_pa;
|
||||
|
|
@ -114,14 +120,14 @@ struct cnss_dump_data {
|
|||
};
|
||||
|
||||
struct cnss_ramdump_info_v2 {
|
||||
struct ramdump_device *ramdump_dev;
|
||||
void *ramdump_dev;
|
||||
unsigned long ramdump_size;
|
||||
void *dump_data_vaddr;
|
||||
u8 dump_data_valid;
|
||||
struct cnss_dump_data dump_data;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ESOC
|
||||
#if IS_ENABLED(CONFIG_ESOC)
|
||||
struct cnss_esoc_info {
|
||||
struct esoc_desc *esoc_desc;
|
||||
u8 notify_modem_status;
|
||||
|
|
@ -339,26 +345,31 @@ struct cnss_plat_data {
|
|||
struct list_head vreg_list;
|
||||
struct list_head clk_list;
|
||||
struct cnss_pinctrl_info pinctrl_info;
|
||||
#if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART)
|
||||
struct cnss_subsys_info subsys_info;
|
||||
#endif
|
||||
struct cnss_ramdump_info ramdump_info;
|
||||
struct cnss_ramdump_info_v2 ramdump_info_v2;
|
||||
#ifdef CONFIG_ESOC
|
||||
#if IS_ENABLED(CONFIG_ESOC)
|
||||
struct cnss_esoc_info esoc_info;
|
||||
#endif
|
||||
struct cnss_bus_bw_info bus_bw_info;
|
||||
struct notifier_block modem_nb;
|
||||
struct notifier_block reboot_nb;
|
||||
struct notifier_block panic_nb;
|
||||
struct cnss_platform_cap cap;
|
||||
struct pm_qos_request qos_request;
|
||||
struct cnss_device_version device_version;
|
||||
unsigned long device_id;
|
||||
enum cnss_driver_status driver_status;
|
||||
u32 recovery_count;
|
||||
u8 recovery_enabled;
|
||||
unsigned long driver_state;
|
||||
struct list_head event_list;
|
||||
spinlock_t event_lock; /* spinlock for driver work event handling */
|
||||
struct work_struct event_work;
|
||||
struct workqueue_struct *event_wq;
|
||||
struct work_struct recovery_work;
|
||||
struct qmi_handle qmi_wlfw;
|
||||
struct wlfw_rf_chip_info chip_info;
|
||||
struct wlfw_rf_board_info board_info;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/completion.h>
|
||||
#include <soc/qcom/ramdump.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "bus.h"
|
||||
|
|
@ -4197,6 +4196,14 @@ void cnss_pci_clear_dump_info(struct cnss_pci_data *pci_priv)
|
|||
plat_priv->ramdump_info_v2.dump_data_valid = false;
|
||||
}
|
||||
|
||||
void cnss_pci_device_crashed(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
if (!pci_priv)
|
||||
return;
|
||||
|
||||
cnss_device_crashed(&pci_priv->pci_dev->dev);
|
||||
}
|
||||
|
||||
static int cnss_mhi_pm_runtime_get(struct mhi_controller *mhi_ctrl, void *priv)
|
||||
{
|
||||
struct cnss_pci_data *pci_priv = priv;
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ void cnss_pci_free_qdss_mem(struct cnss_pci_data *pci_priv);
|
|||
int cnss_pci_load_m3(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_start_mhi(struct cnss_pci_data *pci_priv);
|
||||
void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic);
|
||||
void cnss_pci_device_crashed(struct cnss_pci_data *pci_priv);
|
||||
void cnss_pci_clear_dump_info(struct cnss_pci_data *pci_priv);
|
||||
u32 cnss_pci_get_wake_msi(struct cnss_pci_data *pci_priv);
|
||||
int cnss_pci_force_fw_assert_hdlr(struct cnss_pci_data *pci_priv);
|
||||
|
|
|
|||
Loading…
Reference in a new issue