From 3ea9a05ea4197045ff042588b06f3a270db9b8a3 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 7 Jul 2012 17:24:53 +0200 Subject: [PATCH] carl9170 firmware: add automatic BA filter BA are normally filtered to conserve bandwidth and cpu cycles. However, if the application has sent a BAR, the firmware has to escalate the BA accouting. Hence, for a brief period, the firmware has to let all BA temporarily pass through the filter. Signed-off-by: Christian Lamparter --- carlfw/include/carl9170.h | 2 ++ carlfw/src/fw.c | 1 + carlfw/src/wlan.c | 20 +++++++++++++++++++- include/shared/fwdesc.h | 3 +++ tools/src/fwinfo.c | 1 + 5 files changed, 26 insertions(+), 1 deletion(-) diff --git a/carlfw/include/carl9170.h b/carlfw/include/carl9170.h index d10a74e..cb16415 100644 --- a/carlfw/include/carl9170.h +++ b/carlfw/include/carl9170.h @@ -142,6 +142,8 @@ struct firmware_context_struct { unsigned int ba_tail_idx, ba_head_idx, queued_ba; + + unsigned int queued_bar; } wlan; struct { diff --git a/carlfw/src/fw.c b/carlfw/src/fw.c index fde4a5d..5bde675 100644 --- a/carlfw/src/fw.c +++ b/carlfw/src/fw.c @@ -38,6 +38,7 @@ const struct carl9170_firmware_descriptor __section(fwdsc) carl9170fw_desc = { BIT(CARL9170FW_HANDLE_BACK_REQ) | BIT(CARL9170FW_RX_FILTER) | BIT(CARL9170FW_HW_COUNTERS) | + BIT(CARL9170FW_RX_BA_FILTER) | BIT(CARL9170FW_USB_INIT_FIRMWARE) | #ifdef CONFIG_CARL9170FW_USB_UP_STREAM BIT(CARL9170FW_USB_UP_STREAM) | diff --git a/carlfw/src/wlan.c b/carlfw/src/wlan.c index c23831b..d3328d6 100644 --- a/carlfw/src/wlan.c +++ b/carlfw/src/wlan.c @@ -459,6 +459,10 @@ static bool wlan_tx_status(struct dma_queue *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,6 +497,10 @@ 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; @@ -693,12 +701,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; diff --git a/include/shared/fwdesc.h b/include/shared/fwdesc.h index 6d9c089..66848d4 100644 --- a/include/shared/fwdesc.h +++ b/include/shared/fwdesc.h @@ -78,6 +78,9 @@ enum carl9170fw_feature_list { /* HW (ANI, CCA, MIB) tally counters */ CARL9170FW_HW_COUNTERS, + /* Firmware will pass BA when BARs are queued */ + CARL9170FW_RX_BA_FILTER, + /* KEEP LAST */ __CARL9170FW_FEATURE_NUM }; diff --git a/tools/src/fwinfo.c b/tools/src/fwinfo.c index 995e3ed..0d5cd09 100644 --- a/tools/src/fwinfo.c +++ b/tools/src/fwinfo.c @@ -68,6 +68,7 @@ static const struct feature_list known_otus_features_v1[] = { CHECK_FOR_FEATURE(CARL9170FW_WOL), CHECK_FOR_FEATURE(CARL9170FW_FIXED_5GHZ_PSM), CHECK_FOR_FEATURE(CARL9170FW_HW_COUNTERS), + CHECK_FOR_FEATURE(CARL9170FW_RX_BA_FILTER), }; static void check_feature_list(const struct carl9170fw_desc_head *head, -- 2.31.1