Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Broadcom B43 wireless driver
0004  * PPR (Power Per Rate) management
0005  *
0006  * Copyright (c) 2014 Rafał Miłecki <zajec5@gmail.com>
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     /* Compile-time PPR check */
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     /* OFDM */
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     /* MCS 20 SISO */
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     /* MCS 20 CDD */
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     /* OFDM 20 CDD */
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     /* MCS 20 STBC */
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     /* MCS 20 SDM */
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 }