1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Broadcom B43 wireless driver
4 * PPR (Power Per Rate) management
6 * Copyright (c) 2014 Rafał Miłecki <zajec5@gmail.com>
12 #define ppr_for_each_entry(ppr, i, entry) \
13 for (i = 0, entry = &(ppr)->__all_rates[i]; \
14 i < B43_PPR_RATES_NUM; \
17 void b43_ppr_clear(struct b43_wldev
*dev
, struct b43_ppr
*ppr
)
19 memset(ppr
, 0, sizeof(*ppr
));
21 /* Compile-time PPR check */
22 BUILD_BUG_ON(sizeof(struct b43_ppr
) != B43_PPR_RATES_NUM
* sizeof(u8
));
25 void b43_ppr_add(struct b43_wldev
*dev
, struct b43_ppr
*ppr
, int diff
)
30 ppr_for_each_entry(ppr
, i
, rate
) {
31 *rate
= clamp_val(*rate
+ diff
, 0, 127);
35 void b43_ppr_apply_max(struct b43_wldev
*dev
, struct b43_ppr
*ppr
, u8 max
)
40 ppr_for_each_entry(ppr
, i
, rate
) {
41 *rate
= min(*rate
, max
);
45 void b43_ppr_apply_min(struct b43_wldev
*dev
, struct b43_ppr
*ppr
, u8 min
)
50 ppr_for_each_entry(ppr
, i
, rate
) {
51 *rate
= max(*rate
, min
);
55 u8
b43_ppr_get_max(struct b43_wldev
*dev
, struct b43_ppr
*ppr
)
61 ppr_for_each_entry(ppr
, i
, rate
) {
62 res
= max(*rate
, res
);
68 bool b43_ppr_load_max_from_sprom(struct b43_wldev
*dev
, struct b43_ppr
*ppr
,
71 struct b43_ppr_rates
*rates
= &ppr
->rates
;
72 struct ssb_sprom
*sprom
= dev
->dev
->bus_sprom
;
73 struct b43_phy
*phy
= &dev
->phy
;
77 u8 extra_cdd_po
, extra_stbc_po
;
82 maxpwr
= min(sprom
->core_pwr_info
[0].maxpwr_2g
,
83 sprom
->core_pwr_info
[1].maxpwr_2g
);
84 sprom_ofdm_po
= sprom
->ofdm2gpo
;
85 sprom_mcs_po
= sprom
->mcs2gpo
;
86 extra_cdd_po
= (sprom
->cddpo
>> 0) & 0xf;
87 extra_stbc_po
= (sprom
->stbcpo
>> 0) & 0xf;
90 maxpwr
= min(sprom
->core_pwr_info
[0].maxpwr_5gl
,
91 sprom
->core_pwr_info
[1].maxpwr_5gl
);
92 sprom_ofdm_po
= sprom
->ofdm5glpo
;
93 sprom_mcs_po
= sprom
->mcs5glpo
;
94 extra_cdd_po
= (sprom
->cddpo
>> 8) & 0xf;
95 extra_stbc_po
= (sprom
->stbcpo
>> 8) & 0xf;
98 maxpwr
= min(sprom
->core_pwr_info
[0].maxpwr_5g
,
99 sprom
->core_pwr_info
[1].maxpwr_5g
);
100 sprom_ofdm_po
= sprom
->ofdm5gpo
;
101 sprom_mcs_po
= sprom
->mcs5gpo
;
102 extra_cdd_po
= (sprom
->cddpo
>> 4) & 0xf;
103 extra_stbc_po
= (sprom
->stbcpo
>> 4) & 0xf;
106 maxpwr
= min(sprom
->core_pwr_info
[0].maxpwr_5gh
,
107 sprom
->core_pwr_info
[1].maxpwr_5gh
);
108 sprom_ofdm_po
= sprom
->ofdm5ghpo
;
109 sprom_mcs_po
= sprom
->mcs5ghpo
;
110 extra_cdd_po
= (sprom
->cddpo
>> 12) & 0xf;
111 extra_stbc_po
= (sprom
->stbcpo
>> 12) & 0xf;
118 if (band
== B43_BAND_2G
) {
119 for (i
= 0; i
< 4; i
++) {
120 off
= ((sprom
->cck2gpo
>> (i
* 4)) & 0xf) * 2;
121 rates
->cck
[i
] = maxpwr
- off
;
126 for (i
= 0; i
< 8; i
++) {
127 off
= ((sprom_ofdm_po
>> (i
* 4)) & 0xf) * 2;
128 rates
->ofdm
[i
] = maxpwr
- off
;
132 rates
->mcs_20
[0] = rates
->ofdm
[0];
133 rates
->mcs_20
[1] = rates
->ofdm
[2];
134 rates
->mcs_20
[2] = rates
->ofdm
[3];
135 rates
->mcs_20
[3] = rates
->ofdm
[4];
136 rates
->mcs_20
[4] = rates
->ofdm
[5];
137 rates
->mcs_20
[5] = rates
->ofdm
[6];
138 rates
->mcs_20
[6] = rates
->ofdm
[7];
139 rates
->mcs_20
[7] = rates
->ofdm
[7];
142 for (i
= 0; i
< 4; i
++) {
143 off
= ((sprom_mcs_po
[0] >> (i
* 4)) & 0xf) * 2;
144 rates
->mcs_20_cdd
[i
] = maxpwr
- off
;
145 if (phy
->type
== B43_PHYTYPE_N
&& phy
->rev
>= 3)
146 rates
->mcs_20_cdd
[i
] -= extra_cdd_po
;
148 for (i
= 0; i
< 4; i
++) {
149 off
= ((sprom_mcs_po
[1] >> (i
* 4)) & 0xf) * 2;
150 rates
->mcs_20_cdd
[4 + i
] = maxpwr
- off
;
151 if (phy
->type
== B43_PHYTYPE_N
&& phy
->rev
>= 3)
152 rates
->mcs_20_cdd
[4 + i
] -= extra_cdd_po
;
156 rates
->ofdm_20_cdd
[0] = rates
->mcs_20_cdd
[0];
157 rates
->ofdm_20_cdd
[1] = rates
->mcs_20_cdd
[0];
158 rates
->ofdm_20_cdd
[2] = rates
->mcs_20_cdd
[1];
159 rates
->ofdm_20_cdd
[3] = rates
->mcs_20_cdd
[2];
160 rates
->ofdm_20_cdd
[4] = rates
->mcs_20_cdd
[3];
161 rates
->ofdm_20_cdd
[5] = rates
->mcs_20_cdd
[4];
162 rates
->ofdm_20_cdd
[6] = rates
->mcs_20_cdd
[5];
163 rates
->ofdm_20_cdd
[7] = rates
->mcs_20_cdd
[6];
166 for (i
= 0; i
< 4; i
++) {
167 off
= ((sprom_mcs_po
[0] >> (i
* 4)) & 0xf) * 2;
168 rates
->mcs_20_stbc
[i
] = maxpwr
- off
;
169 if (phy
->type
== B43_PHYTYPE_N
&& phy
->rev
>= 3)
170 rates
->mcs_20_stbc
[i
] -= extra_stbc_po
;
172 for (i
= 0; i
< 4; i
++) {
173 off
= ((sprom_mcs_po
[1] >> (i
* 4)) & 0xf) * 2;
174 rates
->mcs_20_stbc
[4 + i
] = maxpwr
- off
;
175 if (phy
->type
== B43_PHYTYPE_N
&& phy
->rev
>= 3)
176 rates
->mcs_20_stbc
[4 + i
] -= extra_stbc_po
;
180 for (i
= 0; i
< 4; i
++) {
181 off
= ((sprom_mcs_po
[2] >> (i
* 4)) & 0xf) * 2;
182 rates
->mcs_20_sdm
[i
] = maxpwr
- off
;
184 for (i
= 0; i
< 4; i
++) {
185 off
= ((sprom_mcs_po
[3] >> (i
* 4)) & 0xf) * 2;
186 rates
->mcs_20_sdm
[4 + i
] = maxpwr
- off
;