ath10k: Add wlan mode on/off qmi message
PATCH 11/12 ath10k: Add wlan mode on/off qmi message
Add qmi message required for enabling and disabling target to qmi server running in Q6.
--- drivers/net/wireless/ath/ath10k/qmi.c | 226 +++++++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath10k/qmi.h | 62 ++++++---- 2 files changed, 264 insertions(+), 24 deletions(-)
drivers/net/wireless/ath/ath10k/qmi.c +225 -1
@@ -35,7 +35,30 @@#define WLFW_CLIENT_ID 0x4b4e454c#define WLFW_TIMEOUT 500 -static struct ath10k_qmi *qmi; +static struct ath10k_qmi { +struct platform_device *pdev; +struct qmi_handle qmi_hdl; +struct sockaddr_qrtr sq; +bool fw_ready; +bool msa_ready; +struct work_struct work_svc_arrive; +struct work_struct work_svc_exit; +struct work_struct work_msa_ready; +struct workqueue_struct *event_wq; +spinlock_t event_lock;/* spinlock for fw ready status*/ +u32 nr_mem_region; +struct ath10k_msa_mem_region_info + mem_region[MAX_NUM_MEMORY_REGIONS ]; +phys_addr_t msa_pa; +u32 msa_mem_size; +void *msa_va; +struct ath10k_qmi_chip_info chip_info; +struct ath10k_qmi_board_info board_info; +struct ath10k_qmi_soc_info soc_info; +struct ath10k_qmi_fw_version_info fw_version_info; +char fw_build_id[MAX_BUILD_ID_LEN +1 ]; +struct ath10k_qmi_cal_data cal_data[MAX_NUM_CAL_V01 ]; +} *qmi;static int ath10k_qmi_map_msa_permissions (struct ath10k_msa_mem_region_info *mem_region)
@@ -444,6 +467,207 @@ int ath10k_qmi_send_cal_report_req(struct ath10k_qmi *qmi)return ret; } +static int +ath10k_qmi_mode_send_sync_msg (enum wlfw_driver_mode_enum_v01 mode) +{ +struct wlfw_wlan_mode_resp_msg_v01 *resp; +struct wlfw_wlan_mode_req_msg_v01 *req; +struct qmi_txn txn; +int ret; + + req =kzalloc (sizeof (*req),GFP_KERNEL ); +if (!req) +return -ENOMEM ; + + resp =kzalloc (sizeof (*resp),GFP_KERNEL ); +if (!resp) { +kfree (req); +return -ENOMEM ; + } + + ret =qmi_txn_init (&qmi->qmi_hdl, &txn, + wlfw_wlan_mode_resp_msg_v01_ei, + resp); +if (ret <0 ) { +pr_err ("fail to init txn for mode req %d ret %d\n" , mode, ret); + goto out; + } + + req->mode = mode; + req->hw_debug_valid =1 ; + req->hw_debug =0 ; + + ret =qmi_send_request (&qmi->qmi_hdl,NULL , &txn, +QMI_WLFW_WLAN_MODE_REQ_V01 , +WLFW_WLAN_MODE_REQ_MSG_V01_MAX_MSG_LEN , + wlfw_wlan_mode_req_msg_v01_ei, req); +if (ret <0 ) { +qmi_txn_cancel (&txn); +pr_err ("send mode req failed, mode: %d ret: %d\n" , + mode, ret); + goto out; + } + + ret =qmi_txn_wait (&txn,WLFW_TIMEOUT *HZ ); +if (ret <0 ) + goto out; + +if (resp->resp.result !=QMI_RESULT_SUCCESS_V01 ) { +pr_err ("qmi mode request rejected:" ); +pr_err ("mode:%d result:%d error:%d\n" , + mode, resp->resp.result, resp->resp.error); + ret = resp->resp.result; + goto out; + } + +pr_debug ("wlan Mode request completed, mode: %d\n" , mode); +kfree (resp); +kfree (req); +return 0 ; + +out: +kfree (resp); +kfree (req); +return ret; +} + +static int +ath10k_qmi_cfg_send_sync_msg (struct wlfw_wlan_cfg_req_msg_v01 *data) +{ +struct wlfw_wlan_cfg_resp_msg_v01 *resp; +struct wlfw_wlan_cfg_req_msg_v01 *req; +struct qmi_txn txn; +int ret; + + req =kzalloc (sizeof (*req),GFP_KERNEL ); +if (!req) +return -ENOMEM ; + + resp =kzalloc (sizeof (*resp),GFP_KERNEL ); +if (!resp) { +kfree (req); +return -ENOMEM ; + } + + ret =qmi_txn_init (&qmi->qmi_hdl, &txn, + wlfw_wlan_cfg_resp_msg_v01_ei, + resp); +if (ret <0 ) { +pr_err ("fail to init txn for config req %d\n" , ret); + goto out; + } + +memcpy (req, data,sizeof (*req)); + + ret =qmi_send_request (&qmi->qmi_hdl,NULL , &txn, +QMI_WLFW_WLAN_CFG_REQ_V01 , +WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN , + wlfw_wlan_cfg_req_msg_v01_ei, req); +if (ret <0 ) { +qmi_txn_cancel (&txn); +pr_err ("send config req failed %d\n" , ret); + goto out; + } + + ret =qmi_txn_wait (&txn,WLFW_TIMEOUT *HZ ); +if (ret <0 ) + goto out; + +if (resp->resp.result !=QMI_RESULT_SUCCESS_V01 ) { +pr_err ("qmi cfg request rejected:" ); +pr_err ("result:%d error:%d\n" , + resp->resp.result, resp->resp.error); + ret = resp->resp.result; + goto out; + } + +pr_debug ("wlan config request completed\n" ); +kfree (resp); +kfree (req); +return 0 ; + +out: +kfree (resp); +kfree (req); +return ret; +} + +int ath10k_qmi_wlan_enable (struct ath10k_qmi_wlan_enable_cfg *config, +enum ath10k_qmi_driver_mode mode, +const char *host_version) +{ +struct wlfw_wlan_cfg_req_msg_v01 req; +int ret; +u32 i; + +pr_debug ("mode: %d, config: %p:\n" , + mode, config); +memset (&req,0 ,sizeof (req)); +if (!config) { +pr_err ("wlan enable Config Invalid:%p\n" , + config); + ret = -EINVAL ; +return ret; + } + + req.host_version_valid =0 ; + + req.tgt_cfg_valid =1 ; +if (config->num_ce_tgt_cfg >QMI_WLFW_MAX_NUM_CE_V01 ) + req.tgt_cfg_len =QMI_WLFW_MAX_NUM_CE_V01 ; +else + req.tgt_cfg_len = config->num_ce_tgt_cfg; +for (i =0 ; i < req.tgt_cfg_len; i++) { + req.tgt_cfg[i].pipe_num = config->ce_tgt_cfg[i].pipe_num; + req.tgt_cfg[i].pipe_dir = config->ce_tgt_cfg[i].pipe_dir; + req.tgt_cfg[i].nentries = config->ce_tgt_cfg[i].nentries; + req.tgt_cfg[i].nbytes_max = config->ce_tgt_cfg[i].nbytes_max; + req.tgt_cfg[i].flags = config->ce_tgt_cfg[i].flags; + } + + req.svc_cfg_valid =1 ; +if (config->num_ce_svc_pipe_cfg >QMI_WLFW_MAX_NUM_SVC_V01 ) + req.svc_cfg_len =QMI_WLFW_MAX_NUM_SVC_V01 ; +else + req.svc_cfg_len = config->num_ce_svc_pipe_cfg; +for (i =0 ; i < req.svc_cfg_len; i++) { + req.svc_cfg[i].service_id = config->ce_svc_cfg[i].service_id; + req.svc_cfg[i].pipe_dir = config->ce_svc_cfg[i].pipe_dir; + req.svc_cfg[i].pipe_num = config->ce_svc_cfg[i].pipe_num; + } + + req.shadow_reg_valid =1 ; +if (config->num_shadow_reg_cfg > +QMI_WLFW_MAX_NUM_SHADOW_REG_V01 ) + req.shadow_reg_len =QMI_WLFW_MAX_NUM_SHADOW_REG_V01 ; +else + req.shadow_reg_len = config->num_shadow_reg_cfg; + +memcpy (req.shadow_reg, config->shadow_reg_cfg, +sizeof (struct wlfw_shadow_reg_cfg_s_v01 ) * req.shadow_reg_len); + + ret =ath10k_qmi_cfg_send_sync_msg (&req); +if (ret) { +pr_err ("wlan qmi config send failed\n" ); +return ret; + } + + ret =ath10k_qmi_mode_send_sync_msg (mode); +if (ret) { +pr_err ("wlan qmi mode send failed\n" ); +return ret; + } + +return 0 ; +} +EXPORT_SYMBOL_GPL (ath10k_qmi_wlan_enable); + +int ath10k_qmi_wlan_disable (void ) +{ +return ath10k_qmi_mode_send_sync_msg (QMI_WLFW_OFF_V01 ); +} +EXPORT_SYMBOL_GPL (ath10k_qmi_wlan_disable); +static int ath10k_qmi_cap_send_sync_msg (struct ath10k_qmi *qmi) {struct wlfw_cap_resp_msg_v01 *resp;
drivers/net/wireless/ath/ath10k/qmi.h +39 -23
73 lines not on this page · raw message
Signature · 1 line
1.9.1
Quoted 32 lines · Govind Singh
Add qmi message required for enabling and disabling target to qmi server running in Q6.
Signed-off-by Govind Singh <[email protected]>--- drivers/net/wireless/ath/ath10k/qmi.c | 226 +++++++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath10k/qmi.h | 62 ++++++---- 2 files changed, 264 insertions(+), 24 deletions(-)drivers/net/wireless/ath/ath10k/qmi.c +14
-1@@ -35,7 +35,30 @@#define WLFW_CLIENT_ID 0x4b4e454c#define WLFW_TIMEOUT 500 -static struct ath10k_qmi *qmi; +static struct ath10k_qmi { + struct platform_device *pdev; + struct qmi_handle qmi_hdl; + struct sockaddr_qrtr sq; + bool fw_ready; + bool msa_ready; + struct work_struct work_svc_arrive; + struct work_struct work_svc_exit; + struct work_struct work_msa_ready; + struct workqueue_struct *event_wq; + spinlock_t event_lock; /* spinlock for fw ready status*/ + u32 nr_mem_region; + struct ath10k_msa_mem_region_info + mem_region[MAX_NUM_MEMORY_REGIONS];
drivers/net/wireless/ath/ath10k/qmi.c line 61
Quoted 10 lines
drivers/net/wireless/ath/ath10k/qmi.c +10
-0+phys_addr_t msa_pa; +u32 msa_mem_size; +void *msa_va; +struct ath10k_qmi_chip_info chip_info; +struct ath10k_qmi_board_info board_info; +struct ath10k_qmi_soc_info soc_info; +struct ath10k_qmi_fw_version_info fw_version_info; +char fw_build_id[MAX_BUILD_ID_LEN +1 ]; +struct ath10k_qmi_cal_data cal_data[MAX_NUM_CAL_V01 ]; +} *qmi;
Don't end your patch series with a move of this structure, fold it back into each patch.
drivers/net/wireless/ath/ath10k/qmi.c int ath10k_qmi_send_cal_report_req(struct ath10k_qmi *qmi) · line 473
Quoted 11 lines
drivers/net/wireless/ath/ath10k/qmi.c +4
-0static int ath10k_qmi_map_msa_permissions (struct ath10k_msa_mem_region_info *mem_region)@@ -444,6 +467,207 @@ int ath10k_qmi_send_cal_report_req(struct ath10k_qmi *qmi)return ret; } +static int +ath10k_qmi_mode_send_sync_msg (enum wlfw_driver_mode_enum_v01 mode) +{ +struct wlfw_wlan_mode_resp_msg_v01 *resp;
4 bytes
drivers/net/wireless/ath/ath10k/qmi.c int ath10k_qmi_send_cal_report_req(struct ath10k_qmi *qmi) · line 474
Quoted 1 line
drivers/net/wireless/ath/ath10k/qmi.c +1
-0+struct wlfw_wlan_mode_req_msg_v01 *req;
6 bytes, use the stack.
Quoted 53 lines
drivers/net/wireless/ath/ath10k/qmi.c +53
-0+struct qmi_txn txn; +int ret; + + req =kzalloc (sizeof (*req),GFP_KERNEL ); +if (!req) +return -ENOMEM ; + + resp =kzalloc (sizeof (*resp),GFP_KERNEL ); +if (!resp) { +kfree (req); +return -ENOMEM ; + } + + ret =qmi_txn_init (&qmi->qmi_hdl, &txn, + wlfw_wlan_mode_resp_msg_v01_ei, + resp); +if (ret <0 ) { +pr_err ("fail to init txn for mode req %d ret %d\n" , mode, ret); + goto out; + } + + req->mode = mode; + req->hw_debug_valid =1 ; + req->hw_debug =0 ; + + ret =qmi_send_request (&qmi->qmi_hdl,NULL , &txn, +QMI_WLFW_WLAN_MODE_REQ_V01 , +WLFW_WLAN_MODE_REQ_MSG_V01_MAX_MSG_LEN , + wlfw_wlan_mode_req_msg_v01_ei, req); +if (ret <0 ) { +qmi_txn_cancel (&txn); +pr_err ("send mode req failed, mode: %d ret: %d\n" , + mode, ret); + goto out; + } + + ret =qmi_txn_wait (&txn,WLFW_TIMEOUT *HZ ); +if (ret <0 ) + goto out; + +if (resp->resp.result !=QMI_RESULT_SUCCESS_V01 ) { +pr_err ("qmi mode request rejected:" ); +pr_err ("mode:%d result:%d error:%d\n" , + mode, resp->resp.result, resp->resp.error); + ret = resp->resp.result; + goto out; + } + +pr_debug ("wlan Mode request completed, mode: %d\n" , mode); +kfree (resp); +kfree (req); +return 0 ; +
drivers/net/wireless/ath/ath10k/qmi.c int ath10k_qmi_send_cal_report_req(struct ath10k_qmi *qmi) · line 537
Quoted 10 lines
drivers/net/wireless/ath/ath10k/qmi.c +10
-0+out: +kfree (resp); +kfree (req); +return ret; +} + +static int +ath10k_qmi_cfg_send_sync_msg (struct wlfw_wlan_cfg_req_msg_v01 *data) +{ +struct wlfw_wlan_cfg_resp_msg_v01 *resp;
4 bytes, use stack
drivers/net/wireless/ath/ath10k/qmi.c int ath10k_qmi_send_cal_report_req(struct ath10k_qmi *qmi) · line 538
Quoted 1 line
drivers/net/wireless/ath/ath10k/qmi.c +1
-0+struct wlfw_wlan_cfg_req_msg_v01 *req;
This is larger, use heap
Quoted 12 lines
drivers/net/wireless/ath/ath10k/qmi.c +12
-0+struct qmi_txn txn; +int ret; + + req =kzalloc (sizeof (*req),GFP_KERNEL ); +if (!req) +return -ENOMEM ; + + resp =kzalloc (sizeof (*resp),GFP_KERNEL ); +if (!resp) { +kfree (req); +return -ENOMEM ; + }
drivers/net/wireless/ath/ath10k/qmi.c int ath10k_qmi_send_cal_report_req(struct ath10k_qmi *qmi) · line 560
Quoted 10 lines
drivers/net/wireless/ath/ath10k/qmi.c +10
-0+ + ret =qmi_txn_init (&qmi->qmi_hdl, &txn, + wlfw_wlan_cfg_resp_msg_v01_ei, + resp); +if (ret <0 ) { +pr_err ("fail to init txn for config req %d\n" , ret); + goto out; + } + +memcpy (req, data,sizeof (*req));
I see no reason to create a local copy of this struct, just pass data to qmi_send_request.
Quoted 34 lines
drivers/net/wireless/ath/ath10k/qmi.c +34
-0+ + ret =qmi_send_request (&qmi->qmi_hdl,NULL , &txn, +QMI_WLFW_WLAN_CFG_REQ_V01 , +WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN , + wlfw_wlan_cfg_req_msg_v01_ei, req); +if (ret <0 ) { +qmi_txn_cancel (&txn); +pr_err ("send config req failed %d\n" , ret); + goto out; + } + + ret =qmi_txn_wait (&txn,WLFW_TIMEOUT *HZ ); +if (ret <0 ) + goto out; + +if (resp->resp.result !=QMI_RESULT_SUCCESS_V01 ) { +pr_err ("qmi cfg request rejected:" ); +pr_err ("result:%d error:%d\n" , + resp->resp.result, resp->resp.error); + ret = resp->resp.result; + goto out; + } + +pr_debug ("wlan config request completed\n" ); +kfree (resp); +kfree (req); +return 0 ; + +out: +kfree (resp); +kfree (req); +return ret; +} +
drivers/net/wireless/ath/ath10k/qmi.c int ath10k_qmi_send_cal_report_req(struct ath10k_qmi *qmi) · line 604
Quoted 10 lines
drivers/net/wireless/ath/ath10k/qmi.c +10
-0+int ath10k_qmi_wlan_enable (struct ath10k_qmi_wlan_enable_cfg *config, +enum ath10k_qmi_driver_mode mode, +const char *host_version) +{ +struct wlfw_wlan_cfg_req_msg_v01 req; +int ret; +u32 i; + +pr_debug ("mode: %d, config: %p:\n" , + mode, config);
Use dev_dbg() and dev_err()
Quoted 35 lines
drivers/net/wireless/ath/ath10k/qmi.c +35
-0+memset (&req,0 ,sizeof (req)); +if (!config) { +pr_err ("wlan enable Config Invalid:%p\n" , + config); + ret = -EINVAL ; +return ret; + } + + req.host_version_valid =0 ; + + req.tgt_cfg_valid =1 ; +if (config->num_ce_tgt_cfg >QMI_WLFW_MAX_NUM_CE_V01 ) + req.tgt_cfg_len =QMI_WLFW_MAX_NUM_CE_V01 ; +else + req.tgt_cfg_len = config->num_ce_tgt_cfg; +for (i =0 ; i < req.tgt_cfg_len; i++) { + req.tgt_cfg[i].pipe_num = config->ce_tgt_cfg[i].pipe_num; + req.tgt_cfg[i].pipe_dir = config->ce_tgt_cfg[i].pipe_dir; + req.tgt_cfg[i].nentries = config->ce_tgt_cfg[i].nentries; + req.tgt_cfg[i].nbytes_max = config->ce_tgt_cfg[i].nbytes_max; + req.tgt_cfg[i].flags = config->ce_tgt_cfg[i].flags; + } + + req.svc_cfg_valid =1 ; +if (config->num_ce_svc_pipe_cfg >QMI_WLFW_MAX_NUM_SVC_V01 ) + req.svc_cfg_len =QMI_WLFW_MAX_NUM_SVC_V01 ; +else + req.svc_cfg_len = config->num_ce_svc_pipe_cfg; +for (i =0 ; i < req.svc_cfg_len; i++) { + req.svc_cfg[i].service_id = config->ce_svc_cfg[i].service_id; + req.svc_cfg[i].pipe_dir = config->ce_svc_cfg[i].pipe_dir; + req.svc_cfg[i].pipe_num = config->ce_svc_cfg[i].pipe_num; + } + + req.shadow_reg_valid =1 ;
drivers/net/wireless/ath/ath10k/qmi.c int ath10k_qmi_send_cal_report_req(struct ath10k_qmi *qmi) · line 649
Quoted 10 lines
drivers/net/wireless/ath/ath10k/qmi.c +10
-0+if (config->num_shadow_reg_cfg > +QMI_WLFW_MAX_NUM_SHADOW_REG_V01 ) + req.shadow_reg_len =QMI_WLFW_MAX_NUM_SHADOW_REG_V01 ; +else + req.shadow_reg_len = config->num_shadow_reg_cfg; + +memcpy (req.shadow_reg, config->shadow_reg_cfg, +sizeof (struct wlfw_shadow_reg_cfg_s_v01 ) * req.shadow_reg_len); + + ret =ath10k_qmi_cfg_send_sync_msg (&req);
Either move all of the req buildup into ath10k_qmi_cfg_send_sync_msg() or inline that function here - they are logically the two parts of the same function, don't split it like this.
Quoted 4 lines
drivers/net/wireless/ath/ath10k/qmi.c +4
-0+if (ret) { +pr_err ("wlan qmi config send failed\n" ); +return ret; + }
drivers/net/wireless/ath/ath10k/qmi.c int ath10k_qmi_send_cal_report_req(struct ath10k_qmi *qmi) · line 663
Quoted 10 lines
drivers/net/wireless/ath/ath10k/qmi.c +10
-0+ + ret =ath10k_qmi_mode_send_sync_msg (mode); +if (ret) { +pr_err ("wlan qmi mode send failed\n" ); +return ret; + } + +return 0 ; +} +EXPORT_SYMBOL_GPL (ath10k_qmi_wlan_enable);
Regards,
Bjorn