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

Commit 2874ebda authored by Yue Ma's avatar Yue Ma
Browse files

cnss2: Provide the interface to force firmware assert



Once WLAN host driver detects bad states, it will notify platform
driver which always tries to trigger firmware assert first and then
recover from it. If firmware assert doesn't happen, directly recover
from there.

Change-Id: I7ca5db6460513af2d9d0720762ba88279435b4d7
Signed-off-by: default avatarYue Ma <yuem@codeaurora.org>
parent 844aad38
Loading
Loading
Loading
Loading
+55 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#define WLAN_RECOVERY_DELAY		1000
#define FILE_SYSTEM_READY		1
#define FW_READY_TIMEOUT		20000
#define FW_ASSERT_TIMEOUT		5000
#define CNSS_EVENT_PENDING		2989

static struct cnss_plat_data *plat_env;
@@ -665,6 +666,8 @@ static char *cnss_driver_event_to_str(enum cnss_driver_event_type type)
		return "UNREGISTER_DRIVER";
	case CNSS_DRIVER_EVENT_RECOVERY:
		return "RECOVERY";
	case CNSS_DRIVER_EVENT_FORCE_FW_ASSERT:
		return "FORCE_FW_ASSERT";
	case CNSS_DRIVER_EVENT_MAX:
		return "EVENT_MAX";
	}
@@ -1545,6 +1548,55 @@ void cnss_schedule_recovery(struct device *dev,
}
EXPORT_SYMBOL(cnss_schedule_recovery);

static int cnss_force_fw_assert_hdlr(struct cnss_plat_data *plat_priv)
{
	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
	int ret;

	ret = cnss_pci_set_mhi_state(plat_priv->bus_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,
				       CNSS_REASON_DEFAULT);
		return 0;
	}

	if (!test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state)) {
		mod_timer(&plat_priv->fw_boot_timer,
			  jiffies + msecs_to_jiffies(FW_ASSERT_TIMEOUT));
	}

	return 0;
}

int cnss_force_fw_assert(struct device *dev)
{
	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);

	if (!plat_priv) {
		cnss_pr_err("plat_priv is NULL\n");
		return -ENODEV;
	}

	if (plat_priv->device_id == QCA6174_DEVICE_ID) {
		cnss_pr_info("Forced FW assert is not supported\n");
		return -EINVAL;
	}

	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
		cnss_pr_info("Recovery is already in progress, ignore forced FW assert\n");
		return 0;
	}

	cnss_driver_event_post(plat_priv,
			       CNSS_DRIVER_EVENT_FORCE_FW_ASSERT,
			       false, NULL);

	return 0;
}
EXPORT_SYMBOL(cnss_force_fw_assert);

void fw_boot_timeout(unsigned long data)
{
	struct cnss_plat_data *plat_priv = (struct cnss_plat_data *)data;
@@ -1673,6 +1725,9 @@ static void cnss_driver_event_work(struct work_struct *work)
			ret = cnss_driver_recovery_hdlr(plat_priv,
							event->data);
			break;
		case CNSS_DRIVER_EVENT_FORCE_FW_ASSERT:
			ret = cnss_force_fw_assert_hdlr(plat_priv);
			break;
		default:
			cnss_pr_err("Invalid driver event type: %d",
				    event->type);
+1 −0
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ enum cnss_driver_event_type {
	CNSS_DRIVER_EVENT_REGISTER_DRIVER,
	CNSS_DRIVER_EVENT_UNREGISTER_DRIVER,
	CNSS_DRIVER_EVENT_RECOVERY,
	CNSS_DRIVER_EVENT_FORCE_FW_ASSERT,
	CNSS_DRIVER_EVENT_MAX,
};

+6 −0
Original line number Diff line number Diff line
@@ -1032,6 +1032,8 @@ static char *cnss_mhi_state_to_str(enum cnss_mhi_state mhi_state)
		return "SUSPEND";
	case CNSS_MHI_RESUME:
		return "RESUME";
	case CNSS_MHI_TRIGGER_RDDM:
		return "TRIGGER_RDDM";
	case CNSS_MHI_RDDM:
		return "RDDM";
	case CNSS_MHI_RDDM_KERNEL_PANIC:
@@ -1193,6 +1195,8 @@ static enum mhi_dev_ctrl cnss_to_mhi_dev_state(enum cnss_mhi_state state)
		return MHI_DEV_CTRL_SUSPEND;
	case CNSS_MHI_RESUME:
		return MHI_DEV_CTRL_RESUME;
	case CNSS_MHI_TRIGGER_RDDM:
		return MHI_DEV_CTRL_TRIGGER_RDDM;
	case CNSS_MHI_RDDM:
		return MHI_DEV_CTRL_RDDM;
	case CNSS_MHI_RDDM_KERNEL_PANIC:
@@ -1229,6 +1233,7 @@ static int cnss_pci_check_mhi_state_bit(struct cnss_pci_data *pci_priv,
		if (test_bit(CNSS_MHI_SUSPEND, &pci_priv->mhi_state))
			return 0;
		break;
	case CNSS_MHI_TRIGGER_RDDM:
	case CNSS_MHI_RDDM:
	case CNSS_MHI_RDDM_KERNEL_PANIC:
	case CNSS_MHI_NOTIFY_LINK_ERROR:
@@ -1267,6 +1272,7 @@ static void cnss_pci_set_mhi_state_bit(struct cnss_pci_data *pci_priv,
	case CNSS_MHI_RESUME:
		clear_bit(CNSS_MHI_SUSPEND, &pci_priv->mhi_state);
		break;
	case CNSS_MHI_TRIGGER_RDDM:
	case CNSS_MHI_RDDM:
	case CNSS_MHI_RDDM_KERNEL_PANIC:
	case CNSS_MHI_NOTIFY_LINK_ERROR:
+1 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ enum cnss_mhi_state {
	CNSS_MHI_RESUME,
	CNSS_MHI_POWER_OFF,
	CNSS_MHI_POWER_ON,
	CNSS_MHI_TRIGGER_RDDM,
	CNSS_MHI_RDDM,
	CNSS_MHI_RDDM_KERNEL_PANIC,
	CNSS_MHI_NOTIFY_LINK_ERROR,
+1 −0
Original line number Diff line number Diff line
@@ -145,6 +145,7 @@ extern void cnss_schedule_recovery(struct device *dev,
				   enum cnss_recovery_reason reason);
extern int cnss_self_recovery(struct device *dev,
			      enum cnss_recovery_reason reason);
extern int cnss_force_fw_assert(struct device *dev);
extern void *cnss_get_virt_ramdump_mem(unsigned long *size);
extern int cnss_get_fw_files_for_target(struct cnss_fw_files *pfw_files,
					u32 target_type, u32 target_version);