0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <brcmu_wifi.h>
0018 #include <brcmu_utils.h>
0019
0020 #include "d11.h"
0021 #include "pub.h"
0022 #include "rate.h"
0023
0024
0025
0026
0027
0028 const u8 rate_info[BRCM_MAXRATE + 1] = {
0029
0030 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
0031 0x00, 0x37, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00,
0032 0x00, 0x00, 0x6e, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00,
0033 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
0034 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00,
0035 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0036 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0037 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0038 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0039 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
0040 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c
0041 };
0042
0043
0044 const struct brcms_mcs_info mcs_table[MCS_TABLE_SIZE] = {
0045
0046 {6500, 13500, CEIL(6500 * 10, 9), CEIL(13500 * 10, 9), 0x00,
0047 BRCM_RATE_6M},
0048
0049 {13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x08,
0050 BRCM_RATE_12M},
0051
0052 {19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x0A,
0053 BRCM_RATE_18M},
0054
0055 {26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x10,
0056 BRCM_RATE_24M},
0057
0058 {39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x12,
0059 BRCM_RATE_36M},
0060
0061 {52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x19,
0062 BRCM_RATE_48M},
0063
0064 {58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x1A,
0065 BRCM_RATE_54M},
0066
0067 {65000, 135000, CEIL(65000 * 10, 9), CEIL(135000 * 10, 9), 0x1C,
0068 BRCM_RATE_54M},
0069
0070 {13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x40,
0071 BRCM_RATE_6M},
0072
0073 {26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x48,
0074 BRCM_RATE_12M},
0075
0076 {39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x4A,
0077 BRCM_RATE_18M},
0078
0079 {52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x50,
0080 BRCM_RATE_24M},
0081
0082 {78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x52,
0083 BRCM_RATE_36M},
0084
0085 {104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0x59,
0086 BRCM_RATE_48M},
0087
0088 {117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x5A,
0089 BRCM_RATE_54M},
0090
0091 {130000, 270000, CEIL(130000 * 10, 9), CEIL(270000 * 10, 9), 0x5C,
0092 BRCM_RATE_54M},
0093
0094 {19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x80,
0095 BRCM_RATE_6M},
0096
0097 {39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x88,
0098 BRCM_RATE_12M},
0099
0100 {58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x8A,
0101 BRCM_RATE_18M},
0102
0103 {78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x90,
0104 BRCM_RATE_24M},
0105
0106 {117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x92,
0107 BRCM_RATE_36M},
0108
0109 {156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0x99,
0110 BRCM_RATE_48M},
0111
0112 {175500, 364500, CEIL(175500 * 10, 9), CEIL(364500 * 10, 9), 0x9A,
0113 BRCM_RATE_54M},
0114
0115 {195000, 405000, CEIL(195000 * 10, 9), CEIL(405000 * 10, 9), 0x9B,
0116 BRCM_RATE_54M},
0117
0118 {26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0xC0,
0119 BRCM_RATE_6M},
0120
0121 {52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0xC8,
0122 BRCM_RATE_12M},
0123
0124 {78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0xCA,
0125 BRCM_RATE_18M},
0126
0127 {104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0xD0,
0128 BRCM_RATE_24M},
0129
0130 {156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0xD2,
0131 BRCM_RATE_36M},
0132
0133 {208000, 432000, CEIL(208000 * 10, 9), CEIL(432000 * 10, 9), 0xD9,
0134 BRCM_RATE_48M},
0135
0136 {234000, 486000, CEIL(234000 * 10, 9), CEIL(486000 * 10, 9), 0xDA,
0137 BRCM_RATE_54M},
0138
0139 {260000, 540000, CEIL(260000 * 10, 9), CEIL(540000 * 10, 9), 0xDB,
0140 BRCM_RATE_54M},
0141
0142 {0, 6000, 0, CEIL(6000 * 10, 9), 0x00, BRCM_RATE_6M},
0143 };
0144
0145
0146
0147
0148
0149
0150 struct legacy_phycfg {
0151 u32 rate_ofdm;
0152
0153 u8 tx_phy_ctl3;
0154 };
0155
0156
0157 #define LEGACY_PHYCFG_TABLE_SIZE 12
0158
0159
0160
0161
0162
0163
0164 static const struct
0165 legacy_phycfg legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = {
0166 {BRCM_RATE_1M, 0x00},
0167 {BRCM_RATE_2M, 0x08},
0168 {BRCM_RATE_5M5, 0x10},
0169 {BRCM_RATE_11M, 0x18},
0170
0171 {BRCM_RATE_6M, 0x00},
0172
0173 {BRCM_RATE_9M, 0x02},
0174
0175 {BRCM_RATE_12M, 0x08},
0176
0177 {BRCM_RATE_18M, 0x0A},
0178
0179 {BRCM_RATE_24M, 0x10},
0180
0181 {BRCM_RATE_36M, 0x12},
0182
0183 {BRCM_RATE_48M, 0x19},
0184
0185 {BRCM_RATE_54M, 0x1A},
0186 };
0187
0188
0189
0190 const struct brcms_c_rateset cck_ofdm_mimo_rates = {
0191 12,
0192
0193 { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
0194
0195 0x6c},
0196 0x00,
0197 { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0198 0x00, 0x00, 0x00, 0x00, 0x00}
0199 };
0200
0201 const struct brcms_c_rateset ofdm_mimo_rates = {
0202 8,
0203
0204 { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
0205 0x00,
0206 { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0207 0x00, 0x00, 0x00, 0x00, 0x00}
0208 };
0209
0210
0211 static const struct brcms_c_rateset cck_ofdm_40bw_mimo_rates = {
0212 12,
0213
0214 { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
0215
0216 0x6c},
0217 0x00,
0218 { 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0219 0x00, 0x00, 0x00, 0x00, 0x00}
0220 };
0221
0222 static const struct brcms_c_rateset ofdm_40bw_mimo_rates = {
0223 8,
0224
0225 { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
0226 0x00,
0227 { 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0228 0x00, 0x00, 0x00, 0x00, 0x00}
0229 };
0230
0231 const struct brcms_c_rateset cck_ofdm_rates = {
0232 12,
0233
0234 { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
0235
0236 0x6c},
0237 0x00,
0238 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0239 0x00, 0x00, 0x00, 0x00, 0x00}
0240 };
0241
0242 const struct brcms_c_rateset gphy_legacy_rates = {
0243 4,
0244
0245 { 0x82, 0x84, 0x8b, 0x96},
0246 0x00,
0247 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0248 0x00, 0x00, 0x00, 0x00, 0x00}
0249 };
0250
0251 const struct brcms_c_rateset ofdm_rates = {
0252 8,
0253
0254 { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
0255 0x00,
0256 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0257 0x00, 0x00, 0x00, 0x00, 0x00}
0258 };
0259
0260 const struct brcms_c_rateset cck_rates = {
0261 4,
0262
0263 { 0x82, 0x84, 0x0b, 0x16},
0264 0x00,
0265 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0266 0x00, 0x00, 0x00, 0x00, 0x00}
0267 };
0268
0269
0270
0271
0272 static bool brcms_c_rateset_valid(struct brcms_c_rateset *rs, bool check_brate)
0273 {
0274 uint idx;
0275
0276 if (!rs->count)
0277 return false;
0278
0279 if (!check_brate)
0280 return true;
0281
0282
0283 for (idx = 0; idx < rs->count; idx++) {
0284 if (rs->rates[idx] & BRCMS_RATE_FLAG)
0285 return true;
0286 }
0287 return false;
0288 }
0289
0290 void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams)
0291 {
0292 int i;
0293 for (i = txstreams; i < MAX_STREAMS_SUPPORTED; i++)
0294 rs->mcs[i] = 0;
0295 }
0296
0297
0298
0299
0300
0301 bool
0302 brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs,
0303 const struct brcms_c_rateset *hw_rs,
0304 bool check_brate, u8 txstreams)
0305 {
0306 u8 rateset[BRCM_MAXRATE + 1];
0307 u8 r;
0308 uint count;
0309 uint i;
0310
0311 memset(rateset, 0, sizeof(rateset));
0312 count = rs->count;
0313
0314 for (i = 0; i < count; i++) {
0315
0316 r = (int)rs->rates[i] & BRCMS_RATE_MASK;
0317 if ((r > BRCM_MAXRATE) || (rate_info[r] == 0))
0318 continue;
0319 rateset[r] = rs->rates[i];
0320 }
0321
0322
0323 count = 0;
0324 for (i = 0; i < hw_rs->count; i++) {
0325 r = hw_rs->rates[i] & BRCMS_RATE_MASK;
0326 if (rateset[r])
0327 rs->rates[count++] = rateset[r];
0328 }
0329
0330 rs->count = count;
0331
0332
0333 for (i = 0; i < MCSSET_LEN; i++)
0334 rs->mcs[i] = (rs->mcs[i] & hw_rs->mcs[i]);
0335
0336 if (brcms_c_rateset_valid(rs, check_brate))
0337 return true;
0338 else
0339 return false;
0340 }
0341
0342
0343 u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp)
0344 {
0345 int phy_type;
0346 u32 rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT;
0347
0348 phy_type =
0349 ((rxh->RxChan & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT);
0350
0351 if ((phy_type == PHY_TYPE_N) || (phy_type == PHY_TYPE_SSN) ||
0352 (phy_type == PHY_TYPE_LCN) || (phy_type == PHY_TYPE_HT)) {
0353 switch (rxh->PhyRxStatus_0 & PRXS0_FT_MASK) {
0354 case PRXS0_CCK:
0355 rspec =
0356 cck_phy2mac_rate(
0357 ((struct cck_phy_hdr *) plcp)->signal);
0358 break;
0359 case PRXS0_OFDM:
0360 rspec =
0361 ofdm_phy2mac_rate(
0362 ((struct ofdm_phy_hdr *) plcp)->rlpt[0]);
0363 break;
0364 case PRXS0_PREN:
0365 rspec = (plcp[0] & MIMO_PLCP_MCS_MASK) | RSPEC_MIMORATE;
0366 if (plcp[0] & MIMO_PLCP_40MHZ) {
0367
0368 rspec &= ~RSPEC_BW_MASK;
0369 rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
0370 }
0371 break;
0372 case PRXS0_STDN:
0373
0374 default:
0375
0376 break;
0377 }
0378 if (plcp3_issgi(plcp[3]))
0379 rspec |= RSPEC_SHORT_GI;
0380 } else
0381 if ((phy_type == PHY_TYPE_A) || (rxh->PhyRxStatus_0 & PRXS0_OFDM))
0382 rspec = ofdm_phy2mac_rate(
0383 ((struct ofdm_phy_hdr *) plcp)->rlpt[0]);
0384 else
0385 rspec = cck_phy2mac_rate(
0386 ((struct cck_phy_hdr *) plcp)->signal);
0387
0388 return rspec;
0389 }
0390
0391
0392 void brcms_c_rateset_copy(const struct brcms_c_rateset *src,
0393 struct brcms_c_rateset *dst)
0394 {
0395 memcpy(dst, src, sizeof(struct brcms_c_rateset));
0396 }
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407 void
0408 brcms_c_rateset_filter(struct brcms_c_rateset *src, struct brcms_c_rateset *dst,
0409 bool basic_only, u8 rates, uint xmask, bool mcsallow)
0410 {
0411 uint i;
0412 uint r;
0413 uint count;
0414
0415 count = 0;
0416 for (i = 0; i < src->count; i++) {
0417 r = src->rates[i];
0418 if (basic_only && !(r & BRCMS_RATE_FLAG))
0419 continue;
0420 if (rates == BRCMS_RATES_CCK &&
0421 is_ofdm_rate((r & BRCMS_RATE_MASK)))
0422 continue;
0423 if (rates == BRCMS_RATES_OFDM &&
0424 is_cck_rate((r & BRCMS_RATE_MASK)))
0425 continue;
0426 dst->rates[count++] = r & xmask;
0427 }
0428 dst->count = count;
0429 dst->htphy_membership = src->htphy_membership;
0430
0431 if (mcsallow && rates != BRCMS_RATES_CCK)
0432 memcpy(&dst->mcs[0], &src->mcs[0], MCSSET_LEN);
0433 else
0434 brcms_c_rateset_mcs_clear(dst);
0435 }
0436
0437
0438
0439
0440 void
0441 brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt,
0442 const struct brcms_c_rateset *rs_hw,
0443 uint phy_type, int bandtype, bool cck_only,
0444 uint rate_mask, bool mcsallow, u8 bw, u8 txstreams)
0445 {
0446 const struct brcms_c_rateset *rs_dflt;
0447 struct brcms_c_rateset rs_sel;
0448 if ((PHYTYPE_IS(phy_type, PHY_TYPE_HT)) ||
0449 (PHYTYPE_IS(phy_type, PHY_TYPE_N)) ||
0450 (PHYTYPE_IS(phy_type, PHY_TYPE_LCN)) ||
0451 (PHYTYPE_IS(phy_type, PHY_TYPE_SSN))) {
0452 if (bandtype == BRCM_BAND_5G)
0453 rs_dflt = (bw == BRCMS_20_MHZ ?
0454 &ofdm_mimo_rates : &ofdm_40bw_mimo_rates);
0455 else
0456 rs_dflt = (bw == BRCMS_20_MHZ ?
0457 &cck_ofdm_mimo_rates :
0458 &cck_ofdm_40bw_mimo_rates);
0459 } else if (PHYTYPE_IS(phy_type, PHY_TYPE_LP)) {
0460 rs_dflt = (bandtype == BRCM_BAND_5G) ?
0461 &ofdm_rates : &cck_ofdm_rates;
0462 } else if (PHYTYPE_IS(phy_type, PHY_TYPE_A)) {
0463 rs_dflt = &ofdm_rates;
0464 } else if (PHYTYPE_IS(phy_type, PHY_TYPE_G)) {
0465 rs_dflt = &cck_ofdm_rates;
0466 } else {
0467
0468 rs_dflt = &cck_rates;
0469 }
0470
0471
0472 if (!rs_hw)
0473 rs_hw = rs_dflt;
0474
0475 brcms_c_rateset_copy(rs_dflt, &rs_sel);
0476 brcms_c_rateset_mcs_upd(&rs_sel, txstreams);
0477 brcms_c_rateset_filter(&rs_sel, rs_tgt, false,
0478 cck_only ? BRCMS_RATES_CCK : BRCMS_RATES_CCK_OFDM,
0479 rate_mask, mcsallow);
0480 brcms_c_rate_hwrs_filter_sort_validate(rs_tgt, rs_hw, false,
0481 mcsallow ? txstreams : 1);
0482 }
0483
0484 s16 brcms_c_rate_legacy_phyctl(uint rate)
0485 {
0486 uint i;
0487 for (i = 0; i < LEGACY_PHYCFG_TABLE_SIZE; i++)
0488 if (rate == legacy_phycfg_table[i].rate_ofdm)
0489 return legacy_phycfg_table[i].tx_phy_ctl3;
0490
0491 return -1;
0492 }
0493
0494 void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset)
0495 {
0496 uint i;
0497 for (i = 0; i < MCSSET_LEN; i++)
0498 rateset->mcs[i] = 0;
0499 }
0500
0501 void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, u8 txstreams)
0502 {
0503 memcpy(&rateset->mcs[0], &cck_ofdm_mimo_rates.mcs[0], MCSSET_LEN);
0504 brcms_c_rateset_mcs_upd(rateset, txstreams);
0505 }
0506
0507
0508 void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, u8 bw)
0509 {
0510 if (bw == BRCMS_40_MHZ)
0511 setbit(rateset->mcs, 32);
0512 else
0513 clrbit(rateset->mcs, 32);
0514 }