iwlwifi: mvm: fix TDLS discovery with the new firmware API
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Fri, 31 Jan 2020 13:45:29 +0000 (15:45 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 3 Feb 2020 18:09:13 +0000 (20:09 +0200)
I changed the API for asking for a session protection but
I omitted the TDLS flows. Fix that now.
Note that for the TDLS flow, we need to block until the
session protection actually starts, so add this option
to iwl_mvm_schedule_session_protection.
This patch fixes a firmware assert in the TDLS flow since
the old TIME_EVENT_CMD is not supported anymore by newer
firwmare versions.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Fixes: fe959c7b2049 ("iwlwifi: mvm: use the new session protection command")
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
drivers/net/wireless/intel/iwlwifi/mvm/time-event.h

index 8ecd1f6875deb526c0549cfa283efb95d574f326..02df603b6400055befa5ce124ae020e459413a0a 100644 (file)
@@ -3291,7 +3291,7 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
        if (fw_has_capa(&mvm->fw->ucode_capa,
                        IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD))
                iwl_mvm_schedule_session_protection(mvm, vif, 900,
-                                                   min_duration);
+                                                   min_duration, false);
        else
                iwl_mvm_protect_session(mvm, vif, duration,
                                        min_duration, 500, false);
index 1851719e9f4b44699b00ed3753b47df4ea2de362..d781777b6b965885fbad11cb629bae2119ce7eff 100644 (file)
@@ -205,9 +205,15 @@ void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
        u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int;
 
-       mutex_lock(&mvm->mutex);
        /* Protect the session to hear the TDLS setup response on the channel */
-       iwl_mvm_protect_session(mvm, vif, duration, duration, 100, true);
+       mutex_lock(&mvm->mutex);
+       if (fw_has_capa(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD))
+               iwl_mvm_schedule_session_protection(mvm, vif, duration,
+                                                   duration, true);
+       else
+               iwl_mvm_protect_session(mvm, vif, duration,
+                                       duration, 100, true);
        mutex_unlock(&mvm->mutex);
 }
 
index 51b138673ddbc08696de0a038a0951da25956cac..c0b420fe5e48f1b0d0e1cca98f018149e7c43b46 100644 (file)
@@ -1056,13 +1056,42 @@ int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm,
        return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
 }
 
+static bool iwl_mvm_session_prot_notif(struct iwl_notif_wait_data *notif_wait,
+                                      struct iwl_rx_packet *pkt, void *data)
+{
+       struct iwl_mvm *mvm =
+               container_of(notif_wait, struct iwl_mvm, notif_wait);
+       struct iwl_mvm_session_prot_notif *resp;
+       int resp_len = iwl_rx_packet_payload_len(pkt);
+
+       if (WARN_ON(pkt->hdr.cmd != SESSION_PROTECTION_NOTIF ||
+                   pkt->hdr.group_id != MAC_CONF_GROUP))
+               return true;
+
+       if (WARN_ON_ONCE(resp_len != sizeof(*resp))) {
+               IWL_ERR(mvm, "Invalid SESSION_PROTECTION_NOTIF response\n");
+               return true;
+       }
+
+       resp = (void *)pkt->data;
+
+       if (!resp->status)
+               IWL_ERR(mvm,
+                       "TIME_EVENT_NOTIFICATION received but not executed\n");
+
+       return true;
+}
+
 void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
                                         struct ieee80211_vif *vif,
-                                        u32 duration, u32 min_duration)
+                                        u32 duration, u32 min_duration,
+                                        bool wait_for_notif)
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
-
+       const u16 notif[] = { iwl_cmd_id(SESSION_PROTECTION_NOTIF,
+                                        MAC_CONF_GROUP, 0) };
+       struct iwl_notification_wait wait_notif;
        struct iwl_mvm_session_prot_cmd cmd = {
                .id_and_color =
                        cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
@@ -1071,7 +1100,6 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
                .conf_id = cpu_to_le32(SESSION_PROTECT_CONF_ASSOC),
                .duration_tu = cpu_to_le32(MSEC_TO_TU(duration)),
        };
-       int ret;
 
        lockdep_assert_held(&mvm->mutex);
 
@@ -1092,14 +1120,35 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
        IWL_DEBUG_TE(mvm, "Add new session protection, duration %d TU\n",
                     le32_to_cpu(cmd.duration_tu));
 
-       ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD,
-                                                  MAC_CONF_GROUP, 0),
-                                  0, sizeof(cmd), &cmd);
-       if (ret) {
+       if (!wait_for_notif) {
+               if (iwl_mvm_send_cmd_pdu(mvm,
+                                        iwl_cmd_id(SESSION_PROTECTION_CMD,
+                                                   MAC_CONF_GROUP, 0),
+                                        0, sizeof(cmd), &cmd)) {
+                       IWL_ERR(mvm,
+                               "Couldn't send the SESSION_PROTECTION_CMD\n");
+                       spin_lock_bh(&mvm->time_event_lock);
+                       iwl_mvm_te_clear_data(mvm, te_data);
+                       spin_unlock_bh(&mvm->time_event_lock);
+               }
+
+               return;
+       }
+
+       iwl_init_notification_wait(&mvm->notif_wait, &wait_notif,
+                                  notif, ARRAY_SIZE(notif),
+                                  iwl_mvm_session_prot_notif, NULL);
+
+       if (iwl_mvm_send_cmd_pdu(mvm,
+                                iwl_cmd_id(SESSION_PROTECTION_CMD,
+                                           MAC_CONF_GROUP, 0),
+                                0, sizeof(cmd), &cmd)) {
                IWL_ERR(mvm,
-                       "Couldn't send the SESSION_PROTECTION_CMD: %d\n", ret);
-               spin_lock_bh(&mvm->time_event_lock);
-               iwl_mvm_te_clear_data(mvm, te_data);
-               spin_unlock_bh(&mvm->time_event_lock);
+                       "Couldn't send the SESSION_PROTECTION_CMD\n");
+               iwl_remove_notification(&mvm->notif_wait, &wait_notif);
+       } else if (iwl_wait_notification(&mvm->notif_wait, &wait_notif,
+                                        TU_TO_JIFFIES(100))) {
+               IWL_ERR(mvm,
+                       "Failed to protect session until session protection\n");
        }
 }
index df6832b7966661bec68e189989a860617f6670a1..3186d7e40567c40e7460a36025138421ca0a471f 100644 (file)
@@ -250,10 +250,12 @@ iwl_mvm_te_scheduled(struct iwl_mvm_time_event_data *te_data)
  * @mvm: the mvm component
  * @vif: the virtual interface for which the protection issued
  * @duration: the duration of the protection
+ * @wait_for_notif: if true, will block until the start of the protection
  */
 void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
                                         struct ieee80211_vif *vif,
-                                        u32 duration, u32 min_duration);
+                                        u32 duration, u32 min_duration,
+                                        bool wait_for_notif);
 
 /**
  * iwl_mvm_rx_session_protect_notif - handles %SESSION_PROTECTION_NOTIF