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

Commit 647dbbe4 authored by Sandeep Singh's avatar Sandeep Singh
Browse files

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: default avatarSandeep Singh <sandsing@codeaurora.org>
parent 1a490661
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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;
		}

+1 −0
Original line number Diff line number Diff line
@@ -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 {
+3 −0
Original line number Diff line number Diff line
@@ -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);
+51 −9
Original line number Diff line number Diff line
@@ -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 @@ int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv,
	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 @@ int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,
		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 @@ int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv, void *data)

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);
}
+2 −1
Original line number Diff line number Diff line
@@ -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 */