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

Commit 80389af1 authored by Naman Padhiar's avatar Naman Padhiar
Browse files

icnss2: Add get info QMI messages support



These QMI messages are used to get certain info from WLAN firmware.
Results of the info request will be passed back to WLAN driver to
do further processing.
These QMI messages can be used to WMI command over QMI and get WMI
event as QMI Indication and send it to WLAN driver.

Change-Id: I8a7b513d95e9f10c815445b8ebd78f81607fb910
Signed-off-by: default avatarNaman Padhiar <npadhiar@codeaurora.org>
parent 711abd0c
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -1613,6 +1613,32 @@ static int icnss_enable_recovery(struct icnss_priv *priv)
	return 0;
}

int icnss_qmi_send(struct device *dev, int type, void *cmd,
		  int cmd_len, void *cb_ctx,
		  int (*cb)(void *ctx, void *event, int event_len))
{
	struct icnss_priv *priv = icnss_get_plat_priv();
	int ret;

	if (!priv)
		return -ENODEV;

	if (!test_bit(ICNSS_WLFW_CONNECTED, &priv->state))
		return -EINVAL;

	priv->get_info_cb = cb;
	priv->get_info_cb_ctx = cb_ctx;

	ret = icnss_wlfw_get_info_send_sync(priv, type, cmd, cmd_len);
	if (ret) {
		priv->get_info_cb = NULL;
		priv->get_info_cb_ctx = NULL;
	}

	return ret;
}
EXPORT_SYMBOL(icnss_qmi_send);

int __icnss_register_driver(struct icnss_driver_ops *ops,
			    struct module *owner, const char *mod_name)
{
+2 −0
Original line number Diff line number Diff line
@@ -340,6 +340,8 @@ struct icnss_priv {
	atomic_t is_shutdown;
	u32 qdss_mem_seg_len;
	struct icnss_fw_mem qdss_mem[QMI_WLFW_MAX_NUM_MEM_SEG];
	void *get_info_cb_ctx;
	int (*get_info_cb)(void *ctx, void *event, int event_len);
};

struct icnss_reg_info {
+110 −0
Original line number Diff line number Diff line
@@ -462,6 +462,8 @@ int wlfw_ind_register_send_sync_msg(struct icnss_priv *priv)
		req->qdss_trace_save_enable = 1;
		req->qdss_trace_free_enable_valid = 1;
		req->qdss_trace_free_enable = 1;
		req->respond_get_info_enable_valid = 1;
		req->respond_get_info_enable = 1;
	}

	priv->stats.ind_register_req++;
@@ -1716,6 +1718,32 @@ static void wlfw_qdss_trace_free_ind_cb(struct qmi_handle *qmi,
	icnss_driver_event_post(priv, ICNSS_DRIVER_EVENT_QDSS_TRACE_FREE,
				0, NULL);
}

static void icnss_wlfw_respond_get_info_ind_cb(struct qmi_handle *qmi,
					      struct sockaddr_qrtr *sq,
					      struct qmi_txn *txn,
					      const void *data)
{
	struct icnss_priv *priv = container_of(qmi, struct icnss_priv, qmi);
	const struct wlfw_respond_get_info_ind_msg_v01 *ind_msg = data;

	icnss_pr_vdbg("Received QMI WLFW respond get info indication\n");

	if (!txn) {
		icnss_pr_err("Spurious indication\n");
		return;
	}

	icnss_pr_vdbg("Extract message with event length: %d, type: %d, is last: %d, seq no: %d\n",
		     ind_msg->data_len, ind_msg->type,
		     ind_msg->is_last, ind_msg->seq_no);

	if (priv->get_info_cb_ctx && priv->get_info_cb)
		priv->get_info_cb(priv->get_info_cb_ctx,
				       (void *)ind_msg->data,
				       ind_msg->data_len);
}

static struct qmi_msg_handler wlfw_msg_handlers[] = {
	{
		.type = QMI_INDICATION,
@@ -1784,6 +1812,14 @@ static struct qmi_msg_handler wlfw_msg_handlers[] = {
		sizeof(struct wlfw_qdss_trace_free_ind_msg_v01),
		.fn = wlfw_qdss_trace_free_ind_cb
	},
	{
		.type = QMI_INDICATION,
		.msg_id = QMI_WLFW_RESPOND_GET_INFO_IND_V01,
		.ei = wlfw_respond_get_info_ind_msg_v01_ei,
		.decoded_size =
		sizeof(struct wlfw_respond_get_info_ind_msg_v01),
		.fn = icnss_wlfw_respond_get_info_ind_cb
	},
	{}
};

@@ -2145,3 +2181,77 @@ int wlfw_host_cap_send_sync(struct icnss_priv *priv)
	kfree(resp);
	return ret;
}

int icnss_wlfw_get_info_send_sync(struct icnss_priv *plat_priv, int type,
				 void *cmd, int cmd_len)
{
	struct wlfw_get_info_req_msg_v01 *req;
	struct wlfw_get_info_resp_msg_v01 *resp;
	struct qmi_txn txn;
	int ret = 0;

	icnss_pr_dbg("Sending get info message, type: %d, cmd length: %d, state: 0x%lx\n",
		     type, cmd_len, plat_priv->state);

	if (cmd_len > QMI_WLFW_MAX_DATA_SIZE_V01)
		return -EINVAL;

	if (test_bit(ICNSS_FW_DOWN, &priv->state))
		return -EINVAL;

	req = kzalloc(sizeof(*req), GFP_KERNEL);
	if (!req)
		return -ENOMEM;

	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
	if (!resp) {
		kfree(req);
		return -ENOMEM;
	}

	req->type = type;
	req->data_len = cmd_len;
	memcpy(req->data, cmd, req->data_len);

	ret = qmi_txn_init(&plat_priv->qmi, &txn,
			   wlfw_get_info_resp_msg_v01_ei, resp);
	if (ret < 0) {
		icnss_pr_err("Failed to initialize txn for get info request, err: %d\n",
			    ret);
		goto out;
	}

	ret = qmi_send_request(&plat_priv->qmi, NULL, &txn,
			       QMI_WLFW_GET_INFO_REQ_V01,
			       WLFW_GET_INFO_REQ_MSG_V01_MAX_MSG_LEN,
			       wlfw_get_info_req_msg_v01_ei, req);
	if (ret < 0) {
		qmi_txn_cancel(&txn);
		icnss_pr_err("Failed to send get info request, err: %d\n",
			    ret);
		goto out;
	}

	ret = qmi_txn_wait(&txn, plat_priv->ctrl_params.qmi_timeout);
	if (ret < 0) {
		icnss_pr_err("Failed to wait for response of get info request, err: %d\n",
			    ret);
		goto out;
	}

	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
		icnss_pr_err("Get info request failed, result: %d, err: %d\n",
			    resp->resp.result, resp->resp.error);
		ret = -resp->resp.result;
		goto out;
	}

	kfree(req);
	kfree(resp);
	return 0;

out:
	kfree(req);
	kfree(resp);
	return ret;
}
+8 −0
Original line number Diff line number Diff line
@@ -133,6 +133,12 @@ int wlfw_exit_power_save_send_msg(struct icnss_priv *priv)
{
	return 0;
}

int icnss_wlfw_get_info_send_sync(struct icnss_priv *priv, int type,
				  void *cmd, int cmd_len)
{
	return 0;
}
#else
int wlfw_ind_register_send_sync_msg(struct icnss_priv *priv);
int icnss_connect_to_fw_server(struct icnss_priv *priv, void *data);
@@ -169,6 +175,8 @@ int wlfw_wlan_mode_send_sync_msg(struct icnss_priv *priv,
int icnss_wlfw_bdf_dnld_send_sync(struct icnss_priv *priv, u32 bdf_type);
int wlfw_qdss_trace_mem_info_send_sync(struct icnss_priv *priv);
int wlfw_exit_power_save_send_msg(struct icnss_priv *priv);
int icnss_wlfw_get_info_send_sync(struct icnss_priv *priv, int type,
				  void *cmd, int cmd_len);
#endif

#endif /* __ICNSS_QMI_H__*/
+3 −0
Original line number Diff line number Diff line
@@ -164,4 +164,7 @@ extern int icnss_get_user_msi_assignment(struct device *dev, char *user_name,
extern int icnss_get_msi_irq(struct device *dev, unsigned int vector);
extern void icnss_get_msi_address(struct device *dev, u32 *msi_addr_low,
			   u32 *msi_addr_high);
extern int icnss_qmi_send(struct device *dev, int type, void *cmd,
			  int cmd_len, void *cb_ctx,
			  int (*cb)(void *ctx, void *event, int event_len));
#endif /* _ICNSS_WLAN_H_ */