mac80211: Support adding duration for prepare_tx() callback
authorIlan Peer <ilan.peer@intel.com>
Fri, 20 Apr 2018 10:49:25 +0000 (13:49 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 23 May 2018 09:06:10 +0000 (11:06 +0200)
There are specific cases, such as SAE authentication exchange, that
might require long duration to complete. For such cases, add support
for indicating to the driver the required duration of the prepare_tx()
operation, so the driver would still be able to complete the frame
exchange.

Currently, indicate the duration only for SAE authentication exchange,
as SAE authentication can take up to 2000 msec (as defined in IEEE
P802.11-REVmd D1.0 p. 3504).

As the patch modified the prepare_tx() callback API, also modify
the relevant code in iwlwifi.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
include/net/mac80211.h
net/mac80211/driver-ops.h
net/mac80211/mlme.c
net/mac80211/trace.h

index a3be8add56e112f560fec5a381c60382210307f0..b6663c80e7ddcd67c1d5ae41077639a9bdf661ce 100644 (file)
@@ -2544,7 +2544,8 @@ static void ath9k_unassign_vif_chanctx(struct ieee80211_hw *hw,
 }
 
 static void ath9k_mgd_prepare_tx(struct ieee80211_hw *hw,
-                                struct ieee80211_vif *vif)
+                                struct ieee80211_vif *vif,
+                                u16 duration)
 {
        struct ath_softc *sc = hw->priv;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
index 5f0701c992a40192b2e89a3eb57b6c7f1401775f..ec91dd90acfdbcff923d25bacbd92858cd5bedfd 100644 (file)
@@ -2844,7 +2844,8 @@ static int iwl_mvm_mac_conf_tx(struct ieee80211_hw *hw,
 }
 
 static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
-                                     struct ieee80211_vif *vif)
+                                      struct ieee80211_vif *vif,
+                                      u16 req_duration)
 {
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
        u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS;
@@ -2857,6 +2858,9 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
        if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PREPARE_TX))
                return;
 
+       if (req_duration > duration)
+               duration = req_duration;
+
        mutex_lock(&mvm->mutex);
        /* Try really hard to protect the session and hear a beacon */
        iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500, false);
index 604d738a21283208f25065e64cbe0973a58b3028..851a5e19ae320e02044c40cb6c810d6cd0454d4d 100644 (file)
@@ -3378,6 +3378,8 @@ enum ieee80211_reconfig_type {
  *     frame in case that no beacon was heard from the AP/P2P GO.
  *     The callback will be called before each transmission and upon return
  *     mac80211 will transmit the frame right away.
+ *      If duration is greater than zero, mac80211 hints to the driver the
+ *      duration for which the operation is requested.
  *     The callback is optional and can (should!) sleep.
  *
  * @mgd_protect_tdls_discover: Protect a TDLS discovery session. After sending
@@ -3697,7 +3699,8 @@ struct ieee80211_ops {
                                  u32 sset, u8 *data);
 
        void    (*mgd_prepare_tx)(struct ieee80211_hw *hw,
-                                 struct ieee80211_vif *vif);
+                                 struct ieee80211_vif *vif,
+                                 u16 duration);
 
        void    (*mgd_protect_tdls_discover)(struct ieee80211_hw *hw,
                                             struct ieee80211_vif *vif);
index 4d82fe7d627c26f69b9d97c7b9e7f8aa1f2ed8f9..8f6998091d26fc7ae07506b8014e60badcc11e00 100644 (file)
@@ -2,6 +2,7 @@
 /*
 * Portions of this file
 * Copyright(c) 2016 Intel Deutschland GmbH
+* Copyright (C) 2018 Intel Corporation
 */
 
 #ifndef __MAC80211_DRIVER_OPS
@@ -813,7 +814,8 @@ drv_allow_buffered_frames(struct ieee80211_local *local,
 }
 
 static inline void drv_mgd_prepare_tx(struct ieee80211_local *local,
-                                     struct ieee80211_sub_if_data *sdata)
+                                     struct ieee80211_sub_if_data *sdata,
+                                     u16 duration)
 {
        might_sleep();
 
@@ -821,9 +823,9 @@ static inline void drv_mgd_prepare_tx(struct ieee80211_local *local,
                return;
        WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION);
 
-       trace_drv_mgd_prepare_tx(local, sdata);
+       trace_drv_mgd_prepare_tx(local, sdata, duration);
        if (local->ops->mgd_prepare_tx)
-               local->ops->mgd_prepare_tx(&local->hw, &sdata->vif);
+               local->ops->mgd_prepare_tx(&local->hw, &sdata->vif, duration);
        trace_drv_return_void(local);
 }
 
index 233068756502b733520190835bff56b5f869be10..a59187c016e08193e50078becbd169820f2efe9a 100644 (file)
@@ -864,7 +864,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
                return;
        }
 
-       drv_mgd_prepare_tx(local, sdata);
+       drv_mgd_prepare_tx(local, sdata, 0);
 
        IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
        if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
@@ -2022,7 +2022,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
                 */
                if (ieee80211_hw_check(&local->hw, DEAUTH_NEED_MGD_TX_PREP) &&
                    !ifmgd->have_beacon)
-                       drv_mgd_prepare_tx(sdata->local, sdata);
+                       drv_mgd_prepare_tx(sdata->local, sdata, 0);
 
                ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype,
                                               reason, tx, frame_buf);
@@ -2560,7 +2560,7 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
        if (!elems.challenge)
                return;
        auth_data->expected_transaction = 4;
-       drv_mgd_prepare_tx(sdata->local, sdata);
+       drv_mgd_prepare_tx(sdata->local, sdata, 0);
        if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
                tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
                           IEEE80211_TX_INTFL_MLME_CONN_TX;
@@ -3769,6 +3769,7 @@ static int ieee80211_auth(struct ieee80211_sub_if_data *sdata)
        u32 tx_flags = 0;
        u16 trans = 1;
        u16 status = 0;
+       u16 prepare_tx_duration = 0;
 
        sdata_assert_lock(sdata);
 
@@ -3790,7 +3791,11 @@ static int ieee80211_auth(struct ieee80211_sub_if_data *sdata)
                return -ETIMEDOUT;
        }
 
-       drv_mgd_prepare_tx(local, sdata);
+       if (auth_data->algorithm == WLAN_AUTH_SAE)
+               prepare_tx_duration =
+                       jiffies_to_msecs(IEEE80211_AUTH_TIMEOUT_SAE);
+
+       drv_mgd_prepare_tx(local, sdata, prepare_tx_duration);
 
        sdata_info(sdata, "send auth to %pM (try %d/%d)\n",
                   auth_data->bss->bssid, auth_data->tries,
@@ -4994,7 +4999,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
                           req->bssid, req->reason_code,
                           ieee80211_get_reason_code_string(req->reason_code));
 
-               drv_mgd_prepare_tx(sdata->local, sdata);
+               drv_mgd_prepare_tx(sdata->local, sdata, 0);
                ieee80211_send_deauth_disassoc(sdata, req->bssid,
                                               IEEE80211_STYPE_DEAUTH,
                                               req->reason_code, tx,
@@ -5014,7 +5019,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
                           req->bssid, req->reason_code,
                           ieee80211_get_reason_code_string(req->reason_code));
 
-               drv_mgd_prepare_tx(sdata->local, sdata);
+               drv_mgd_prepare_tx(sdata->local, sdata, 0);
                ieee80211_send_deauth_disassoc(sdata, req->bssid,
                                               IEEE80211_STYPE_DEAUTH,
                                               req->reason_code, tx,
index 591ad02e1fa4f777d2c2f260ff0f00245e2c094c..80a7edf8d314a12a22f62047e585275a7baa3ab9 100644 (file)
@@ -2,6 +2,7 @@
 /*
 * Portions of this file
 * Copyright(c) 2016 Intel Deutschland GmbH
+* Copyright (C) 2018 Intel Corporation
 */
 
 #if !defined(__MAC80211_DRIVER_TRACE) || defined(TRACE_HEADER_MULTI_READ)
@@ -1413,11 +1414,29 @@ DEFINE_EVENT(release_evt, drv_allow_buffered_frames,
        TP_ARGS(local, sta, tids, num_frames, reason, more_data)
 );
 
-DEFINE_EVENT(local_sdata_evt, drv_mgd_prepare_tx,
+TRACE_EVENT(drv_mgd_prepare_tx,
        TP_PROTO(struct ieee80211_local *local,
-                struct ieee80211_sub_if_data *sdata),
+                struct ieee80211_sub_if_data *sdata,
+                u16 duration),
 
-       TP_ARGS(local, sdata)
+       TP_ARGS(local, sdata, duration),
+
+       TP_STRUCT__entry(
+               LOCAL_ENTRY
+               VIF_ENTRY
+               __field(u32, duration)
+       ),
+
+       TP_fast_assign(
+               LOCAL_ASSIGN;
+               VIF_ASSIGN;
+               __entry->duration = duration;
+       ),
+
+       TP_printk(
+               LOCAL_PR_FMT VIF_PR_FMT " duration: %u",
+               LOCAL_PR_ARG, VIF_PR_ARG, __entry->duration
+       )
 );
 
 DEFINE_EVENT(local_sdata_evt, drv_mgd_protect_tdls_discover,