From c44c4d8d92080ad3231b0e36b0245ddc19253daa Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Tue, 9 May 2017 05:31:38 +0000 Subject: [PATCH] [iwm] Allow listening on both chains/atennas to get diversity. This might improve throughput slightly when far from the accesspoint, apparently by allowing the firmware to listen on either of the two antennas (if there are two, i.e. on 7260/7265/8260), whichever has a better reception. Obtained from: dragonflybsd.git 3b7fc5aac51f81062da0a2c8fdac23e683fbd548 --- sys/dev/iwm/if_iwm_phy_ctxt.c | 12 ++++++++++++ sys/dev/iwm/if_iwm_util.c | 15 +++++++++++++++ sys/dev/iwm/if_iwm_util.h | 2 ++ 3 files changed, 29 insertions(+) diff --git a/sys/dev/iwm/if_iwm_phy_ctxt.c b/sys/dev/iwm/if_iwm_phy_ctxt.c index 5d8d7d24059..242e3abc388 100644 --- a/sys/dev/iwm/if_iwm_phy_ctxt.c +++ b/sys/dev/iwm/if_iwm_phy_ctxt.c @@ -218,6 +218,18 @@ iwm_mvm_phy_ctxt_cmd_data(struct iwm_softc *sc, idle_cnt = chains_static; active_cnt = chains_dynamic; + /* In scenarios where we only ever use a single-stream rates, + * i.e. legacy 11b/g/a associations, single-stream APs or even + * static SMPS, enable both chains to get diversity, improving + * the case where we're far enough from the AP that attenuation + * between the two antennas is sufficiently different to impact + * performance. + */ + if (active_cnt == 1 && iwm_mvm_rx_diversity_allowed(sc)) { + idle_cnt = 2; + active_cnt = 2; + } + cmd->rxchain_info = htole32(iwm_mvm_get_valid_rx_ant(sc) << IWM_PHY_RX_CHAIN_VALID_POS); cmd->rxchain_info |= htole32(idle_cnt << IWM_PHY_RX_CHAIN_CNT_POS); diff --git a/sys/dev/iwm/if_iwm_util.c b/sys/dev/iwm/if_iwm_util.c index 4ce9c8a6db5..4744fa16340 100644 --- a/sys/dev/iwm/if_iwm_util.c +++ b/sys/dev/iwm/if_iwm_util.c @@ -153,6 +153,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -487,3 +488,17 @@ iwm_dma_contig_free(struct iwm_dma_info *dma) dma->tag = NULL; } } + +boolean_t +iwm_mvm_rx_diversity_allowed(struct iwm_softc *sc) +{ + if (num_of_ant(iwm_mvm_get_valid_rx_ant(sc)) == 1) + return FALSE; + + /* + * XXX Also return FALSE when SMPS (Spatial Multiplexing Powersave) + * is used on any vap (in the future). + */ + + return TRUE; +} diff --git a/sys/dev/iwm/if_iwm_util.h b/sys/dev/iwm/if_iwm_util.h index 460c660877c..f2109d4798a 100644 --- a/sys/dev/iwm/if_iwm_util.h +++ b/sys/dev/iwm/if_iwm_util.h @@ -120,6 +120,8 @@ extern int iwm_dma_contig_alloc(bus_dma_tag_t tag, struct iwm_dma_info *dma, bus_size_t size, bus_size_t alignment); extern void iwm_dma_contig_free(struct iwm_dma_info *); +extern boolean_t iwm_mvm_rx_diversity_allowed(struct iwm_softc *sc); + extern uint8_t iwm_ridx2rate(struct ieee80211_rateset *rs, int ridx); static inline uint8_t