aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith <Sujith.Manoharan@atheros.com>2009-03-09 00:01:57 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-03-16 18:09:38 -0400
commitc37452b0687e5c8942dd4866f7c614105e6050c3 (patch)
tree4d1d44cbbf601973cf48b07c9e3f0b06e0f9f4f8
parent9c81e8be236b7f1c94f9d055a97a83f84c81890f (diff)
ath9k: Fix bug in TX aggregation
mac80211 expects the driver to fill in the starting sequence number of an ADDBA request to initiate TX aggregation. IEEE80211_TX_CTL_AMPDU would be set for frames only after a successful ADDBA exchange, but we have to increment the internal sequence counter for the normal(non-AMPDU) data frames proerly. Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath9k/xmit.c49
1 files changed, 33 insertions, 16 deletions
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c
index a82d2ab7c3a0..f61ba2b7de71 100644
--- a/drivers/net/wireless/ath9k/xmit.c
+++ b/drivers/net/wireless/ath9k/xmit.c
@@ -55,9 +55,9 @@ static u32 bits_per_symbol[][2] = {
55 55
56#define IS_HT_RATE(_rate) ((_rate) & 0x80) 56#define IS_HT_RATE(_rate) ((_rate) & 0x80)
57 57
58static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, 58static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
59 struct ath_atx_tid *tid, 59 struct ath_atx_tid *tid,
60 struct list_head *bf_head); 60 struct list_head *bf_head);
61static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, 61static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
62 struct list_head *bf_q, 62 struct list_head *bf_q,
63 int txok, int sendbar); 63 int txok, int sendbar);
@@ -152,7 +152,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
152 bf = list_first_entry(&tid->buf_q, struct ath_buf, list); 152 bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
153 ASSERT(!bf_isretried(bf)); 153 ASSERT(!bf_isretried(bf));
154 list_move_tail(&bf->list, &bf_head); 154 list_move_tail(&bf->list, &bf_head);
155 ath_tx_send_normal(sc, txq, tid, &bf_head); 155 ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
156 } 156 }
157 157
158 spin_unlock_bh(&txq->axq_lock); 158 spin_unlock_bh(&txq->axq_lock);
@@ -1238,9 +1238,9 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
1238 ath_tx_txqaddbuf(sc, txctl->txq, bf_head); 1238 ath_tx_txqaddbuf(sc, txctl->txq, bf_head);
1239} 1239}
1240 1240
1241static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, 1241static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
1242 struct ath_atx_tid *tid, 1242 struct ath_atx_tid *tid,
1243 struct list_head *bf_head) 1243 struct list_head *bf_head)
1244{ 1244{
1245 struct ath_buf *bf; 1245 struct ath_buf *bf;
1246 1246
@@ -1256,6 +1256,19 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
1256 ath_tx_txqaddbuf(sc, txq, bf_head); 1256 ath_tx_txqaddbuf(sc, txq, bf_head);
1257} 1257}
1258 1258
1259static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
1260 struct list_head *bf_head)
1261{
1262 struct ath_buf *bf;
1263
1264 bf = list_first_entry(bf_head, struct ath_buf, list);
1265
1266 bf->bf_lastbf = bf;
1267 bf->bf_nframes = 1;
1268 ath_buf_set_rate(sc, bf);
1269 ath_tx_txqaddbuf(sc, txq, bf_head);
1270}
1271
1259static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) 1272static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
1260{ 1273{
1261 struct ieee80211_hdr *hdr; 1274 struct ieee80211_hdr *hdr;
@@ -1522,8 +1535,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
1522 1535
1523 bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3); 1536 bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3);
1524 1537
1525 if ((conf_is_ht(&sc->hw->conf) && !is_pae(skb) && 1538 if (conf_is_ht(&sc->hw->conf) && !is_pae(skb))
1526 (tx_info->flags & IEEE80211_TX_CTL_AMPDU)))
1527 bf->bf_state.bf_type |= BUF_HT; 1539 bf->bf_state.bf_type |= BUF_HT;
1528 1540
1529 bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq); 1541 bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq);
@@ -1560,14 +1572,17 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
1560{ 1572{
1561 struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; 1573 struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
1562 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 1574 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1575 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1563 struct ath_node *an = NULL; 1576 struct ath_node *an = NULL;
1564 struct list_head bf_head; 1577 struct list_head bf_head;
1565 struct ath_desc *ds; 1578 struct ath_desc *ds;
1566 struct ath_atx_tid *tid; 1579 struct ath_atx_tid *tid;
1567 struct ath_hw *ah = sc->sc_ah; 1580 struct ath_hw *ah = sc->sc_ah;
1568 int frm_type; 1581 int frm_type;
1582 __le16 fc;
1569 1583
1570 frm_type = get_hw_packet_type(skb); 1584 frm_type = get_hw_packet_type(skb);
1585 fc = hdr->frame_control;
1571 1586
1572 INIT_LIST_HEAD(&bf_head); 1587 INIT_LIST_HEAD(&bf_head);
1573 list_add_tail(&bf->list, &bf_head); 1588 list_add_tail(&bf->list, &bf_head);
@@ -1592,6 +1607,11 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
1592 an = (struct ath_node *)tx_info->control.sta->drv_priv; 1607 an = (struct ath_node *)tx_info->control.sta->drv_priv;
1593 tid = ATH_AN_2_TID(an, bf->bf_tidno); 1608 tid = ATH_AN_2_TID(an, bf->bf_tidno);
1594 1609
1610 if (!ieee80211_is_data_qos(fc)) {
1611 ath_tx_send_normal(sc, txctl->txq, &bf_head);
1612 goto tx_done;
1613 }
1614
1595 if (ath_aggr_query(sc, an, bf->bf_tidno)) { 1615 if (ath_aggr_query(sc, an, bf->bf_tidno)) {
1596 /* 1616 /*
1597 * Try aggregation if it's a unicast data frame 1617 * Try aggregation if it's a unicast data frame
@@ -1603,17 +1623,14 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
1603 * Send this frame as regular when ADDBA 1623 * Send this frame as regular when ADDBA
1604 * exchange is neither complete nor pending. 1624 * exchange is neither complete nor pending.
1605 */ 1625 */
1606 ath_tx_send_normal(sc, txctl->txq, 1626 ath_tx_send_ht_normal(sc, txctl->txq,
1607 tid, &bf_head); 1627 tid, &bf_head);
1608 } 1628 }
1609 } else { 1629 } else {
1610 bf->bf_lastbf = bf; 1630 ath_tx_send_normal(sc, txctl->txq, &bf_head);
1611 bf->bf_nframes = 1;
1612
1613 ath_buf_set_rate(sc, bf);
1614 ath_tx_txqaddbuf(sc, txctl->txq, &bf_head);
1615 } 1631 }
1616 1632
1633tx_done:
1617 spin_unlock_bh(&txctl->txq->axq_lock); 1634 spin_unlock_bh(&txctl->txq->axq_lock);
1618} 1635}
1619 1636