diff options
author | Sujith Manoharan <c_manoha@qca.qualcomm.com> | 2014-10-07 23:13:19 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-10-08 15:24:15 -0400 |
commit | ca14405e3b25b38221d027d8970c1d74ed0b6532 (patch) | |
tree | e4ea8b1a4e189c9d9d7e7a3fc4b6b018a08b3a3d | |
parent | 2f29fed3f814f652a24b10c975b9d415a154fc9c (diff) |
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>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/beacon.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/tx99.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 34 |
4 files changed, 35 insertions, 23 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index bfa0b1518da1..01a7db061c6a 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -294,7 +294,6 @@ struct ath_tx_control { | |||
294 | * (axq_qnum). | 294 | * (axq_qnum). |
295 | */ | 295 | */ |
296 | struct ath_tx { | 296 | struct ath_tx { |
297 | u16 seq_no; | ||
298 | u32 txqsetup; | 297 | u32 txqsetup; |
299 | spinlock_t txbuflock; | 298 | spinlock_t txbuflock; |
300 | struct list_head txbuf; | 299 | struct list_head txbuf; |
@@ -563,6 +562,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs); | |||
563 | int ath_txq_update(struct ath_softc *sc, int qnum, | 562 | int ath_txq_update(struct ath_softc *sc, int qnum, |
564 | struct ath9k_tx_queue_info *q); | 563 | struct ath9k_tx_queue_info *q); |
565 | void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop); | 564 | void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop); |
565 | void ath_assign_seq(struct ath_common *common, struct sk_buff *skb); | ||
566 | int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | 566 | int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, |
567 | struct ath_tx_control *txctl); | 567 | struct ath_tx_control *txctl); |
568 | void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 568 | void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
@@ -592,6 +592,8 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, | |||
592 | struct ath_vif { | 592 | struct ath_vif { |
593 | struct list_head list; | 593 | struct list_head list; |
594 | 594 | ||
595 | u16 seq_no; | ||
596 | |||
595 | /* BSS info */ | 597 | /* BSS info */ |
596 | u8 bssid[ETH_ALEN]; | 598 | u8 bssid[ETH_ALEN]; |
597 | u16 aid; | 599 | u16 aid; |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index a6af855ef6ed..ecb783beeec2 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -144,16 +144,8 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw, | |||
144 | mgmt_hdr->u.beacon.timestamp = avp->tsf_adjust; | 144 | mgmt_hdr->u.beacon.timestamp = avp->tsf_adjust; |
145 | 145 | ||
146 | info = IEEE80211_SKB_CB(skb); | 146 | info = IEEE80211_SKB_CB(skb); |
147 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 147 | |
148 | /* | 148 | ath_assign_seq(common, skb); |
149 | * TODO: make sure the seq# gets assigned properly (vs. other | ||
150 | * TX frames) | ||
151 | */ | ||
152 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
153 | sc->tx.seq_no += 0x10; | ||
154 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
155 | hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); | ||
156 | } | ||
157 | 149 | ||
158 | if (vif->p2p) | 150 | if (vif->p2p) |
159 | ath9k_beacon_add_noa(sc, avp, skb); | 151 | ath9k_beacon_add_noa(sc, avp, skb); |
diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c index 8a69d08ec55c..40ab65e6882f 100644 --- a/drivers/net/wireless/ath/ath9k/tx99.c +++ b/drivers/net/wireless/ath/ath9k/tx99.c | |||
@@ -54,6 +54,12 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) | |||
54 | struct ieee80211_hdr *hdr; | 54 | struct ieee80211_hdr *hdr; |
55 | struct ieee80211_tx_info *tx_info; | 55 | struct ieee80211_tx_info *tx_info; |
56 | struct sk_buff *skb; | 56 | struct sk_buff *skb; |
57 | struct ath_vif *avp; | ||
58 | |||
59 | if (!sc->tx99_vif) | ||
60 | return NULL; | ||
61 | |||
62 | avp = (struct ath_vif *)sc->tx99_vif->drv_priv; | ||
57 | 63 | ||
58 | skb = alloc_skb(len, GFP_KERNEL); | 64 | skb = alloc_skb(len, GFP_KERNEL); |
59 | if (!skb) | 65 | if (!skb) |
@@ -71,7 +77,7 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) | |||
71 | memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); | 77 | memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); |
72 | memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); | 78 | memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); |
73 | 79 | ||
74 | hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); | 80 | hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); |
75 | 81 | ||
76 | tx_info = IEEE80211_SKB_CB(skb); | 82 | tx_info = IEEE80211_SKB_CB(skb); |
77 | memset(tx_info, 0, sizeof(*tx_info)); | 83 | memset(tx_info, 0, sizeof(*tx_info)); |
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, | |||
2139 | return bf; | 2139 | return bf; |
2140 | } | 2140 | } |
2141 | 2141 | ||
2142 | void ath_assign_seq(struct ath_common *common, struct sk_buff *skb) | ||
2143 | { | ||
2144 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
2145 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
2146 | struct ieee80211_vif *vif = info->control.vif; | ||
2147 | struct ath_vif *avp; | ||
2148 | |||
2149 | if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) | ||
2150 | return; | ||
2151 | |||
2152 | if (!vif) | ||
2153 | return; | ||
2154 | |||
2155 | avp = (struct ath_vif *)vif->drv_priv; | ||
2156 | |||
2157 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | ||
2158 | avp->seq_no += 0x10; | ||
2159 | |||
2160 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
2161 | hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); | ||
2162 | } | ||
2163 | |||
2142 | static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, | 2164 | static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, |
2143 | struct ath_tx_control *txctl) | 2165 | struct ath_tx_control *txctl) |
2144 | { | 2166 | { |
@@ -2162,17 +2184,7 @@ static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2162 | if (info->control.hw_key) | 2184 | if (info->control.hw_key) |
2163 | frmlen += info->control.hw_key->icv_len; | 2185 | frmlen += info->control.hw_key->icv_len; |
2164 | 2186 | ||
2165 | /* | 2187 | ath_assign_seq(ath9k_hw_common(sc->sc_ah), skb); |
2166 | * As a temporary workaround, assign seq# here; this will likely need | ||
2167 | * to be cleaned up to work better with Beacon transmission and virtual | ||
2168 | * BSSes. | ||
2169 | */ | ||
2170 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | ||
2171 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | ||
2172 | sc->tx.seq_no += 0x10; | ||
2173 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
2174 | hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); | ||
2175 | } | ||
2176 | 2188 | ||
2177 | if ((vif && vif->type != NL80211_IFTYPE_AP && | 2189 | if ((vif && vif->type != NL80211_IFTYPE_AP && |
2178 | vif->type != NL80211_IFTYPE_AP_VLAN) || | 2190 | vif->type != NL80211_IFTYPE_AP_VLAN) || |