Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F159744150
D45508.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D45508.diff
View Options
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -145,6 +145,7 @@
static struct lkpi_sta *lkpi_find_lsta_by_ni(struct lkpi_vif *,
struct ieee80211_node *);
#endif
+static void lkpi_80211_txq_tx_one(struct lkpi_sta *, struct mbuf *);
static void lkpi_80211_txq_task(void *, int);
static void lkpi_80211_lhw_rxq_task(void *, int);
static void lkpi_ieee80211_free_skb_mbuf(void *);
@@ -1061,6 +1062,51 @@
}
}
+/*
+ * On the way down from RUN -> ASSOC -> AUTH we may send a DISASSOC or DEAUTH
+ * packet. The problem is that the state machine functions tend to hold the
+ * LHW lock which will prevent lkpi_80211_txq_tx_one() from sending the packet.
+ * We call this after dropping the ic lock and before acquiring the LHW lock.
+ * we make sure no further packets are queued and if they are queued the task
+ * will finish or be cancelled. At the end if a packet is left we manually
+ * send it. scan_to_auth() would re-enable sending if the lsta would be
+ * re-used.
+ */
+static void
+lkpi_80211_flush_tx(struct lkpi_hw *lhw, struct lkpi_sta *lsta)
+{
+ struct mbufq mq;
+ struct mbuf *m;
+ int len;
+
+ LKPI_80211_LHW_UNLOCK_ASSERT(lhw);
+
+ /* Do not accept any new packets until scan_to_auth or lsta_free(). */
+ LKPI_80211_LSTA_TXQ_LOCK(lsta);
+ lsta->txq_ready = false;
+ LKPI_80211_LSTA_TXQ_UNLOCK(lsta);
+
+ while (taskqueue_cancel(taskqueue_thread, &lsta->txq_task, NULL) != 0)
+ taskqueue_drain(taskqueue_thread, &lsta->txq_task);
+
+ LKPI_80211_LSTA_TXQ_LOCK(lsta);
+ len = mbufq_len(&lsta->txq);
+ if (len <= 0) {
+ LKPI_80211_LSTA_TXQ_UNLOCK(lsta);
+ return;
+ }
+
+ mbufq_init(&mq, IFQ_MAXLEN);
+ mbufq_concat(&mq, &lsta->txq);
+ LKPI_80211_LSTA_TXQ_UNLOCK(lsta);
+
+ m = mbufq_dequeue(&mq);
+ while (m != NULL) {
+ lkpi_80211_txq_tx_one(lsta, m);
+ m = mbufq_dequeue(&mq);
+ }
+}
+
/* -------------------------------------------------------------------------- */
static int
@@ -1274,6 +1320,14 @@
__func__, ni, ni->ni_drv_data));
lsta = ni->ni_drv_data;
+ /*
+ * Make sure in case the sta did not change and we re-add it,
+ * that we can tx again.
+ */
+ LKPI_80211_LSTA_TXQ_LOCK(lsta);
+ lsta->txq_ready = true;
+ LKPI_80211_LSTA_TXQ_UNLOCK(lsta);
+
LKPI_80211_LVIF_LOCK(lvif);
/* Insert the [l]sta into the list of known stations. */
TAILQ_INSERT_TAIL(&lvif->lsta_head, lsta, lsta_entry);
@@ -1426,7 +1480,7 @@
lkpi_80211_mo_flush(hw, vif, nitems(sta->txq), true);
/* Wake tx queues to get packet(s) out. */
- lkpi_wake_tx_queues(hw, sta, true, true);
+ lkpi_wake_tx_queues(hw, sta, false, true);
/* flush, no drop */
lkpi_80211_mo_flush(hw, vif, nitems(sta->txq), false);
@@ -1584,7 +1638,7 @@
}
/* Wake tx queue to get packet out. */
- lkpi_wake_tx_queues(hw, LSTA_TO_STA(lsta), true, true);
+ lkpi_wake_tx_queues(hw, LSTA_TO_STA(lsta), false, true);
/*
* <twiddle> .. we end up in "assoc_to_run"
@@ -1728,7 +1782,7 @@
LKPI_80211_LHW_UNLOCK(lhw);
IEEE80211_LOCK(vap->iv_ic);
- /* Call iv_newstate first so we get potential DISASSOC packet out. */
+ /* Call iv_newstate first so we get potential DEAUTH packet out. */
error = lvif->iv_newstate(vap, nstate, arg);
if (error != 0) {
ic_printf(vap->iv_ic, "%s:%d: iv_newstate(%p, %d, %d) "
@@ -1737,12 +1791,16 @@
}
IEEE80211_UNLOCK(vap->iv_ic);
+
+ /* Ensure the packets get out. */
+ lkpi_80211_flush_tx(lhw, lsta);
+
LKPI_80211_LHW_LOCK(lhw);
lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
/* Wake tx queues to get packet(s) out. */
- lkpi_wake_tx_queues(hw, sta, true, true);
+ lkpi_wake_tx_queues(hw, sta, false, true);
/* flush, no drop */
lkpi_80211_mo_flush(hw, vif, nitems(sta->txq), false);
@@ -2120,12 +2178,16 @@
}
IEEE80211_UNLOCK(vap->iv_ic);
+
+ /* Ensure the packets get out. */
+ lkpi_80211_flush_tx(lhw, lsta);
+
LKPI_80211_LHW_LOCK(lhw);
lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
/* Wake tx queues to get packet(s) out. */
- lkpi_wake_tx_queues(hw, sta, true, true);
+ lkpi_wake_tx_queues(hw, sta, false, true);
/* flush, no drop */
lkpi_80211_mo_flush(hw, vif, nitems(sta->txq), false);
@@ -2254,12 +2316,16 @@
}
IEEE80211_UNLOCK(vap->iv_ic);
+
+ /* Ensure the packets get out. */
+ lkpi_80211_flush_tx(lhw, lsta);
+
LKPI_80211_LHW_LOCK(lhw);
lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
/* Wake tx queues to get packet(s) out. */
- lkpi_wake_tx_queues(hw, sta, true, true);
+ lkpi_wake_tx_queues(hw, sta, false, true);
/* flush, no drop */
lkpi_80211_mo_flush(hw, vif, nitems(sta->txq), false);
@@ -3595,7 +3661,7 @@
lsta = ni->ni_drv_data;
LKPI_80211_LSTA_TXQ_LOCK(lsta);
- if (!lsta->txq_ready) {
+ if (!lsta->added_to_drv || !lsta->txq_ready) {
LKPI_80211_LSTA_TXQ_UNLOCK(lsta);
/*
* Free the mbuf (do NOT release ni ref for the m_pkthdr.rcvif!
@@ -3821,6 +3887,7 @@
struct lkpi_sta *lsta;
struct mbufq mq;
struct mbuf *m;
+ bool shall_tx;
lsta = ctx;
@@ -3836,9 +3903,19 @@
LKPI_80211_LSTA_TXQ_LOCK(lsta);
/*
* Do not re-check lsta->txq_ready here; we may have a pending
- * disassoc frame still.
+ * disassoc/deauth frame still. On the contrary if txq_ready is
+ * false we do not have a valid sta anymore in the firmware so no
+ * point to try to TX.
+ * We also use txq_ready as a semaphore and will drain the txq manually
+ * if needed on our way towards SCAN/INIT in the state machine.
+ */
+ shall_tx = lsta->added_to_drv && lsta->txq_ready;
+ if (__predict_true(shall_tx))
+ mbufq_concat(&mq, &lsta->txq);
+ /*
+ * else a state change will push the packets out manually or
+ * lkpi_lsta_free() will drain the lsta->txq and free the mbufs.
*/
- mbufq_concat(&mq, &lsta->txq);
LKPI_80211_LSTA_TXQ_UNLOCK(lsta);
m = mbufq_dequeue(&mq);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jun 18, 7:02 PM (19 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34055578
Default Alt Text
D45508.diff (5 KB)
Attached To
Mode
D45508: LinuxKPI: 802.11: make sure we can send DISASSOC or DEAUTH frames
Attached
Detach File
Event Timeline
Log In to Comment