diff options
author | Sujith Manoharan <c_manoha@qca.qualcomm.com> | 2014-10-08 07:13:19 +0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-10-08 23:24:15 +0400 |
commit | ca14405e3b25b38221d027d8970c1d74ed0b6532 (patch) | |
tree | e4ea8b1a4e189c9d9d7e7a3fc4b6b018a08b3a3d /drivers/net/wireless/ath/ath9k/xmit.c | |
parent | 2f29fed3f814f652a24b10c975b9d415a154fc9c (diff) | |
download | linux-ca14405e3b25b38221d027d8970c1d74ed0b6532.tar.xz |
ath9k: Fix sequence number assignment
Currently, ath9k uses a global counter for all
frames that need to be assigned a sequence number.
QoS-data frames are handled properly since they
have a per-tid counter. But, beacons and other
management frames use the same counter even if
multiple interfaces or contexts are present.
Fix this issue by making the counter per-interface
and using it when mac80211 sets IEEE80211_TX_CTL_ASSIGN_SEQ.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/xmit.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 151ae49fa57e..493a183d0aaf 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2139,6 +2139,28 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, return bf; } +void ath_assign_seq(struct ath_common *common, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; + struct ath_vif *avp; + + if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) + return; + + if (!vif) + return; + + avp = (struct ath_vif *)vif->drv_priv; + + if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + avp->seq_no += 0x10; + + hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); +} + static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, struct ath_tx_control *txctl) { @@ -2162,17 +2184,7 @@ static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, if (info->control.hw_key) frmlen += info->control.hw_key->icv_len; - /* - * As a temporary workaround, assign seq# here; this will likely need - * to be cleaned up to work better with Beacon transmission and virtual - * BSSes. - */ - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - sc->tx.seq_no += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); - } + ath_assign_seq(ath9k_hw_common(sc->sc_ah), skb); if ((vif && vif->type != NL80211_IFTYPE_AP && vif->type != NL80211_IFTYPE_AP_VLAN) || |