carl9170: utilize fw seq counter for mgmt/non-QoS data frames
authorChristian Lamparter <chunkeey@googlemail.com>
Sat, 22 Jan 2011 23:18:28 +0000 (00:18 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 27 Jan 2011 21:03:56 +0000 (16:03 -0500)
"mac80211 will properly assign sequence numbers to QoS-data
frames but cannot do so correctly for non-QoS-data and
management frames because beacons need them from that counter
as well and mac80211 cannot guarantee proper sequencing."

Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/carl9170/carl9170.h
drivers/net/wireless/ath/carl9170/fw.c
drivers/net/wireless/ath/carl9170/main.c
drivers/net/wireless/ath/carl9170/tx.c

index d07ff7f2fd92d653103538b86353c6c986f9aca9..420d437f95803e196c02afc3f752d326ed827901 100644 (file)
@@ -283,6 +283,7 @@ struct ar9170 {
                unsigned int mem_blocks;
                unsigned int mem_block_size;
                unsigned int rx_size;
+               unsigned int tx_seq_table;
        } fw;
 
        /* reset / stuck frames/queue detection */
index a4e5b4458c00fa0c1a823434d7d25bc3146aa578..9517ede9e2dfdbb104042c3f520e9cb36a18c778 100644 (file)
@@ -150,6 +150,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
        const struct carl9170fw_otus_desc *otus_desc;
        const struct carl9170fw_chk_desc *chk_desc;
        const struct carl9170fw_last_desc *last_desc;
+       const struct carl9170fw_txsq_desc *txsq_desc;
 
        last_desc = carl9170_fw_find_desc(ar, LAST_MAGIC,
                sizeof(*last_desc), CARL9170FW_LAST_DESC_CUR_VER);
@@ -299,6 +300,17 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
                }
        }
 
+       txsq_desc = carl9170_fw_find_desc(ar, TXSQ_MAGIC,
+               sizeof(*txsq_desc), CARL9170FW_TXSQ_DESC_CUR_VER);
+
+       if (txsq_desc) {
+               ar->fw.tx_seq_table = le32_to_cpu(txsq_desc->seq_table_addr);
+               if (!valid_cpu_addr(ar->fw.tx_seq_table))
+                       return -EINVAL;
+       } else {
+               ar->fw.tx_seq_table = 0;
+       }
+
 #undef SUPPORTED
        return 0;
 }
index ecfb80b059d1e80393da2cd9d13aa72e8ea36fe6..ede3d7e5a048d3a356cc56890318ea391df81241 100644 (file)
@@ -662,6 +662,13 @@ init:
                        goto unlock;
        }
 
+       if (ar->fw.tx_seq_table) {
+               err = carl9170_write_reg(ar, ar->fw.tx_seq_table + vif_id * 4,
+                                        0);
+               if (err)
+                       goto unlock;
+       }
+
 unlock:
        if (err && (vif_id >= 0)) {
                vif_priv->active = false;
index 6cc58e052d101727c00e084667ba4527d7d74ef1..6f41e21d3a1c92e2526813769935be2fb4b8bab1 100644 (file)
@@ -862,6 +862,9 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
        if (unlikely(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM))
                txc->s.misc |= CARL9170_TX_SUPER_MISC_CAB;
 
+       if (unlikely(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
+               txc->s.misc |= CARL9170_TX_SUPER_MISC_ASSIGN_SEQ;
+
        if (unlikely(ieee80211_is_probe_resp(hdr->frame_control)))
                txc->s.misc |= CARL9170_TX_SUPER_MISC_FILL_IN_TSF;