ath10k: add wmi command barrier utility
authorMichal Kazior <michal.kazior@tieto.com>
Fri, 19 Aug 2016 10:37:42 +0000 (13:37 +0300)
committerKalle Valo <kvalo@qca.qualcomm.com>
Wed, 31 Aug 2016 07:27:35 +0000 (10:27 +0300)
This allows placing command barriers for explicit
serializing and synchronizing state.

Useful for future driver development.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/wmi.c
drivers/net/wireless/ath/ath10k/wmi.h

index cc6e66fdf49811faf5d2214f27a95974c269ff5e..56daeb7926f9bddc28ab237f2e610a66e7036610 100644 (file)
@@ -142,6 +142,7 @@ struct ath10k_wmi {
        enum ath10k_htc_ep_id eid;
        struct completion service_ready;
        struct completion unified_ready;
+       struct completion barrier;
        wait_queue_head_t tx_credits_wq;
        DECLARE_BITMAP(svc_map, WMI_SERVICE_MAX);
        struct wmi_cmd_map *cmd;
index b802ca9c0edf59864842820c791b0fbd18629373..ae5f541ec966974137fd382caeab842989d1aa72 100644 (file)
@@ -29,6 +29,9 @@
 #include "p2p.h"
 #include "hw.h"
 
+#define ATH10K_WMI_BARRIER_ECHO_ID 0xBA991E9
+#define ATH10K_WMI_BARRIER_TIMEOUT_HZ (3 * HZ)
+
 /* MAIN WMI cmd track */
 static struct wmi_cmd_map wmi_cmd_map = {
        .init_cmdid = WMI_INIT_CMDID,
@@ -2507,6 +2510,9 @@ void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb)
        ath10k_dbg(ar, ATH10K_DBG_WMI,
                   "wmi event echo value 0x%08x\n",
                   le32_to_cpu(arg.value));
+
+       if (le32_to_cpu(arg.value) == ATH10K_WMI_BARRIER_ECHO_ID)
+               complete(&ar->wmi.barrier);
 }
 
 int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb)
@@ -7715,6 +7721,30 @@ ath10k_wmi_op_gen_echo(struct ath10k *ar, u32 value)
        return skb;
 }
 
+int
+ath10k_wmi_barrier(struct ath10k *ar)
+{
+       int ret;
+       int time_left;
+
+       spin_lock_bh(&ar->data_lock);
+       reinit_completion(&ar->wmi.barrier);
+       spin_unlock_bh(&ar->data_lock);
+
+       ret = ath10k_wmi_echo(ar, ATH10K_WMI_BARRIER_ECHO_ID);
+       if (ret) {
+               ath10k_warn(ar, "failed to submit wmi echo: %d\n", ret);
+               return ret;
+       }
+
+       time_left = wait_for_completion_timeout(&ar->wmi.barrier,
+                                               ATH10K_WMI_BARRIER_TIMEOUT_HZ);
+       if (!time_left)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
 static const struct wmi_ops wmi_ops = {
        .rx = ath10k_wmi_op_rx,
        .map_svc = wmi_main_svc_map,
@@ -8112,6 +8142,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
 
        init_completion(&ar->wmi.service_ready);
        init_completion(&ar->wmi.unified_ready);
+       init_completion(&ar->wmi.barrier);
 
        INIT_WORK(&ar->svc_rdy_work, ath10k_wmi_event_service_ready_work);
 
index 086d78807d2f953067ee616b9b2b93ff8f9caaff..89adfa90ee8dfc8cd021b5a7689511a6735fcc76 100644 (file)
@@ -6628,5 +6628,6 @@ void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
                                      char *buf);
 int ath10k_wmi_op_get_vdev_subtype(struct ath10k *ar,
                                   enum wmi_vdev_subtype subtype);
+int ath10k_wmi_barrier(struct ath10k *ar);
 
 #endif /* _WMI_H_ */