iwlwifi: mvm: remove session protection to allow channel switch
authorAvraham Stern <avraham.stern@intel.com>
Wed, 2 Aug 2017 09:13:20 +0000 (12:13 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Fri, 18 Aug 2017 13:10:43 +0000 (16:10 +0300)
If a time event is already scheduled when trying to schedule one for
channel switch, the code assumes the channel switch is already
scheduled and no further action is required.
However, it is possible that the scheduled time event is actually
for session protection (e.g. when the first beacon after association
contains the CSA IE). In this case the channel switch will not be
scheduled which will finally lead to disconnection.

Fix this by removing the old time event and schduling a new one for
the channel switch.

Signed-off-by: Avraham Stern <avraham.stern@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/time-event.c

index 2d1404c9fbf4de1bf6813f0eab537e0c2963a04b..01143c491e53f07562d88ac6c2309b216df19f98 100644 (file)
@@ -2023,8 +2023,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
                 * We received a beacon from the associated AP so
                 * remove the session protection.
                 */
-               iwl_mvm_remove_time_event(mvm, mvmvif,
-                                         &mvmvif->time_event_data);
+               iwl_mvm_stop_session_protection(mvm, vif);
 
                iwl_mvm_sf_update(mvm, vif, false);
                WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
index 65d8299108d579c7d41141d022b2440fa4cce052..4d0314912e94794b7728af17707618cd72ad2908 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2017 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -33,6 +34,7 @@
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2017 Intel Deutschland GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -726,8 +728,21 @@ void iwl_mvm_stop_session_protection(struct iwl_mvm *mvm,
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
+       u32 id;
 
        lockdep_assert_held(&mvm->mutex);
+
+       spin_lock_bh(&mvm->time_event_lock);
+       id = te_data->id;
+       spin_unlock_bh(&mvm->time_event_lock);
+
+       if (id != TE_BSS_STA_AGGRESSIVE_ASSOC) {
+               IWL_DEBUG_TE(mvm,
+                            "don't remove TE with id=%u (not session protection)\n",
+                            id);
+               return;
+       }
+
        iwl_mvm_remove_time_event(mvm, mvmvif, te_data);
 }
 
@@ -859,8 +874,23 @@ int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm,
        lockdep_assert_held(&mvm->mutex);
 
        if (te_data->running) {
-               IWL_DEBUG_TE(mvm, "CS period is already scheduled\n");
-               return -EBUSY;
+               u32 id;
+
+               spin_lock_bh(&mvm->time_event_lock);
+               id = te_data->id;
+               spin_unlock_bh(&mvm->time_event_lock);
+
+               if (id == TE_CHANNEL_SWITCH_PERIOD) {
+                       IWL_DEBUG_TE(mvm, "CS period is already scheduled\n");
+                       return -EBUSY;
+               }
+
+               /*
+                * Remove the session protection time event to allow the
+                * channel switch. If we got here, we just heard a beacon so
+                * the session protection is not needed anymore anyway.
+                */
+               iwl_mvm_remove_time_event(mvm, mvmvif, te_data);
        }
 
        time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD);