X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=carlfw%2Fsrc%2Fwlan.c;h=3d879bd3c4be5e2a1a06c1a96db4865cd2072a6f;hb=5d61afe9cc7019ce23856396488846950e656245;hp=e581fa8ddea34db0095a4d9d2516cf5eba89056e;hpb=54c07b610832e9400a528911ab11d900d1143abe;p=carl9170fw.git diff --git a/carlfw/src/wlan.c b/carlfw/src/wlan.c index e581fa8..3d879bd 100644 --- a/carlfw/src/wlan.c +++ b/carlfw/src/wlan.c @@ -452,13 +452,15 @@ static bool wlan_tx_status(struct dma_queue *queue, return true; } -#ifdef CONFIG_CARL9170FW_CAB_QUEUE if (unlikely(super->s.cab)) fw.wlan.cab_queue_len[super->s.vif_id]--; -#endif /* CONFIG_CARL9170FW_CAB_QUEUE */ wlan_tx_complete(super, success); + if (ieee80211_is_back_req(super->f.data.i3e.frame_control)) { + fw.wlan.queued_bar--; + } + /* recycle freed descriptors */ dma_reclaim(&fw.pta.down_queue, desc); down_trigger(); @@ -493,18 +495,20 @@ void __hot wlan_tx(struct dma_desc *desc) { struct carl9170_tx_superframe *super = DESC_PAYLOAD(desc); + if (ieee80211_is_back_req(super->f.data.i3e.frame_control)) { + fw.wlan.queued_bar++; + } + /* initialize rate control struct */ super->s.rix = 0; super->s.cnt = 1; hide_super(desc); -#ifdef CONFIG_CARL9170FW_CAB_QUEUE if (unlikely(super->s.cab)) { fw.wlan.cab_queue_len[super->s.vif_id]++; dma_put(&fw.wlan.cab_queue[super->s.vif_id], desc); return; } -#endif /* CONFIG_CARL9170FW_CAB_QUEUE */ _wlan_tx(desc); __wlan_tx(desc); @@ -566,8 +570,10 @@ static void wlan_send_buffered_ba(void) /* format outgoing BA */ ba->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK); ba->duration = cpu_to_le16(0); - memcpy(ba->ta, ctx->ta, 6); - memcpy(ba->ra, ctx->ra, 6); + + /* the BAR contains all necessary MACs. All we need is to swap them */ + memcpy(ba->ra, ctx->ta, 6); + memcpy(ba->ta, ctx->ra, 6); /* * Unfortunately, we cannot look into the hardware's scoreboard. @@ -576,7 +582,11 @@ static void wlan_send_buffered_ba(void) */ memset(ba->bitmap, 0x0, sizeof(ba->bitmap)); - ba->control = ctx->control; + /* + * Both, the original firmare and ath9k set the NO ACK flag in + * the BA Ack Policy subfield. + */ + ba->control = ctx->control | cpu_to_le16(1); ba->start_seq_num = ctx->start_seq_num; wlan_tx_fw(&baf->s, NULL); } @@ -628,9 +638,8 @@ static void handle_bar(struct dma_desc *desc __unused, struct ieee80211_hdr *hdr ctx = wlan_get_bar_cache_buffer(); - /* Brilliant! The BAR provides all necessary MACs! */ - memcpy(ctx->ra, bar->ta, 6); - memcpy(ctx->ta, bar->ra, 6); + memcpy(ctx->ra, bar->ra, 6); + memcpy(ctx->ta, bar->ta, 6); ctx->control = bar->control; ctx->start_seq_num = bar->start_seq_num; } @@ -688,12 +697,22 @@ static unsigned int wlan_rx_filter(struct dma_desc *desc) switch (le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE) { case IEEE80211_STYPE_BACK_REQ: handle_bar(desc, hdr, data_len, mac_err); - /* fallthrough */ rx_filter |= CARL9170_RX_FILTER_CTL_BACKR; break; case IEEE80211_STYPE_PSPOLL: rx_filter |= CARL9170_RX_FILTER_CTL_PSPOLL; break; + case IEEE80211_STYPE_BACK: + if (fw.wlan.queued_bar) { + /* + * Don't filter block acks when the application + * has queued BARs. This is because the firmware + * can't do the accouting and the application + * has to sort out if the BA belongs to any BARs. + */ + break; + } + /* otherwise fall through */ default: rx_filter |= CARL9170_RX_FILTER_CTL_OTHER; break; @@ -728,7 +747,6 @@ static void handle_rx(void) } } -#ifdef CONFIG_CARL9170FW_CAB_QUEUE void wlan_cab_flush_queue(const unsigned int vif) { struct dma_queue *cab_queue = &fw.wlan.cab_queue[vif]; @@ -849,7 +867,6 @@ static void wlan_send_buffered_cab(void) } } -#endif /* CONFIG_CARL9170FW_CAB_QUEUE */ static void handle_beacon_config(void) { @@ -862,9 +879,7 @@ static void handle_beacon_config(void) static void handle_pretbtt(void) { -#ifdef CONFIG_CARL9170FW_CAB_QUEUE fw.wlan.cab_flush_time = get_clock_counter(); -#endif /* CONFIG_CARL9170FW_CAB_QUEUE */ #ifdef CONFIG_CARL9170FW_RADIO_FUNCTIONS rf_psm(); @@ -897,9 +912,7 @@ static void handle_radar(void) static void wlan_janitor(void) { -#ifdef CONFIG_CARL9170FW_CAB_QUEUE wlan_send_buffered_cab(); -#endif /* CONFIG_CARL9170FW_CAB_QUEUE */ wlan_send_buffered_tx_status();