diff options
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/qmi.c | 441 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/qmi.h | 132 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/snoc.c | 7 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/snoc.h | 69 |
4 files changed, 580 insertions, 69 deletions
diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c index 7b5fc52d269a..1d92965d671e 100644 --- a/drivers/net/wireless/ath/ath10k/qmi.c +++ b/drivers/net/wireless/ath/ath10k/qmi.c @@ -12,10 +12,14 @@ #include <soc/qcom/subsystem_notif.h> #include <soc/qcom/subsystem_restart.h> #include <soc/qcom/service-notifier.h> +#include <soc/qcom/msm_qmi_interface.h> +#include <soc/qcom/service-locator.h> #include "core.h" #include "qmi.h" #include "snoc.h" -#include <soc/qcom/icnss.h> +#include "wcn3990_qmi_service_v01.h" + +static DECLARE_WAIT_QUEUE_HEAD(ath10k_fw_ready_wait_event); static int ath10k_snoc_service_notifier_notify(struct notifier_block *nb, @@ -228,3 +232,438 @@ int ath10k_snoc_modem_ssr_unregister_notifier(struct ath10k *ar) return 0; } +static char * +ath10k_snoc_driver_event_to_str(enum ath10k_snoc_driver_event_type type) +{ + switch (type) { + case ATH10K_SNOC_DRIVER_EVENT_SERVER_ARRIVE: + return "SERVER_ARRIVE"; + case ATH10K_SNOC_DRIVER_EVENT_SERVER_EXIT: + return "SERVER_EXIT"; + case ATH10K_SNOC_DRIVER_EVENT_FW_READY_IND: + return "FW_READY"; + case ATH10K_SNOC_DRIVER_EVENT_MAX: + return "EVENT_MAX"; + } + + return "UNKNOWN"; +}; + +static int +ath10k_snoc_driver_event_post(enum ath10k_snoc_driver_event_type type, + u32 flags, void *data) +{ + int ret = 0; + int i = 0; + struct ath10k *ar = (struct ath10k *)data; + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + struct ath10k_snoc_qmi_config *qmi_cfg = &ar_snoc->qmi_cfg; + + ath10k_dbg(ar, ATH10K_DBG_SNOC, "Posting event: %s type: %d\n", + ath10k_snoc_driver_event_to_str(type), type); + + if (type >= ATH10K_SNOC_DRIVER_EVENT_MAX) { + ath10k_err(ar, "Invalid Event type: %d, can't post", type); + return -EINVAL; + } + + spin_lock_bh(&qmi_cfg->event_lock); + + for (i = 0; i < ATH10K_SNOC_DRIVER_EVENT_MAX; i++) { + if (atomic_read(&qmi_cfg->qmi_ev_list[i].event_handled)) { + qmi_cfg->qmi_ev_list[i].type = type; + qmi_cfg->qmi_ev_list[i].data = data; + init_completion(&qmi_cfg->qmi_ev_list[i].complete); + qmi_cfg->qmi_ev_list[i].ret = + ATH10K_SNOC_EVENT_PENDING; + qmi_cfg->qmi_ev_list[i].sync = + !!(flags & ATH10K_SNOC_EVENT_SYNC); + atomic_set(&qmi_cfg->qmi_ev_list[i].event_handled, 0); + list_add_tail(&qmi_cfg->qmi_ev_list[i].list, + &qmi_cfg->event_list); + break; + } + } + + if (i >= ATH10K_SNOC_DRIVER_EVENT_MAX) + i = ATH10K_SNOC_DRIVER_EVENT_SERVER_ARRIVE; + + spin_unlock_bh(&qmi_cfg->event_lock); + + queue_work(qmi_cfg->event_wq, &qmi_cfg->event_work); + + if (!(flags & ATH10K_SNOC_EVENT_SYNC)) + goto out; + + if (flags & ATH10K_SNOC_EVENT_UNINTERRUPTIBLE) + wait_for_completion(&qmi_cfg->qmi_ev_list[i].complete); + else + ret = wait_for_completion_interruptible( + &qmi_cfg->qmi_ev_list[i].complete); + + ath10k_dbg(ar, ATH10K_DBG_SNOC, "Completed event: %s(%d)\n", + ath10k_snoc_driver_event_to_str(type), type); + + spin_lock_bh(&qmi_cfg->event_lock); + if (ret == -ERESTARTSYS && + qmi_cfg->qmi_ev_list[i].ret == ATH10K_SNOC_EVENT_PENDING) { + qmi_cfg->qmi_ev_list[i].sync = false; + atomic_set(&qmi_cfg->qmi_ev_list[i].event_handled, 1); + spin_unlock_bh(&qmi_cfg->event_lock); + ret = -EINTR; + goto out; + } + spin_unlock_bh(&qmi_cfg->event_lock); + +out: + return ret; +} + +static int ath10k_snoc_ind_register_send_sync_msg(struct ath10k *ar) +{ + int ret; + struct wlfw_ind_register_req_msg_v01 req; + struct wlfw_ind_register_resp_msg_v01 resp; + struct msg_desc req_desc, resp_desc; + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + struct ath10k_snoc_qmi_config *qmi_cfg = &ar_snoc->qmi_cfg; + + ath10k_dbg(ar, ATH10K_DBG_SNOC, + "Sending indication register message,\n"); + + memset(&req, 0, sizeof(req)); + memset(&resp, 0, sizeof(resp)); + + req.client_id_valid = 1; + req.client_id = WLFW_CLIENT_ID; + req.fw_ready_enable_valid = 1; + req.fw_ready_enable = 1; + req.msa_ready_enable_valid = 1; + req.msa_ready_enable = 1; + + req_desc.max_msg_len = WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN; + req_desc.msg_id = QMI_WLFW_IND_REGISTER_REQ_V01; + req_desc.ei_array = wlfw_ind_register_req_msg_v01_ei; + + resp_desc.max_msg_len = WLFW_IND_REGISTER_RESP_MSG_V01_MAX_MSG_LEN; + resp_desc.msg_id = QMI_WLFW_IND_REGISTER_RESP_V01; + resp_desc.ei_array = wlfw_ind_register_resp_msg_v01_ei; + + ret = qmi_send_req_wait(qmi_cfg->wlfw_clnt, + &req_desc, &req, sizeof(req), + &resp_desc, &resp, sizeof(resp), + WLFW_TIMEOUT_MS); + if (ret < 0) { + ath10k_err(ar, "Send indication register req failed %d\n", ret); + return ret; + } + + if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { + ath10k_err(ar, "QMI indication register request rejected:"); + ath10k_err(ar, "resut:%d error:%d\n", + resp.resp.result, resp.resp.error); + ret = resp.resp.result; + return ret; + } + + return 0; +} + +static void ath10k_snoc_qmi_wlfw_clnt_notify_work(struct work_struct *work) +{ + int ret; + struct ath10k_snoc_qmi_config *qmi_cfg = + container_of(work, struct ath10k_snoc_qmi_config, + qmi_recv_msg_work); + struct ath10k_snoc *ar_snoc = + container_of(qmi_cfg, struct ath10k_snoc, qmi_cfg); + struct ath10k *ar = ar_snoc->ar; + + ath10k_dbg(ar, ATH10K_DBG_SNOC, + "Receiving Event in work queue context\n"); + + do { + } while ((ret = qmi_recv_msg(qmi_cfg->wlfw_clnt)) == 0); + + if (ret != -ENOMSG) + ath10k_err(ar, "Error receiving message: %d\n", ret); + + ath10k_dbg(ar, ATH10K_DBG_SNOC, "Receiving Event completed\n"); +} + +static void +ath10k_snoc_qmi_wlfw_clnt_notify(struct qmi_handle *handle, + enum qmi_event_type event, + void *notify_priv) +{ + struct ath10k_snoc_qmi_config *qmi_cfg = + (struct ath10k_snoc_qmi_config *)notify_priv; + struct ath10k_snoc *ar_snoc = + container_of(qmi_cfg, struct ath10k_snoc, qmi_cfg); + struct ath10k *ar = ar_snoc->ar; + + ath10k_dbg(ar, ATH10K_DBG_SNOC, "QMI client notify: %d\n", event); + + if (!qmi_cfg || !qmi_cfg->wlfw_clnt) + return; + + switch (event) { + case QMI_RECV_MSG: + schedule_work(&qmi_cfg->qmi_recv_msg_work); + break; + default: + ath10k_dbg(ar, ATH10K_DBG_SNOC, "Unknown Event: %d\n", event); + break; + } +} + +static void +ath10k_snoc_qmi_wlfw_clnt_ind(struct qmi_handle *handle, + unsigned int msg_id, void *msg, + unsigned int msg_len, void *ind_cb_priv) +{ + struct ath10k_snoc_qmi_config *qmi_cfg = + (struct ath10k_snoc_qmi_config *)ind_cb_priv; + struct ath10k_snoc *ar_snoc = + container_of(qmi_cfg, struct ath10k_snoc, qmi_cfg); + struct ath10k *ar = ar_snoc->ar; + + ath10k_dbg(ar, ATH10K_DBG_SNOC, + "Received Ind 0x%x, msg_len: %d\n", msg_id, msg_len); + switch (msg_id) { + case QMI_WLFW_FW_READY_IND_V01: + ath10k_snoc_driver_event_post( + ATH10K_SNOC_DRIVER_EVENT_FW_READY_IND, 0, ar); + break; + case QMI_WLFW_MSA_READY_IND_V01: + qmi_cfg->msa_ready = true; + ath10k_dbg(ar, ATH10K_DBG_SNOC, + "Received MSA Ready, ind = 0x%x\n", msg_id); + break; + default: + ath10k_err(ar, "Invalid msg_id 0x%x\n", msg_id); + break; + } +} + +static int ath10k_snoc_driver_event_server_arrive(struct ath10k *ar) +{ + int ret = 0; + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + struct ath10k_snoc_qmi_config *qmi_cfg = &ar_snoc->qmi_cfg; + + if (!qmi_cfg) + return -ENODEV; + + qmi_cfg->wlfw_clnt = qmi_handle_create( + ath10k_snoc_qmi_wlfw_clnt_notify, qmi_cfg); + if (!qmi_cfg->wlfw_clnt) { + ath10k_dbg(ar, ATH10K_DBG_SNOC, + "QMI client handle create failed\n"); + return -ENOMEM; + } + + ret = qmi_connect_to_service(qmi_cfg->wlfw_clnt, + WLFW_SERVICE_ID_V01, + WLFW_SERVICE_VERS_V01, + WLFW_SERVICE_INS_ID_V01); + if (ret < 0) { + ath10k_err(ar, "QMI WLAN Service not found : %d\n", ret); + goto err_qmi_config; + } + + ret = qmi_register_ind_cb(qmi_cfg->wlfw_clnt, + ath10k_snoc_qmi_wlfw_clnt_ind, qmi_cfg); + if (ret < 0) { + ath10k_err(ar, "Failed to register indication callback: %d\n", + ret); + goto err_qmi_config; + } + + ret = ath10k_snoc_ind_register_send_sync_msg(ar); + if (ret) { + ath10k_err(ar, "Failed to config qmi ind register\n"); + goto err_qmi_config; + } + + ath10k_dbg(ar, ATH10K_DBG_SNOC, + "QMI Server Arrive Configuration Success\n"); + return 0; + +err_qmi_config: + qmi_handle_destroy(qmi_cfg->wlfw_clnt); + qmi_cfg->wlfw_clnt = NULL; + return ret; +} + +static int ath10k_snoc_driver_event_server_exit(struct ath10k *ar) +{ + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + + ath10k_dbg(ar, ATH10K_DBG_SNOC, "QMI Server Exit event received\n"); + ar_snoc->qmi_cfg.fw_ready = false; + ar_snoc->qmi_cfg.msa_ready = false; + + return 0; +} + +static int ath10k_snoc_driver_event_fw_ready_ind(struct ath10k *ar) +{ + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + + ath10k_dbg(ar, ATH10K_DBG_SNOC, "FW Ready event received.\n"); + ar_snoc->qmi_cfg.fw_ready = true; + wake_up_all(&ath10k_fw_ready_wait_event); + + return 0; +} + +static void ath10k_snoc_driver_event_work(struct work_struct *work) +{ + struct ath10k_snoc_qmi_driver_event *event; + int ret; + struct ath10k_snoc_qmi_config *qmi_cfg = + container_of(work, struct ath10k_snoc_qmi_config, event_work); + struct ath10k_snoc *ar_snoc = + container_of(qmi_cfg, struct ath10k_snoc, qmi_cfg); + struct ath10k *ar = ar_snoc->ar; + + spin_lock_bh(&qmi_cfg->event_lock); + + while (!list_empty(&qmi_cfg->event_list)) { + event = list_first_entry(&qmi_cfg->event_list, + struct ath10k_snoc_qmi_driver_event, + list); + list_del(&event->list); + spin_unlock_bh(&qmi_cfg->event_lock); + + ath10k_dbg(ar, ATH10K_DBG_SNOC, "Processing event: %s%s(%d)\n", + ath10k_snoc_driver_event_to_str(event->type), + event->sync ? "-sync" : "", event->type); + + switch (event->type) { + case ATH10K_SNOC_DRIVER_EVENT_SERVER_ARRIVE: + ret = ath10k_snoc_driver_event_server_arrive(ar); + break; + case ATH10K_SNOC_DRIVER_EVENT_SERVER_EXIT: + ret = ath10k_snoc_driver_event_server_exit(ar); + break; + case ATH10K_SNOC_DRIVER_EVENT_FW_READY_IND: + ret = ath10k_snoc_driver_event_fw_ready_ind(ar); + break; + default: + ath10k_err(ar, "Invalid Event type: %d", event->type); + kfree(event); + continue; + } + + atomic_set(&event->event_handled, 1); + ath10k_dbg(ar, ATH10K_DBG_SNOC, + "Event Processed: %s%s(%d), ret: %d\n", + ath10k_snoc_driver_event_to_str(event->type), + event->sync ? "-sync" : "", event->type, ret); + spin_lock_bh(&qmi_cfg->event_lock); + if (event->sync) { + event->ret = ret; + complete(&event->complete); + continue; + } + spin_unlock_bh(&qmi_cfg->event_lock); + spin_lock_bh(&qmi_cfg->event_lock); + } + + spin_unlock_bh(&qmi_cfg->event_lock); +} + +static int +ath10k_snoc_qmi_wlfw_clnt_svc_event_notify(struct notifier_block *this, + unsigned long code, + void *_cmd) +{ + int ret = 0; + struct ath10k_snoc_qmi_config *qmi_cfg = + container_of(this, struct ath10k_snoc_qmi_config, wlfw_clnt_nb); + struct ath10k_snoc *ar_snoc = + container_of(qmi_cfg, struct ath10k_snoc, qmi_cfg); + struct ath10k *ar = ar_snoc->ar; + + ath10k_dbg(ar, ATH10K_DBG_SNOC, "Event Notify: code: %ld", code); + + switch (code) { + case QMI_SERVER_ARRIVE: + ret = ath10k_snoc_driver_event_post( + ATH10K_SNOC_DRIVER_EVENT_SERVER_ARRIVE, 0, ar); + break; + case QMI_SERVER_EXIT: + ret = ath10k_snoc_driver_event_post( + ATH10K_SNOC_DRIVER_EVENT_SERVER_EXIT, 0, ar); + break; + default: + ath10k_err(ar, "Invalid code: %ld", code); + break; + } + + return ret; +} + +int ath10k_snoc_start_qmi_service(struct ath10k *ar) +{ + int ret; + int i; + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + struct ath10k_snoc_qmi_config *qmi_cfg = &ar_snoc->qmi_cfg; + + qmi_cfg->event_wq = alloc_workqueue("ath10k_snoc_driver_event", + WQ_UNBOUND, 1); + if (!qmi_cfg->event_wq) { + ath10k_err(ar, "Workqueue creation failed\n"); + return -EFAULT; + } + + spin_lock_init(&qmi_cfg->event_lock); + qmi_cfg->fw_ready = false; + + INIT_WORK(&qmi_cfg->event_work, ath10k_snoc_driver_event_work); + INIT_WORK(&qmi_cfg->qmi_recv_msg_work, + ath10k_snoc_qmi_wlfw_clnt_notify_work); + INIT_LIST_HEAD(&qmi_cfg->event_list); + + for (i = 0; i < ATH10K_SNOC_DRIVER_EVENT_MAX; i++) + atomic_set(&qmi_cfg->qmi_ev_list[i].event_handled, 1); + + qmi_cfg->wlfw_clnt_nb.notifier_call = + ath10k_snoc_qmi_wlfw_clnt_svc_event_notify; + ret = qmi_svc_event_notifier_register(WLFW_SERVICE_ID_V01, + WLFW_SERVICE_VERS_V01, + WLFW_SERVICE_INS_ID_V01, + &qmi_cfg->wlfw_clnt_nb); + if (ret < 0) { + ath10k_err(ar, "Notifier register failed: %d\n", ret); + ret = -EFAULT; + goto out_destroy_wq; + } + + ath10k_dbg(ar, ATH10K_DBG_SNOC, "QMI service started successfully\n"); + return 0; + +out_destroy_wq: + destroy_workqueue(qmi_cfg->event_wq); + return ret; +} + +void ath10k_snoc_stop_qmi_service(struct ath10k *ar) +{ + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + struct ath10k_snoc_qmi_config *qmi_cfg = &ar_snoc->qmi_cfg; + + ath10k_dbg(ar, ATH10K_DBG_SNOC, "Removing QMI service..\n"); + + qmi_svc_event_notifier_unregister(WLFW_SERVICE_ID_V01, + WLFW_SERVICE_VERS_V01, + WLFW_SERVICE_INS_ID_V01, + &qmi_cfg->wlfw_clnt_nb); + + wake_up_all(&ath10k_fw_ready_wait_event); + destroy_workqueue(qmi_cfg->event_wq); + qmi_cfg = NULL; +} diff --git a/drivers/net/wireless/ath/ath10k/qmi.h b/drivers/net/wireless/ath/ath10k/qmi.h index f8ba3288753b..9305847e9ec4 100644 --- a/drivers/net/wireless/ath/ath10k/qmi.h +++ b/drivers/net/wireless/ath/ath10k/qmi.h @@ -11,9 +11,139 @@ */ #ifndef _QMI_H_ #define _QMI_H_ + +#define ATH10K_SNOC_EVENT_PENDING 2989 +#define ATH10K_SNOC_EVENT_SYNC BIT(0) +#define ATH10K_SNOC_EVENT_UNINTERRUPTIBLE BIT(1) +#define ATH10K_SNOC_WLAN_FW_READY_TIMEOUT 6000 + +#define WLFW_SERVICE_INS_ID_V01 0 +#define WLFW_CLIENT_ID 0x4b4e454c +#define WLFW_TIMEOUT_MS 20000 + +enum ath10k_snoc_driver_event_type { + ATH10K_SNOC_DRIVER_EVENT_SERVER_ARRIVE, + ATH10K_SNOC_DRIVER_EVENT_SERVER_EXIT, + ATH10K_SNOC_DRIVER_EVENT_FW_READY_IND, + ATH10K_SNOC_DRIVER_EVENT_MAX, +}; + +/* enum ath10k_driver_mode: ath10k driver mode + * @ATH10K_MISSION: mission mode + * @ATH10K_FTM: ftm mode + * @ATH10K_EPPING: epping mode + * @ATH10K_OFF: off mode + */ +enum ath10k_driver_mode { + ATH10K_MISSION, + ATH10K_FTM, + ATH10K_EPPING, + ATH10K_OFF +}; + +/* struct ath10k_ce_tgt_pipe_cfg: target pipe configuration + * @pipe_num: pipe number + * @pipe_dir: pipe direction + * @nentries: entries in pipe + * @nbytes_max: pipe max size + * @flags: pipe flags + * @reserved: reserved + */ +struct ath10k_ce_tgt_pipe_cfg { + u32 pipe_num; + u32 pipe_dir; + u32 nentries; + u32 nbytes_max; + u32 flags; + u32 reserved; +}; + +/* struct ath10k_ce_svc_pipe_cfg: service pipe configuration + * @service_id: target version + * @pipe_dir: pipe direction + * @pipe_num: pipe number + */ +struct ath10k_ce_svc_pipe_cfg { + u32 service_id; + u32 pipe_dir; + u32 pipe_num; +}; + +/* struct ath10k_shadow_reg_cfg: shadow register configuration + * @ce_id: copy engine id + * @reg_offset: offset to copy engine + */ +struct ath10k_shadow_reg_cfg { + u16 ce_id; + u16 reg_offset; +}; + +/* struct ath10k_wlan_enable_cfg: wlan enable configuration + * @num_ce_tgt_cfg: no of ce target configuration + * @ce_tgt_cfg: target ce configuration + * @num_ce_svc_pipe_cfg: no of ce service configuration + * @ce_svc_cfg: ce service configuration + * @num_shadow_reg_cfg: no of shadow registers + * @shadow_reg_cfg: shadow register configuration + */ +struct ath10k_wlan_enable_cfg { + u32 num_ce_tgt_cfg; + struct ath10k_ce_tgt_pipe_cfg *ce_tgt_cfg; + u32 num_ce_svc_pipe_cfg; + struct ath10k_ce_svc_pipe_cfg *ce_svc_cfg; + u32 num_shadow_reg_cfg; + struct ath10k_shadow_reg_cfg *shadow_reg_cfg; +}; + +/* struct ath10k_snoc_qmi_driver_event: qmi driver event + * event_handled: event handled by event work handler + * sync: event synced + * ret: event received return value + * list: list to queue qmi event for process + * type: driver event type + * complete: completion for event handle complete + * data: encapsulate driver data for event handler callback + */ +struct ath10k_snoc_qmi_driver_event { + atomic_t event_handled; + bool sync; + int ret; + struct list_head list; + enum ath10k_snoc_driver_event_type type; + struct completion complete; + void *data; +}; + +/* struct ath10k_snoc_qmi_config: qmi service configuration + * fw_ready: wlan firmware ready for wlan operation + * msa_ready: wlan firmware msa memory ready for board data download + * event_work: QMI event work + * event_list: QMI event list + * qmi_recv_msg_work: QMI message receive work + * event_wq: QMI event work queue + * wlfw_clnt_nb: WLAN firmware indication callback + * wlfw_clnt: QMI notifier handler for wlan firmware + * qmi_ev_list: QMI event list + * event_lock: spinlock for qmi event work queue + */ +struct ath10k_snoc_qmi_config { + bool fw_ready; + bool msa_ready; + struct work_struct event_work; + struct list_head event_list; + struct work_struct qmi_recv_msg_work; + struct workqueue_struct *event_wq; + struct notifier_block wlfw_clnt_nb; + struct qmi_handle *wlfw_clnt; + struct ath10k_snoc_qmi_driver_event + qmi_ev_list[ATH10K_SNOC_DRIVER_EVENT_MAX]; + spinlock_t event_lock; /* spinlock for qmi event work queue */ +}; + int ath10k_snoc_pd_restart_enable(struct ath10k *ar); int ath10k_snoc_modem_ssr_register_notifier(struct ath10k *ar); int ath10k_snoc_modem_ssr_unregister_notifier(struct ath10k *ar); int ath10k_snoc_pdr_unregister_notifier(struct ath10k *ar); - +int ath10k_snoc_start_qmi_service(struct ath10k *ar); +void ath10k_snoc_stop_qmi_service(struct ath10k *ar); #endif diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index 89042dcf70a0..4358bc8abfd3 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -1245,6 +1245,12 @@ static int ath10k_snoc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ar); ar_snoc->ar = ar; + ret = ath10k_snoc_start_qmi_service(ar); + if (ret) { + ath10k_err(ar, "failed to start QMI service: %d\n", ret); + goto err_core_destroy; + } + spin_lock_init(&ar_snoc->opaque_ctx.ce_lock); ar_snoc->opaque_ctx.bus_ops = &ath10k_snoc_bus_ops; ath10k_snoc_resource_init(ar); @@ -1325,6 +1331,7 @@ static int ath10k_snoc_remove(struct platform_device *pdev) ath10k_snoc_free_irq(ar); ath10k_snoc_release_resource(ar); ath10k_snoc_free_pipes(ar); + ath10k_snoc_stop_qmi_service(ar); ath10k_core_destroy(ar); ath10k_dbg(ar, ATH10K_DBG_SNOC, "%s:WCN3990 removed\n", __func__); diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h index c62519b2a340..99ae157885bb 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.h +++ b/drivers/net/wireless/ath/ath10k/snoc.h @@ -16,6 +16,7 @@ #include "hw.h" #include "ce.h" #include "pci.h" +#include "qmi.h" #include <soc/qcom/service-locator.h> #define ATH10K_SNOC_RX_POST_RETRY_MS 50 #define CE_POLL_PIPE 4 @@ -143,60 +144,7 @@ struct ath10k_snoc { int total_domains; struct notifier_block get_service_nb; atomic_t fw_crashed; -}; - -/* struct ath10k_ce_tgt_pipe_cfg: target pipe configuration - * @pipe_num: pipe number - * @pipe_dir: pipe direction - * @nentries: entries in pipe - * @nbytes_max: pipe max size - * @flags: pipe flags - * @reserved: reserved - */ -struct ath10k_ce_tgt_pipe_cfg { - u32 pipe_num; - u32 pipe_dir; - u32 nentries; - u32 nbytes_max; - u32 flags; - u32 reserved; -}; - -/* struct ath10k_ce_svc_pipe_cfg: service pipe configuration - * @service_id: target version - * @pipe_dir: pipe direction - * @pipe_num: pipe number - */ -struct ath10k_ce_svc_pipe_cfg { - u32 service_id; - u32 pipe_dir; - u32 pipe_num; -}; - -/* struct ath10k_shadow_reg_cfg: shadow register configuration - * @ce_id: copy engine id - * @reg_offset: offset to copy engine - */ -struct ath10k_shadow_reg_cfg { - u16 ce_id; - u16 reg_offset; -}; - -/* struct ath10k_wlan_enable_cfg: wlan enable configuration - * @num_ce_tgt_cfg: no of ce target configuration - * @ce_tgt_cfg: target ce configuration - * @num_ce_svc_pipe_cfg: no of ce service configuration - * @ce_svc_cfg: ce service configuration - * @num_shadow_reg_cfg: no of shadow registers - * @shadow_reg_cfg: shadow register configuration - */ -struct ath10k_wlan_enable_cfg { - u32 num_ce_tgt_cfg; - struct ath10k_ce_tgt_pipe_cfg *ce_tgt_cfg; - u32 num_ce_svc_pipe_cfg; - struct ath10k_ce_svc_pipe_cfg *ce_svc_cfg; - u32 num_shadow_reg_cfg; - struct ath10k_shadow_reg_cfg *shadow_reg_cfg; + struct ath10k_snoc_qmi_config qmi_cfg; }; struct ath10k_event_pd_down_data { @@ -204,19 +152,6 @@ struct ath10k_event_pd_down_data { bool fw_rejuvenate; }; -/* enum ath10k_driver_mode: ath10k driver mode - * @ATH10K_MISSION: mission mode - * @ATH10K_FTM: ftm mode - * @ATH10K_EPPING: epping mode - * @ATH10K_OFF: off mode - */ -enum ath10k_driver_mode { - ATH10K_MISSION, - ATH10K_FTM, - ATH10K_EPPING, - ATH10K_OFF -}; - static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar) { return (struct ath10k_snoc *)ar->drv_priv; |
