cnss2: Release qmi handle after server exit

Release qmi handle after server exit which will help
cnss2 driver to bail out pending qmi transactions gracefully.
QMI server calls server exit whenever a client tries to
release qmi handle and calls server arrive whenever a
client tries to register for service and service is up.
This change also ensures the next server arrive is processed
only when earlier server exit has been processed successfully.


Change-Id: Ia3332694c769731a36bfdb6d7136a3115f5159e4
Signed-off-by: Sandeep Singh <sandsing@codeaurora.org>
This commit is contained in:
Sandeep Singh 2020-08-10 18:43:21 +05:30
commit 647dbbe4d4
5 changed files with 59 additions and 10 deletions

View file

@ -118,6 +118,8 @@ static int cnss_stats_show_state(struct seq_file *s,
continue;
case CNSS_IN_PANIC:
seq_puts(s, "IN_PANIC");
case CNSS_QMI_DEL_SERVER:
seq_puts(s, "DEL_SERVER_IN_PROGRESS");
continue;
}

View file

@ -281,6 +281,7 @@ enum cnss_driver_state {
CNSS_IN_REBOOT,
CNSS_COLD_BOOT_CAL_DONE,
CNSS_IN_PANIC,
CNSS_QMI_DEL_SERVER,
};
struct cnss_recovery_data {

View file

@ -4451,12 +4451,14 @@ static void cnss_mhi_notify_status(struct mhi_controller *mhi_ctrl, void *priv,
case MHI_CB_EE_MISSION_MODE:
return;
case MHI_CB_FATAL_ERROR:
cnss_ignore_qmi_failure(true);
set_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state);
del_timer(&plat_priv->fw_boot_timer);
cnss_pci_update_status(pci_priv, CNSS_FW_DOWN);
cnss_reason = CNSS_REASON_DEFAULT;
break;
case MHI_CB_SYS_ERROR:
cnss_ignore_qmi_failure(true);
set_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state);
del_timer(&plat_priv->fw_boot_timer);
mod_timer(&pci_priv->dev_rddm_timer,
@ -4464,6 +4466,7 @@ static void cnss_mhi_notify_status(struct mhi_controller *mhi_ctrl, void *priv,
cnss_pci_update_status(pci_priv, CNSS_FW_DOWN);
return;
case MHI_CB_EE_RDDM:
cnss_ignore_qmi_failure(true);
set_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state);
del_timer(&plat_priv->fw_boot_timer);
del_timer(&pci_priv->dev_rddm_timer);

View file

@ -31,6 +31,18 @@
#define QMI_WLFW_MAC_READY_TIMEOUT_MS 50
#define QMI_WLFW_MAC_READY_MAX_RETRY 200
#ifdef CONFIG_CNSS2_DEBUG
static bool ignore_qmi_failure;
#define CNSS_QMI_ASSERT() CNSS_ASSERT(ignore_qmi_failure)
void cnss_ignore_qmi_failure(bool ignore)
{
ignore_qmi_failure = ignore;
}
#else
#define CNSS_QMI_ASSERT() do { } while (0)
void cnss_ignore_qmi_failure(bool ignore) { }
#endif
static char *cnss_qmi_mode_to_str(enum cnss_driver_mode mode)
{
switch (mode) {
@ -144,7 +156,7 @@ static int cnss_wlfw_ind_register_send_sync(struct cnss_plat_data *plat_priv)
return 0;
out:
CNSS_ASSERT(0);
CNSS_QMI_ASSERT();
qmi_registered:
kfree(req);
@ -264,7 +276,7 @@ static int cnss_wlfw_host_cap_send_sync(struct cnss_plat_data *plat_priv)
return 0;
out:
CNSS_ASSERT(0);
CNSS_QMI_ASSERT();
kfree(req);
kfree(resp);
return ret;
@ -353,7 +365,7 @@ int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv)
return 0;
out:
CNSS_ASSERT(0);
CNSS_QMI_ASSERT();
kfree(req);
kfree(resp);
return ret;
@ -469,7 +481,7 @@ int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv)
return 0;
out:
CNSS_ASSERT(0);
CNSS_QMI_ASSERT();
kfree(req);
kfree(resp);
return ret;
@ -657,7 +669,7 @@ err_req_fw:
if (!(bdf_type == CNSS_BDF_REGDB ||
test_bit(CNSS_IN_REBOOT, &plat_priv->driver_state) ||
ret == -EAGAIN))
CNSS_ASSERT(0);
CNSS_QMI_ASSERT();
kfree(req);
kfree(resp);
return ret;
@ -734,7 +746,7 @@ int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv)
return 0;
out:
CNSS_ASSERT(0);
CNSS_QMI_ASSERT();
kfree(req);
kfree(resp);
return ret;
@ -945,7 +957,7 @@ out:
cnss_pr_dbg("WLFW service is disconnected while sending mode off request\n");
ret = 0;
} else {
CNSS_ASSERT(0);
CNSS_QMI_ASSERT();
}
kfree(req);
kfree(resp);
@ -1055,7 +1067,7 @@ int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
return 0;
out:
CNSS_ASSERT(0);
CNSS_QMI_ASSERT();
kfree(req);
kfree(resp);
return ret;
@ -2325,7 +2337,7 @@ static int cnss_wlfw_connect_to_server(struct cnss_plat_data *plat_priv,
return 0;
out:
CNSS_ASSERT(0);
CNSS_QMI_ASSERT();
kfree(data);
return ret;
}
@ -2343,6 +2355,8 @@ int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv, void *data)
return -EINVAL;
}
cnss_ignore_qmi_failure(false);
ret = cnss_wlfw_connect_to_server(plat_priv, data);
if (ret < 0)
goto out;
@ -2366,6 +2380,8 @@ out:
int cnss_wlfw_server_exit(struct cnss_plat_data *plat_priv)
{
int ret;
if (!plat_priv)
return -ENODEV;
@ -2374,6 +2390,15 @@ int cnss_wlfw_server_exit(struct cnss_plat_data *plat_priv)
cnss_pr_info("QMI WLFW service disconnected, state: 0x%lx\n",
plat_priv->driver_state);
cnss_qmi_deinit(plat_priv);
clear_bit(CNSS_QMI_DEL_SERVER, &plat_priv->driver_state);
ret = cnss_qmi_init(plat_priv);
if (ret < 0) {
cnss_pr_err("QMI WLFW service registraton failed, ret\n", ret);
CNSS_ASSERT(0);
}
return 0;
}
@ -2384,6 +2409,12 @@ static int wlfw_new_server(struct qmi_handle *qmi_wlfw,
container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
struct cnss_qmi_event_server_arrive_data *event_data;
if (plat_priv && test_bit(CNSS_QMI_DEL_SERVER, &plat_priv->driver_state)) {
cnss_pr_info("WLFW server delete in progress, Ignore server arrive, state: 0x%lx\n",
plat_priv->driver_state);
return 0;
}
cnss_pr_dbg("WLFW server arriving: node %u port %u\n",
service->node, service->port);
@ -2406,8 +2437,19 @@ static void wlfw_del_server(struct qmi_handle *qmi_wlfw,
struct cnss_plat_data *plat_priv =
container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
if (plat_priv && test_bit(CNSS_QMI_DEL_SERVER, &plat_priv->driver_state)) {
cnss_pr_info("WLFW server delete in progress, Ignore server delete, state: 0x%lx\n",
plat_priv->driver_state);
return;
}
cnss_pr_dbg("WLFW server exiting\n");
if (plat_priv) {
cnss_ignore_qmi_failure(true);
set_bit(CNSS_QMI_DEL_SERVER, &plat_priv->driver_state);
}
cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_SERVER_EXIT,
0, NULL);
}

View file

@ -68,6 +68,7 @@ int cnss_wlfw_qdss_trace_mem_info_send_sync(struct cnss_plat_data *plat_priv);
int cnss_register_ims_service(struct cnss_plat_data *plat_priv);
void cnss_unregister_ims_service(struct cnss_plat_data *plat_priv);
int cnss_wlfw_send_pcie_gen_speed_sync(struct cnss_plat_data *plat_priv);
void cnss_ignore_qmi_failure(bool ignore);
#else
#define QMI_WLFW_TIMEOUT_MS 10000
@ -220,7 +221,7 @@ void cnss_unregister_ims_service(struct cnss_plat_data *plat_priv) {}
static inline
int cnss_wlfw_send_pcie_gen_speed_sync(struct cnss_plat_data *plat_priv) {}
void cnss_ignore_qmi_failure(bool ignore) {};
#endif /* CONFIG_CNSS2_QMI */
#endif /* _CNSS_QMI_H */