Пример #1
0
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);
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}