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

Commit 4f476c17 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "cnss2: Support unified QMI sequence"

parents 3463b695 6fa70646
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1690,6 +1690,7 @@ static int cnss_cold_boot_cal_start_hdlr(struct cnss_plat_data *plat_priv)

static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv)
{
	plat_priv->cal_done = true;
	cnss_wlfw_wlan_mode_send_sync(plat_priv, QMI_WLFW_OFF_V01);
	cnss_shutdown(plat_priv);
	clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
+4 −1
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ struct cnss_fw_mem {
	void *va;
	phys_addr_t pa;
	bool valid;
	u32 type;
};

enum cnss_driver_event_type {
@@ -192,7 +193,8 @@ struct cnss_plat_data {
	struct wlfw_rf_board_info_s_v01 board_info;
	struct wlfw_soc_info_s_v01 soc_info;
	struct wlfw_fw_version_info_s_v01 fw_version_info;
	struct cnss_fw_mem fw_mem;
	u32 fw_mem_seg_len;
	struct cnss_fw_mem fw_mem[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
	struct cnss_fw_mem m3_mem;
	struct cnss_pin_connect_result pin_result;
	struct dentry *root_dentry;
@@ -204,6 +206,7 @@ struct cnss_plat_data {
	u32 diag_reg_read_mem_type;
	u32 diag_reg_read_len;
	u8 *diag_reg_read_buf;
	bool cal_done;
};

void *cnss_bus_dev_to_bus_priv(struct device *dev);
+33 −22
Original line number Diff line number Diff line
@@ -737,20 +737,23 @@ int cnss_pm_request_resume(struct cnss_pci_data *pci_priv)
int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv)
{
	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
	struct cnss_fw_mem *fw_mem = &plat_priv->fw_mem;

	if (!fw_mem->va && fw_mem->size) {
		fw_mem->va = dma_alloc_coherent(&pci_priv->pci_dev->dev,
						fw_mem->size, &fw_mem->pa,
						GFP_KERNEL);
		if (!fw_mem->va) {
			cnss_pr_err("Failed to allocate memory for FW, size: 0x%zx\n",
				    fw_mem->size);
			fw_mem->size = 0;
	struct cnss_fw_mem *fw_mem = plat_priv->fw_mem;
	int i;

	for (i = 0; i < plat_priv->fw_mem_seg_len; i++) {
		if (!fw_mem[i].va && fw_mem[i].size) {
			fw_mem[i].va =
				dma_alloc_coherent(&pci_priv->pci_dev->dev,
						   fw_mem[i].size,
						   &fw_mem[i].pa, GFP_KERNEL);
			if (!fw_mem[i].va) {
				cnss_pr_err("Failed to allocate memory for FW, size: 0x%zx, type: %u\n",
					    fw_mem[i].size, fw_mem[i].type);

				return -ENOMEM;
			}
		}
	}

	return 0;
}
@@ -758,19 +761,27 @@ int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv)
static void cnss_pci_free_fw_mem(struct cnss_pci_data *pci_priv)
{
	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
	struct cnss_fw_mem *fw_mem = &plat_priv->fw_mem;
	struct cnss_fw_mem *fw_mem = plat_priv->fw_mem;
	int i;

	if (fw_mem->va && fw_mem->size) {
		cnss_pr_dbg("Freeing memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx\n",
			    fw_mem->va, &fw_mem->pa, fw_mem->size);
		dma_free_coherent(&pci_priv->pci_dev->dev, fw_mem->size,
				  fw_mem->va, fw_mem->pa);
		fw_mem->va = NULL;
		fw_mem->pa = 0;
		fw_mem->size = 0;
	for (i = 0; i < plat_priv->fw_mem_seg_len; i++) {
		if (fw_mem[i].va && fw_mem[i].size) {
			cnss_pr_dbg("Freeing memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx, type: %u\n",
				    fw_mem[i].va, &fw_mem[i].pa,
				    fw_mem[i].size, fw_mem[i].type);
			dma_free_coherent(&pci_priv->pci_dev->dev,
					  fw_mem[i].size, fw_mem[i].va,
					  fw_mem[i].pa);
			fw_mem[i].va = NULL;
			fw_mem[i].pa = 0;
			fw_mem[i].size = 0;
			fw_mem[i].type = 0;
		}
	}

	plat_priv->fw_mem_seg_len = 0;
}

int cnss_pci_load_m3(struct cnss_pci_data *pci_priv)
{
	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+92 −37
Original line number Diff line number Diff line
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -159,10 +159,9 @@ static int cnss_wlfw_host_cap_send_sync(struct cnss_plat_data *plat_priv)
	memset(&req, 0, sizeof(req));
	memset(&resp, 0, sizeof(resp));

	req.daemon_support_valid = 1;
	req.daemon_support = daemon_support;

	cnss_pr_dbg("daemon_support is %d\n", req.daemon_support);
	req.num_clients_valid = 1;
	req.num_clients = daemon_support ? 2 : 1;
	cnss_pr_dbg("Number of clients is %d\n", req.num_clients);

	req.wake_msi = cnss_get_wake_msi(plat_priv);
	if (req.wake_msi) {
@@ -170,6 +169,19 @@ static int cnss_wlfw_host_cap_send_sync(struct cnss_plat_data *plat_priv)
		req.wake_msi_valid = 1;
	}

	req.bdf_support_valid = 1;
	req.bdf_support = 1;

	req.m3_support_valid = 1;
	req.m3_support = 1;

	req.m3_cache_support_valid = 1;
	req.m3_cache_support = 1;

	req.cal_done_valid = 1;
	req.cal_done = plat_priv->cal_done;
	cnss_pr_dbg("Calibration done is %d\n", plat_priv->cal_done);

	req_desc.max_msg_len = WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN;
	req_desc.msg_id = QMI_WLFW_HOST_CAP_REQ_V01;
	req_desc.ei_array = wlfw_host_cap_req_msg_v01_ei;
@@ -221,8 +233,8 @@ static int cnss_wlfw_ind_register_send_sync(struct cnss_plat_data *plat_priv)
	req.request_mem_enable = 1;
	req.fw_mem_ready_enable_valid = 1;
	req.fw_mem_ready_enable = 1;
	req.cold_boot_cal_done_enable_valid = 1;
	req.cold_boot_cal_done_enable = 1;
	req.fw_init_done_enable_valid = 1;
	req.fw_init_done_enable = 1;
	req.pin_connect_result_enable_valid = 1;
	req.pin_connect_result_enable = 1;

@@ -260,27 +272,48 @@ static int cnss_wlfw_request_mem_ind_hdlr(struct cnss_plat_data *plat_priv,
					  void *msg, unsigned int msg_len)
{
	struct msg_desc ind_desc;
	struct wlfw_request_mem_ind_msg_v01 ind_msg;
	struct cnss_fw_mem *fw_mem = &plat_priv->fw_mem;
	int ret = 0;
	struct wlfw_request_mem_ind_msg_v01 *ind_msg;
	int ret = 0, i;

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

	ind_desc.msg_id = QMI_WLFW_REQUEST_MEM_IND_V01;
	ind_desc.max_msg_len = WLFW_REQUEST_MEM_IND_MSG_V01_MAX_MSG_LEN;
	ind_desc.ei_array = wlfw_request_mem_ind_msg_v01_ei;

	ret = qmi_kernel_decode(&ind_desc, &ind_msg, msg, msg_len);
	ret = qmi_kernel_decode(&ind_desc, ind_msg, msg, msg_len);
	if (ret < 0) {
		cnss_pr_err("Failed to decode request memory indication, msg_len: %u, err = %d\n",
			    ret, msg_len);
		return ret;
		goto out;
	}

	if (ind_msg->mem_seg_len == 0 ||
	    ind_msg->mem_seg_len > QMI_WLFW_MAX_NUM_MEM_SEG_V01) {
		cnss_pr_err("Invalid memory segment length: %u\n",
			    ind_msg->mem_seg_len);
		ret = -EINVAL;
		goto out;
	}

	fw_mem->size = ind_msg.size;
	cnss_pr_dbg("FW memory segment count is %u\n", ind_msg->mem_seg_len);
	plat_priv->fw_mem_seg_len = ind_msg->mem_seg_len;
	for (i = 0; i < plat_priv->fw_mem_seg_len; i++) {
		plat_priv->fw_mem[i].type = ind_msg->mem_seg[i].type;
		plat_priv->fw_mem[i].size = ind_msg->mem_seg[i].size;
	}

	cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_REQUEST_MEM,
			       0, NULL);

	kfree(ind_msg);
	return 0;

out:
	kfree(ind_msg);
	return ret;
}

static int cnss_qmi_pin_result_ind_hdlr(struct cnss_plat_data *plat_priv,
@@ -317,29 +350,46 @@ static int cnss_qmi_pin_result_ind_hdlr(struct cnss_plat_data *plat_priv,

int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv)
{
	struct wlfw_respond_mem_req_msg_v01 req;
	struct wlfw_respond_mem_resp_msg_v01 resp;
	struct wlfw_respond_mem_req_msg_v01 *req;
	struct wlfw_respond_mem_resp_msg_v01 *resp;
	struct msg_desc req_desc, resp_desc;
	struct cnss_fw_mem *fw_mem = &plat_priv->fw_mem;
	int ret = 0;
	struct cnss_fw_mem *fw_mem = plat_priv->fw_mem;
	int ret = 0, i;

	cnss_pr_dbg("Sending respond memory message, state: 0x%lx\n",
		    plat_priv->driver_state);

	if (!fw_mem->pa || !fw_mem->size) {
		cnss_pr_err("Memory for FW is not available!\n");
	req = kzalloc(sizeof(*req), GFP_KERNEL);
	if (!req)
		return -ENOMEM;

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

	req->mem_seg_len = plat_priv->fw_mem_seg_len;
	for (i = 0; i < req->mem_seg_len; i++) {
		if (!fw_mem[i].pa || !fw_mem[i].size) {
			if (fw_mem[i].type == 0) {
				cnss_pr_err("Invalid memory for FW type, segment = %d\n",
					    i);
				ret = -EINVAL;
				goto out;
			}
			cnss_pr_err("Memory for FW is not available for type: %u\n",
				    fw_mem[i].type);
			ret = -ENOMEM;
			goto out;
		}

	cnss_pr_dbg("Memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx\n",
		    fw_mem->va, &fw_mem->pa, fw_mem->size);
		cnss_pr_dbg("Memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx, type: %u\n",
			    fw_mem[i].va, &fw_mem[i].pa,
			    fw_mem[i].size, fw_mem[i].type);

	memset(&req, 0, sizeof(req));
	memset(&resp, 0, sizeof(resp));

	req.addr = fw_mem->pa;
	req.size = fw_mem->size;
		req->mem_seg[i].addr = fw_mem[i].pa;
		req->mem_seg[i].size = fw_mem[i].size;
		req->mem_seg[i].type = fw_mem[i].type;
	}

	req_desc.max_msg_len = WLFW_RESPOND_MEM_REQ_MSG_V01_MAX_MSG_LEN;
	req_desc.msg_id = QMI_WLFW_RESPOND_MEM_REQ_V01;
@@ -349,8 +399,8 @@ int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv)
	resp_desc.msg_id = QMI_WLFW_RESPOND_MEM_RESP_V01;
	resp_desc.ei_array = wlfw_respond_mem_resp_msg_v01_ei;

	ret = qmi_send_req_wait(plat_priv->qmi_wlfw_clnt, &req_desc, &req,
				sizeof(req), &resp_desc, &resp, sizeof(resp),
	ret = qmi_send_req_wait(plat_priv->qmi_wlfw_clnt, &req_desc, req,
				sizeof(*req), &resp_desc, resp, sizeof(*resp),
				QMI_WLFW_TIMEOUT_MS);
	if (ret < 0) {
		cnss_pr_err("Failed to send respond memory request, err = %d\n",
@@ -358,16 +408,21 @@ int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv)
		goto out;
	}

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

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

out:
	CNSS_ASSERT(0);
	kfree(req);
	kfree(resp);
	return ret;
}

@@ -908,12 +963,12 @@ static void cnss_wlfw_clnt_ind(struct qmi_handle *handle,
				       CNSS_DRIVER_EVENT_FW_MEM_READY,
				       0, NULL);
		break;
	case QMI_WLFW_COLD_BOOT_CAL_DONE_IND_V01:
	case QMI_WLFW_FW_READY_IND_V01:
		cnss_driver_event_post(plat_priv,
				       CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE,
				       0, NULL);
		break;
	case QMI_WLFW_FW_READY_IND_V01:
	case QMI_WLFW_FW_INIT_DONE_IND_V01:
		cnss_driver_event_post(plat_priv,
				       CNSS_DRIVER_EVENT_FW_READY,
				       0, NULL);
@@ -974,11 +1029,11 @@ int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv)
	cnss_pr_info("QMI WLFW service connected, state: 0x%lx\n",
		     plat_priv->driver_state);

	ret = cnss_wlfw_host_cap_send_sync(plat_priv);
	ret = cnss_wlfw_ind_register_send_sync(plat_priv);
	if (ret < 0)
		goto out;

	ret = cnss_wlfw_ind_register_send_sync(plat_priv);
	ret = cnss_wlfw_host_cap_send_sync(plat_priv);
	if (ret < 0)
		goto out;

Loading