ath6kl: Add wmi functions to configure WOW mode and host sleep mode
authorRaja Mani <rmani@qca.qualcomm.com>
Mon, 7 Nov 2011 20:52:45 +0000 (22:52 +0200)
committerKalle Valo <kvalo@qca.qualcomm.com>
Fri, 11 Nov 2011 10:59:59 +0000 (12:59 +0200)
It will be used in WOW suspend/resume functions to
active/deactivate WOW suspend mode.

Signed-off-by: Raja Mani <rmani@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/ath/ath6kl/wmi.h

index 925ef4c9bec98a852cc9cb65953ad01edd075f73..3da1fb502bf54c2ec0c32c7bc19cc829e3e7544c 100644 (file)
@@ -2412,6 +2412,114 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd)
        return ret;
 }
 
+static void ath6kl_wmi_relinquish_implicit_pstream_credits(struct wmi *wmi)
+{
+       u16 active_tsids;
+       u8 stream_exist;
+       int i;
+
+       /*
+        * Relinquish credits from all implicitly created pstreams
+        * since when we go to sleep. If user created explicit
+        * thinstreams exists with in a fatpipe leave them intact
+        * for the user to delete.
+        */
+       spin_lock_bh(&wmi->lock);
+       stream_exist = wmi->fat_pipe_exist;
+       spin_unlock_bh(&wmi->lock);
+
+       for (i = 0; i < WMM_NUM_AC; i++) {
+               if (stream_exist & (1 << i)) {
+
+                       /*
+                        * FIXME: Is this lock & unlock inside
+                        * for loop correct? may need rework.
+                        */
+                       spin_lock_bh(&wmi->lock);
+                       active_tsids = wmi->stream_exist_for_ac[i];
+                       spin_unlock_bh(&wmi->lock);
+
+                       /*
+                        * If there are no user created thin streams
+                        * delete the fatpipe
+                        */
+                       if (!active_tsids) {
+                               stream_exist &= ~(1 << i);
+                               /*
+                                * Indicate inactivity to driver layer for
+                                * this fatpipe (pstream)
+                                */
+                               ath6kl_indicate_tx_activity(wmi->parent_dev,
+                                                           i, false);
+                       }
+               }
+       }
+
+       /* FIXME: Can we do this assignment without locking ? */
+       spin_lock_bh(&wmi->lock);
+       wmi->fat_pipe_exist = stream_exist;
+       spin_unlock_bh(&wmi->lock);
+}
+
+int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
+                                      enum ath6kl_host_mode host_mode)
+{
+       struct sk_buff *skb;
+       struct wmi_set_host_sleep_mode_cmd *cmd;
+       int ret;
+
+       if ((host_mode != ATH6KL_HOST_MODE_ASLEEP) &&
+           (host_mode != ATH6KL_HOST_MODE_AWAKE)) {
+               ath6kl_err("invalid host sleep mode: %d\n", host_mode);
+               return -EINVAL;
+       }
+
+       skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+       if (!skb)
+               return -ENOMEM;
+
+       cmd = (struct wmi_set_host_sleep_mode_cmd *) skb->data;
+
+       if (host_mode == ATH6KL_HOST_MODE_ASLEEP) {
+               ath6kl_wmi_relinquish_implicit_pstream_credits(wmi);
+               cmd->asleep = cpu_to_le32(1);
+       } else
+               cmd->awake = cpu_to_le32(1);
+
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
+                                 WMI_SET_HOST_SLEEP_MODE_CMDID,
+                                 NO_SYNC_WMIFLAG);
+       return ret;
+}
+
+int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
+                               enum ath6kl_wow_mode wow_mode,
+                               u32 filter, u16 host_req_delay)
+{
+       struct sk_buff *skb;
+       struct wmi_set_wow_mode_cmd *cmd;
+       int ret;
+
+       if ((wow_mode != ATH6KL_WOW_MODE_ENABLE) &&
+            wow_mode != ATH6KL_WOW_MODE_DISABLE) {
+               ath6kl_err("invalid wow mode: %d\n", wow_mode);
+               return -EINVAL;
+       }
+
+       skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+       if (!skb)
+               return -ENOMEM;
+
+       cmd = (struct wmi_set_wow_mode_cmd *) skb->data;
+       cmd->enable_wow = cpu_to_le32(wow_mode);
+       cmd->filter = cpu_to_le32(filter);
+       cmd->host_req_delay = cpu_to_le16(host_req_delay);
+
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_WOW_MODE_CMDID,
+                                 NO_SYNC_WMIFLAG);
+       return ret;
+}
+
 int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
                                   u8 list_id, u8 filter_size,
                                   u8 filter_offset, u8 *filter, u8 *mask)
index df42e4be876ad217b748921fdec6a34b7cbd24cb..a65eee20d18a9fb717ba8159a12c181aeca8aa3a 100644 (file)
@@ -1818,6 +1818,42 @@ struct wmi_set_ip_cmd {
        __le32 ips[MAX_IP_ADDRS];
 } __packed;
 
+enum ath6kl_wow_filters {
+       WOW_FILTER_SSID                 = BIT(0),
+       WOW_FILTER_OPTION_MAGIC_PACKET  = BIT(2),
+       WOW_FILTER_OPTION_EAP_REQ       = BIT(3),
+       WOW_FILTER_OPTION_PATTERNS      = BIT(4),
+       WOW_FILTER_OPTION_OFFLOAD_ARP   = BIT(5),
+       WOW_FILTER_OPTION_OFFLOAD_NS    = BIT(6),
+       WOW_FILTER_OPTION_OFFLOAD_GTK   = BIT(7),
+       WOW_FILTER_OPTION_8021X_4WAYHS  = BIT(8),
+       WOW_FILTER_OPTION_NLO_DISCVRY   = BIT(9),
+       WOW_FILTER_OPTION_NWK_DISASSOC  = BIT(10),
+       WOW_FILTER_OPTION_GTK_ERROR     = BIT(11),
+       WOW_FILTER_OPTION_TEST_MODE     = BIT(15),
+};
+
+enum ath6kl_host_mode {
+       ATH6KL_HOST_MODE_AWAKE,
+       ATH6KL_HOST_MODE_ASLEEP,
+};
+
+struct wmi_set_host_sleep_mode_cmd {
+       __le32 awake;
+       __le32 asleep;
+} __packed;
+
+enum ath6kl_wow_mode {
+       ATH6KL_WOW_MODE_DISABLE,
+       ATH6KL_WOW_MODE_ENABLE,
+};
+
+struct wmi_set_wow_mode_cmd {
+       __le32 enable_wow;
+       __le32 filter;
+       __le16 host_req_delay;
+} __packed;
+
 struct wmi_add_wow_pattern_cmd {
        u8 filter_list_id;
        u8 filter_size;
@@ -2285,6 +2321,11 @@ int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len);
 s32 ath6kl_wmi_get_rate(s8 rate_index);
 
 int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd);
+int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
+                                      enum ath6kl_host_mode host_mode);
+int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
+                               enum ath6kl_wow_mode wow_mode,
+                               u32 filter, u16 host_req_delay);
 int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
                                   u8 list_id, u8 filter_size,
                                   u8 filter_offset, u8 *filter, u8 *mask);