iwlwifi: mvm: Change the settings of AP beacon time
authorIlan Peer <ilan.peer@intel.com>
Thu, 13 Jun 2013 05:30:12 +0000 (08:30 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 25 Jun 2013 10:13:36 +0000 (12:13 +0200)
In case that an AP/GO interface is started while there is a
station/P2P client associated, need to make sure that the AP/GO
beacon time is far enough from the station's one in oder to allow
the station to receive the DTIM beacons and the following traffic
etc.

To resolve this, when the AP is started, check if there is an
active station interface, and guarantee that the AP/GO TBTT is far
enough from the station one.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c

index 273b0cc197ab4e2e7e8af2ea2b65d6baffcdb8a9..94aae9c8562c41fadd4069c20d7ae3cbe8eb2683 100644 (file)
@@ -865,6 +865,30 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
        return ret;
 }
 
+struct iwl_mvm_mac_ap_iterator_data {
+       struct iwl_mvm *mvm;
+       struct ieee80211_vif *vif;
+       u32 beacon_device_ts;
+       u16 beacon_int;
+};
+
+/* Find the beacon_device_ts and beacon_int for a managed interface */
+static void iwl_mvm_mac_ap_iterator(void *_data, u8 *mac,
+                                   struct ieee80211_vif *vif)
+{
+       struct iwl_mvm_mac_ap_iterator_data *data = _data;
+
+       if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc)
+               return;
+
+       /* Station client has higher priority over P2P client*/
+       if (vif->p2p && data->beacon_device_ts)
+               return;
+
+       data->beacon_device_ts = vif->bss_conf.sync_device_ts;
+       data->beacon_int = vif->bss_conf.beacon_int;
+}
+
 /*
  * Fill the specific data for mac context of type AP of P2P GO
  */
@@ -874,6 +898,11 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
                                         bool add)
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       struct iwl_mvm_mac_ap_iterator_data data = {
+               .mvm = mvm,
+               .vif = vif,
+               .beacon_device_ts = 0
+       };
 
        ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int);
        ctxt_ap->bi_reciprocal =
@@ -887,16 +916,33 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
        ctxt_ap->mcast_qid = cpu_to_le32(vif->cab_queue);
 
        /*
-        * Only read the system time when the MAC is being added, when we
+        * Only set the beacon time when the MAC is being added, when we
         * just modify the MAC then we should keep the time -- the firmware
         * can otherwise have a "jumping" TBTT.
         */
-       if (add)
-               mvmvif->ap_beacon_time =
-                       iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG);
+       if (add) {
+               /*
+                * If there is a station/P2P client interface which is
+                * associated, set the AP's TBTT far enough from the station's
+                * TBTT. Otherwise, set it to the current system time
+                */
+               ieee80211_iterate_active_interfaces_atomic(
+                       mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+                       iwl_mvm_mac_ap_iterator, &data);
+
+               if (data.beacon_device_ts) {
+                       u32 rand = (prandom_u32() % (80 - 20)) + 20;
+                       mvmvif->ap_beacon_time = data.beacon_device_ts +
+                               ieee80211_tu_to_usec(data.beacon_int * rand /
+                                                    100);
+               } else {
+                       mvmvif->ap_beacon_time =
+                               iwl_read_prph(mvm->trans,
+                                             DEVICE_SYSTEM_TIME_REG);
+               }
+       }
 
        ctxt_ap->beacon_time = cpu_to_le32(mvmvif->ap_beacon_time);
-
        ctxt_ap->beacon_tsf = 0; /* unused */
 
        /* TODO: Assume that the beacon id == mac context id */