|
@@ -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 */
|