Search Linux Wireless

[PATCH] mac80211: don't call drv_ampdu_action() during reconfig

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When tearing down BA sessions during HW reconfig, the low level driver
is not aware of them yet. Add a parameter to relevant Rx/Tx BA functions
to prevent calls to the driver, while removing all mac80211 related state.

Signed-off-by: Arik Nemtsov <arik@xxxxxxxxxx>
---
 net/mac80211/agg-rx.c      |   16 ++++++++++------
 net/mac80211/agg-tx.c      |   18 +++++++++++-------
 net/mac80211/debugfs_sta.c |    2 +-
 net/mac80211/ht.c          |   19 +++++++++++--------
 net/mac80211/ieee80211_i.h |   13 ++++++++-----
 net/mac80211/iface.c       |    2 +-
 net/mac80211/mlme.c        |    2 +-
 net/mac80211/pm.c          |    2 +-
 net/mac80211/sta_info.c    |    2 +-
 net/mac80211/util.c        |    3 ++-
 10 files changed, 47 insertions(+), 32 deletions(-)

diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index a070d4f..d1afa99 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -59,7 +59,8 @@ static void ieee80211_free_tid_rx(struct rcu_head *h)
 }
 
 void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
-				     u16 initiator, u16 reason, bool tx)
+				     u16 initiator, u16 reason, bool tx,
+				     bool call_drv)
 {
 	struct ieee80211_local *local = sta->local;
 	struct tid_ampdu_rx *tid_rx;
@@ -82,8 +83,9 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
 	       (int)reason);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
-	if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP,
-			     &sta->sta, tid, NULL, 0))
+	if (call_drv && drv_ampdu_action(local, sta->sdata,
+					 IEEE80211_AMPDU_RX_STOP,
+					 &sta->sta, tid, NULL, 0))
 		printk(KERN_DEBUG "HW problem - can not stop rx "
 				"aggregation for tid %d\n", tid);
 
@@ -98,10 +100,12 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
 }
 
 void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
-				    u16 initiator, u16 reason, bool tx)
+				    u16 initiator, u16 reason, bool tx,
+				    bool call_drv)
 {
 	mutex_lock(&sta->ampdu_mlme.mtx);
-	___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, tx);
+	___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, tx,
+					call_drv);
 	mutex_unlock(&sta->ampdu_mlme.mtx);
 }
 
@@ -290,7 +294,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
 		/* delete existing Rx BA session on the same tid */
 		___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
 						WLAN_STATUS_UNSPECIFIED_QOS,
-						false);
+						false, true);
 	}
 
 	/* prepare A-MPDU MLME for Rx aggregation */
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 7cf0715..daa1764 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -150,7 +150,7 @@ void ieee80211_assign_tid_tx(struct sta_info *sta, int tid,
 
 int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
 				    enum ieee80211_back_parties initiator,
-				    bool tx)
+				    bool tx, bool call_drv)
 {
 	struct ieee80211_local *local = sta->local;
 	struct tid_ampdu_tx *tid_tx;
@@ -216,9 +216,12 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
 	tid_tx->stop_initiator = initiator;
 	tid_tx->tx_stop = tx;
 
-	ret = drv_ampdu_action(local, sta->sdata,
-			       IEEE80211_AMPDU_TX_STOP,
-			       &sta->sta, tid, NULL, 0);
+	if (call_drv)
+		ret = drv_ampdu_action(local, sta->sdata,
+				       IEEE80211_AMPDU_TX_STOP,
+				       &sta->sta, tid, NULL, 0);
+	else
+		ret = 0;
 
 	/* HW shall not deny going back to legacy */
 	if (WARN_ON(ret)) {
@@ -688,13 +691,14 @@ EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
 
 int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
 				   enum ieee80211_back_parties initiator,
-				   bool tx)
+				   bool tx, bool call_drv)
 {
 	int ret;
 
 	mutex_lock(&sta->ampdu_mlme.mtx);
 
-	ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator, tx);
+	ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator, tx,
+					      call_drv);
 
 	mutex_unlock(&sta->ampdu_mlme.mtx);
 
@@ -911,7 +915,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
 
 	} else {
 		___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR,
-						true);
+						true, true);
 	}
 
  out:
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 5ccec2c..0127367 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -230,7 +230,7 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu
 			ret = ieee80211_stop_tx_ba_session(&sta->sta, tid);
 	} else {
 		__ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
-					       3, true);
+					       3, true, true);
 		ret = 0;
 	}
 
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 9b60336..a8125cb 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -179,16 +179,19 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
 	ieee80211_apply_htcap_overrides(sdata, ht_cap);
 }
 
-void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx)
+void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx,
+					 bool call_drv)
 {
 	int i;
 
 	cancel_work_sync(&sta->ampdu_mlme.work);
 
 	for (i = 0; i <  STA_TID_NUM; i++) {
-		__ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR, tx);
+		__ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR, tx,
+					       call_drv);
 		__ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT,
-					       WLAN_REASON_QSTA_LEAVE_QBSS, tx);
+					       WLAN_REASON_QSTA_LEAVE_QBSS, tx,
+					       call_drv);
 	}
 }
 
@@ -213,13 +216,13 @@ void ieee80211_ba_session_work(struct work_struct *work)
 		if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired))
 			___ieee80211_stop_rx_ba_session(
 				sta, tid, WLAN_BACK_RECIPIENT,
-				WLAN_REASON_QSTA_TIMEOUT, true);
+				WLAN_REASON_QSTA_TIMEOUT, true, true);
 
 		if (test_and_clear_bit(tid,
 				       sta->ampdu_mlme.tid_rx_stop_requested))
 			___ieee80211_stop_rx_ba_session(
 				sta, tid, WLAN_BACK_RECIPIENT,
-				WLAN_REASON_UNSPECIFIED, true);
+				WLAN_REASON_UNSPECIFIED, true, true);
 
 		tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
 		if (tid_tx) {
@@ -246,7 +249,7 @@ void ieee80211_ba_session_work(struct work_struct *work)
 						 &tid_tx->state))
 			___ieee80211_stop_tx_ba_session(sta, tid,
 							WLAN_BACK_INITIATOR,
-							true);
+							true, true);
 	}
 	mutex_unlock(&sta->ampdu_mlme.mtx);
 }
@@ -314,10 +317,10 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
 
 	if (initiator == WLAN_BACK_INITIATOR)
 		__ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0,
-					       true);
+					       true, true);
 	else
 		__ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
-					       true);
+					       true, true);
 }
 
 int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ae046b5..1975f35 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1336,10 +1336,13 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
 void ieee80211_request_smps_work(struct work_struct *work);
 
 void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
-				     u16 initiator, u16 reason, bool stop);
+				     u16 initiator, u16 reason, bool stop,
+				     bool call_drv);
 void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
-				    u16 initiator, u16 reason, bool stop);
-void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx);
+				    u16 initiator, u16 reason, bool stop,
+				    bool call_drv);
+void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx,
+					 bool call_drv);
 void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
 			     struct sta_info *sta,
 			     struct ieee80211_mgmt *mgmt, size_t len);
@@ -1354,10 +1357,10 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
 
 int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
 				   enum ieee80211_back_parties initiator,
-				   bool tx);
+				   bool tx, bool call_drv);
 int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
 				    enum ieee80211_back_parties initiator,
-				    bool tx);
+				    bool tx, bool call_drv);
 void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid);
 void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid);
 void ieee80211_ba_session_work(struct work_struct *work);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index c550945..859271d 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -922,7 +922,7 @@ static void ieee80211_iface_work(struct work_struct *work)
 				__ieee80211_stop_rx_ba_session(
 					sta, tid, WLAN_BACK_RECIPIENT,
 					WLAN_REASON_QSTA_REQUIRE_SETUP,
-					true);
+					true, true);
 			}
 			mutex_unlock(&local->sta_mtx);
 		} else switch (sdata->vif.type) {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 40c933c..4ae9b23 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1363,7 +1363,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 	sta = sta_info_get(sdata, bssid);
 	if (sta) {
 		set_sta_flag(sta, WLAN_STA_BLOCK_BA);
-		ieee80211_sta_tear_down_BA_sessions(sta, tx);
+		ieee80211_sta_tear_down_BA_sessions(sta, tx, true);
 	}
 	mutex_unlock(&local->sta_mtx);
 
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index af1c4e2..52cb3d3 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -43,7 +43,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 		mutex_lock(&local->sta_mtx);
 		list_for_each_entry(sta, &local->sta_list, list) {
 			set_sta_flag(sta, WLAN_STA_BLOCK_BA);
-			ieee80211_sta_tear_down_BA_sessions(sta, true);
+			ieee80211_sta_tear_down_BA_sessions(sta, true, true);
 		}
 		mutex_unlock(&local->sta_mtx);
 	}
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 97a9d66..f5c2b7e 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -682,7 +682,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
 	 * will be sufficient.
 	 */
 	set_sta_flag(sta, WLAN_STA_BLOCK_BA);
-	ieee80211_sta_tear_down_BA_sessions(sta, true);
+	ieee80211_sta_tear_down_BA_sessions(sta, true, true);
 
 	ret = sta_info_hash_del(local, sta);
 	if (ret)
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index a44c680..7c7e571 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1391,7 +1391,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 		mutex_lock(&local->sta_mtx);
 
 		list_for_each_entry(sta, &local->sta_list, list) {
-			ieee80211_sta_tear_down_BA_sessions(sta, true);
+			/* don't call the driver when tearing down sessions */
+			ieee80211_sta_tear_down_BA_sessions(sta, true, false);
 			clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
 		}
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux