From 647dbbe4d4ca0306a4bc5e2799f9e94f01fccd61 Mon Sep 17 00:00:00 2001 From: Sandeep Singh Date: Mon, 10 Aug 2020 18:43:21 +0530 Subject: [PATCH] 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 --- drivers/net/wireless/cnss2/debug.c | 2 + drivers/net/wireless/cnss2/main.h | 1 + drivers/net/wireless/cnss2/pci.c | 3 ++ drivers/net/wireless/cnss2/qmi.c | 60 +++++++++++++++++++++++++----- drivers/net/wireless/cnss2/qmi.h | 3 +- 5 files changed, 59 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/cnss2/debug.c b/drivers/net/wireless/cnss2/debug.c index cd1b3bbbd1b3..5556b95d8e82 100644 --- a/drivers/net/wireless/cnss2/debug.c +++ b/drivers/net/wireless/cnss2/debug.c @@ -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; } diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h index 92f569e27fbe..c58161caae33 100644 --- a/drivers/net/wireless/cnss2/main.h +++ b/drivers/net/wireless/cnss2/main.h @@ -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 { diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 6f8c9c278adf..bcd83fda89f4 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -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); diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c index 89ddb98d10ed..d788b393b64f 100644 --- a/drivers/net/wireless/cnss2/qmi.c +++ b/drivers/net/wireless/cnss2/qmi.c @@ -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); } diff --git a/drivers/net/wireless/cnss2/qmi.h b/drivers/net/wireless/cnss2/qmi.h index 798492a2ffb2..9413a93dac70 100644 --- a/drivers/net/wireless/cnss2/qmi.h +++ b/drivers/net/wireless/cnss2/qmi.h @@ -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 */