carl9170 firmware: improve mac reset handling
[carl9170fw.git] / carlfw / src / wlan.c
index de13dbf317e57495428881e4d53196674e2b7e31..09f48fdc43b4640fbcfaf595eab10730c07a95ce 100644 (file)
@@ -625,16 +625,11 @@ void wlan_cab_flush_queue(const unsigned int vif)
        }
 }
 
-static uint8_t *beacon_find_ie(uint8_t ie)
+static uint8_t *beacon_find_ie(uint8_t ie, void *addr,
+                              const unsigned int len)
 {
-       struct ieee80211_mgmt *mgmt = getp(AR9170_MAC_REG_BCN_ADDR);
+       struct ieee80211_mgmt *mgmt = addr;
        uint8_t *pos, *end;
-       unsigned int len;
-
-       len = get(AR9170_MAC_REG_BCN_LENGTH);
-
-       if (len < FCS_LEN + sizeof(mgmt))
-               return NULL;
 
        pos = mgmt->u.beacon.variable;
        end = (uint8_t *) ((unsigned long)mgmt + (len - FCS_LEN));
@@ -651,12 +646,13 @@ static uint8_t *beacon_find_ie(uint8_t ie)
        return NULL;
 }
 
-void wlan_cab_modify_dtim_beacon(const unsigned int vif)
+void wlan_cab_modify_dtim_beacon(const unsigned int vif,
+       const unsigned int addr, const unsigned int len)
 {
        uint8_t *_ie;
        struct ieee80211_tim_ie *ie;
 
-       _ie = beacon_find_ie(WLAN_EID_TIM);
+       _ie = beacon_find_ie(WLAN_EID_TIM, (void *)addr, len);
        if (likely(_ie)) {
                ie = (struct ieee80211_tim_ie *) &_ie[2];
 
@@ -669,7 +665,7 @@ void wlan_cab_modify_dtim_beacon(const unsigned int vif)
                        fw.wlan.cab_flush_trigger[vif] = CARL9170_CAB_TRIGGER_EMPTY;
                }
 
-               /* Triggered by CARL9170_CAB_TRIGGER_ARMED || CARL9170_CAB_TRIGGER_READY || CARL9170_CAB_TRIGGER_DEFER */
+               /* Triggered by CARL9170_CAB_TRIGGER_ARMED || CARL9170_CAB_TRIGGER_DEFER */
                if (fw.wlan.cab_flush_trigger[vif]) {
                        /* Set the almighty Multicast Traffic Indication Bit. */
                        ie->bitmap_ctrl |= 0x1;
@@ -685,26 +681,13 @@ 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);
+
+       set(AR9170_MAC_REG_BCN_CTRL, AR9170_BCN_CTRL_READY);
 }
 
 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 */
 
@@ -745,7 +728,7 @@ static void wlan_janitor(void)
        unsigned int i;
 
        for (i = 0; i < CARL9170_INTF_NUM; i++) {
-               if (unlikely(fw.wlan.cab_flush_trigger[i] == CARL9170_CAB_TRIGGER_READY)) {
+               if (unlikely(fw.wlan.cab_flush_trigger[i] == CARL9170_CAB_TRIGGER_ARMED)) {
                        /*
                         * This is hardcoded into carl9170usb driver.
                         *
@@ -801,6 +784,9 @@ void handle_wlan(void)
                }                                       \
        } while (0)
 
+       intr |= fw.wlan.soft_int;
+       fw.wlan.soft_int = 0;
+
        HANDLER(intr, AR9170_MAC_INT_PRETBTT, handle_pretbtt);
 
        HANDLER(intr, AR9170_MAC_INT_ATIM, handle_atim);
@@ -928,6 +914,7 @@ static void wlan_mac_reset(void)
        uint32_t cam_mode;
        uint32_t ack_power;
        uint32_t rts_cts_tpc;
+       uint32_t rts_cts_rate;
        unsigned int i;
 
 #ifdef CONFIG_CARL9170FW_RADIO_FUNCTIONS
@@ -948,6 +935,7 @@ static void wlan_mac_reset(void)
 
        ack_power = get(AR9170_MAC_REG_ACK_TPC);
        rts_cts_tpc = get(AR9170_MAC_REG_RTS_CTS_TPC);
+       rts_cts_rate = get(AR9170_MAC_REG_RTS_CTS_RATE);
 
 #ifdef CONFIG_CARL9170FW_RADIO_FUNCTIONS
        /* 0x1c8960 write only */
@@ -989,6 +977,7 @@ static void wlan_mac_reset(void)
 
        set(AR9170_MAC_REG_RTS_CTS_TPC, rts_cts_tpc);
        set(AR9170_MAC_REG_ACK_TPC, ack_power);
+       set(AR9170_MAC_REG_RTS_CTS_RATE, rts_cts_rate);
 
 #ifdef CONFIG_CARL9170FW_RADIO_FUNCTIONS
        set(AR9170_PHY_REG_SWITCH_CHAIN_2, rx_BB);
@@ -1000,17 +989,24 @@ static void wlan_mac_reset(void)
         * set(AR9170_PHY_REG_CCA_THRESHOLD, 0x0);
         */
 
+       /* Reinitialize all WLAN TX DMA queues. */
        for (i = 0; i < __AR9170_NUM_TX_QUEUES; i++) {
-               DBG("Q:%d l:%d h:%p t:%p\n", i, queue_len(&fw.wlan.tx_queue[i]),
-                    fw.wlan.tx_queue[i].head, fw.wlan.tx_queue[i].terminator);
+               struct dma_desc *iter;
 
-               set_wlan_txq_dma_addr(i, (uint32_t) fw.wlan.tx_queue[i].head);
+               __for_each_desc_bits(iter, &fw.wlan.tx_queue[i], AR9170_OWN_BITS_SW);
 
-               if (!queue_empty(&fw.wlan.tx_queue[i]))
+               set_wlan_txq_dma_addr(i, (uint32_t) iter);
+               if (!is_terminator(&fw.wlan.tx_queue[i], iter))
                        wlan_trigger(BIT(i));
+
+               DBG("Q:%d l:%d h:%p t:%p cu:%p it:%p ct:%x st:%x\n", i, queue_len(&fw.wlan.tx_queue[i]),
+                    fw.wlan.tx_queue[i].head, fw.wlan.tx_queue[i].terminator,
+                    get_wlan_txq_addr(i), iter, iter->ctrl, iter->status);
        }
 
-       handle_rx();
+       fw.wlan.soft_int |= AR9170_MAC_INT_RXC | AR9170_MAC_INT_TXC |
+                           AR9170_MAC_INT_RETRY_FAIL;
+
        set(AR9170_MAC_REG_DMA_RXQ_ADDR, (uint32_t) fw.wlan.rx_queue.head);
        wlan_trigger(AR9170_DMA_TRIGGER_RXQ);
 }