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>
This commit is contained in:
parent
2f29fed3f8
commit
ca14405e3b
|
@ -294,7 +294,6 @@ struct ath_tx_control {
|
|||
* (axq_qnum).
|
||||
*/
|
||||
struct ath_tx {
|
||||
u16 seq_no;
|
||||
u32 txqsetup;
|
||||
spinlock_t txbuflock;
|
||||
struct list_head txbuf;
|
||||
|
@ -563,6 +562,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs);
|
|||
int ath_txq_update(struct ath_softc *sc, int qnum,
|
||||
struct ath9k_tx_queue_info *q);
|
||||
void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop);
|
||||
void ath_assign_seq(struct ath_common *common, struct sk_buff *skb);
|
||||
int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ath_tx_control *txctl);
|
||||
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,
|
|||
struct ath_vif {
|
||||
struct list_head list;
|
||||
|
||||
u16 seq_no;
|
||||
|
||||
/* BSS info */
|
||||
u8 bssid[ETH_ALEN];
|
||||
u16 aid;
|
||||
|
|
|
@ -144,16 +144,8 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw,
|
|||
mgmt_hdr->u.beacon.timestamp = avp->tsf_adjust;
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
|
||||
/*
|
||||
* TODO: make sure the seq# gets assigned properly (vs. other
|
||||
* TX frames)
|
||||
*/
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
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(common, skb);
|
||||
|
||||
if (vif->p2p)
|
||||
ath9k_beacon_add_noa(sc, avp, skb);
|
||||
|
|
|
@ -54,6 +54,12 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc)
|
|||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
struct sk_buff *skb;
|
||||
struct ath_vif *avp;
|
||||
|
||||
if (!sc->tx99_vif)
|
||||
return NULL;
|
||||
|
||||
avp = (struct ath_vif *)sc->tx99_vif->drv_priv;
|
||||
|
||||
skb = alloc_skb(len, GFP_KERNEL);
|
||||
if (!skb)
|
||||
|
@ -71,7 +77,7 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc)
|
|||
memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
|
||||
memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
|
||||
|
||||
hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
|
||||
hdr->seq_ctrl |= cpu_to_le16(avp->seq_no);
|
||||
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
memset(tx_info, 0, sizeof(*tx_info));
|
||||
|
|
|
@ -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) ||
|
||||
|
|
Loading…
Reference in New Issue