ath6kl: Set optimal listen intvl,bmiss,scan params while going to wow suspend
authorRaja Mani <rmani@qca.qualcomm.com>
Mon, 20 Feb 2012 13:38:08 +0000 (19:08 +0530)
committerKalle Valo <kvalo@qca.qualcomm.com>
Wed, 7 Mar 2012 07:49:47 +0000 (09:49 +0200)
* In order to save the target power in WOW suspend state,
  configure the best optimal values for the below parameters,
     - listen interval.
     - beacon miss interval.
     - scan parameters.

  Default values for above attributes are reverted in
  wow resume operation.

* The default listen interval is set before the host issue
  connect request.

* New function is added to configure beacon miss count.

kvalo: minor changes to fix open parenthesis alignment

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

index 8d6bb323bb74f32a480a7c2074fc4f399ebe7b51..baa3895b16434da24e2688770bd8df7f3854454c 100644 (file)
@@ -423,6 +423,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
        struct ath6kl_vif *vif = netdev_priv(dev);
        int status;
        u8 nw_subtype = (ar->p2p) ? SUBTYPE_P2PDEV : SUBTYPE_NONE;
+       u16 interval;
 
        ath6kl_cfg80211_sscan_disable(vif);
 
@@ -577,6 +578,20 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                   vif->grp_crypto_len, vif->ch_hint);
 
        vif->reconnect_flag = 0;
+
+       if (vif->nw_type == INFRA_NETWORK) {
+               interval = max(vif->listen_intvl_t,
+                              (u16) ATH6KL_MAX_WOW_LISTEN_INTL);
+               status = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
+                                                      interval,
+                                                      0);
+               if (status) {
+                       ath6kl_err("couldn't set listen intervel\n");
+                       up(&ar->sem);
+                       return status;
+               }
+       }
+
        status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type,
                                        vif->dot11_auth_mode, vif->auth_mode,
                                        vif->prwise_crypto,
@@ -1911,7 +1926,7 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
        struct ath6kl_vif *vif;
        int ret, left;
        u32 filter = 0;
-       u16 i;
+       u16 i, bmiss_time;
        u8 index = 0;
        __be32 ips[MAX_IP_ADDRS];
 
@@ -1950,6 +1965,30 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
 
        netif_stop_queue(vif->ndev);
 
+       if (vif->nw_type != AP_NETWORK) {
+               ret = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
+                                                   ATH6KL_MAX_WOW_LISTEN_INTL,
+                                                   0);
+               if (ret)
+                       return ret;
+
+               /* Set listen interval x 15 times as bmiss time */
+               bmiss_time = ATH6KL_MAX_WOW_LISTEN_INTL * 15;
+               if (bmiss_time > ATH6KL_MAX_BMISS_TIME)
+                       bmiss_time = ATH6KL_MAX_BMISS_TIME;
+
+               ret = ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
+                                              bmiss_time, 0);
+               if (ret)
+                       return ret;
+
+               ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
+                                               0xFFFF, 0, 0xFFFF, 0, 0, 0,
+                                               0, 0, 0, 0);
+               if (ret)
+                       return ret;
+       }
+
        ar->state = ATH6KL_STATE_SUSPENDING;
 
        /* Setup own IP addr for ARP agent. */
@@ -2041,6 +2080,23 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
                return ret;
        }
 
+       if (vif->nw_type != AP_NETWORK) {
+               ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
+                                               0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
+               if (ret)
+                       return ret;
+
+               ret = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
+                                                   vif->listen_intvl_t, 0);
+               if (ret)
+                       return ret;
+
+               ret = ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
+                                              vif->bmiss_time_t, 0);
+               if (ret)
+                       return ret;
+       }
+
        ar->state = ATH6KL_STATE_ON;
 
        netif_wake_queue(vif->ndev);
@@ -3034,6 +3090,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
        vif->fw_vif_idx = fw_vif_idx;
        vif->nw_type = vif->next_mode = nw_type;
        vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
+       vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
 
        memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
        if (fw_vif_idx != 0)
index 727267eb83138499a47f41d58fb24383bcb734ce..01763cd243b49ad533842eaa354155f44566c272 100644 (file)
@@ -186,6 +186,9 @@ struct ath6kl_fw_ie {
 #define MBOX_YIELD_LIMIT 99
 
 #define ATH6KL_DEFAULT_LISTEN_INTVAL   100 /* in TUs */
+#define ATH6KL_DEFAULT_BMISS_TIME      1500
+#define ATH6KL_MAX_WOW_LISTEN_INTL     300 /* in TUs */
+#define ATH6KL_MAX_BMISS_TIME          5000
 
 /* configuration lags */
 /*
@@ -511,6 +514,7 @@ struct ath6kl_vif {
        u16 next_chan;
        u16 assoc_bss_beacon_int;
        u16 listen_intvl_t;
+       u16 bmiss_time_t;
        u8 assoc_bss_dtim_period;
        struct net_device_stats net_stats;
        struct target_stats target_stats;
index 0a57dcc6041a7e3464cb0fe27ec76dd6695c48d1..573cb26077a9ae3c286a1f2a1781ed806e8e1af7 100644 (file)
@@ -2027,6 +2027,26 @@ int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u8 if_idx,
        return ret;
 }
 
+int ath6kl_wmi_bmisstime_cmd(struct wmi *wmi, u8 if_idx,
+                            u16 bmiss_time, u16 num_beacons)
+{
+       struct sk_buff *skb;
+       struct wmi_bmiss_time_cmd *cmd;
+       int ret;
+
+       skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+       if (!skb)
+               return -ENOMEM;
+
+       cmd = (struct wmi_bmiss_time_cmd *) skb->data;
+       cmd->bmiss_time = cpu_to_le16(bmiss_time);
+       cmd->num_beacons = cpu_to_le16(num_beacons);
+
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_BMISS_TIME_CMDID,
+                                 NO_SYNC_WMIFLAG);
+       return ret;
+}
+
 int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 if_idx, u8 pwr_mode)
 {
        struct sk_buff *skb;
index cea7429a8a0b2c13b42b12582f1cee3eee71b7c1..892a7a0a1378c75a59d5b0175f921ddbf869f80a 100644 (file)
@@ -998,6 +998,12 @@ struct wmi_listen_int_cmd {
        __le16 num_beacons;
 } __packed;
 
+/* WMI_SET_BMISS_TIME_CMDID */
+struct wmi_bmiss_time_cmd {
+       __le16 bmiss_time;
+       __le16 num_beacons;
+};
+
 /* WMI_SET_POWER_MODE_CMDID */
 enum wmi_power_mode {
        REC_POWER = 0x01,
@@ -2418,6 +2424,8 @@ int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag,
 int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u8 if_idx,
                                  u16 listen_interval,
                                  u16 listen_beacons);
+int ath6kl_wmi_bmisstime_cmd(struct wmi *wmi, u8 if_idx,
+                            u16 bmiss_time, u16 num_beacons);
 int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 if_idx, u8 pwr_mode);
 int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u8 if_idx, u16 idle_period,
                            u16 ps_poll_num, u16 dtim_policy,