aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-05-03 05:16:15 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-10-02 12:00:34 -0400
commit016d27e13b08416988fa06013f66e94fa195244a (patch)
tree3b7c7590c731212641665b9567ffec5b21fbd5c2 /drivers/net/wireless/iwlwifi
parent4837b448dfa90d76bc3a73e12425ce85f0186865 (diff)
iwlwifi: mvm: give client MACs time to synchronise during restart
When firmware restart happens, the timers are obviously reset and the new firmware has no synchronisation with the AP as we program timings to the pre-restart values. The firmware should attempt to synchronise by itself, but in multi-channel scenarios this isn't easy, particularly since it has to try to keep service quality up for other MACs. To make it more reliable, give each client MAC some time to catch beacons when restarting or resuming. Service quality was impacted anyway (or in resume doesn't really matter much.) Reviewed-by: Moshe Island <moshe.island@intel.com> Reviewed-by: Ilan Peer <ilan.peer@intel.com> Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c23
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.c5
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.h4
3 files changed, 28 insertions, 4 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 3261730181fa..77166520bc01 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -803,6 +803,27 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
803 return; 803 return;
804 } 804 }
805 iwl_mvm_configure_mcast_filter(mvm, vif); 805 iwl_mvm_configure_mcast_filter(mvm, vif);
806
807 if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
808 &mvm->status)) {
809 /*
810 * If we're restarting then the firmware will
811 * obviously have lost synchronisation with
812 * the AP. It will attempt to synchronise by
813 * itself, but we can make it more reliable by
814 * scheduling a session protection time event.
815 *
816 * The firmware needs to receive a beacon to
817 * catch up with synchronisation, use 110% of
818 * the beacon interval.
819 *
820 * Set a large maximum delay to allow for more
821 * than a single interface.
822 */
823 u32 dur = (11 * vif->bss_conf.beacon_int) / 10;
824 iwl_mvm_protect_session(mvm, vif, dur, dur,
825 5 * dur);
826 }
806 } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { 827 } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
807 /* remove AP station now that the MAC is unassoc */ 828 /* remove AP station now that the MAC is unassoc */
808 ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id); 829 ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id);
@@ -1170,7 +1191,7 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
1170 1191
1171 mutex_lock(&mvm->mutex); 1192 mutex_lock(&mvm->mutex);
1172 /* Try really hard to protect the session and hear a beacon */ 1193 /* Try really hard to protect the session and hear a beacon */
1173 iwl_mvm_protect_session(mvm, vif, duration, min_duration); 1194 iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500);
1174 mutex_unlock(&mvm->mutex); 1195 mutex_unlock(&mvm->mutex);
1175} 1196}
1176 1197
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index 76a3c177e100..33cf56fdfc41 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -387,7 +387,8 @@ static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm,
387 387
388void iwl_mvm_protect_session(struct iwl_mvm *mvm, 388void iwl_mvm_protect_session(struct iwl_mvm *mvm,
389 struct ieee80211_vif *vif, 389 struct ieee80211_vif *vif,
390 u32 duration, u32 min_duration) 390 u32 duration, u32 min_duration,
391 u32 max_delay)
391{ 392{
392 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 393 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
393 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; 394 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
@@ -426,7 +427,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
426 cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG)); 427 cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG));
427 428
428 time_cmd.max_frags = TE_V2_FRAG_NONE; 429 time_cmd.max_frags = TE_V2_FRAG_NONE;
429 time_cmd.max_delay = cpu_to_le32(500); 430 time_cmd.max_delay = cpu_to_le32(max_delay);
430 /* TODO: why do we need to interval = bi if it is not periodic? */ 431 /* TODO: why do we need to interval = bi if it is not periodic? */
431 time_cmd.interval = cpu_to_le32(1); 432 time_cmd.interval = cpu_to_le32(1);
432 time_cmd.duration = cpu_to_le32(duration); 433 time_cmd.duration = cpu_to_le32(duration);
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.h b/drivers/net/wireless/iwlwifi/mvm/time-event.h
index f86c51065ed3..d9c8d6cfa2db 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.h
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.h
@@ -123,6 +123,7 @@
123 * @duration: the duration of the session in TU. 123 * @duration: the duration of the session in TU.
124 * @min_duration: will start a new session if the current session will end 124 * @min_duration: will start a new session if the current session will end
125 * in less than min_duration. 125 * in less than min_duration.
126 * @max_delay: maximum delay before starting the time event (in TU)
126 * 127 *
127 * This function can be used to start a session protection which means that the 128 * This function can be used to start a session protection which means that the
128 * fw will stay on the channel for %duration_ms milliseconds. This function 129 * fw will stay on the channel for %duration_ms milliseconds. This function
@@ -133,7 +134,8 @@
133 */ 134 */
134void iwl_mvm_protect_session(struct iwl_mvm *mvm, 135void iwl_mvm_protect_session(struct iwl_mvm *mvm,
135 struct ieee80211_vif *vif, 136 struct ieee80211_vif *vif,
136 u32 duration, u32 min_duration); 137 u32 duration, u32 min_duration,
138 u32 max_delay);
137 139
138/** 140/**
139 * iwl_mvm_stop_session_protection - cancel the session protection. 141 * iwl_mvm_stop_session_protection - cancel the session protection.