carl9170 firmware: revamp Content After Beacon handling
authorChristian Lamparter <chunkeey@googlemail.com>
Tue, 24 Aug 2010 00:44:50 +0000 (02:44 +0200)
committerChristian Lamparter <chunkeey@googlemail.com>
Tue, 24 Aug 2010 01:31:38 +0000 (03:31 +0200)
Commit "carl9170 firmware: Support multiple CAB queues"
introduced a regression. The CAB queue was drained too
early and therefore the bc/mc buffered frames were sent
out at the wrong dtim period.

This patch takes care of the stated regression, but it
also fixes yet another, this time a more theoretical
race in multi AP mode.

Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
carlfw/include/carl9170.h
carlfw/src/cmd.c
carlfw/src/wlan.c

index 6b19303cb15142ff58b1abb517016fb0a8518112..2ae4f630e3d10e717c21b318d64d3b157cd0c183 100644 (file)
@@ -45,8 +45,9 @@ struct carl9170_bar_ctx {
 #ifdef CONFIG_CARL9170FW_CAB_QUEUE
 enum carl9170_cab_trigger {
        CARL9170_CAB_TRIGGER_EMPTY      = 0,
-       CARL9170_CAB_TRIGGER_ARMED      = BIT(0),
-       CARL9170_CAB_TRIGGER_DEFER      = BIT(1),
+       CARL9170_CAB_TRIGGER_READY      = BIT(0),
+       CARL9170_CAB_TRIGGER_ARMED      = BIT(1),
+       CARL9170_CAB_TRIGGER_DEFER      = BIT(2),
 };
 #endif /* CONFIG_CARL9170FW_CAB_QUEUE */
 
@@ -105,8 +106,8 @@ struct firmware_context_struct {
                /* CAB */
                struct dma_queue cab_queue[CARL9170_INTF_NUM];
                unsigned int cab_queue_len[CARL9170_INTF_NUM];
-               unsigned int cab_flush_time, cab_flush_vif;
-               enum carl9170_cab_trigger cab_flush_trigger;
+               unsigned int cab_flush_time;
+               enum carl9170_cab_trigger cab_flush_trigger[CARL9170_INTF_NUM];
 #endif /* CONFIG_CARL9170FW_CAB_QUEUE */
 
                /* tx status */
index 281ae9c9a1b19ad1f8befb896843e54c10a23771..5cfd8705e44786cafd195401f438da71ba5a2239 100644 (file)
@@ -90,8 +90,7 @@ void handle_cmd(struct carl9170_rsp *resp)
                        set(AR9170_MAC_REG_BCN_CTRL, AR9170_BCN_CTRL_READY);
                } else {
                        wlan_cab_flush_queue(cmd->cab_flush.vif_id);
-                       if (fw.wlan.cab_flush_vif == cmd->cab_flush.vif_id)
-                               fw.wlan.cab_flush_trigger = CARL9170_CAB_TRIGGER_EMPTY;
+                       fw.wlan.cab_flush_trigger[i] = CARL9170_CAB_TRIGGER_EMPTY;
                }
                break;
 #endif /* CONFIG_CARL9170FW_CAB_QUEUE */
index cd169ff5cac4361270ca1c1f0c30a295e2998c09..de13dbf317e57495428881e4d53196674e2b7e31 100644 (file)
@@ -659,19 +659,18 @@ void wlan_cab_modify_dtim_beacon(const unsigned int vif)
        _ie = beacon_find_ie(WLAN_EID_TIM);
        if (likely(_ie)) {
                ie = (struct ieee80211_tim_ie *) &_ie[2];
-               fw.wlan.cab_flush_vif = vif;
 
                if (!queue_empty(&fw.wlan.cab_queue[vif]) && (ie->dtim_count == 0)) {
                        /* schedule DTIM transfer */
-                       fw.wlan.cab_flush_trigger = CARL9170_CAB_TRIGGER_ARMED;
-               } else if ((fw.wlan.cab_queue_len[vif] == 0) && (fw.wlan.cab_flush_trigger)) {
+                       fw.wlan.cab_flush_trigger[vif] = CARL9170_CAB_TRIGGER_ARMED;
+               } else if ((fw.wlan.cab_queue_len[vif] == 0) && (fw.wlan.cab_flush_trigger[vif])) {
                        /* undo all chances to the beacon structure */
                        ie->bitmap_ctrl &= ~0x1;
-                       fw.wlan.cab_flush_trigger = CARL9170_CAB_TRIGGER_EMPTY;
+                       fw.wlan.cab_flush_trigger[vif] = CARL9170_CAB_TRIGGER_EMPTY;
                }
 
-               /* Triggered by CARL9170_CAB_TRIGGER_ARMED || CARL9170_CAB_TRIGGER_DEFER */
-               if (fw.wlan.cab_flush_trigger) {
+               /* Triggered by CARL9170_CAB_TRIGGER_ARMED || CARL9170_CAB_TRIGGER_READY || CARL9170_CAB_TRIGGER_DEFER */
+               if (fw.wlan.cab_flush_trigger[vif]) {
                        /* Set the almighty Multicast Traffic Indication Bit. */
                        ie->bitmap_ctrl |= 0x1;
                }
@@ -691,6 +690,21 @@ static void handle_beacon_config(void)
 static void handle_pretbtt(void)
 {
 #ifdef CONFIG_CARL9170FW_CAB_QUEUE
+#if CARL9170_INTF_NUM != 2
+       /* GCC BUG ? */
+       unsigned int i;
+
+       for (i = 0; i < CARL9170_INTF_NUM; i++) {
+               if (unlikely(fw.wlan.cab_flush_trigger[i] == CARL9170_CAB_TRIGGER_ARMED))
+                       fw.wlan.cab_flush_trigger[i] = CARL9170_CAB_TRIGGER_READY;
+       }
+#else
+       if (unlikely(fw.wlan.cab_flush_trigger[0] == CARL9170_CAB_TRIGGER_ARMED))
+               fw.wlan.cab_flush_trigger[0] = CARL9170_CAB_TRIGGER_READY;
+       if (unlikely(fw.wlan.cab_flush_trigger[1] == CARL9170_CAB_TRIGGER_ARMED))
+               fw.wlan.cab_flush_trigger[1] = CARL9170_CAB_TRIGGER_READY;
+#endif
+
        fw.wlan.cab_flush_time = get_clock_counter();
 #endif /* CONFIG_CARL9170FW_CAB_QUEUE */
 
@@ -728,28 +742,33 @@ static void handle_radar(void)
 static void wlan_janitor(void)
 {
 #ifdef CONFIG_CARL9170FW_CAB_QUEUE
-       if (unlikely(fw.wlan.cab_flush_trigger == CARL9170_CAB_TRIGGER_ARMED)) {
-               /*
-                * This is hardcoded into carl9170usb driver.
-                *
-                * The driver must set the PRETBTT event to beacon_interval -
-                * CARL9170_PRETBTT_KUS (usually 6) Kus.
-                *
-                * But still, we can only do so much about 802.11-2007 9.3.2.1 &
-                * 11.2.1.6. Let's hope the current solution is adequate enough.
-                */
-
-               if (is_after_msecs(fw.wlan.cab_flush_time, (CARL9170_TBTT_DELTA))) {
-                       wlan_cab_flush_queue(fw.wlan.cab_flush_vif);
+       unsigned int i;
 
+       for (i = 0; i < CARL9170_INTF_NUM; i++) {
+               if (unlikely(fw.wlan.cab_flush_trigger[i] == CARL9170_CAB_TRIGGER_READY)) {
                        /*
-                        * This prevents the code from sending new BC/MC frames
-                        * which were queued after the previous buffered traffic
-                        * has been sent out... They will have to wait until the
-                        * next DTIM beacon comes along.
+                        * This is hardcoded into carl9170usb driver.
+                        *
+                        * The driver must set the PRETBTT event to beacon_interval -
+                        * CARL9170_PRETBTT_KUS (usually 6) Kus.
+                        *
+                        * But still, we can only do so much about 802.11-2007 9.3.2.1 &
+                        * 11.2.1.6. Let's hope the current solution is adequate enough.
                         */
-                       fw.wlan.cab_flush_trigger = CARL9170_CAB_TRIGGER_DEFER;
+
+                       if (is_after_msecs(fw.wlan.cab_flush_time, (CARL9170_TBTT_DELTA))) {
+                               wlan_cab_flush_queue(i);
+
+                               /*
+                                * This prevents the code from sending new BC/MC frames
+                                * which were queued after the previous buffered traffic
+                                * has been sent out... They will have to wait until the
+                                * next DTIM beacon comes along.
+                                */
+                               fw.wlan.cab_flush_trigger[i] = CARL9170_CAB_TRIGGER_DEFER;
+                       }
                }
+
        }
 #endif /* CONFIG_CARL9170FW_CAB_QUEUE */