1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2018-2019 Realtek Corporation.
10 void rtw_bf_disassoc(struct rtw_dev
*rtwdev
, struct ieee80211_vif
*vif
,
11 struct ieee80211_bss_conf
*bss_conf
)
13 struct rtw_chip_info
*chip
= rtwdev
->chip
;
14 struct rtw_vif
*rtwvif
= (struct rtw_vif
*)vif
->drv_priv
;
15 struct rtw_bfee
*bfee
= &rtwvif
->bfee
;
16 struct rtw_bf_info
*bfinfo
= &rtwdev
->bf_info
;
18 if (bfee
->role
== RTW_BFEE_NONE
)
21 if (bfee
->role
== RTW_BFEE_MU
)
22 bfinfo
->bfer_mu_cnt
--;
23 else if (bfee
->role
== RTW_BFEE_SU
)
24 bfinfo
->bfer_su_cnt
--;
26 chip
->ops
->config_bfee(rtwdev
, rtwvif
, bfee
, false);
28 bfee
->role
= RTW_BFEE_NONE
;
31 void rtw_bf_assoc(struct rtw_dev
*rtwdev
, struct ieee80211_vif
*vif
,
32 struct ieee80211_bss_conf
*bss_conf
)
34 struct ieee80211_hw
*hw
= rtwdev
->hw
;
35 struct rtw_vif
*rtwvif
= (struct rtw_vif
*)vif
->drv_priv
;
36 struct rtw_bfee
*bfee
= &rtwvif
->bfee
;
37 struct rtw_bf_info
*bfinfo
= &rtwdev
->bf_info
;
38 struct rtw_chip_info
*chip
= rtwdev
->chip
;
39 struct ieee80211_sta
*sta
;
40 struct ieee80211_sta_vht_cap
*vht_cap
;
41 struct ieee80211_sta_vht_cap
*ic_vht_cap
;
42 const u8
*bssid
= bss_conf
->bssid
;
44 u8 bfee_role
= RTW_BFEE_NONE
;
47 if (!(chip
->band
& RTW_BAND_5G
))
52 sta
= ieee80211_find_sta(vif
, bssid
);
54 rtw_warn(rtwdev
, "failed to find station entry for bss %pM\n",
59 ic_vht_cap
= &hw
->wiphy
->bands
[NL80211_BAND_5GHZ
]->vht_cap
;
60 vht_cap
= &sta
->vht_cap
;
62 if ((ic_vht_cap
->cap
& IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE
) &&
63 (vht_cap
->cap
& IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE
)) {
64 if (bfinfo
->bfer_mu_cnt
>= chip
->bfer_mu_max_num
) {
65 rtw_dbg(rtwdev
, RTW_DBG_BF
, "mu bfer number over limit\n");
69 ether_addr_copy(bfee
->mac_addr
, bssid
);
70 bfee_role
= RTW_BFEE_MU
;
71 bfee
->p_aid
= (bssid
[5] << 1) | (bssid
[4] >> 7);
72 bfee
->aid
= bss_conf
->aid
;
73 bfinfo
->bfer_mu_cnt
++;
75 chip
->ops
->config_bfee(rtwdev
, rtwvif
, bfee
, true);
76 } else if ((ic_vht_cap
->cap
& IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE
) &&
77 (vht_cap
->cap
& IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE
)) {
78 if (bfinfo
->bfer_su_cnt
>= chip
->bfer_su_max_num
) {
79 rtw_dbg(rtwdev
, RTW_DBG_BF
, "su bfer number over limit\n");
83 sound_dim
= vht_cap
->cap
&
84 IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK
;
85 sound_dim
>>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT
;
87 ether_addr_copy(bfee
->mac_addr
, bssid
);
88 bfee_role
= RTW_BFEE_SU
;
89 bfee
->sound_dim
= (u8
)sound_dim
;
91 bfee
->p_aid
= (bssid
[5] << 1) | (bssid
[4] >> 7);
92 bfinfo
->bfer_su_cnt
++;
93 for (i
= 0; i
< chip
->bfer_su_max_num
; i
++) {
94 if (!test_bit(i
, bfinfo
->bfer_su_reg_maping
)) {
95 set_bit(i
, bfinfo
->bfer_su_reg_maping
);
96 bfee
->su_reg_index
= i
;
101 chip
->ops
->config_bfee(rtwdev
, rtwvif
, bfee
, true);
105 bfee
->role
= bfee_role
;
109 void rtw_bf_init_bfer_entry_mu(struct rtw_dev
*rtwdev
,
110 struct mu_bfer_init_para
*param
)
113 u8
*addr
= param
->bfer_address
;
116 for (i
= 0; i
< ETH_ALEN
; i
++)
117 rtw_write8(rtwdev
, REG_ASSOCIATED_BFMER0_INFO
+ i
, addr
[i
]);
118 rtw_write16(rtwdev
, REG_ASSOCIATED_BFMER0_INFO
+ 6, param
->paid
);
119 rtw_write16(rtwdev
, REG_TX_CSI_RPT_PARAM_BW20
, param
->csi_para
);
121 mu_bf_ctl
= rtw_read16(rtwdev
, REG_WMAC_MU_BF_CTL
) & 0xC000;
122 mu_bf_ctl
|= param
->my_aid
| (param
->csi_length_sel
<< 12);
123 rtw_write16(rtwdev
, REG_WMAC_MU_BF_CTL
, mu_bf_ctl
);
126 void rtw_bf_cfg_sounding(struct rtw_dev
*rtwdev
, struct rtw_vif
*vif
,
127 enum rtw_trx_desc_rate rate
)
132 psf_ctl
= rtw_read32(rtwdev
, REG_BBPSF_CTRL
) |
133 BIT_WMAC_USE_NDPARATE
|
136 rtw_write8(rtwdev
, REG_SND_PTCL_CTRL
, RTW_SND_CTRL_SOUNDING
);
137 rtw_write8(rtwdev
, REG_SND_PTCL_CTRL
+ 3, 0x26);
138 rtw_write8_clr(rtwdev
, REG_RXFLTMAP1
, BIT_RXFLTMAP1_BF_REPORT_POLL
);
139 rtw_write8_clr(rtwdev
, REG_RXFLTMAP4
, BIT_RXFLTMAP4_BF_REPORT_POLL
);
141 if (vif
->net_type
== RTW_NET_AP_MODE
)
142 rtw_write32(rtwdev
, REG_BBPSF_CTRL
, psf_ctl
| BIT(12));
144 rtw_write32(rtwdev
, REG_BBPSF_CTRL
, psf_ctl
& ~BIT(12));
147 void rtw_bf_cfg_mu_bfee(struct rtw_dev
*rtwdev
, struct cfg_mumimo_para
*param
)
152 mu_valid
= rtw_read8(rtwdev
, REG_MU_TX_CTL
) &
153 ~BIT_MASK_R_MU_TABLE_VALID
;
155 rtw_write8(rtwdev
, REG_MU_TX_CTL
,
156 (mu_valid
| BIT(0) | BIT(1)) & ~(BIT(7)));
158 mu_tbl_sel
= rtw_read8(rtwdev
, REG_MU_TX_CTL
+ 1) & 0xF8;
160 rtw_write8(rtwdev
, REG_MU_TX_CTL
+ 1, mu_tbl_sel
);
161 rtw_write32(rtwdev
, REG_MU_STA_GID_VLD
, param
->given_gid_tab
[0]);
162 rtw_write32(rtwdev
, REG_MU_STA_USER_POS_INFO
, param
->given_user_pos
[0]);
163 rtw_write32(rtwdev
, REG_MU_STA_USER_POS_INFO
+ 4,
164 param
->given_user_pos
[1]);
166 rtw_write8(rtwdev
, REG_MU_TX_CTL
+ 1, mu_tbl_sel
| 1);
167 rtw_write32(rtwdev
, REG_MU_STA_GID_VLD
, param
->given_gid_tab
[1]);
168 rtw_write32(rtwdev
, REG_MU_STA_USER_POS_INFO
, param
->given_user_pos
[2]);
169 rtw_write32(rtwdev
, REG_MU_STA_USER_POS_INFO
+ 4,
170 param
->given_user_pos
[3]);
173 void rtw_bf_del_bfer_entry_mu(struct rtw_dev
*rtwdev
)
175 rtw_write32(rtwdev
, REG_ASSOCIATED_BFMER0_INFO
, 0);
176 rtw_write32(rtwdev
, REG_ASSOCIATED_BFMER0_INFO
+ 4, 0);
177 rtw_write16(rtwdev
, REG_WMAC_MU_BF_CTL
, 0);
178 rtw_write8(rtwdev
, REG_MU_TX_CTL
, 0);
181 void rtw_bf_del_sounding(struct rtw_dev
*rtwdev
)
183 rtw_write8(rtwdev
, REG_SND_PTCL_CTRL
, 0);
186 void rtw_bf_enable_bfee_su(struct rtw_dev
*rtwdev
, struct rtw_vif
*vif
,
187 struct rtw_bfee
*bfee
)
190 u8 nr_index
= bfee
->sound_dim
;
191 u8 grouping
= 0, codebookinfo
= 1, coefficientsize
= 3;
192 u32 addr_bfer_info
, addr_csi_rpt
, csi_param
;
195 rtw_dbg(rtwdev
, RTW_DBG_BF
, "config as an su bfee\n");
197 switch (bfee
->su_reg_index
) {
199 addr_bfer_info
= REG_ASSOCIATED_BFMER1_INFO
;
200 addr_csi_rpt
= REG_TX_CSI_RPT_PARAM_BW20
+ 2;
204 addr_bfer_info
= REG_ASSOCIATED_BFMER0_INFO
;
205 addr_csi_rpt
= REG_TX_CSI_RPT_PARAM_BW20
;
209 /* Sounding protocol control */
210 rtw_write8(rtwdev
, REG_SND_PTCL_CTRL
, RTW_SND_CTRL_SOUNDING
);
212 /* MAC address/Partial AID of Beamformer */
213 for (i
= 0; i
< ETH_ALEN
; i
++)
214 rtw_write8(rtwdev
, addr_bfer_info
+ i
, bfee
->mac_addr
[i
]);
216 csi_param
= (u16
)((coefficientsize
<< 10) |
217 (codebookinfo
<< 8) |
221 rtw_write16(rtwdev
, addr_csi_rpt
, csi_param
);
223 /* ndp rx standby timer */
224 rtw_write8(rtwdev
, REG_SND_PTCL_CTRL
+ 3, RTW_NDP_RX_STANDBY_TIME
);
227 /* nc index: 1 2T2R 0 1T1R
228 * nr index: 1 use Nsts 0 use reg setting
229 * codebookinfo: 1 802.11ac 3 802.11n
231 void rtw_bf_enable_bfee_mu(struct rtw_dev
*rtwdev
, struct rtw_vif
*vif
,
232 struct rtw_bfee
*bfee
)
234 struct rtw_bf_info
*bf_info
= &rtwdev
->bf_info
;
235 struct mu_bfer_init_para param
;
236 u8 nc_index
= 1, nr_index
= 1;
237 u8 grouping
= 0, codebookinfo
= 1, coefficientsize
= 0;
240 rtw_dbg(rtwdev
, RTW_DBG_BF
, "config as an mu bfee\n");
242 csi_param
= (u16
)((coefficientsize
<< 10) |
243 (codebookinfo
<< 8) |
248 rtw_dbg(rtwdev
, RTW_DBG_BF
, "nc=%d nr=%d group=%d codebookinfo=%d coefficientsize=%d\n",
249 nc_index
, nr_index
, grouping
, codebookinfo
,
252 param
.paid
= bfee
->p_aid
;
253 param
.csi_para
= csi_param
;
254 param
.my_aid
= bfee
->aid
& 0xfff;
255 param
.csi_length_sel
= HAL_CSI_SEG_4K
;
256 ether_addr_copy(param
.bfer_address
, bfee
->mac_addr
);
258 rtw_bf_init_bfer_entry_mu(rtwdev
, ¶m
);
260 bf_info
->cur_csi_rpt_rate
= DESC_RATE6M
;
261 rtw_bf_cfg_sounding(rtwdev
, vif
, DESC_RATE6M
);
263 /* accept action_no_ack */
264 rtw_write16_set(rtwdev
, REG_RXFLTMAP0
, BIT_RXFLTMAP0_ACTIONNOACK
);
266 /* accept NDPA and BF report poll */
267 rtw_write16_set(rtwdev
, REG_RXFLTMAP1
, BIT_RXFLTMAP1_BF
);
270 void rtw_bf_remove_bfee_su(struct rtw_dev
*rtwdev
,
271 struct rtw_bfee
*bfee
)
273 struct rtw_bf_info
*bfinfo
= &rtwdev
->bf_info
;
275 rtw_dbg(rtwdev
, RTW_DBG_BF
, "remove as a su bfee\n");
276 rtw_write8(rtwdev
, REG_SND_PTCL_CTRL
, RTW_SND_CTRL_REMOVE
);
278 switch (bfee
->su_reg_index
) {
280 rtw_write32(rtwdev
, REG_ASSOCIATED_BFMER0_INFO
, 0);
281 rtw_write16(rtwdev
, REG_ASSOCIATED_BFMER0_INFO
+ 4, 0);
282 rtw_write16(rtwdev
, REG_TX_CSI_RPT_PARAM_BW20
, 0);
285 rtw_write32(rtwdev
, REG_ASSOCIATED_BFMER1_INFO
, 0);
286 rtw_write16(rtwdev
, REG_ASSOCIATED_BFMER1_INFO
+ 4, 0);
287 rtw_write16(rtwdev
, REG_TX_CSI_RPT_PARAM_BW20
+ 2, 0);
291 clear_bit(bfee
->su_reg_index
, bfinfo
->bfer_su_reg_maping
);
292 bfee
->su_reg_index
= 0xFF;
295 void rtw_bf_remove_bfee_mu(struct rtw_dev
*rtwdev
,
296 struct rtw_bfee
*bfee
)
298 struct rtw_bf_info
*bfinfo
= &rtwdev
->bf_info
;
300 rtw_write8(rtwdev
, REG_SND_PTCL_CTRL
, RTW_SND_CTRL_REMOVE
);
302 rtw_bf_del_bfer_entry_mu(rtwdev
);
304 if (bfinfo
->bfer_su_cnt
== 0 && bfinfo
->bfer_mu_cnt
== 0)
305 rtw_bf_del_sounding(rtwdev
);
308 void rtw_bf_set_gid_table(struct rtw_dev
*rtwdev
, struct ieee80211_vif
*vif
,
309 struct ieee80211_bss_conf
*conf
)
311 struct rtw_vif
*rtwvif
= (struct rtw_vif
*)vif
->drv_priv
;
312 struct rtw_bfee
*bfee
= &rtwvif
->bfee
;
313 struct cfg_mumimo_para param
;
315 if (bfee
->role
!= RTW_BFEE_MU
) {
316 rtw_dbg(rtwdev
, RTW_DBG_BF
, "this vif is not mu bfee\n");
320 param
.grouping_bitmap
= 0;
322 memset(param
.sounding_sts
, 0, 6);
323 memcpy(param
.given_gid_tab
, conf
->mu_group
.membership
, 8);
324 memcpy(param
.given_user_pos
, conf
->mu_group
.position
, 16);
325 rtw_dbg(rtwdev
, RTW_DBG_BF
, "STA0: gid_valid=0x%x, user_position_l=0x%x, user_position_h=0x%x\n",
326 param
.given_gid_tab
[0], param
.given_user_pos
[0],
327 param
.given_user_pos
[1]);
329 rtw_dbg(rtwdev
, RTW_DBG_BF
, "STA1: gid_valid=0x%x, user_position_l=0x%x, user_position_h=0x%x\n",
330 param
.given_gid_tab
[1], param
.given_user_pos
[2],
331 param
.given_user_pos
[3]);
333 rtw_bf_cfg_mu_bfee(rtwdev
, ¶m
);
336 void rtw_bf_phy_init(struct rtw_dev
*rtwdev
)
340 u8 retry_limit
= 0xA;
344 tmp32
= rtw_read32(rtwdev
, REG_MU_TX_CTL
);
345 /* Enable P1 aggr new packet according to P0 transfer time */
346 tmp32
|= BIT_MU_P1_WAIT_STATE_EN
;
348 tmp32
&= ~BIT_MASK_R_MU_RL
;
349 tmp32
|= (retry_limit
<< BIT_SHIFT_R_MU_RL
) & BIT_MASK_R_MU_RL
;
350 /* Disable Tx MU-MIMO until sounding done */
351 tmp32
&= ~BIT_EN_MU_MIMO
;
352 /* Clear validity of MU STAs */
353 tmp32
&= ~BIT_MASK_R_MU_TABLE_VALID
;
354 rtw_write32(rtwdev
, REG_MU_TX_CTL
, tmp32
);
356 /* MU-MIMO Option as default value */
357 tmp8
= ack_policy
<< BIT_SHIFT_WMAC_TXMU_ACKPOLICY
;
358 tmp8
|= BIT_WMAC_TXMU_ACKPOLICY_EN
;
359 rtw_write8(rtwdev
, REG_WMAC_MU_BF_OPTION
, tmp8
);
361 /* MU-MIMO Control as default value */
362 rtw_write16(rtwdev
, REG_WMAC_MU_BF_CTL
, 0);
363 /* Set MU NDPA rate & BW source */
364 rtw_write32_set(rtwdev
, REG_TXBF_CTRL
, BIT_USE_NDPA_PARAMETER
);
366 rtw_write8(rtwdev
, REG_NDPA_OPT_CTRL
, ndpa_rate
);
368 rtw_write32_mask(rtwdev
, REG_BBPSF_CTRL
, BIT_MASK_CSI_RATE
,
372 void rtw_bf_cfg_csi_rate(struct rtw_dev
*rtwdev
, u8 rssi
, u8 cur_rate
,
373 u8 fixrate_en
, u8
*new_rate
)
378 csi_cfg
= rtw_read32(rtwdev
, REG_BBPSF_CTRL
) & ~BIT_MASK_CSI_RATE
;
379 cur_rrsr
= rtw_read16(rtwdev
, REG_RRSR
);
382 if (cur_rate
!= DESC_RATE54M
) {
383 cur_rrsr
|= BIT(DESC_RATE54M
);
384 csi_cfg
|= (DESC_RATE54M
& BIT_MASK_CSI_RATE_VAL
) <<
386 rtw_write16(rtwdev
, REG_RRSR
, cur_rrsr
);
387 rtw_write32(rtwdev
, REG_BBPSF_CTRL
, csi_cfg
);
389 *new_rate
= DESC_RATE54M
;
391 if (cur_rate
!= DESC_RATE24M
) {
392 cur_rrsr
&= ~BIT(DESC_RATE54M
);
393 csi_cfg
|= (DESC_RATE54M
& BIT_MASK_CSI_RATE_VAL
) <<
395 rtw_write16(rtwdev
, REG_RRSR
, cur_rrsr
);
396 rtw_write32(rtwdev
, REG_BBPSF_CTRL
, csi_cfg
);
398 *new_rate
= DESC_RATE24M
;