aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith Manoharan <c_manoha@qca.qualcomm.com>2014-10-07 23:13:19 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-10-08 15:24:15 -0400
commitca14405e3b25b38221d027d8970c1d74ed0b6532 (patch)
treee4ea8b1a4e189c9d9d7e7a3fc4b6b018a08b3a3d
parent2f29fed3f814f652a24b10c975b9d415a154fc9c (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.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/tx99.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c34
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 */
296struct ath_tx { 296struct 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);
563int ath_txq_update(struct ath_softc *sc, int qnum, 562int ath_txq_update(struct ath_softc *sc, int qnum,
564 struct ath9k_tx_queue_info *q); 563 struct ath9k_tx_queue_info *q);
565void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop); 564void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop);
565void ath_assign_seq(struct ath_common *common, struct sk_buff *skb);
566int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, 566int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
567 struct ath_tx_control *txctl); 567 struct ath_tx_control *txctl);
568void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 568void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
@@ -592,6 +592,8 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
592struct ath_vif { 592struct 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
2142void 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
2142static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, 2164static 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) ||