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
;
46 if (!(chip
->band
& RTW_BAND_5G
))
51 sta
= ieee80211_find_sta(vif
, bssid
);
53 rtw_warn(rtwdev
, "failed to find station entry for bss %pM\n",
58 ic_vht_cap
= &hw
->wiphy
->bands
[NL80211_BAND_5GHZ
]->vht_cap
;
59 vht_cap
= &sta
->vht_cap
;
61 if ((ic_vht_cap
->cap
& IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE
) &&
62 (vht_cap
->cap
& IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE
)) {
63 if (bfinfo
->bfer_mu_cnt
>= chip
->bfer_mu_max_num
) {
64 rtw_dbg(rtwdev
, RTW_DBG_BF
, "mu bfer number over limit\n");
68 ether_addr_copy(bfee
->mac_addr
, bssid
);
69 bfee
->role
= RTW_BFEE_MU
;
70 bfee
->p_aid
= (bssid
[5] << 1) | (bssid
[4] >> 7);
71 bfee
->aid
= bss_conf
->aid
;
72 bfinfo
->bfer_mu_cnt
++;
74 chip
->ops
->config_bfee(rtwdev
, rtwvif
, bfee
, true);
75 } else if ((ic_vht_cap
->cap
& IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE
) &&
76 (vht_cap
->cap
& IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE
)) {
77 if (bfinfo
->bfer_su_cnt
>= chip
->bfer_su_max_num
) {
78 rtw_dbg(rtwdev
, RTW_DBG_BF
, "su bfer number over limit\n");
82 sound_dim
= vht_cap
->cap
&
83 IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK
;
84 sound_dim
>>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT
;
86 ether_addr_copy(bfee
->mac_addr
, bssid
);
87 bfee
->role
= RTW_BFEE_SU
;
88 bfee
->sound_dim
= (u8
)sound_dim
;
90 bfee
->p_aid
= (bssid
[5] << 1) | (bssid
[4] >> 7);
91 bfinfo
->bfer_su_cnt
++;
92 for (i
= 0; i
< chip
->bfer_su_max_num
; i
++) {
93 if (!test_bit(i
, bfinfo
->bfer_su_reg_maping
)) {
94 set_bit(i
, bfinfo
->bfer_su_reg_maping
);
95 bfee
->su_reg_index
= i
;
100 chip
->ops
->config_bfee(rtwdev
, rtwvif
, bfee
, true);
107 void rtw_bf_init_bfer_entry_mu(struct rtw_dev
*rtwdev
,
108 struct mu_bfer_init_para
*param
)
111 u8
*addr
= param
->bfer_address
;
114 for (i
= 0; i
< ETH_ALEN
; i
++)
115 rtw_write8(rtwdev
, REG_ASSOCIATED_BFMER0_INFO
+ i
, addr
[i
]);
116 rtw_write16(rtwdev
, REG_ASSOCIATED_BFMER0_INFO
+ 6, param
->paid
);
117 rtw_write16(rtwdev
, REG_TX_CSI_RPT_PARAM_BW20
, param
->csi_para
);
119 mu_bf_ctl
= rtw_read16(rtwdev
, REG_WMAC_MU_BF_CTL
) & 0xC000;
120 mu_bf_ctl
|= param
->my_aid
| (param
->csi_length_sel
<< 12);
121 rtw_write16(rtwdev
, REG_WMAC_MU_BF_CTL
, mu_bf_ctl
);
124 void rtw_bf_cfg_sounding(struct rtw_dev
*rtwdev
, struct rtw_vif
*vif
,
125 enum rtw_trx_desc_rate rate
)
130 psf_ctl
= rtw_read32(rtwdev
, REG_BBPSF_CTRL
) |
131 BIT_WMAC_USE_NDPARATE
|
134 rtw_write8(rtwdev
, REG_SND_PTCL_CTRL
, RTW_SND_CTRL_SOUNDING
);
135 rtw_write8(rtwdev
, REG_SND_PTCL_CTRL
+ 3, 0x26);
136 rtw_write8_clr(rtwdev
, REG_RXFLTMAP1
, BIT_RXFLTMAP1_BF_REPORT_POLL
);
137 rtw_write8_clr(rtwdev
, REG_RXFLTMAP4
, BIT_RXFLTMAP4_BF_REPORT_POLL
);
139 if (vif
->net_type
== RTW_NET_AP_MODE
)
140 rtw_write32(rtwdev
, REG_BBPSF_CTRL
, psf_ctl
| BIT(12));
142 rtw_write32(rtwdev
, REG_BBPSF_CTRL
, psf_ctl
& ~BIT(12));
145 void rtw_bf_cfg_mu_bfee(struct rtw_dev
*rtwdev
, struct cfg_mumimo_para
*param
)
150 mu_valid
= rtw_read8(rtwdev
, REG_MU_TX_CTL
) &
151 ~BIT_MASK_R_MU_TABLE_VALID
;
153 rtw_write8(rtwdev
, REG_MU_TX_CTL
,
154 (mu_valid
| BIT(0) | BIT(1)) & ~(BIT(7)));
156 mu_tbl_sel
= rtw_read8(rtwdev
, REG_MU_TX_CTL
+ 1) & 0xF8;
158 rtw_write8(rtwdev
, REG_MU_TX_CTL
+ 1, mu_tbl_sel
);
159 rtw_write32(rtwdev
, REG_MU_STA_GID_VLD
, param
->given_gid_tab
[0]);
160 rtw_write32(rtwdev
, REG_MU_STA_USER_POS_INFO
, param
->given_user_pos
[0]);
161 rtw_write32(rtwdev
, REG_MU_STA_USER_POS_INFO
+ 4,
162 param
->given_user_pos
[1]);
164 rtw_write8(rtwdev
, REG_MU_TX_CTL
+ 1, mu_tbl_sel
| 1);
165 rtw_write32(rtwdev
, REG_MU_STA_GID_VLD
, param
->given_gid_tab
[1]);
166 rtw_write32(rtwdev
, REG_MU_STA_USER_POS_INFO
, param
->given_user_pos
[2]);
167 rtw_write32(rtwdev
, REG_MU_STA_USER_POS_INFO
+ 4,
168 param
->given_user_pos
[3]);
171 void rtw_bf_del_bfer_entry_mu(struct rtw_dev
*rtwdev
)
173 rtw_write32(rtwdev
, REG_ASSOCIATED_BFMER0_INFO
, 0);
174 rtw_write32(rtwdev
, REG_ASSOCIATED_BFMER0_INFO
+ 4, 0);
175 rtw_write16(rtwdev
, REG_WMAC_MU_BF_CTL
, 0);
176 rtw_write8(rtwdev
, REG_MU_TX_CTL
, 0);
179 void rtw_bf_del_sounding(struct rtw_dev
*rtwdev
)
181 rtw_write8(rtwdev
, REG_SND_PTCL_CTRL
, 0);
184 void rtw_bf_enable_bfee_su(struct rtw_dev
*rtwdev
, struct rtw_vif
*vif
,
185 struct rtw_bfee
*bfee
)
188 u8 nr_index
= bfee
->sound_dim
;
189 u8 grouping
= 0, codebookinfo
= 1, coefficientsize
= 3;
190 u32 addr_bfer_info
, addr_csi_rpt
, csi_param
;
193 rtw_dbg(rtwdev
, RTW_DBG_BF
, "config as an su bfee\n");
195 switch (bfee
->su_reg_index
) {
197 addr_bfer_info
= REG_ASSOCIATED_BFMER1_INFO
;
198 addr_csi_rpt
= REG_TX_CSI_RPT_PARAM_BW20
+ 2;
202 addr_bfer_info
= REG_ASSOCIATED_BFMER0_INFO
;
203 addr_csi_rpt
= REG_TX_CSI_RPT_PARAM_BW20
;
207 /* Sounding protocol control */
208 rtw_write8(rtwdev
, REG_SND_PTCL_CTRL
, RTW_SND_CTRL_SOUNDING
);
210 /* MAC address/Partial AID of Beamformer */
211 for (i
= 0; i
< ETH_ALEN
; i
++)
212 rtw_write8(rtwdev
, addr_bfer_info
+ i
, bfee
->mac_addr
[i
]);
214 csi_param
= (u16
)((coefficientsize
<< 10) |
215 (codebookinfo
<< 8) |
219 rtw_write16(rtwdev
, addr_csi_rpt
, csi_param
);
221 /* ndp rx standby timer */
222 rtw_write8(rtwdev
, REG_SND_PTCL_CTRL
+ 3, RTW_NDP_RX_STANDBY_TIME
);
225 /* nc index: 1 2T2R 0 1T1R
226 * nr index: 1 use Nsts 0 use reg setting
227 * codebookinfo: 1 802.11ac 3 802.11n
229 void rtw_bf_enable_bfee_mu(struct rtw_dev
*rtwdev
, struct rtw_vif
*vif
,
230 struct rtw_bfee
*bfee
)
232 struct rtw_bf_info
*bf_info
= &rtwdev
->bf_info
;
233 struct mu_bfer_init_para param
;
234 u8 nc_index
= 1, nr_index
= 1;
235 u8 grouping
= 0, codebookinfo
= 1, coefficientsize
= 0;
238 rtw_dbg(rtwdev
, RTW_DBG_BF
, "config as an mu bfee\n");
240 csi_param
= (u16
)((coefficientsize
<< 10) |
241 (codebookinfo
<< 8) |
246 rtw_dbg(rtwdev
, RTW_DBG_BF
, "nc=%d nr=%d group=%d codebookinfo=%d coefficientsize=%d\n",
247 nc_index
, nr_index
, grouping
, codebookinfo
,
250 param
.paid
= bfee
->p_aid
;
251 param
.csi_para
= csi_param
;
252 param
.my_aid
= bfee
->aid
& 0xfff;
253 param
.csi_length_sel
= HAL_CSI_SEG_4K
;
254 ether_addr_copy(param
.bfer_address
, bfee
->mac_addr
);
256 rtw_bf_init_bfer_entry_mu(rtwdev
, ¶m
);
258 bf_info
->cur_csi_rpt_rate
= DESC_RATE6M
;
259 rtw_bf_cfg_sounding(rtwdev
, vif
, DESC_RATE6M
);
261 /* accept action_no_ack */
262 rtw_write16_set(rtwdev
, REG_RXFLTMAP0
, BIT_RXFLTMAP0_ACTIONNOACK
);
264 /* accept NDPA and BF report poll */
265 rtw_write16_set(rtwdev
, REG_RXFLTMAP1
, BIT_RXFLTMAP1_BF
);
268 void rtw_bf_remove_bfee_su(struct rtw_dev
*rtwdev
,
269 struct rtw_bfee
*bfee
)
271 struct rtw_bf_info
*bfinfo
= &rtwdev
->bf_info
;
273 rtw_dbg(rtwdev
, RTW_DBG_BF
, "remove as a su bfee\n");
274 rtw_write8(rtwdev
, REG_SND_PTCL_CTRL
, RTW_SND_CTRL_REMOVE
);
276 switch (bfee
->su_reg_index
) {
278 rtw_write32(rtwdev
, REG_ASSOCIATED_BFMER0_INFO
, 0);
279 rtw_write16(rtwdev
, REG_ASSOCIATED_BFMER0_INFO
+ 4, 0);
280 rtw_write16(rtwdev
, REG_TX_CSI_RPT_PARAM_BW20
, 0);
283 rtw_write32(rtwdev
, REG_ASSOCIATED_BFMER1_INFO
, 0);
284 rtw_write16(rtwdev
, REG_ASSOCIATED_BFMER1_INFO
+ 4, 0);
285 rtw_write16(rtwdev
, REG_TX_CSI_RPT_PARAM_BW20
+ 2, 0);
289 clear_bit(bfee
->su_reg_index
, bfinfo
->bfer_su_reg_maping
);
290 bfee
->su_reg_index
= 0xFF;
293 void rtw_bf_remove_bfee_mu(struct rtw_dev
*rtwdev
,
294 struct rtw_bfee
*bfee
)
296 struct rtw_bf_info
*bfinfo
= &rtwdev
->bf_info
;
298 rtw_write8(rtwdev
, REG_SND_PTCL_CTRL
, RTW_SND_CTRL_REMOVE
);
300 rtw_bf_del_bfer_entry_mu(rtwdev
);
302 if (bfinfo
->bfer_su_cnt
== 0 && bfinfo
->bfer_mu_cnt
== 0)
303 rtw_bf_del_sounding(rtwdev
);
306 void rtw_bf_set_gid_table(struct rtw_dev
*rtwdev
, struct ieee80211_vif
*vif
,
307 struct ieee80211_bss_conf
*conf
)
309 struct rtw_vif
*rtwvif
= (struct rtw_vif
*)vif
->drv_priv
;
310 struct rtw_bfee
*bfee
= &rtwvif
->bfee
;
311 struct cfg_mumimo_para param
;
313 if (bfee
->role
!= RTW_BFEE_MU
) {
314 rtw_dbg(rtwdev
, RTW_DBG_BF
, "this vif is not mu bfee\n");
318 param
.grouping_bitmap
= 0;
320 memset(param
.sounding_sts
, 0, 6);
321 memcpy(param
.given_gid_tab
, conf
->mu_group
.membership
, 8);
322 memcpy(param
.given_user_pos
, conf
->mu_group
.position
, 16);
323 rtw_dbg(rtwdev
, RTW_DBG_BF
, "STA0: gid_valid=0x%x, user_position_l=0x%x, user_position_h=0x%x\n",
324 param
.given_gid_tab
[0], param
.given_user_pos
[0],
325 param
.given_user_pos
[1]);
327 rtw_dbg(rtwdev
, RTW_DBG_BF
, "STA1: gid_valid=0x%x, user_position_l=0x%x, user_position_h=0x%x\n",
328 param
.given_gid_tab
[1], param
.given_user_pos
[2],
329 param
.given_user_pos
[3]);
331 rtw_bf_cfg_mu_bfee(rtwdev
, ¶m
);
334 void rtw_bf_phy_init(struct rtw_dev
*rtwdev
)
338 u8 retry_limit
= 0xA;
342 tmp32
= rtw_read32(rtwdev
, REG_MU_TX_CTL
);
343 /* Enable P1 aggr new packet according to P0 transfer time */
344 tmp32
|= BIT_MU_P1_WAIT_STATE_EN
;
346 tmp32
&= ~BIT_MASK_R_MU_RL
;
347 tmp32
|= (retry_limit
<< BIT_SHIFT_R_MU_RL
) & BIT_MASK_R_MU_RL
;
348 /* Disable Tx MU-MIMO until sounding done */
349 tmp32
&= ~BIT_EN_MU_MIMO
;
350 /* Clear validity of MU STAs */
351 tmp32
&= ~BIT_MASK_R_MU_TABLE_VALID
;
352 rtw_write32(rtwdev
, REG_MU_TX_CTL
, tmp32
);
354 /* MU-MIMO Option as default value */
355 tmp8
= ack_policy
<< BIT_SHIFT_WMAC_TXMU_ACKPOLICY
;
356 tmp8
|= BIT_WMAC_TXMU_ACKPOLICY_EN
;
357 rtw_write8(rtwdev
, REG_WMAC_MU_BF_OPTION
, tmp8
);
359 /* MU-MIMO Control as default value */
360 rtw_write16(rtwdev
, REG_WMAC_MU_BF_CTL
, 0);
361 /* Set MU NDPA rate & BW source */
362 rtw_write32_set(rtwdev
, REG_TXBF_CTRL
, BIT_USE_NDPA_PARAMETER
);
364 rtw_write8(rtwdev
, REG_NDPA_OPT_CTRL
, ndpa_rate
);
366 rtw_write32_mask(rtwdev
, REG_BBPSF_CTRL
, BIT_MASK_CSI_RATE
,
370 void rtw_bf_cfg_csi_rate(struct rtw_dev
*rtwdev
, u8 rssi
, u8 cur_rate
,
371 u8 fixrate_en
, u8
*new_rate
)
376 csi_cfg
= rtw_read32(rtwdev
, REG_BBPSF_CTRL
) & ~BIT_MASK_CSI_RATE
;
377 cur_rrsr
= rtw_read16(rtwdev
, REG_RRSR
);
380 if (cur_rate
!= DESC_RATE54M
) {
381 cur_rrsr
|= BIT(DESC_RATE54M
);
382 csi_cfg
|= (DESC_RATE54M
& BIT_MASK_CSI_RATE_VAL
) <<
384 rtw_write16(rtwdev
, REG_RRSR
, cur_rrsr
);
385 rtw_write32(rtwdev
, REG_BBPSF_CTRL
, csi_cfg
);
387 *new_rate
= DESC_RATE54M
;
389 if (cur_rate
!= DESC_RATE24M
) {
390 cur_rrsr
&= ~BIT(DESC_RATE54M
);
391 csi_cfg
|= (DESC_RATE54M
& BIT_MASK_CSI_RATE_VAL
) <<
393 rtw_write16(rtwdev
, REG_RRSR
, cur_rrsr
);
394 rtw_write32(rtwdev
, REG_BBPSF_CTRL
, csi_cfg
);
396 *new_rate
= DESC_RATE24M
;