Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 567a978c authored by Yue Ma's avatar Yue Ma
Browse files

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: default avatarYue Ma <yuem@codeaurora.org>
parent 7e27194c
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -267,6 +267,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)
+1 −0
Original line number Diff line number Diff line
@@ -37,6 +37,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);
+135 −23
Original line number Diff line number Diff line
@@ -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
@@ -792,6 +790,7 @@ static void cnss_put_resources(struct cnss_plat_data *plat_priv)
	cnss_put_vreg_type(plat_priv, CNSS_VREG_PRIM);
}

#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
static int cnss_modem_notifier_nb(struct notifier_block *nb,
				  unsigned long code,
				  void *ss_handle)
@@ -983,6 +982,39 @@ 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 int cnss_register_esoc(struct cnss_plat_data *plat_priv) { return 0; }
static void cnss_unregister_esoc(struct cnss_plat_data *plat_priv) { }

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);
@@ -1017,9 +1049,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)
@@ -1052,11 +1081,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;

@@ -1613,6 +1638,7 @@ int cnss_va_to_pa(struct device *dev, size_t size, void *va, dma_addr_t dma,
	return 0;
}

#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
int cnss_register_subsys(struct cnss_plat_data *plat_priv)
{
	int ret = 0;
@@ -1664,6 +1690,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;
@@ -1687,12 +1777,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",
@@ -1720,9 +1808,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;
@@ -1746,7 +1832,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,
@@ -1757,14 +1844,12 @@ static void cnss_unregister_ramdump_v1(struct cnss_plat_data *plat_priv)
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;

@@ -1794,9 +1879,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;
@@ -1818,7 +1901,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;
@@ -1979,6 +2062,32 @@ static void cnss_unregister_bus_scale(struct cnss_plat_data *plat_priv)
		msm_bus_scale_unregister_client(bus_bw_info->bus_client);
}

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)
@@ -2042,10 +2151,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,
};

@@ -2173,6 +2284,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);
+15 −2
Original line number Diff line number Diff line
@@ -11,7 +11,11 @@
#include <linux/pm_qos.h>
#include <net/cnss2.h>
#include <soc/qcom/memory_dump.h>
#ifdef 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"

@@ -79,14 +83,20 @@ struct cnss_pinctrl_info {
	struct pinctrl_state *wlan_en_sleep;
};

#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
struct cnss_subsys_info {
	struct subsys_device *subsys_device;
	struct subsys_desc subsys_desc;
	void *subsys_handle;
};
#else
struct cnss_subsys_info {
	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;
@@ -110,7 +120,7 @@ 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;
@@ -331,17 +341,20 @@ struct cnss_plat_data {
	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;
+8 −1
Original line number Diff line number Diff line
@@ -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"
@@ -4029,6 +4028,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;
Loading