void wlc_stf_phy_chain_calc(struct wlc_info *wlc) { /* get available rx/tx chains */ wlc->stf->hw_txchain = (u8) getintvar(wlc->pub->vars, "txchain"); wlc->stf->hw_rxchain = (u8) getintvar(wlc->pub->vars, "rxchain"); /* these parameter are intended to be used for all PHY types */ if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) { if (WLCISNPHY(wlc->band)) { wlc->stf->hw_txchain = TXCHAIN_DEF_NPHY; } else { wlc->stf->hw_txchain = TXCHAIN_DEF; } } wlc->stf->txchain = wlc->stf->hw_txchain; wlc->stf->txstreams = (u8) WLC_BITSCNT(wlc->stf->hw_txchain); if (wlc->stf->hw_rxchain == 0 || wlc->stf->hw_rxchain == 0xf) { if (WLCISNPHY(wlc->band)) { wlc->stf->hw_rxchain = RXCHAIN_DEF_NPHY; } else { wlc->stf->hw_rxchain = RXCHAIN_DEF; } } wlc->stf->rxchain = wlc->stf->hw_rxchain; wlc->stf->rxstreams = (u8) WLC_BITSCNT(wlc->stf->hw_rxchain); /* initialize the txcore table */ bcopy(txcore_default, wlc->stf->txcore, sizeof(wlc->stf->txcore)); /* default spatial_policy */ wlc->stf->spatial_policy = MIN_SPATIAL_EXPANSION; wlc_stf_spatial_policy_set(wlc, MIN_SPATIAL_EXPANSION); }
static int wlc_stf_txcore_set(struct wlc_info *wlc, u8 Nsts, u8 core_mask) { WL_TRACE("wl%d: %s: Nsts %d core_mask %x\n", wlc->pub->unit, __func__, Nsts, core_mask); ASSERT((Nsts > 0) && (Nsts <= MAX_STREAMS_SUPPORTED)); if (WLC_BITSCNT(core_mask) > wlc->stf->txstreams) { core_mask = 0; } if ((WLC_BITSCNT(core_mask) == wlc->stf->txstreams) && ((core_mask & ~wlc->stf->txchain) || !(core_mask & wlc->stf->txchain))) { core_mask = wlc->stf->txchain; } ASSERT(!core_mask || Nsts <= WLC_BITSCNT(core_mask)); wlc->stf->txcore[Nsts] = core_mask; /* Nsts = 1..4, txcore index = 1..4 */ if (Nsts == 1) { /* Needs to update beacon and ucode generated response * frames when 1 stream core map changed */ wlc->stf->phytxant = core_mask << PHY_TXC_ANT_SHIFT; wlc_bmac_txant_set(wlc->hw, wlc->stf->phytxant); if (wlc->clk) { wlc_suspend_mac_and_wait(wlc); wlc_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec); wlc_enable_mac(wlc); } } return BCME_OK; }
static int wlc_olpc_get_min_2ss3ss_sdm_pwr(wlc_olpc_eng_info_t *olpc, ppr_t *txpwr, chanspec_t channel) { int8 sdmmin; int min_txpwr_limit = 0xffff; int err = 0; uint txchains = WLC_BITSCNT(olpc->wlc->stf->txchain); wl_tx_bw_t txbw = PPR_CHSPEC_BW(channel); while (WL_OLPC_BW_ITER_HAS_NEXT(txbw)) { /* get min of 2x2 */ if (txchains > 1) { err = ppr_get_vht_mcs_min(txpwr, txbw, WL_TX_NSS_2, WL_TX_MODE_NONE, WL_TX_CHAINS_2, &sdmmin); if (err == BCME_OK) { WL_OLPC_ENTRY(olpc, ("wl%d:%s: nss2 min=%d sdmmin=%d\n", olpc->wlc->pub->unit, __FUNCTION__, min_txpwr_limit, sdmmin)); if (sdmmin != WL_RATE_DISABLED) { min_txpwr_limit = MIN(min_txpwr_limit, sdmmin); } } } /* get min of 3x3 */ if (txchains > 2) { err = ppr_get_vht_mcs_min(txpwr, txbw, WL_TX_NSS_3, WL_TX_MODE_NONE, WL_TX_CHAINS_3, &sdmmin); if (err == BCME_OK) { WL_OLPC_ENTRY(olpc, ("wl%d:%s: nss3 min=%d sdmmin=%d\n", olpc->wlc->pub->unit, __FUNCTION__, min_txpwr_limit, sdmmin)); if (sdmmin != WL_RATE_DISABLED) { min_txpwr_limit = MIN(min_txpwr_limit, sdmmin); } } } txbw = wlc_olpc_bw_iter_next(txbw); } return min_txpwr_limit; }
int wlc_stf_txchain_set(struct wlc_info *wlc, s32 int_val, bool force) { u8 txchain = (u8) int_val; u8 txstreams; uint i; if (wlc->stf->txchain == txchain) return BCME_OK; if ((txchain & ~wlc->stf->hw_txchain) || !(txchain & wlc->stf->hw_txchain)) return BCME_RANGE; /* if nrate override is configured to be non-SISO STF mode, reject reducing txchain to 1 */ txstreams = (u8) WLC_BITSCNT(txchain); if (txstreams > MAX_STREAMS_SUPPORTED) return BCME_RANGE; if (txstreams == 1) { for (i = 0; i < NBANDS(wlc); i++) if ((RSPEC_STF(wlc->bandstate[i]->rspec_override) != PHY_TXC1_MODE_SISO) || (RSPEC_STF(wlc->bandstate[i]->mrspec_override) != PHY_TXC1_MODE_SISO)) { if (!force) return BCME_ERROR; /* over-write the override rspec */ if (RSPEC_STF(wlc->bandstate[i]->rspec_override) != PHY_TXC1_MODE_SISO) { wlc->bandstate[i]->rspec_override = 0; WL_ERROR("%s(): temp sense override non-SISO rspec_override\n", __func__); } if (RSPEC_STF (wlc->bandstate[i]->mrspec_override) != PHY_TXC1_MODE_SISO) { wlc->bandstate[i]->mrspec_override = 0; WL_ERROR("%s(): temp sense override non-SISO mrspec_override\n", __func__); } } } wlc->stf->txchain = txchain; wlc->stf->txstreams = txstreams; wlc_stf_stbc_tx_set(wlc, wlc->band->band_stf_stbc_tx); wlc_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]); wlc_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]); wlc->stf->txant = (wlc->stf->txstreams == 1) ? ANT_TX_FORCE_0 : ANT_TX_DEF; _wlc_stf_phy_txant_upd(wlc); wlc_phy_stf_chain_set(wlc->band->pi, wlc->stf->txchain, wlc->stf->rxchain); for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) wlc_stf_txcore_set(wlc, (u8) i, txcore_default[i]); return BCME_OK; }