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: Manikandan Mohan <manikand@codeaurora.org>
This commit is contained in:
Manikandan Mohan 2020-08-18 15:24:32 -07:00
commit cd7f415867
3 changed files with 30 additions and 6 deletions

View file

@ -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)

View file

@ -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);

View file

@ -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;