X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=carlfw%2Fsrc%2Fhostif.c;h=e445d5f164ad008ef7c14e25ca08b1e17766650b;hb=bd3e83c8a4065c23c0f437b231e8d4c26f82e20a;hp=5a1c62f4e324725a944786171220e3fa692e9655;hpb=12d3f1ba6ba522cd1ef11483d813fe2c2e64f04b;p=carl9170fw.git diff --git a/carlfw/src/hostif.c b/carlfw/src/hostif.c index 5a1c62f..e445d5f 100644 --- a/carlfw/src/hostif.c +++ b/carlfw/src/hostif.c @@ -30,7 +30,7 @@ static bool length_check(struct dma_desc *desc) { - volatile struct carl9170_tx_superframe *super = DESC_PAYLOAD(desc); + volatile struct carl9170_tx_superframe *super = __get_super(desc); if (unlikely(desc->totalLen < sizeof(struct carl9170_tx_superdesc))) return false; @@ -56,7 +56,7 @@ static void handle_download(void) * Under normal conditions, all completed descs should have * the AR9170_OWN_BITS_SE status flag set. * However there seems to be a undocumented case where the flag - * is _SW... + * is _SW ( handle_download_exception ) */ for_each_desc_not_bits(desc, &fw.pta.down_queue, AR9170_OWN_BITS_HW) { @@ -69,12 +69,12 @@ static void handle_download(void) * timeout mechanism. */ + wlan_tx_complete(__get_super(desc), false); dma_reclaim(&fw.pta.down_queue, desc); down_trigger(); - continue; + } else { + wlan_tx(desc); } - - wlan_tx(desc); } #ifdef CONFIG_CARL9170FW_DEBUG_LED_HEARTBEAT @@ -96,13 +96,8 @@ static void handle_upload(void) fw.usb.int_desc = desc; fw.usb.int_desc_available = 1; } else { -#ifdef CONFIG_CARL9170FW_LOOPBACK - dma_reclaim(&fw.pta.down_queue, desc); - down_trigger(); -#else dma_reclaim(&fw.wlan.rx_queue, desc); - _wlan_trigger(AR9170_DMA_TRIGGER_RXQ); -#endif /* CONFIG_CARL9170FW_LOOPBACK */ + wlan_trigger(AR9170_DMA_TRIGGER_RXQ); } } @@ -111,6 +106,39 @@ static void handle_upload(void) #endif /* CONFIG_CARL9170FW_DEBUG_LED_HEARTBEAT */ } +static void handle_download_exception(void) +{ + struct dma_desc *desc, *target; + + /* actually, the queue should be stopped by now? */ + usb_stop_down_queue(); + + target = (void *)((get(AR9170_PTA_REG_DN_CURR_ADDRH) << 16) | + get(AR9170_PTA_REG_DN_CURR_ADDRL)); + + /* + * Put "forgotten" packets from the head of the queue, back + * to the current position + */ + __while_desc_bits(desc, &fw.pta.down_queue, AR9170_OWN_BITS_HW) { + if (desc == target) + break; + + dma_reclaim(&fw.pta.down_queue, + dma_unlink_head(&fw.pta.down_queue)); + } + + __for_each_desc_continue(desc, &fw.pta.down_queue) { + if ((desc->status & AR9170_OWN_BITS) == AR9170_OWN_BITS_SW) + dma_fix_downqueue(desc); + } + + + usb_start_down_queue(); + + down_trigger(); +} + /* handle interrupts from DMA chip */ void handle_host_interface(void) { @@ -129,5 +157,9 @@ void handle_host_interface(void) HANDLER(pta_int, AR9170_PTA_INT_FLAG_UP, handle_upload); + /* This is just guesswork and MAGIC */ + pta_int = get(AR9170_PTA_REG_DMA_STATUS); + HANDLER(pta_int, 0x1, handle_download_exception); + #undef HANDLER }