carl9170 firmware: per-vif tx sequence counter
authorChristian Lamparter <chunkeey@googlemail.com>
Sat, 22 Jan 2011 19:52:56 +0000 (20:52 +0100)
committerChristian Lamparter <chunkeey@googlemail.com>
Sat, 22 Jan 2011 21:38:43 +0000 (22:38 +0100)
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>
carlfw/include/carl9170.h
carlfw/include/fwdsc.h
carlfw/include/wl.h
carlfw/src/cmd.c
carlfw/src/fw.c
carlfw/src/wlan.c
include/shared/fwdesc.h
include/shared/version.h
include/shared/wlan.h
tools/src/fwinfo.c

index b57993d2d7e70abafc582aa86f64fee80564416e..29e1e29c062d70b058665ba5396a2dcd6d0fda02 100644 (file)
@@ -114,6 +114,9 @@ struct firmware_context_struct {
                unsigned int rx_total;
                unsigned int rx_overruns;
 
                unsigned int rx_total;
                unsigned int rx_overruns;
 
+               /* tx sequence control counters */
+               unsigned int sequence[CARL9170_INTF_NUM];
+
 #ifdef CONFIG_CARL9170FW_TX_AMPDU
                /* tx aggregate scheduling */
                struct carl9170_tx_superframe *ampdu_prev[__AR9170_NUM_TX_QUEUES];
 #ifdef CONFIG_CARL9170FW_TX_AMPDU
                /* tx aggregate scheduling */
                struct carl9170_tx_superframe *ampdu_prev[__AR9170_NUM_TX_QUEUES];
index efab7fc5e9edf932cf9890d24e460ba63b301b60..d702795b3e91a3a4fed4c4beb83818cea0005ea6 100644 (file)
@@ -30,6 +30,7 @@
 
 struct carl9170_firmware_descriptor {
        struct carl9170fw_otus_desc otus;
 
 struct carl9170_firmware_descriptor {
        struct carl9170fw_otus_desc otus;
+       struct carl9170fw_txsq_desc txsq;
        struct carl9170fw_motd_desc motd;
        struct carl9170fw_dbg_desc  dbg;
        struct carl9170fw_last_desc last;
        struct carl9170fw_motd_desc motd;
        struct carl9170fw_dbg_desc  dbg;
        struct carl9170fw_last_desc last;
index 8c06f6a12ca0673bcd8a016bfd15723df125bb98..577fd05f31b789d778881441fad1b76de2f90f77 100644 (file)
@@ -261,9 +261,9 @@ void wlan_timer(void);
 void handle_wlan(void);
 
 void wlan_cab_flush_queue(const unsigned int vif);
 void handle_wlan(void);
 
 void wlan_cab_flush_queue(const unsigned int vif);
-void wlan_cab_modify_dtim_beacon(const unsigned int vif,
-                                const unsigned int bcn_addr,
-                                const unsigned int bcn_len);
+void wlan_modify_beacon(const unsigned int vif,
+                       const unsigned int bcn_addr,
+                       const unsigned int bcn_len);
 
 static inline void wlan_prepare_wol(void)
 {
 
 static inline void wlan_prepare_wol(void)
 {
index 5887891aa7abdb880c1e020c2acf92581af2bec8..a222c6ca25dff0bbaeb272c64e872423dd8498cf 100644 (file)
@@ -91,7 +91,7 @@ void handle_cmd(struct carl9170_rsp *resp)
                resp->hdr.len = 0;
 
                if (cmd->bcn_ctrl.mode & CARL9170_BCN_CTRL_CAB_TRIGGER) {
                resp->hdr.len = 0;
 
                if (cmd->bcn_ctrl.mode & CARL9170_BCN_CTRL_CAB_TRIGGER) {
-                       wlan_cab_modify_dtim_beacon(cmd->bcn_ctrl.vif_id,
+                       wlan_modify_beacon(cmd->bcn_ctrl.vif_id,
                                cmd->bcn_ctrl.bcn_addr, cmd->bcn_ctrl.bcn_len);
                        set(AR9170_MAC_REG_BCN_ADDR, cmd->bcn_ctrl.bcn_addr);
                        set(AR9170_MAC_REG_BCN_LENGTH, cmd->bcn_ctrl.bcn_len);
                                cmd->bcn_ctrl.bcn_addr, cmd->bcn_ctrl.bcn_len);
                        set(AR9170_MAC_REG_BCN_ADDR, cmd->bcn_ctrl.bcn_addr);
                        set(AR9170_MAC_REG_BCN_LENGTH, cmd->bcn_ctrl.bcn_len);
index e71425f3c94d8b87e5137e7cfddd909f84134ef0..1af4d90f595c3b445adf9cc64afd22d010aedf0c 100644 (file)
@@ -83,6 +83,10 @@ const struct carl9170_firmware_descriptor __section(fwdsc) carl9170fw_desc = {
             .api_ver = CONFIG_CARL9170FW_RELEASE_VERSION,
        ),
 
             .api_ver = CONFIG_CARL9170FW_RELEASE_VERSION,
        ),
 
+       FILL(txsq, TXSQ,
+            .seq_table_addr = cpu_to_le32(&fw.wlan.sequence),
+       ),
+
        FILL(motd, MOTD,
             .fw_year_month_day = cpu_to_le32(
                        CARL9170FW_SET_DAY(CARL9170FW_VERSION_DAY) +
        FILL(motd, MOTD,
             .fw_year_month_day = cpu_to_le32(
                        CARL9170FW_SET_DAY(CARL9170FW_VERSION_DAY) +
index 9eb336a267eee7c4858d1e057e18358cede4b7c8..c4cf0b3dfb0062b9957e706ab1ea76f1ea32a3f3 100644 (file)
@@ -296,11 +296,24 @@ static void __wlan_tx(struct dma_desc *desc)
 #endif /* CONFIG_CARL9170FW_LOOPBACK */
 }
 
 #endif /* CONFIG_CARL9170FW_LOOPBACK */
 }
 
+static void wlan_assign_seq(struct ieee80211_hdr *hdr, unsigned int vif)
+{
+       hdr->seq_ctrl &= cpu_to_le16(~IEEE80211_SCTL_SEQ);
+       hdr->seq_ctrl |= cpu_to_le16(fw.wlan.sequence[vif]);
+
+       if (!(hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG)))
+               fw.wlan.sequence[vif] += 0x10;
+}
+
 /* prepares frame for the first transmission */
 static void _wlan_tx(struct dma_desc *desc)
 {
        struct carl9170_tx_superframe *super = get_super(desc);
 
 /* prepares frame for the first transmission */
 static void _wlan_tx(struct dma_desc *desc)
 {
        struct carl9170_tx_superframe *super = get_super(desc);
 
+       if (unlikely(super->s.assign_seq)) {
+               wlan_assign_seq(&super->f.data.i3e, super->s.vif_id);
+       }
+
        if (unlikely(super->s.ampdu_commit_density)) {
                set(AR9170_MAC_REG_AMPDU_DENSITY,
                    MOD_VAL(AR9170_MAC_AMPDU_DENSITY,
        if (unlikely(super->s.ampdu_commit_density)) {
                set(AR9170_MAC_REG_AMPDU_DENSITY,
                    MOD_VAL(AR9170_MAC_AMPDU_DENSITY,
@@ -842,7 +855,7 @@ static uint8_t *beacon_find_ie(uint8_t ie, void *addr,
        return NULL;
 }
 
        return NULL;
 }
 
-void wlan_cab_modify_dtim_beacon(const unsigned int vif,
+void wlan_modify_beacon(const unsigned int vif,
        const unsigned int addr, const unsigned int len)
 {
        uint8_t *_ie;
        const unsigned int addr, const unsigned int len)
 {
        uint8_t *_ie;
@@ -867,6 +880,15 @@ void wlan_cab_modify_dtim_beacon(const unsigned int vif,
                        ie->bitmap_ctrl |= 0x1;
                }
        }
                        ie->bitmap_ctrl |= 0x1;
                }
        }
+
+       /*
+        * Ideally, the sequence number should be assigned by the TX arbiter
+        * hardware. But AFAIK that's not possible, so we have to go for the
+        * next best thing and write it into the beacon fifo during the open
+        * beacon update window.
+        */
+
+       wlan_assign_seq((struct ieee80211_hdr *)addr, vif);
 }
 #endif /* CONFIG_CARL9170FW_CAB_QUEUE */
 
 }
 #endif /* CONFIG_CARL9170FW_CAB_QUEUE */
 
@@ -877,8 +899,6 @@ static void handle_beacon_config(void)
        bcn_count = get(AR9170_MAC_REG_BCN_COUNT);
        send_cmd_to_host(4, CARL9170_RSP_BEACON_CONFIG, 0x00,
                         (uint8_t *) &bcn_count);
        bcn_count = get(AR9170_MAC_REG_BCN_COUNT);
        send_cmd_to_host(4, CARL9170_RSP_BEACON_CONFIG, 0x00,
                         (uint8_t *) &bcn_count);
-
-       set(AR9170_MAC_REG_BCN_CTRL, AR9170_BCN_CTRL_READY);
 }
 
 static void handle_pretbtt(void)
 }
 
 static void handle_pretbtt(void)
index 59c721336121cd299f7df621c70f189d47599287..921066822dd5a77529b9834fd958b1d7c7da3dbc 100644 (file)
@@ -81,6 +81,7 @@ enum carl9170fw_feature_list {
 #define FIX_MAGIC      "FIX\0"
 #define DBG_MAGIC      "DBG\0"
 #define CHK_MAGIC      "CHK\0"
 #define FIX_MAGIC      "FIX\0"
 #define DBG_MAGIC      "DBG\0"
 #define CHK_MAGIC      "CHK\0"
+#define TXSQ_MAGIC     "TXSQ"
 #define LAST_MAGIC     "LAST"
 
 #define CARL9170FW_SET_DAY(d) (((d) - 1) % 31)
 #define LAST_MAGIC     "LAST"
 
 #define CARL9170FW_SET_DAY(d) (((d) - 1) % 31)
@@ -175,6 +176,16 @@ struct carl9170fw_chk_desc {
 #define CARL9170FW_CHK_DESC_SIZE                       \
        (sizeof(struct carl9170fw_chk_desc))
 
 #define CARL9170FW_CHK_DESC_SIZE                       \
        (sizeof(struct carl9170fw_chk_desc))
 
+#define CARL9170FW_TXSQ_DESC_MIN_VER                   1
+#define CARL9170FW_TXSQ_DESC_CUR_VER                   1
+struct carl9170fw_txsq_desc {
+       struct carl9170fw_desc_head head;
+
+       __le32 seq_table_addr;
+} __packed;
+#define CARL9170FW_TXSQ_DESC_SIZE                      \
+       (sizeof(struct carl9170fw_txsq_desc))
+
 #define CARL9170FW_LAST_DESC_MIN_VER                   1
 #define CARL9170FW_LAST_DESC_CUR_VER                   2
 struct carl9170fw_last_desc {
 #define CARL9170FW_LAST_DESC_MIN_VER                   1
 #define CARL9170FW_LAST_DESC_CUR_VER                   2
 struct carl9170fw_last_desc {
index 043454a9ad587c72cb514e0f5c29b213f2c794fe..15095c035169c71c2f0b0576329d50e45be3e004 100644 (file)
@@ -2,6 +2,6 @@
 #define __CARL9170_SHARED_VERSION_H
 #define CARL9170FW_VERSION_YEAR 11
 #define CARL9170FW_VERSION_MONTH 1
 #define __CARL9170_SHARED_VERSION_H
 #define CARL9170FW_VERSION_YEAR 11
 #define CARL9170FW_VERSION_MONTH 1
-#define CARL9170FW_VERSION_DAY 15
+#define CARL9170FW_VERSION_DAY 22
 #define CARL9170FW_VERSION_GIT "1.9.2"
 #endif /* __CARL9170_SHARED_VERSION_H */
 #define CARL9170FW_VERSION_GIT "1.9.2"
 #endif /* __CARL9170_SHARED_VERSION_H */
index ff3b91713394306539e065eaf9353ff030e6bb1c..9e1324b67e08e19cc0bea538b74ed9ab0b5fb924 100644 (file)
@@ -251,7 +251,7 @@ struct carl9170_tx_superdesc {
        u8 ampdu_commit_factor:1;
        u8 ampdu_unused_bit:1;
        u8 queue:2;
        u8 ampdu_commit_factor:1;
        u8 ampdu_unused_bit:1;
        u8 queue:2;
-       u8 reserved:1;
+       u8 assign_seq:1;
        u8 vif_id:3;
        u8 fill_in_tsf:1;
        u8 cab:1;
        u8 vif_id:3;
        u8 fill_in_tsf:1;
        u8 cab:1;
@@ -299,6 +299,7 @@ struct _ar9170_tx_hwdesc {
 
 #define CARL9170_TX_SUPER_MISC_QUEUE                   0x3
 #define CARL9170_TX_SUPER_MISC_QUEUE_S                 0
 
 #define CARL9170_TX_SUPER_MISC_QUEUE                   0x3
 #define CARL9170_TX_SUPER_MISC_QUEUE_S                 0
+#define CARL9170_TX_SUPER_MISC_ASSIGN_SEQ              0x4
 #define        CARL9170_TX_SUPER_MISC_VIF_ID                   0x38
 #define        CARL9170_TX_SUPER_MISC_VIF_ID_S                 3
 #define        CARL9170_TX_SUPER_MISC_FILL_IN_TSF              0x40
 #define        CARL9170_TX_SUPER_MISC_VIF_ID                   0x38
 #define        CARL9170_TX_SUPER_MISC_VIF_ID_S                 3
 #define        CARL9170_TX_SUPER_MISC_FILL_IN_TSF              0x40
index 18ca8be67bf21f9cc779f178e0e132d304fea0fe..c54ff81e80f98916c27ee5ba9e2ce8f3910ea306 100644 (file)
@@ -165,6 +165,15 @@ static void show_dbg_desc(const struct carl9170fw_desc_head *head,
        DBG_ADDR("rx filer     ", rx_filter);
 }
 
        DBG_ADDR("rx filer     ", rx_filter);
 }
 
+static void show_txsq_desc(const struct carl9170fw_desc_head *head,
+                           struct carlfw *fw __unused)
+{
+       const struct carl9170fw_txsq_desc *txsq = (const void *) head;
+
+       fprintf(stdout, "\t\ttx-seq table addr: 0x%x\n",
+               le32_to_cpu(txsq->seq_table_addr));
+}
+
 static void show_chk_desc(const struct carl9170fw_desc_head *head,
                            struct carlfw *fw __unused)
 {
 static void show_chk_desc(const struct carl9170fw_desc_head *head,
                            struct carlfw *fw __unused)
 {
@@ -200,6 +209,7 @@ static const struct {
        uint16_t size;
 } known_magics[] = {
        ADD_HANDLER(OTUS, show_otus_desc),
        uint16_t size;
 } known_magics[] = {
        ADD_HANDLER(OTUS, show_otus_desc),
+       ADD_HANDLER(TXSQ, show_txsq_desc),
        ADD_HANDLER(MOTD, show_motd_desc),
        ADD_HANDLER(DBG, show_dbg_desc),
        ADD_HANDLER(FIX, show_fix_desc),
        ADD_HANDLER(MOTD, show_motd_desc),
        ADD_HANDLER(DBG, show_dbg_desc),
        ADD_HANDLER(FIX, show_fix_desc),