/* * This function returns the channel number that control traffic is being sent on, for legacy * channels this is just the channel number, for 40MHZ channels it is the upper or lowre 20MHZ * sideband depending on the chanspec selected */ uint8 wf_chspec_ctlchan(chanspec_t chspec) { uint8 ctl_chan; /* Is there a sideband ? */ if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) { return CHSPEC_CHANNEL(chspec); } else { /* we only support 40MHZ with sidebands */ ASSERT(CHSPEC_BW(chspec) == WL_CHANSPEC_BW_40); /* chanspec channel holds the centre frequency, use that and the * side band information to reconstruct the control channel number */ if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) { /* control chan is the upper 20 MHZ SB of the 40MHZ channel */ ctl_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec)); } else { ASSERT(CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_LOWER); /* control chan is the lower 20 MHZ SB of the 40MHZ channel */ ctl_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec)); } } return ctl_chan; }
uint8 wf_chspec_ctlchan(chanspec_t chspec) { uint8 ctl_chan; DHD_MYTRACE(("%s-%s\n", __FILE__, __FUNCTION__)); if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) { return CHSPEC_CHANNEL(chspec); } else { ASSERT(CHSPEC_BW(chspec) == WL_CHANSPEC_BW_40); if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) { ctl_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec)); } else { ASSERT(CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_LOWER); ctl_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec)); } } return ctl_chan; }
void add_roam_cache(wl_bss_info_t *bi) { int i; uint8 channel; #if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) if (roamscan_mode == ROAMSCAN_MODE_WES) return; #endif if (n_roam_cache >= MAX_ROAM_CACHE) return; for (i = 0; i < n_roam_cache; i++) { if ((roam_cache[i].ssid_len == bi->SSID_len) && (roam_cache[i].chanspec == bi->chanspec) && (memcmp(roam_cache[i].ssid, bi->SSID, bi->SSID_len) == 0)) { /* identical one found, just return */ return; } } roam_cache[n_roam_cache].ssid_len = bi->SSID_len; channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch; WL_DBG(("CHSPEC 0x%X %d, CTL %d\n", bi->chanspec, CHSPEC_CHANNEL(bi->chanspec), bi->ctl_ch)); roam_cache[n_roam_cache].chanspec = (channel <= CH_MAX_2G_CHANNEL ? band2G : band5G) | band_bw | channel; memcpy(roam_cache[n_roam_cache].ssid, bi->SSID, bi->SSID_len); n_roam_cache++; }
static bool brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, u16 chspec) { return (wlc_cm->wlc->pub->_n_enab & SUPPORT_11N) && CHSPEC_IS40(chspec) ? (isset(wlc_cm->quiet_channels.vec, lower_20_sb(CHSPEC_CHANNEL(chspec))) || isset(wlc_cm->quiet_channels.vec, upper_20_sb(CHSPEC_CHANNEL(chspec)))) : isset(wlc_cm->quiet_channels.vec, CHSPEC_CHANNEL(chspec)); }
bool wlc_quiet_chanspec(wlc_cm_info_t *wlc_cm, chanspec_t chspec) { return N_ENAB(wlc_cm->wlc->pub) && CHSPEC_IS40(chspec) ? (isset (wlc_cm->quiet_channels.vec, LOWER_20_SB(CHSPEC_CHANNEL(chspec))) || isset(wlc_cm->quiet_channels.vec, UPPER_20_SB(CHSPEC_CHANNEL(chspec)))) : isset(wlc_cm-> quiet_channels. vec, CHSPEC_CHANNEL (chspec)); }
static uint8 spec_to_chan(chanspec_t chspec) { switch (CHSPEC_CTL_SB(chspec)) { case WL_CHANSPEC_CTL_SB_NONE: return CHSPEC_CHANNEL(chspec); case WL_CHANSPEC_CTL_SB_UPPER: return UPPER_20_SB(CHSPEC_CHANNEL(chspec)); case WL_CHANSPEC_CTL_SB_LOWER: return LOWER_20_SB(CHSPEC_CHANNEL(chspec)); default: return 0; } }
void add_roam_cache(wl_bss_info_t *bi) { int i; uint8 channel; #if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) if (roamscan_mode) return; #endif if (n_roam_cache == MAX_ROAM_CACHE) return; for (i = 0; i < n_roam_cache; i++) { if ((roam_cache[i].ssid_len == bi->SSID_len) && (roam_cache[i].chanspec == bi->chanspec) && (memcmp(roam_cache[i].ssid, bi->SSID, bi->SSID_len) == 0)) { /* identical one found, just return */ return; } } roam_cache[n_roam_cache].ssid_len = bi->SSID_len; channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch; roam_cache[n_roam_cache].chanspec = WL_CHANSPEC_BW_20 | (channel <= 14 ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G) | channel; memcpy(roam_cache[n_roam_cache].ssid, bi->SSID, bi->SSID_len); n_roam_cache++; }
/* given a chanspec and a string buffer, format the chanspec as a * string, and return the original pointer a. * Min buffer length must be CHANSPEC_STR_LEN. * On error return NULL */ char * wf_chspec_ntoa(chanspec_t chspec, char *buf) { const char *band, *bw, *sb; uint channel; band = ""; bw = ""; sb = ""; channel = CHSPEC_CHANNEL(chspec); /* check for non-default band spec */ if ((CHSPEC_IS2G(chspec) && channel > CH_MAX_2G_CHANNEL) || (CHSPEC_IS5G(chspec) && channel <= CH_MAX_2G_CHANNEL)) band = (CHSPEC_IS2G(chspec)) ? "b" : "a"; if (CHSPEC_IS40(chspec)) { if (CHSPEC_SB_UPPER(chspec)) { sb = "u"; channel += CH_10MHZ_APART; } else { sb = "l"; channel -= CH_10MHZ_APART; } } else if (CHSPEC_IS10(chspec)) { bw = "n"; } /* Outputs a max of 6 chars including '\0' */ snprintf(buf, 6, "%d%s%s%s", channel, band, bw, sb); return (buf); }
char * wf_chspec_ntoa(chanspec_t chspec, char *buf) { const char *band, *bw, *sb; uint channel; DHD_MYTRACE(("%s-%s\n", __FILE__, __FUNCTION__)); band = ""; bw = ""; sb = ""; channel = CHSPEC_CHANNEL(chspec); if ((CHSPEC_IS2G(chspec) && channel > CH_MAX_2G_CHANNEL) || (CHSPEC_IS5G(chspec) && channel <= CH_MAX_2G_CHANNEL)) band = (CHSPEC_IS2G(chspec)) ? "b" : "a"; if (CHSPEC_IS40(chspec)) { if (CHSPEC_SB_UPPER(chspec)) { sb = "u"; channel += CH_10MHZ_APART; } else { sb = "l"; channel -= CH_10MHZ_APART; } } else if (CHSPEC_IS10(chspec)) { bw = "n"; } snprintf(buf, 6, "%d%s%s%s", channel, band, bw, sb); return (buf); }
static uint8 spec_to_chan(chanspec_t chspec) { uint8 center_ch, edge, primary, sb; center_ch = CHSPEC_CHANNEL(chspec); if (CHSPEC_IS20(chspec)) { return center_ch; } else { /* the lower edge of the wide channel is half the bw from * the center channel. */ if (CHSPEC_IS40(chspec)) { edge = center_ch - CH_20MHZ_APART; } else { /* must be 80MHz (until we support more) */ ASSERT(CHSPEC_IS80(chspec)); edge = center_ch - CH_40MHZ_APART; } /* find the channel number of the lowest 20MHz primary channel */ primary = edge + CH_10MHZ_APART; /* select the actual subband */ sb = (chspec & WL_CHANSPEC_CTL_SB_MASK) >> WL_CHANSPEC_CTL_SB_SHIFT; primary = primary + sb * CH_20MHZ_APART; return primary; } }
/* given a chanspec and a string buffer, format the chanspec as a * string, and return the original pointer a. * Min buffer length must be CHANSPEC_STR_LEN. * On error return NULL */ char * wf_chspec_ntoa(chanspec_t chspec, char *buf) { const char *band; uint ctl_chan; if (wf_chspec_malformed(chspec)) return NULL; band = ""; /* check for non-default band spec */ if ((CHSPEC_IS2G(chspec) && CHSPEC_CHANNEL(chspec) > CH_MAX_2G_CHANNEL) || (CHSPEC_IS5G(chspec) && CHSPEC_CHANNEL(chspec) <= CH_MAX_2G_CHANNEL)) band = (CHSPEC_IS2G(chspec)) ? "2g" : "5g"; /* ctl channel */ ctl_chan = wf_chspec_ctlchan(chspec); /* bandwidth and ctl sideband */ if (CHSPEC_IS20(chspec)) { snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, ctl_chan); } else if (!CHSPEC_IS8080(chspec)) { const char *bw; const char *sb = ""; bw = wf_chspec_bw_str[(chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT]; #ifdef CHANSPEC_NEW_40MHZ_FORMAT /* ctl sideband string if needed for 2g 40MHz */ if (CHSPEC_IS40(chspec) && CHSPEC_IS2G(chspec)) { sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l"; } snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, ctl_chan, bw, sb); #else /* ctl sideband string instead of BW for 40MHz */ if (CHSPEC_IS40(chspec)) { sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l"; snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, ctl_chan, sb); } else { snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, ctl_chan, bw); } #endif /* CHANSPEC_NEW_40MHZ_FORMAT */ } else {
char * wf_chspec_ntoa(chanspec_t chspec, char *buf) { const char *band; uint ctl_chan; if (wf_chspec_malformed(chspec)) return NULL; band = ""; if ((CHSPEC_IS2G(chspec) && CHSPEC_CHANNEL(chspec) > CH_MAX_2G_CHANNEL) || (CHSPEC_IS5G(chspec) && CHSPEC_CHANNEL(chspec) <= CH_MAX_2G_CHANNEL)) band = (CHSPEC_IS2G(chspec)) ? "2g" : "5g"; ctl_chan = wf_chspec_ctlchan(chspec); if (CHSPEC_IS20(chspec)) { snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, ctl_chan); } else if (!CHSPEC_IS8080(chspec)) { const char *bw; const char *sb = ""; bw = wf_chspec_bw_str[(chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT]; #ifdef CHANSPEC_NEW_40MHZ_FORMAT if (CHSPEC_IS40(chspec) && CHSPEC_IS2G(chspec)) { sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l"; } snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, ctl_chan, bw, sb); #else if (CHSPEC_IS40(chspec)) { sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l"; snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, ctl_chan, sb); } else { snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, ctl_chan, bw); } #endif } else {
chanspec_t wf_chspec_ctlchspec(chanspec_t chspec) { chanspec_t ctl_chspec = 0; uint8 channel; ASSERT(!wf_chspec_malformed(chspec)); /* Is there a sideband ? */ if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) { return chspec; } else { if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) { channel = UPPER_20_SB(CHSPEC_CHANNEL(chspec)); } else { channel = LOWER_20_SB(CHSPEC_CHANNEL(chspec)); } ctl_chspec = channel | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE; ctl_chspec |= CHSPEC_BAND(chspec); } return ctl_chspec; }
chanspec_t wf_chspec_ctlchspec(chanspec_t chspec) { DHD_MYTRACE(("%s-%s\n", __FILE__, __FUNCTION__)); chanspec_t ctl_chspec = 0; uint8 channel; ASSERT(!wf_chspec_malformed(chspec)); if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) { return chspec; } else { if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) { channel = UPPER_20_SB(CHSPEC_CHANNEL(chspec)); } else { channel = LOWER_20_SB(CHSPEC_CHANNEL(chspec)); } ctl_chspec = channel | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE; ctl_chspec |= CHSPEC_BAND(chspec); } return ctl_chspec; }
uint8 wf_chspec_ctlchan(chanspec_t chspec) { uint8 ctl_chan; if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) { return CHSPEC_CHANNEL(chspec); } else { ASSERT(CHSPEC_BW(chspec) == WL_CHANSPEC_BW_40); if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) { ctl_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec)); } else { ASSERT(CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_LOWER); ctl_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec)); } } return ctl_chan; }
void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel, u16 chanspec) { struct tx_power power; u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id; /* Clear previous settings */ *ss_algo_channel = 0; if (!wlc->pub->up) { *ss_algo_channel = (u16) -1; return; } wlc_phy_txpower_get_current(wlc->band->pi, &power, CHSPEC_CHANNEL(chanspec)); siso_mcs_id = (CHSPEC_IS40(chanspec)) ? WL_TX_POWER_MCS40_SISO_FIRST : WL_TX_POWER_MCS20_SISO_FIRST; cdd_mcs_id = (CHSPEC_IS40(chanspec)) ? WL_TX_POWER_MCS40_CDD_FIRST : WL_TX_POWER_MCS20_CDD_FIRST; stbc_mcs_id = (CHSPEC_IS40(chanspec)) ? WL_TX_POWER_MCS40_STBC_FIRST : WL_TX_POWER_MCS20_STBC_FIRST; /* criteria to choose stf mode */ /* * the "+3dbm (12 0.25db units)" is to account for the fact that with * CDD, tx occurs on both chains */ if (power.target[siso_mcs_id] > (power.target[cdd_mcs_id] + 12)) setbit(ss_algo_channel, PHY_TXC1_MODE_SISO); else setbit(ss_algo_channel, PHY_TXC1_MODE_CDD); /* * STBC is ORed into to algo channel as STBC requires per-packet SCB * capability check so cannot be default mode of operation. One of * SISO, CDD have to be set */ if (power.target[siso_mcs_id] <= (power.target[stbc_mcs_id] + 12)) setbit(ss_algo_channel, PHY_TXC1_MODE_STBC); }
void add_roam_cache(wl_bss_info_t *bi) { int i; uint8 channel; if (n_roam_cache == MAX_ROAM_CACHE) return; for (i = 0; i < n_roam_cache; i++) { if ((roam_cache[i].ssid_len == bi->SSID_len) && (roam_cache[i].chanspec == bi->chanspec) && (memcmp(roam_cache[i].ssid, bi->SSID, bi->SSID_len) == 0)) { /* identical one found, just return */ return; } } roam_cache[n_roam_cache].ssid_len = bi->SSID_len; channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch; roam_cache[n_roam_cache].chanspec = WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE | (channel <= 14 ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G) | channel; memcpy(roam_cache[n_roam_cache].ssid, bi->SSID, bi->SSID_len); n_roam_cache++; }
/* * Validate the chanspec for this locale, for 40MHZ we need to also * check that the sidebands are valid 20MZH channels in this locale * and they are also a legal HT combination */ static bool brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec, bool dualband) { struct brcms_c_info *wlc = wlc_cm->wlc; u8 channel = CHSPEC_CHANNEL(chspec); /* check the chanspec */ if (brcms_c_chspec_malformed(chspec)) { wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n", wlc->pub->unit, chspec); return false; } if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) != chspec_bandunit(chspec)) return false; /* Check a 20Mhz channel */ if (CHSPEC_IS20(chspec)) { if (dualband) return brcms_c_valid_channel20_db(wlc_cm->wlc->cmi, channel); else return brcms_c_valid_channel20(wlc_cm->wlc->cmi, channel); } #ifdef SUPPORT_40MHZ /* * We know we are now checking a 40MHZ channel, so we should * only be here for NPHYS */ if (BRCMS_ISNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) { u8 upper_sideband = 0, idx; u8 num_ch20_entries = sizeof(chan20_info) / sizeof(struct chan20_info); if (!VALID_40CHANSPEC_IN_BAND(wlc, chspec_bandunit(chspec))) return false; if (dualband) { if (!brcms_c_valid_channel20_db(wlc->cmi, lower_20_sb(channel)) || !brcms_c_valid_channel20_db(wlc->cmi, upper_20_sb(channel))) return false; } else { if (!brcms_c_valid_channel20(wlc->cmi, lower_20_sb(channel)) || !brcms_c_valid_channel20(wlc->cmi, upper_20_sb(channel))) return false; } /* find the lower sideband info in the sideband array */ for (idx = 0; idx < num_ch20_entries; idx++) { if (chan20_info[idx].sb == lower_20_sb(channel)) upper_sideband = chan20_info[idx].adj_sbs; } /* check that the lower sideband allows an upper sideband */ if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) == (CH_UPPER_SB | CH_EWA_VALID)) return true; return false; } #endif /* 40 MHZ */ return false; }
void wlc_channel_reg_limits(wlc_cm_info_t *wlc_cm, chanspec_t chanspec, txpwr_limits_t *txpwr) { struct wlc_info *wlc = wlc_cm->wlc; uint i; uint chan; int maxpwr; int delta; const country_info_t *country; struct wlcband *band; const locale_info_t *li; int conducted_max; int conducted_ofdm_max; const locale_mimo_info_t *li_mimo; int maxpwr20, maxpwr40; int maxpwr_idx; uint j; memset(txpwr, 0, sizeof(txpwr_limits_t)); if (!wlc_valid_chanspec_db(wlc_cm, chanspec)) { country = wlc_country_lookup(wlc, wlc->autocountry_default); if (country == NULL) return; } else { country = wlc_cm->country; } chan = CHSPEC_CHANNEL(chanspec); band = wlc->bandstate[CHSPEC_WLCBANDUNIT(chanspec)]; li = BAND_5G(band->bandtype) ? wlc_get_locale_5g(country->locale_5G) : wlc_get_locale_2g(country->locale_2G); li_mimo = BAND_5G(band->bandtype) ? wlc_get_mimo_5g(country->locale_mimo_5G) : wlc_get_mimo_2g(country->locale_mimo_2G); if (li->flags & WLC_EIRP) { delta = band->antgain; } else { delta = 0; if (band->antgain > QDB(6)) delta = band->antgain - QDB(6); /* Excess over 6 dB */ } if (li == &locale_i) { conducted_max = QDB(22); conducted_ofdm_max = QDB(22); } /* CCK txpwr limits for 2.4G band */ if (BAND_2G(band->bandtype)) { maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_CCK(chan)]; maxpwr = maxpwr - delta; maxpwr = max(maxpwr, 0); maxpwr = min(maxpwr, conducted_max); for (i = 0; i < WLC_NUM_RATES_CCK; i++) txpwr->cck[i] = (u8) maxpwr; } /* OFDM txpwr limits for 2.4G or 5G bands */ if (BAND_2G(band->bandtype)) { maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)]; } else { maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)]; } maxpwr = maxpwr - delta; maxpwr = max(maxpwr, 0); maxpwr = min(maxpwr, conducted_ofdm_max); /* Keep OFDM lmit below CCK limit */ if (BAND_2G(band->bandtype)) maxpwr = min_t(int, maxpwr, txpwr->cck[0]); for (i = 0; i < WLC_NUM_RATES_OFDM; i++) { txpwr->ofdm[i] = (u8) maxpwr; } for (i = 0; i < WLC_NUM_RATES_OFDM; i++) { /* OFDM 40 MHz SISO has the same power as the corresponding MCS0-7 rate unless * overriden by the locale specific code. We set this value to 0 as a * flag (presumably 0 dBm isn't a possibility) and then copy the MCS0-7 value * to the 40 MHz value if it wasn't explicitly set. */ txpwr->ofdm_40_siso[i] = 0; txpwr->ofdm_cdd[i] = (u8) maxpwr; txpwr->ofdm_40_cdd[i] = 0; } /* MIMO/HT specific limits */ if (li_mimo->flags & WLC_EIRP) { delta = band->antgain; } else { delta = 0; if (band->antgain > QDB(6)) delta = band->antgain - QDB(6); /* Excess over 6 dB */ } if (BAND_2G(band->bandtype)) maxpwr_idx = (chan - 1); else maxpwr_idx = CHANNEL_POWER_IDX_5G(chan); maxpwr20 = li_mimo->maxpwr20[maxpwr_idx]; maxpwr40 = li_mimo->maxpwr40[maxpwr_idx]; maxpwr20 = maxpwr20 - delta; maxpwr20 = max(maxpwr20, 0); maxpwr40 = maxpwr40 - delta; maxpwr40 = max(maxpwr40, 0); /* Fill in the MCS 0-7 (SISO) rates */ for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) { /* 20 MHz has the same power as the corresponding OFDM rate unless * overriden by the locale specific code. */ txpwr->mcs_20_siso[i] = txpwr->ofdm[i]; txpwr->mcs_40_siso[i] = 0; } /* Fill in the MCS 0-7 CDD rates */ for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) { txpwr->mcs_20_cdd[i] = (u8) maxpwr20; txpwr->mcs_40_cdd[i] = (u8) maxpwr40; } /* These locales have SISO expressed in the table and override CDD later */ if (li_mimo == &locale_bn) { if (li_mimo == &locale_bn) { maxpwr20 = QDB(16); maxpwr40 = 0; if (chan >= 3 && chan <= 11) { maxpwr40 = QDB(16); } } for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) { txpwr->mcs_20_siso[i] = (u8) maxpwr20; txpwr->mcs_40_siso[i] = (u8) maxpwr40; } } /* Fill in the MCS 0-7 STBC rates */ for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) { txpwr->mcs_20_stbc[i] = 0; txpwr->mcs_40_stbc[i] = 0; } /* Fill in the MCS 8-15 SDM rates */ for (i = 0; i < WLC_NUM_RATES_MCS_2_STREAM; i++) { txpwr->mcs_20_mimo[i] = (u8) maxpwr20; txpwr->mcs_40_mimo[i] = (u8) maxpwr40; } /* Fill in MCS32 */ txpwr->mcs32 = (u8) maxpwr40; for (i = 0, j = 0; i < WLC_NUM_RATES_OFDM; i++, j++) { if (txpwr->ofdm_40_cdd[i] == 0) txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j]; if (i == 0) { i = i + 1; if (txpwr->ofdm_40_cdd[i] == 0) txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j]; } } /* Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO value if it wasn't * provided explicitly. */ for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) { if (txpwr->mcs_40_siso[i] == 0) txpwr->mcs_40_siso[i] = txpwr->mcs_40_cdd[i]; } for (i = 0, j = 0; i < WLC_NUM_RATES_OFDM; i++, j++) { if (txpwr->ofdm_40_siso[i] == 0) txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j]; if (i == 0) { i = i + 1; if (txpwr->ofdm_40_siso[i] == 0) txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j]; } } /* Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding STBC values if they weren't * provided explicitly. */ for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) { if (txpwr->mcs_20_stbc[i] == 0) txpwr->mcs_20_stbc[i] = txpwr->mcs_20_cdd[i]; if (txpwr->mcs_40_stbc[i] == 0) txpwr->mcs_40_stbc[i] = txpwr->mcs_40_cdd[i]; } #ifdef POWER_DBG wlc_phy_txpower_limits_dump(txpwr); #endif return; }
/* * Validate the chanspec for this locale, for 40MHZ we need to also check that the sidebands * are valid 20MZH channels in this locale and they are also a legal HT combination */ static bool wlc_valid_chanspec_ext(wlc_cm_info_t *wlc_cm, chanspec_t chspec, bool dualband) { struct wlc_info *wlc = wlc_cm->wlc; u8 channel = CHSPEC_CHANNEL(chspec); /* check the chanspec */ if (wf_chspec_malformed(chspec)) { WL_ERROR("wl%d: malformed chanspec 0x%x\n", wlc->pub->unit, chspec); ASSERT(0); return false; } if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) != CHSPEC_WLCBANDUNIT(chspec)) return false; /* Check a 20Mhz channel */ if (CHSPEC_IS20(chspec)) { if (dualband) return VALID_CHANNEL20_DB(wlc_cm->wlc, channel); else return VALID_CHANNEL20(wlc_cm->wlc, channel); } #ifdef SUPPORT_40MHZ /* We know we are now checking a 40MHZ channel, so we should only be here * for NPHYS */ if (WLCISNPHY(wlc->band) || WLCISSSLPNPHY(wlc->band)) { u8 upper_sideband = 0, idx; u8 num_ch20_entries = sizeof(chan20_info) / sizeof(struct chan20_info); if (!VALID_40CHANSPEC_IN_BAND(wlc, CHSPEC_WLCBANDUNIT(chspec))) return false; if (dualband) { if (!VALID_CHANNEL20_DB(wlc, LOWER_20_SB(channel)) || !VALID_CHANNEL20_DB(wlc, UPPER_20_SB(channel))) return false; } else { if (!VALID_CHANNEL20(wlc, LOWER_20_SB(channel)) || !VALID_CHANNEL20(wlc, UPPER_20_SB(channel))) return false; } /* find the lower sideband info in the sideband array */ for (idx = 0; idx < num_ch20_entries; idx++) { if (chan20_info[idx].sb == LOWER_20_SB(channel)) upper_sideband = chan20_info[idx].adj_sbs; } /* check that the lower sideband allows an upper sideband */ if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) == (CH_UPPER_SB | CH_EWA_VALID)) return true; return false; } #endif /* 40 MHZ */ return false; }