0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ppr.h"
0010 #include "b43.h"
0011
0012 #define ppr_for_each_entry(ppr, i, entry) \
0013 for (i = 0, entry = &(ppr)->__all_rates[i]; \
0014 i < B43_PPR_RATES_NUM; \
0015 i++, entry++)
0016
0017 void b43_ppr_clear(struct b43_wldev *dev, struct b43_ppr *ppr)
0018 {
0019 memset(ppr, 0, sizeof(*ppr));
0020
0021
0022 BUILD_BUG_ON(sizeof(struct b43_ppr) != B43_PPR_RATES_NUM * sizeof(u8));
0023 }
0024
0025 void b43_ppr_add(struct b43_wldev *dev, struct b43_ppr *ppr, int diff)
0026 {
0027 int i;
0028 u8 *rate;
0029
0030 ppr_for_each_entry(ppr, i, rate) {
0031 *rate = clamp_val(*rate + diff, 0, 127);
0032 }
0033 }
0034
0035 void b43_ppr_apply_max(struct b43_wldev *dev, struct b43_ppr *ppr, u8 max)
0036 {
0037 int i;
0038 u8 *rate;
0039
0040 ppr_for_each_entry(ppr, i, rate) {
0041 *rate = min(*rate, max);
0042 }
0043 }
0044
0045 void b43_ppr_apply_min(struct b43_wldev *dev, struct b43_ppr *ppr, u8 min)
0046 {
0047 int i;
0048 u8 *rate;
0049
0050 ppr_for_each_entry(ppr, i, rate) {
0051 *rate = max(*rate, min);
0052 }
0053 }
0054
0055 u8 b43_ppr_get_max(struct b43_wldev *dev, struct b43_ppr *ppr)
0056 {
0057 u8 res = 0;
0058 int i;
0059 u8 *rate;
0060
0061 ppr_for_each_entry(ppr, i, rate) {
0062 res = max(*rate, res);
0063 }
0064
0065 return res;
0066 }
0067
0068 bool b43_ppr_load_max_from_sprom(struct b43_wldev *dev, struct b43_ppr *ppr,
0069 enum b43_band band)
0070 {
0071 struct b43_ppr_rates *rates = &ppr->rates;
0072 struct ssb_sprom *sprom = dev->dev->bus_sprom;
0073 struct b43_phy *phy = &dev->phy;
0074 u8 maxpwr, off;
0075 u32 sprom_ofdm_po;
0076 u16 *sprom_mcs_po;
0077 u8 extra_cdd_po, extra_stbc_po;
0078 int i;
0079
0080 switch (band) {
0081 case B43_BAND_2G:
0082 maxpwr = min(sprom->core_pwr_info[0].maxpwr_2g,
0083 sprom->core_pwr_info[1].maxpwr_2g);
0084 sprom_ofdm_po = sprom->ofdm2gpo;
0085 sprom_mcs_po = sprom->mcs2gpo;
0086 extra_cdd_po = (sprom->cddpo >> 0) & 0xf;
0087 extra_stbc_po = (sprom->stbcpo >> 0) & 0xf;
0088 break;
0089 case B43_BAND_5G_LO:
0090 maxpwr = min(sprom->core_pwr_info[0].maxpwr_5gl,
0091 sprom->core_pwr_info[1].maxpwr_5gl);
0092 sprom_ofdm_po = sprom->ofdm5glpo;
0093 sprom_mcs_po = sprom->mcs5glpo;
0094 extra_cdd_po = (sprom->cddpo >> 8) & 0xf;
0095 extra_stbc_po = (sprom->stbcpo >> 8) & 0xf;
0096 break;
0097 case B43_BAND_5G_MI:
0098 maxpwr = min(sprom->core_pwr_info[0].maxpwr_5g,
0099 sprom->core_pwr_info[1].maxpwr_5g);
0100 sprom_ofdm_po = sprom->ofdm5gpo;
0101 sprom_mcs_po = sprom->mcs5gpo;
0102 extra_cdd_po = (sprom->cddpo >> 4) & 0xf;
0103 extra_stbc_po = (sprom->stbcpo >> 4) & 0xf;
0104 break;
0105 case B43_BAND_5G_HI:
0106 maxpwr = min(sprom->core_pwr_info[0].maxpwr_5gh,
0107 sprom->core_pwr_info[1].maxpwr_5gh);
0108 sprom_ofdm_po = sprom->ofdm5ghpo;
0109 sprom_mcs_po = sprom->mcs5ghpo;
0110 extra_cdd_po = (sprom->cddpo >> 12) & 0xf;
0111 extra_stbc_po = (sprom->stbcpo >> 12) & 0xf;
0112 break;
0113 default:
0114 WARN_ON_ONCE(1);
0115 return false;
0116 }
0117
0118 if (band == B43_BAND_2G) {
0119 for (i = 0; i < 4; i++) {
0120 off = ((sprom->cck2gpo >> (i * 4)) & 0xf) * 2;
0121 rates->cck[i] = maxpwr - off;
0122 }
0123 }
0124
0125
0126 for (i = 0; i < 8; i++) {
0127 off = ((sprom_ofdm_po >> (i * 4)) & 0xf) * 2;
0128 rates->ofdm[i] = maxpwr - off;
0129 }
0130
0131
0132 rates->mcs_20[0] = rates->ofdm[0];
0133 rates->mcs_20[1] = rates->ofdm[2];
0134 rates->mcs_20[2] = rates->ofdm[3];
0135 rates->mcs_20[3] = rates->ofdm[4];
0136 rates->mcs_20[4] = rates->ofdm[5];
0137 rates->mcs_20[5] = rates->ofdm[6];
0138 rates->mcs_20[6] = rates->ofdm[7];
0139 rates->mcs_20[7] = rates->ofdm[7];
0140
0141
0142 for (i = 0; i < 4; i++) {
0143 off = ((sprom_mcs_po[0] >> (i * 4)) & 0xf) * 2;
0144 rates->mcs_20_cdd[i] = maxpwr - off;
0145 if (phy->type == B43_PHYTYPE_N && phy->rev >= 3)
0146 rates->mcs_20_cdd[i] -= extra_cdd_po;
0147 }
0148 for (i = 0; i < 4; i++) {
0149 off = ((sprom_mcs_po[1] >> (i * 4)) & 0xf) * 2;
0150 rates->mcs_20_cdd[4 + i] = maxpwr - off;
0151 if (phy->type == B43_PHYTYPE_N && phy->rev >= 3)
0152 rates->mcs_20_cdd[4 + i] -= extra_cdd_po;
0153 }
0154
0155
0156 rates->ofdm_20_cdd[0] = rates->mcs_20_cdd[0];
0157 rates->ofdm_20_cdd[1] = rates->mcs_20_cdd[0];
0158 rates->ofdm_20_cdd[2] = rates->mcs_20_cdd[1];
0159 rates->ofdm_20_cdd[3] = rates->mcs_20_cdd[2];
0160 rates->ofdm_20_cdd[4] = rates->mcs_20_cdd[3];
0161 rates->ofdm_20_cdd[5] = rates->mcs_20_cdd[4];
0162 rates->ofdm_20_cdd[6] = rates->mcs_20_cdd[5];
0163 rates->ofdm_20_cdd[7] = rates->mcs_20_cdd[6];
0164
0165
0166 for (i = 0; i < 4; i++) {
0167 off = ((sprom_mcs_po[0] >> (i * 4)) & 0xf) * 2;
0168 rates->mcs_20_stbc[i] = maxpwr - off;
0169 if (phy->type == B43_PHYTYPE_N && phy->rev >= 3)
0170 rates->mcs_20_stbc[i] -= extra_stbc_po;
0171 }
0172 for (i = 0; i < 4; i++) {
0173 off = ((sprom_mcs_po[1] >> (i * 4)) & 0xf) * 2;
0174 rates->mcs_20_stbc[4 + i] = maxpwr - off;
0175 if (phy->type == B43_PHYTYPE_N && phy->rev >= 3)
0176 rates->mcs_20_stbc[4 + i] -= extra_stbc_po;
0177 }
0178
0179
0180 for (i = 0; i < 4; i++) {
0181 off = ((sprom_mcs_po[2] >> (i * 4)) & 0xf) * 2;
0182 rates->mcs_20_sdm[i] = maxpwr - off;
0183 }
0184 for (i = 0; i < 4; i++) {
0185 off = ((sprom_mcs_po[3] >> (i * 4)) & 0xf) * 2;
0186 rates->mcs_20_sdm[4 + i] = maxpwr - off;
0187 }
0188
0189 return true;
0190 }