carl9170 firmware: add automatic BA filter
authorChristian Lamparter <chunkeey@googlemail.com>
Sat, 7 Jul 2012 15:24:53 +0000 (17:24 +0200)
committerChristian Lamparter <chunkeey@googlemail.com>
Sat, 7 Jul 2012 15:24:53 +0000 (17:24 +0200)
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 <chunkeey@googlemail.com>
carlfw/include/carl9170.h
carlfw/src/fw.c
carlfw/src/wlan.c
include/shared/fwdesc.h
tools/src/fwinfo.c

index d10a74e8064448eebbb60502a53b23c1bc7744ad..cb16415c5adbeed7a0350f99f680ccda3f19b453 100644 (file)
@@ -142,6 +142,8 @@ struct firmware_context_struct {
                unsigned int ba_tail_idx,
                             ba_head_idx,
                             queued_ba;
                unsigned int ba_tail_idx,
                             ba_head_idx,
                             queued_ba;
+
+               unsigned int queued_bar;
        } wlan;
 
        struct {
        } wlan;
 
        struct {
index fde4a5d4a3263f33a9408080f43c29d5324ee245..5bde67505e2b0250003382d24dfb2a8afdc2179b 100644 (file)
@@ -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_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) |
                                        BIT(CARL9170FW_USB_INIT_FIRMWARE) |
 #ifdef CONFIG_CARL9170FW_USB_UP_STREAM
                                        BIT(CARL9170FW_USB_UP_STREAM) |
index c23831bd358ffad0f2a4d5453e4f838dbb85004f..d3328d67e74a9be0a57cc467ce3af72548114e6c 100644 (file)
@@ -459,6 +459,10 @@ static bool wlan_tx_status(struct dma_queue *queue,
 
        wlan_tx_complete(super, success);
 
 
        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();
        /* 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);
 
 {
        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;
        /* 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);
                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;
                        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;
                default:
                        rx_filter |= CARL9170_RX_FILTER_CTL_OTHER;
                        break;
index 6d9c0891ce7f9edd1c0cf91af5b15e203dbd7c72..66848d47c88e993c2c04d328699e94249c5bad61 100644 (file)
@@ -78,6 +78,9 @@ enum carl9170fw_feature_list {
        /* HW (ANI, CCA, MIB) tally counters */
        CARL9170FW_HW_COUNTERS,
 
        /* 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
 };
        /* KEEP LAST */
        __CARL9170FW_FEATURE_NUM
 };
index 995e3ed11becdd2d274b33b2d0323cce71201680..0d5cd0947922d92243c61645a3b0ecb7f88827ed 100644 (file)
@@ -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_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,
 };
 
 static void check_feature_list(const struct carl9170fw_desc_head *head,