diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/time-event.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/time-event.h | 4 |
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 | ||
388 | void iwl_mvm_protect_session(struct iwl_mvm *mvm, | 388 | void 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 | */ |
134 | void iwl_mvm_protect_session(struct iwl_mvm *mvm, | 135 | void 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. |