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

Commit cd7f4158 authored by Manikandan Mohan's avatar Manikandan Mohan
Browse files

cnss2: Wait for power up complete during SSR restart



Update SSR power up function to wait for FW recovery complete to
avoid race condition with linux PM sleep entry.

Change-Id: Ief0d64e7699956ba30f2ff84732e36f6b2fdc3b0
Signed-off-by: default avatarManikandan Mohan <manikand@codeaurora.org>
parent adbbbc56
Loading
Loading
Loading
Loading
+24 −3
Original line number Diff line number Diff line
@@ -895,6 +895,7 @@ static inline void cnss_unregister_esoc(struct cnss_plat_data *plat_priv) {}
static int cnss_subsys_powerup(const struct subsys_desc *subsys_desc)
{
	struct cnss_plat_data *plat_priv;
	int ret = 0;

	if (!subsys_desc->dev) {
		cnss_pr_err("dev from subsys_desc is NULL\n");
@@ -912,7 +913,10 @@ static int cnss_subsys_powerup(const struct subsys_desc *subsys_desc)
		return 0;
	}

	return cnss_bus_dev_powerup(plat_priv);
	ret = cnss_bus_dev_powerup(plat_priv);
	if (ret)
		__pm_relax(plat_priv->recovery_ws);
	return ret;
}

static int cnss_subsys_shutdown(const struct subsys_desc *subsys_desc,
@@ -998,7 +1002,11 @@ static void cnss_recovery_work_handler(struct work_struct *work)

	cnss_bus_dev_shutdown(plat_priv);
	msleep(RECOVERY_DELAY_MS);
	cnss_bus_dev_powerup(plat_priv);

	ret = cnss_bus_dev_powerup(plat_priv);
	if (ret)
		__pm_relax(plat_priv->recovery_ws);
	return;
}

void cnss_device_crashed(struct device *dev)
@@ -1058,6 +1066,14 @@ static int cnss_do_recovery(struct cnss_plat_data *plat_priv,
		return 0;
	}

	/* FW recovery sequence has multiple steps and firmware load requires
	 * linux PM in awake state. Thus hold the cnss wake source until
	 * WLAN MISSION enabled.
	 */
	pm_wakeup_ws_event(plat_priv->recovery_ws, RECOVERY_TIMEOUT +
			   cnss_get_boot_timeout(NULL),
			   true);

	switch (reason) {
	case CNSS_REASON_LINK_DOWN:
		if (!cnss_bus_check_link_status(plat_priv)) {
@@ -1079,7 +1095,6 @@ static int cnss_do_recovery(struct cnss_plat_data *plat_priv,
			    cnss_recovery_reason_to_str(reason), reason);
		break;
	}

	cnss_bus_device_crashed(plat_priv);

	return 0;
@@ -2358,6 +2373,11 @@ static int cnss_misc_init(struct cnss_plat_data *plat_priv)
	init_completion(&plat_priv->recovery_complete);
	mutex_init(&plat_priv->dev_lock);
	mutex_init(&plat_priv->driver_ops_lock);
	plat_priv->recovery_ws =
		wakeup_source_register(&plat_priv->plat_dev->dev,
				       "CNSS_FW_RECOVERY");
	if (!plat_priv->recovery_ws)
		cnss_pr_err("Failed to setup FW recovery wake source\n");

	return 0;
}
@@ -2372,6 +2392,7 @@ static void cnss_misc_deinit(struct cnss_plat_data *plat_priv)
	unregister_reboot_notifier(&plat_priv->reboot_nb);
	unregister_pm_notifier(&cnss_pm_notifier);
	del_timer(&plat_priv->fw_boot_timer);
	wakeup_source_unregister(plat_priv->recovery_ws);
}

static void cnss_init_control_params(struct cnss_plat_data *plat_priv)
+1 −0
Original line number Diff line number Diff line
@@ -411,6 +411,7 @@ struct cnss_plat_data {
	struct qmi_handle coex_qmi;
	struct qmi_handle ims_qmi;
	struct qmi_txn txn;
	struct wakeup_source *recovery_ws;
	u64 dynamic_feature;
	void *get_info_cb_ctx;
	int (*get_info_cb)(void *ctx, void *event, int event_len);
+5 −3
Original line number Diff line number Diff line
@@ -1443,7 +1443,6 @@ int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv)
				    ret);
			goto out;
		}
		clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
		complete(&plat_priv->recovery_complete);
	} else if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state)) {
		ret = pci_priv->driver_ops->probe(pci_priv->pci_dev,
@@ -1453,7 +1452,6 @@ int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv)
				    ret);
			goto out;
		}
		clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
		clear_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state);
		set_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state);
		complete_all(&plat_priv->power_up_complete);
@@ -1466,13 +1464,17 @@ int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv)
				    ret);
			goto out;
		}
		clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
		clear_bit(CNSS_DRIVER_IDLE_RESTART, &plat_priv->driver_state);
		complete_all(&plat_priv->power_up_complete);
	} else {
		complete(&plat_priv->power_up_complete);
	}

	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
		clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
		__pm_relax(plat_priv->recovery_ws);
	}

	cnss_pci_start_time_sync_update(pci_priv);

	return 0;