iwlwifi: mvm: modify the tsf_id master/slave logic

For TSF master/slave synchronization, the FW does not require
exact match in the beacon interval between the master interface
and the slave one, but instead requires that the beacon interval
of one interface is the module of the other.

Modify the tsf_id selection to align with the above.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
This commit is contained in:
Ilan Peer 2014-02-02 21:54:35 +02:00 committed by Emmanuel Grumbach
parent b92e661b40
commit 2c3e62a148
1 changed files with 46 additions and 30 deletions

View File

@ -90,6 +90,7 @@ static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
{ {
struct iwl_mvm_mac_iface_iterator_data *data = _data; struct iwl_mvm_mac_iface_iterator_data *data = _data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u16 min_bi;
/* Skip the interface for which we are trying to assign a tsf_id */ /* Skip the interface for which we are trying to assign a tsf_id */
if (vif == data->vif) if (vif == data->vif)
@ -114,42 +115,57 @@ static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
switch (data->vif->type) { switch (data->vif->type) {
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
/* /*
* The new interface is client, so if the existing one * The new interface is a client, so if the one we're iterating
* we're iterating is an AP, and both interfaces have the * is an AP, and the beacon interval of the AP is a multiple or
* same beacon interval, the same TSF should be used to * divisor of the beacon interval of the client, the same TSF
* avoid drift between the new client and existing AP, * should be used to avoid drift between the new client and
* the existing AP will get drift updates from the new * existing AP. The existing AP will get drift updates from the
* client context in this case * new client context in this case.
*/ */
if (vif->type == NL80211_IFTYPE_AP) { if (vif->type != NL80211_IFTYPE_AP ||
if (data->preferred_tsf == NUM_TSF_IDS && data->preferred_tsf != NUM_TSF_IDS ||
test_bit(mvmvif->tsf_id, data->available_tsf_ids) && !test_bit(mvmvif->tsf_id, data->available_tsf_ids))
(vif->bss_conf.beacon_int == break;
data->vif->bss_conf.beacon_int)) {
data->preferred_tsf = mvmvif->tsf_id; min_bi = min(data->vif->bss_conf.beacon_int,
return; vif->bss_conf.beacon_int);
}
if (!min_bi)
break;
if ((data->vif->bss_conf.beacon_int -
vif->bss_conf.beacon_int) % min_bi == 0) {
data->preferred_tsf = mvmvif->tsf_id;
return;
} }
break; break;
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
/* /*
* The new interface is AP/GO, so in case both interfaces * The new interface is AP/GO, so if its beacon interval is a
* have the same beacon interval, it should get drift * multiple or a divisor of the beacon interval of an existing
* updates from an existing client or use the same * interface, it should get drift updates from an existing
* TSF as an existing GO. There's no drift between * client or use the same TSF as an existing GO. There's no
* TSFs internally but if they used different TSFs * drift between TSFs internally but if they used different
* then a new client MAC could update one of them * TSFs then a new client MAC could update one of them and
* and cause drift that way. * cause drift that way.
*/ */
if (vif->type == NL80211_IFTYPE_STATION || if ((vif->type != NL80211_IFTYPE_AP &&
vif->type == NL80211_IFTYPE_AP) { vif->type != NL80211_IFTYPE_STATION) ||
if (data->preferred_tsf == NUM_TSF_IDS && data->preferred_tsf != NUM_TSF_IDS ||
test_bit(mvmvif->tsf_id, data->available_tsf_ids) && !test_bit(mvmvif->tsf_id, data->available_tsf_ids))
(vif->bss_conf.beacon_int == break;
data->vif->bss_conf.beacon_int)) {
data->preferred_tsf = mvmvif->tsf_id; min_bi = min(data->vif->bss_conf.beacon_int,
return; vif->bss_conf.beacon_int);
}
if (!min_bi)
break;
if ((data->vif->bss_conf.beacon_int -
vif->bss_conf.beacon_int) % min_bi == 0) {
data->preferred_tsf = mvmvif->tsf_id;
return;
} }
break; break;
default: default: