On 09/21/2010 03:41 PM, Felix Fietkau wrote:
On 2010-09-21 10:19 PM, Ben Greear wrote:
On 09/21/2010 12:32 PM, Felix Fietkau wrote:
On 2010-09-21 9:28 PM, Johannes Berg wrote:
On Tue, 2010-09-21 at 20:00 +0200, Felix Fietkau wrote:
Could we just poke a pointer to the STA into the ath_buf structure?
No, that doesn't work because of RCU.
Well, it could work, if you walk all the structures upon sta_notify and
remove now stale pointers (or just drop the frames or something).
I think it would be much better to just add the helper function that
checks the RA on STA lookup. Keeps things simple, especially since
nothing else in the tx path needs the vif.
How about this. Seems to do the trick on my system:
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 85a7323..09815a1 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -328,8 +328,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
rcu_read_lock();
- /* XXX: use ieee80211_find_sta! */
- sta = ieee80211_find_sta_by_hw(hw, hdr->addr1);
+ sta = tx_info->control.sta;
As I mentioned in another email: at the time we get the tx status
report, we have to consider the sta pointer stale. It may or may not
still be valid.
How about this one. I think it ensures that the sta will never be stale,
since it flushes the tx queue on vif removal. Minimal testing shows it
working, but of course I might be missing something.
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 8b327bc..8485729 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1459,6 +1459,12 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&sc->mutex);
+ /* Make sure we have no outstanding packets that might reference
+ * the vif. This way, we can always reference tx_info->control.sta
+ * in the tx_complete logic.
+ */
+ ath_drain_all_txq(sc, false);
+
/* Stop ANI */
sc->sc_flags &= ~SC_OP_ANI_RUN;
del_timer_sync(&common->ani.timer);
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 85a7323..09815a1 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -328,8 +328,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
rcu_read_lock();
- /* XXX: use ieee80211_find_sta! */
- sta = ieee80211_find_sta_by_hw(hw, hdr->addr1);
+ sta = tx_info->control.sta;
if (!sta) {
rcu_read_unlock();
Thanks,
Ben
- Felix
--
Ben Greear <greearb@xxxxxxxxxxxxxxx>
Candela Technologies Inc http://www.candelatech.com
--
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