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

Commit b81d100b authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "cnss2: Add recovery reason to string support"

parents ee517b63 b27ebc61
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -92,6 +92,11 @@ static int cnss_stats_show_state(struct seq_file *s,
		case CNSS_DRIVER_RECOVERY:
			seq_puts(s, "DRIVER_RECOVERY");
			continue;
		case CNSS_FW_BOOT_RECOVERY:
			seq_puts(s, "FW_BOOT_RECOVERY");
			continue;
		case CNSS_DEV_ERR_NOTIFY:
			seq_puts(s, "DEV_ERR");
		}

		seq_printf(s, "UNKNOWN-%d", i);
+87 −42
Original line number Diff line number Diff line
@@ -594,19 +594,18 @@ out:

static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv)
{
	struct cnss_pci_data *pci_priv;
	int ret = 0;

	if (!plat_priv)
		return -ENODEV;

	del_timer(&plat_priv->fw_ready_timer);

	del_timer(&plat_priv->fw_boot_timer);
	set_bit(CNSS_FW_READY, &plat_priv->driver_state);

	pci_priv = plat_priv->bus_priv;
	if (!pci_priv)
		return -ENODEV;
	if (test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state)) {
		clear_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state);
		clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
	}

	if (enable_waltest) {
		ret = cnss_wlfw_wlan_mode_send_sync(plat_priv,
@@ -624,8 +623,8 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv)
	return 0;

shutdown:
	cnss_pci_stop_mhi(pci_priv);
	cnss_suspend_pci_link(pci_priv);
	cnss_pci_stop_mhi(plat_priv->bus_priv);
	cnss_suspend_pci_link(plat_priv->bus_priv);
	cnss_power_off_device(plat_priv);

	return ret;
@@ -1051,10 +1050,16 @@ static int cnss_qca6290_powerup(struct cnss_plat_data *plat_priv)
		goto power_off;
	}

	timeout = cnss_get_qmi_timeout();

	ret = cnss_pci_start_mhi(pci_priv);
	if (ret) {
		cnss_pr_err("Failed to start MHI, err = %d\n", ret);
		goto suspend_link;
		if (!test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state) &&
		    !pci_priv->pci_link_down_ind && timeout)
			mod_timer(&plat_priv->fw_boot_timer,
				  jiffies + msecs_to_jiffies(timeout >> 1));
		return 0;
	}

	cnss_set_pin_connect_status(plat_priv);
@@ -1063,11 +1068,8 @@ static int cnss_qca6290_powerup(struct cnss_plat_data *plat_priv)
		ret = cnss_driver_call_probe(plat_priv);
		if (ret)
			goto stop_mhi;
	} else {
		timeout = cnss_get_qmi_timeout();
		cnss_pr_dbg("QMI timeout is %u ms\n", timeout);
		if (timeout)
			mod_timer(&plat_priv->fw_ready_timer,
	} else if (timeout) {
		mod_timer(&plat_priv->fw_boot_timer,
			  jiffies + msecs_to_jiffies(timeout << 1));
	}

@@ -1075,7 +1077,6 @@ static int cnss_qca6290_powerup(struct cnss_plat_data *plat_priv)

stop_mhi:
	cnss_pci_stop_mhi(pci_priv);
suspend_link:
	cnss_suspend_pci_link(pci_priv);
power_off:
	cnss_power_off_device(plat_priv);
@@ -1091,7 +1092,8 @@ static int cnss_qca6290_shutdown(struct cnss_plat_data *plat_priv)
	if (!pci_priv)
		return -ENODEV;

	if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state))
	if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state) ||
	    test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state))
		goto skip_driver_remove;

	if (!plat_priv->driver_ops)
@@ -1344,6 +1346,22 @@ static void cnss_crash_shutdown(const struct subsys_desc *subsys_desc)
	}
}

static const char *cnss_recovery_reason_to_str(enum cnss_recovery_reason reason)
{
	switch (reason) {
	case CNSS_REASON_DEFAULT:
		return "DEFAULT";
	case CNSS_REASON_LINK_DOWN:
		return "LINK_DOWN";
	case CNSS_REASON_RDDM:
		return "RDDM";
	case CNSS_REASON_TIMEOUT:
		return "TIMEOUT";
	}

	return "UNKNOWN";
};

static int cnss_do_recovery(struct cnss_plat_data *plat_priv,
			    enum cnss_recovery_reason reason)
{
@@ -1362,22 +1380,29 @@ static int cnss_do_recovery(struct cnss_plat_data *plat_priv,
		plat_priv->driver_ops->update_status(pci_priv->pci_dev,
						     CNSS_RECOVERY);

	if (reason == CNSS_REASON_LINK_DOWN &&
	    test_bit(LINK_DOWN_SELF_RECOVERY, &quirks))
	switch (reason) {
	case CNSS_REASON_LINK_DOWN:
		if (test_bit(LINK_DOWN_SELF_RECOVERY, &quirks))
			goto self_recovery;

	if (reason != CNSS_REASON_RDDM)
		goto subsys_restart;

		break;
	case CNSS_REASON_RDDM:
		clear_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state);
		ret = cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_RDDM);
		if (ret) {
		cnss_pr_err("Fail to complete RDDM, err = %d\n", ret);
		goto subsys_restart;
			cnss_pr_err("Failed to complete RDDM, err = %d\n", ret);
			break;
		}

		cnss_pci_collect_dump_info(pci_priv);
		break;
	case CNSS_REASON_DEFAULT:
	case CNSS_REASON_TIMEOUT:
		break;
	default:
		cnss_pr_err("Unsupported recovery reason: %s(%d)\n",
			    cnss_recovery_reason_to_str(reason), reason);
		break;
	}

subsys_restart:
	if (!subsys_info->subsys_device)
		return 0;

@@ -1399,7 +1424,8 @@ static int cnss_driver_recovery_hdlr(struct cnss_plat_data *plat_priv,
	struct cnss_recovery_data *recovery_data = data;
	int ret = 0;

	cnss_pr_dbg("Driver recovery is triggered: reason %d\n",
	cnss_pr_dbg("Driver recovery is triggered with reason: %s(%d)\n",
		    cnss_recovery_reason_to_str(recovery_data->reason),
		    recovery_data->reason);

	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
@@ -1408,15 +1434,34 @@ static int cnss_driver_recovery_hdlr(struct cnss_plat_data *plat_priv,
		goto out;
	}

	if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) ||
	    test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) {
		cnss_pr_err("Driver load or unload is in progress!\n");
	if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) {
		cnss_pr_err("Driver unload is in progress, ignore recovery\n");
		ret = -EINVAL;
		goto out;
	}

	set_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
	switch (plat_priv->device_id) {
	case QCA6174_DEVICE_ID:
		if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state)) {
			cnss_pr_err("Driver load is in progress, ignore recovery\n");
			ret = -EINVAL;
			goto out;
		}
		break;
	default:
		if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
			set_bit(CNSS_FW_BOOT_RECOVERY,
				&plat_priv->driver_state);
		} else if (test_bit(CNSS_DRIVER_LOADING,
			   &plat_priv->driver_state)) {
			cnss_pr_err("Driver probe is in progress, ignore recovery\n");
			ret = -EINVAL;
			goto out;
		}
		break;
	}

	set_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
	ret = cnss_do_recovery(plat_priv, recovery_data->reason);

out:
@@ -1453,16 +1498,15 @@ void cnss_schedule_recovery(struct device *dev,
}
EXPORT_SYMBOL(cnss_schedule_recovery);

void fw_ready_timeout(unsigned long data)
void fw_boot_timeout(unsigned long data)
{
	struct cnss_plat_data *plat_priv = (struct cnss_plat_data *)data;
	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;

	cnss_pr_err("Timeout waiting for FW ready indication!\n");

	cnss_pci_stop_mhi(pci_priv);
	cnss_suspend_pci_link(pci_priv);
	cnss_power_off_device(plat_priv);
	cnss_schedule_recovery(&pci_priv->pci_dev->dev,
			       CNSS_REASON_TIMEOUT);
}

static int cnss_register_driver_hdlr(struct cnss_plat_data *plat_priv,
@@ -2071,8 +2115,8 @@ static int cnss_probe(struct platform_device *plat_dev)
	if (ret)
		goto deinit_qmi;

	setup_timer(&plat_priv->fw_ready_timer,
		    fw_ready_timeout, (unsigned long)plat_priv);
	setup_timer(&plat_priv->fw_boot_timer,
		    fw_boot_timeout, (unsigned long)plat_priv);

	register_pm_notifier(&cnss_pm_notifier);

@@ -2108,6 +2152,7 @@ static int cnss_remove(struct platform_device *plat_dev)
	struct cnss_plat_data *plat_priv = platform_get_drvdata(plat_dev);

	unregister_pm_notifier(&cnss_pm_notifier);
	del_timer(&plat_priv->fw_boot_timer);
	cnss_debugfs_destroy(plat_priv);
	cnss_qmi_deinit(plat_priv);
	cnss_event_work_deinit(plat_priv);
+3 −1
Original line number Diff line number Diff line
@@ -136,6 +136,8 @@ enum cnss_driver_state {
	CNSS_DRIVER_UNLOADING,
	CNSS_DRIVER_PROBED,
	CNSS_DRIVER_RECOVERY,
	CNSS_FW_BOOT_RECOVERY,
	CNSS_DEV_ERR_NOTIFY,
};

struct cnss_recovery_data {
@@ -196,7 +198,7 @@ struct cnss_plat_data {
	struct cnss_pin_connect_result pin_result;
	struct dentry *root_dentry;
	atomic_t pm_count;
	struct timer_list fw_ready_timer;
	struct timer_list fw_boot_timer;
};

void *cnss_bus_dev_to_bus_priv(struct device *dev);
+4 −0
Original line number Diff line number Diff line
@@ -1111,6 +1111,7 @@ void cnss_pci_clear_dump_info(struct cnss_pci_data *pci_priv)
static void cnss_mhi_notify_status(enum MHI_CB_REASON reason, void *priv)
{
	struct cnss_pci_data *pci_priv = priv;
	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
	enum cnss_recovery_reason cnss_reason = CNSS_REASON_RDDM;

	if (!pci_priv)
@@ -1118,6 +1119,9 @@ static void cnss_mhi_notify_status(enum MHI_CB_REASON reason, void *priv)

	cnss_pr_dbg("MHI status cb is called with reason %d\n", reason);

	set_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state);
	del_timer(&plat_priv->fw_boot_timer);

	if (reason == MHI_CB_SYS_ERROR)
		cnss_reason = CNSS_REASON_TIMEOUT;

+5 −3
Original line number Diff line number Diff line
@@ -26,8 +26,8 @@
#define BDF_FILE_NAME_PREFIX		"bdwlan.b"

#ifdef CONFIG_CNSS2_DEBUG
static unsigned long qmi_timeout = 10000;
module_param(qmi_timeout, ulong, S_IRUSR | S_IWUSR);
static unsigned int qmi_timeout = 10000;
module_param(qmi_timeout, uint, S_IRUSR | S_IWUSR);
MODULE_PARM_DESC(qmi_timeout, "Timeout for QMI message in milliseconds");

#define QMI_WLFW_TIMEOUT_MS		qmi_timeout
@@ -841,7 +841,9 @@ static void cnss_wlfw_clnt_ind(struct qmi_handle *handle,

unsigned int cnss_get_qmi_timeout(void)
{
	return qmi_timeout;
	cnss_pr_dbg("QMI timeout is %u ms\n", QMI_WLFW_TIMEOUT_MS);

	return QMI_WLFW_TIMEOUT_MS;
}
EXPORT_SYMBOL(cnss_get_qmi_timeout);