Loading drivers/net/wireless/cnss2/main.c +88 −0 Original line number Diff line number Diff line Loading @@ -436,6 +436,94 @@ int cnss_wlan_disable(struct device *dev, enum cnss_driver_mode mode) } EXPORT_SYMBOL(cnss_wlan_disable); #ifdef CONFIG_CNSS2_DEBUG int cnss_athdiag_read(struct device *dev, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *output) { struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); int ret = 0; if (!plat_priv) { cnss_pr_err("plat_priv is NULL!\n"); return -EINVAL; } if (plat_priv->device_id == QCA6174_DEVICE_ID) return 0; if (!output || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) { cnss_pr_err("Invalid parameters for athdiag read: output %p, data_len %u\n", output, data_len); ret = -EINVAL; goto out; } if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) { cnss_pr_err("Invalid state for athdiag read: 0x%lx\n", plat_priv->driver_state); ret = -EINVAL; goto out; } ret = cnss_wlfw_athdiag_read_send_sync(plat_priv, offset, mem_type, data_len, output); out: return ret; } EXPORT_SYMBOL(cnss_athdiag_read); int cnss_athdiag_write(struct device *dev, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *input) { struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); int ret = 0; if (!plat_priv) { cnss_pr_err("plat_priv is NULL!\n"); return -EINVAL; } if (plat_priv->device_id == QCA6174_DEVICE_ID) return 0; if (!input || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) { cnss_pr_err("Invalid parameters for athdiag write: input %p, data_len %u\n", input, data_len); ret = -EINVAL; goto out; } if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) { cnss_pr_err("Invalid state for athdiag write: 0x%lx\n", plat_priv->driver_state); ret = -EINVAL; goto out; } ret = cnss_wlfw_athdiag_write_send_sync(plat_priv, offset, mem_type, data_len, input); out: return ret; } EXPORT_SYMBOL(cnss_athdiag_write); #else int cnss_athdiag_read(struct device *dev, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *output) { return -EPERM; } EXPORT_SYMBOL(cnss_athdiag_read); int cnss_athdiag_write(struct device *dev, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *input) { return -EPERM; } EXPORT_SYMBOL(cnss_athdiag_write); #endif static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv) { int ret = 0; Loading drivers/net/wireless/cnss2/qmi.c +124 −0 Original line number Diff line number Diff line Loading @@ -672,6 +672,130 @@ out: return ret; } int cnss_wlfw_athdiag_read_send_sync(struct cnss_plat_data *plat_priv, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *data) { struct wlfw_athdiag_read_req_msg_v01 req; struct wlfw_athdiag_read_resp_msg_v01 *resp; struct msg_desc req_desc, resp_desc; int ret = 0; if (!plat_priv) return -ENODEV; if (!plat_priv->qmi_wlfw_clnt) return -EINVAL; cnss_pr_dbg("athdiag read: state 0x%lx, offset %x, mem_type %x, data_len %u\n", plat_priv->driver_state, offset, mem_type, data_len); resp = kzalloc(sizeof(*resp), GFP_KERNEL); if (!resp) return -ENOMEM; memset(&req, 0, sizeof(req)); req.offset = offset; req.mem_type = mem_type; req.data_len = data_len; req_desc.max_msg_len = WLFW_ATHDIAG_READ_REQ_MSG_V01_MAX_MSG_LEN; req_desc.msg_id = QMI_WLFW_ATHDIAG_READ_REQ_V01; req_desc.ei_array = wlfw_athdiag_read_req_msg_v01_ei; resp_desc.max_msg_len = WLFW_ATHDIAG_READ_RESP_MSG_V01_MAX_MSG_LEN; resp_desc.msg_id = QMI_WLFW_ATHDIAG_READ_RESP_V01; resp_desc.ei_array = wlfw_athdiag_read_resp_msg_v01_ei; 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 athdiag read request, err = %d\n", ret); goto out; } if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { cnss_pr_err("athdiag read request failed, result: %d, err: %d\n", resp->resp.result, resp->resp.error); ret = resp->resp.result; goto out; } if (!resp->data_valid || resp->data_len <= data_len) { cnss_pr_err("athdiag read data is invalid, data_valid = %u, data_len = %u\n", resp->data_valid, resp->data_len); ret = -EINVAL; goto out; } memcpy(data, resp->data, resp->data_len); out: kfree(resp); return ret; } int cnss_wlfw_athdiag_write_send_sync(struct cnss_plat_data *plat_priv, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *data) { struct wlfw_athdiag_write_req_msg_v01 *req; struct wlfw_athdiag_write_resp_msg_v01 resp; struct msg_desc req_desc, resp_desc; int ret = 0; if (!plat_priv) return -ENODEV; if (!plat_priv->qmi_wlfw_clnt) return -EINVAL; cnss_pr_dbg("athdiag write: state 0x%lx, offset %x, mem_type %x, data_len %u, data %p\n", plat_priv->driver_state, offset, mem_type, data_len, data); req = kzalloc(sizeof(*req), GFP_KERNEL); if (!req) return -ENOMEM; memset(&resp, 0, sizeof(resp)); req->offset = offset; req->mem_type = mem_type; req->data_len = data_len; memcpy(req->data, data, data_len); req_desc.max_msg_len = WLFW_ATHDIAG_WRITE_REQ_MSG_V01_MAX_MSG_LEN; req_desc.msg_id = QMI_WLFW_ATHDIAG_WRITE_REQ_V01; req_desc.ei_array = wlfw_athdiag_write_req_msg_v01_ei; resp_desc.max_msg_len = WLFW_ATHDIAG_WRITE_RESP_MSG_V01_MAX_MSG_LEN; resp_desc.msg_id = QMI_WLFW_ATHDIAG_WRITE_RESP_V01; resp_desc.ei_array = wlfw_athdiag_write_resp_msg_v01_ei; 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 athdiag write request, err = %d\n", ret); goto out; } if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { cnss_pr_err("athdiag write request failed, result: %d, err: %d\n", resp.resp.result, resp.resp.error); ret = resp.resp.result; goto out; } out: kfree(req); return ret; } static void cnss_wlfw_clnt_ind(struct qmi_handle *handle, unsigned int msg_id, void *msg, unsigned int msg_len, void *ind_cb_priv) Loading drivers/net/wireless/cnss2/qmi.h +6 −0 Original line number Diff line number Diff line Loading @@ -29,5 +29,11 @@ int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv, enum wlfw_driver_mode_enum_v01 mode); int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv, struct wlfw_wlan_cfg_req_msg_v01 *data); int cnss_wlfw_athdiag_read_send_sync(struct cnss_plat_data *plat_priv, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *data); int cnss_wlfw_athdiag_write_send_sync(struct cnss_plat_data *plat_priv, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *data); #endif /* _CNSS_QMI_H */ include/net/cnss2.h +6 −0 Original line number Diff line number Diff line Loading @@ -180,5 +180,11 @@ extern int cnss_wlan_enable(struct device *dev, const char *host_version); extern int cnss_wlan_disable(struct device *dev, enum cnss_driver_mode mode); extern unsigned int cnss_get_qmi_timeout(void); extern int cnss_athdiag_read(struct device *dev, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *output); extern int cnss_athdiag_write(struct device *dev, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *input); #endif /* _NET_CNSS2_H */ Loading
drivers/net/wireless/cnss2/main.c +88 −0 Original line number Diff line number Diff line Loading @@ -436,6 +436,94 @@ int cnss_wlan_disable(struct device *dev, enum cnss_driver_mode mode) } EXPORT_SYMBOL(cnss_wlan_disable); #ifdef CONFIG_CNSS2_DEBUG int cnss_athdiag_read(struct device *dev, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *output) { struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); int ret = 0; if (!plat_priv) { cnss_pr_err("plat_priv is NULL!\n"); return -EINVAL; } if (plat_priv->device_id == QCA6174_DEVICE_ID) return 0; if (!output || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) { cnss_pr_err("Invalid parameters for athdiag read: output %p, data_len %u\n", output, data_len); ret = -EINVAL; goto out; } if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) { cnss_pr_err("Invalid state for athdiag read: 0x%lx\n", plat_priv->driver_state); ret = -EINVAL; goto out; } ret = cnss_wlfw_athdiag_read_send_sync(plat_priv, offset, mem_type, data_len, output); out: return ret; } EXPORT_SYMBOL(cnss_athdiag_read); int cnss_athdiag_write(struct device *dev, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *input) { struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); int ret = 0; if (!plat_priv) { cnss_pr_err("plat_priv is NULL!\n"); return -EINVAL; } if (plat_priv->device_id == QCA6174_DEVICE_ID) return 0; if (!input || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) { cnss_pr_err("Invalid parameters for athdiag write: input %p, data_len %u\n", input, data_len); ret = -EINVAL; goto out; } if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) { cnss_pr_err("Invalid state for athdiag write: 0x%lx\n", plat_priv->driver_state); ret = -EINVAL; goto out; } ret = cnss_wlfw_athdiag_write_send_sync(plat_priv, offset, mem_type, data_len, input); out: return ret; } EXPORT_SYMBOL(cnss_athdiag_write); #else int cnss_athdiag_read(struct device *dev, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *output) { return -EPERM; } EXPORT_SYMBOL(cnss_athdiag_read); int cnss_athdiag_write(struct device *dev, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *input) { return -EPERM; } EXPORT_SYMBOL(cnss_athdiag_write); #endif static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv) { int ret = 0; Loading
drivers/net/wireless/cnss2/qmi.c +124 −0 Original line number Diff line number Diff line Loading @@ -672,6 +672,130 @@ out: return ret; } int cnss_wlfw_athdiag_read_send_sync(struct cnss_plat_data *plat_priv, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *data) { struct wlfw_athdiag_read_req_msg_v01 req; struct wlfw_athdiag_read_resp_msg_v01 *resp; struct msg_desc req_desc, resp_desc; int ret = 0; if (!plat_priv) return -ENODEV; if (!plat_priv->qmi_wlfw_clnt) return -EINVAL; cnss_pr_dbg("athdiag read: state 0x%lx, offset %x, mem_type %x, data_len %u\n", plat_priv->driver_state, offset, mem_type, data_len); resp = kzalloc(sizeof(*resp), GFP_KERNEL); if (!resp) return -ENOMEM; memset(&req, 0, sizeof(req)); req.offset = offset; req.mem_type = mem_type; req.data_len = data_len; req_desc.max_msg_len = WLFW_ATHDIAG_READ_REQ_MSG_V01_MAX_MSG_LEN; req_desc.msg_id = QMI_WLFW_ATHDIAG_READ_REQ_V01; req_desc.ei_array = wlfw_athdiag_read_req_msg_v01_ei; resp_desc.max_msg_len = WLFW_ATHDIAG_READ_RESP_MSG_V01_MAX_MSG_LEN; resp_desc.msg_id = QMI_WLFW_ATHDIAG_READ_RESP_V01; resp_desc.ei_array = wlfw_athdiag_read_resp_msg_v01_ei; 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 athdiag read request, err = %d\n", ret); goto out; } if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { cnss_pr_err("athdiag read request failed, result: %d, err: %d\n", resp->resp.result, resp->resp.error); ret = resp->resp.result; goto out; } if (!resp->data_valid || resp->data_len <= data_len) { cnss_pr_err("athdiag read data is invalid, data_valid = %u, data_len = %u\n", resp->data_valid, resp->data_len); ret = -EINVAL; goto out; } memcpy(data, resp->data, resp->data_len); out: kfree(resp); return ret; } int cnss_wlfw_athdiag_write_send_sync(struct cnss_plat_data *plat_priv, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *data) { struct wlfw_athdiag_write_req_msg_v01 *req; struct wlfw_athdiag_write_resp_msg_v01 resp; struct msg_desc req_desc, resp_desc; int ret = 0; if (!plat_priv) return -ENODEV; if (!plat_priv->qmi_wlfw_clnt) return -EINVAL; cnss_pr_dbg("athdiag write: state 0x%lx, offset %x, mem_type %x, data_len %u, data %p\n", plat_priv->driver_state, offset, mem_type, data_len, data); req = kzalloc(sizeof(*req), GFP_KERNEL); if (!req) return -ENOMEM; memset(&resp, 0, sizeof(resp)); req->offset = offset; req->mem_type = mem_type; req->data_len = data_len; memcpy(req->data, data, data_len); req_desc.max_msg_len = WLFW_ATHDIAG_WRITE_REQ_MSG_V01_MAX_MSG_LEN; req_desc.msg_id = QMI_WLFW_ATHDIAG_WRITE_REQ_V01; req_desc.ei_array = wlfw_athdiag_write_req_msg_v01_ei; resp_desc.max_msg_len = WLFW_ATHDIAG_WRITE_RESP_MSG_V01_MAX_MSG_LEN; resp_desc.msg_id = QMI_WLFW_ATHDIAG_WRITE_RESP_V01; resp_desc.ei_array = wlfw_athdiag_write_resp_msg_v01_ei; 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 athdiag write request, err = %d\n", ret); goto out; } if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { cnss_pr_err("athdiag write request failed, result: %d, err: %d\n", resp.resp.result, resp.resp.error); ret = resp.resp.result; goto out; } out: kfree(req); return ret; } static void cnss_wlfw_clnt_ind(struct qmi_handle *handle, unsigned int msg_id, void *msg, unsigned int msg_len, void *ind_cb_priv) Loading
drivers/net/wireless/cnss2/qmi.h +6 −0 Original line number Diff line number Diff line Loading @@ -29,5 +29,11 @@ int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv, enum wlfw_driver_mode_enum_v01 mode); int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv, struct wlfw_wlan_cfg_req_msg_v01 *data); int cnss_wlfw_athdiag_read_send_sync(struct cnss_plat_data *plat_priv, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *data); int cnss_wlfw_athdiag_write_send_sync(struct cnss_plat_data *plat_priv, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *data); #endif /* _CNSS_QMI_H */
include/net/cnss2.h +6 −0 Original line number Diff line number Diff line Loading @@ -180,5 +180,11 @@ extern int cnss_wlan_enable(struct device *dev, const char *host_version); extern int cnss_wlan_disable(struct device *dev, enum cnss_driver_mode mode); extern unsigned int cnss_get_qmi_timeout(void); extern int cnss_athdiag_read(struct device *dev, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *output); extern int cnss_athdiag_write(struct device *dev, uint32_t offset, uint32_t mem_type, uint32_t data_len, uint8_t *input); #endif /* _NET_CNSS2_H */