diff options
| author | Jouni Malinen <jouni.malinen@atheros.com> | 2008-08-11 07:01:50 -0400 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2008-09-11 11:10:28 -0400 |
| commit | 69da6b87fcb270f758fe75141c32e041f8db510c (patch) | |
| tree | 6e68be8ee39eaf96347a41e31348f714db2ca24f | |
| parent | e550dfb0c2c31b6363aa463a035fc9f8dcaa3c9b (diff) | |
ath9k: Assign seq# when mac80211 requests this
Use TX control flag IEEE80211_TX_CTL_ASSIGN_SEQ as a request to update
the seq# for the frames. This will likely require some further cleanup
to get seq# correctly for Beacons vs. other frames and also potentially
for multiple BSSes. Anyway, this is better than ending up sending out
most frames with seq# 0.
(This is a backport of patch w/ same title already in net-next-2.6.
It is verified to fix http://bugzilla.kernel.org/show_bug.cgi?id=11394
and it should be acceptable for -rc due to the driver being new
in 2.6.27.)
Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
| -rw-r--r-- | drivers/net/wireless/ath9k/beacon.c | 13 | ||||
| -rw-r--r-- | drivers/net/wireless/ath9k/core.h | 1 | ||||
| -rw-r--r-- | drivers/net/wireless/ath9k/main.c | 14 |
3 files changed, 28 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index caf569401a34..00a0eaa08866 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c | |||
| @@ -209,6 +209,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) | |||
| 209 | unsigned int curlen; | 209 | unsigned int curlen; |
| 210 | struct ath_txq *cabq; | 210 | struct ath_txq *cabq; |
| 211 | struct ath_txq *mcastq; | 211 | struct ath_txq *mcastq; |
| 212 | struct ieee80211_tx_info *info; | ||
| 212 | avp = sc->sc_vaps[if_id]; | 213 | avp = sc->sc_vaps[if_id]; |
| 213 | 214 | ||
| 214 | mcastq = &avp->av_mcastq; | 215 | mcastq = &avp->av_mcastq; |
| @@ -232,6 +233,18 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) | |||
| 232 | */ | 233 | */ |
| 233 | curlen = skb->len; | 234 | curlen = skb->len; |
| 234 | 235 | ||
| 236 | info = IEEE80211_SKB_CB(skb); | ||
| 237 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | ||
| 238 | /* | ||
| 239 | * TODO: make sure the seq# gets assigned properly (vs. other | ||
| 240 | * TX frames) | ||
| 241 | */ | ||
| 242 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
| 243 | sc->seq_no += 0x10; | ||
| 244 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
| 245 | hdr->seq_ctrl |= cpu_to_le16(sc->seq_no); | ||
| 246 | } | ||
| 247 | |||
| 235 | /* XXX: spin_lock_bh should not be used here, but sparse bitches | 248 | /* XXX: spin_lock_bh should not be used here, but sparse bitches |
| 236 | * otherwise. We should fix sparse :) */ | 249 | * otherwise. We should fix sparse :) */ |
| 237 | spin_lock_bh(&mcastq->axq_lock); | 250 | spin_lock_bh(&mcastq->axq_lock); |
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 673b3d81133a..4ee695b76b88 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h | |||
| @@ -992,6 +992,7 @@ struct ath_softc { | |||
| 992 | u32 sc_txintrperiod; /* tx interrupt batching */ | 992 | u32 sc_txintrperiod; /* tx interrupt batching */ |
| 993 | int sc_haltype2q[ATH9K_WME_AC_VO+1]; /* HAL WME AC -> h/w qnum */ | 993 | int sc_haltype2q[ATH9K_WME_AC_VO+1]; /* HAL WME AC -> h/w qnum */ |
| 994 | u32 sc_ant_tx[8]; /* recent tx frames/antenna */ | 994 | u32 sc_ant_tx[8]; /* recent tx frames/antenna */ |
| 995 | u16 seq_no; /* TX sequence number */ | ||
| 995 | 996 | ||
| 996 | /* Beacon */ | 997 | /* Beacon */ |
| 997 | struct ath9k_tx_queue_info sc_beacon_qi; | 998 | struct ath9k_tx_queue_info sc_beacon_qi; |
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index c5107f269f24..99badf1404c3 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
| @@ -369,6 +369,20 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
| 369 | { | 369 | { |
| 370 | struct ath_softc *sc = hw->priv; | 370 | struct ath_softc *sc = hw->priv; |
| 371 | int hdrlen, padsize; | 371 | int hdrlen, padsize; |
| 372 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
| 373 | |||
| 374 | /* | ||
| 375 | * As a temporary workaround, assign seq# here; this will likely need | ||
| 376 | * to be cleaned up to work better with Beacon transmission and virtual | ||
| 377 | * BSSes. | ||
| 378 | */ | ||
| 379 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | ||
| 380 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
| 381 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | ||
| 382 | sc->seq_no += 0x10; | ||
| 383 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
| 384 | hdr->seq_ctrl |= cpu_to_le16(sc->seq_no); | ||
| 385 | } | ||
| 372 | 386 | ||
| 373 | /* Add the padding after the header if this is not already done */ | 387 | /* Add the padding after the header if this is not already done */ |
| 374 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 388 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
