1 | // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause |
2 | /* Copyright(c) 2018-2019 Realtek Corporation |
3 | */ |
4 | |
5 | #include "main.h" |
6 | #include "sec.h" |
7 | #include "tx.h" |
8 | #include "fw.h" |
9 | #include "mac.h" |
10 | #include "coex.h" |
11 | #include "ps.h" |
12 | #include "reg.h" |
13 | #include "bf.h" |
14 | #include "debug.h" |
15 | #include "wow.h" |
16 | #include "sar.h" |
17 | |
18 | static void rtw_ops_tx(struct ieee80211_hw *hw, |
19 | struct ieee80211_tx_control *control, |
20 | struct sk_buff *skb) |
21 | { |
22 | struct rtw_dev *rtwdev = hw->priv; |
23 | |
24 | if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags)) { |
25 | ieee80211_free_txskb(hw, skb); |
26 | return; |
27 | } |
28 | |
29 | rtw_tx(rtwdev, control, skb); |
30 | } |
31 | |
32 | static void rtw_ops_wake_tx_queue(struct ieee80211_hw *hw, |
33 | struct ieee80211_txq *txq) |
34 | { |
35 | struct rtw_dev *rtwdev = hw->priv; |
36 | struct rtw_txq *rtwtxq = (struct rtw_txq *)txq->drv_priv; |
37 | |
38 | if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags)) |
39 | return; |
40 | |
41 | spin_lock_bh(lock: &rtwdev->txq_lock); |
42 | if (list_empty(head: &rtwtxq->list)) |
43 | list_add_tail(new: &rtwtxq->list, head: &rtwdev->txqs); |
44 | spin_unlock_bh(lock: &rtwdev->txq_lock); |
45 | |
46 | /* ensure to dequeue EAPOL (4/4) at the right time */ |
47 | if (txq->ac == IEEE80211_AC_VO) |
48 | __rtw_tx_work(rtwdev); |
49 | else |
50 | queue_work(wq: rtwdev->tx_wq, work: &rtwdev->tx_work); |
51 | } |
52 | |
53 | static int rtw_ops_start(struct ieee80211_hw *hw) |
54 | { |
55 | struct rtw_dev *rtwdev = hw->priv; |
56 | int ret; |
57 | |
58 | mutex_lock(&rtwdev->mutex); |
59 | ret = rtw_core_start(rtwdev); |
60 | mutex_unlock(lock: &rtwdev->mutex); |
61 | |
62 | return ret; |
63 | } |
64 | |
65 | static void rtw_ops_stop(struct ieee80211_hw *hw) |
66 | { |
67 | struct rtw_dev *rtwdev = hw->priv; |
68 | |
69 | mutex_lock(&rtwdev->mutex); |
70 | rtw_core_stop(rtwdev); |
71 | mutex_unlock(lock: &rtwdev->mutex); |
72 | } |
73 | |
74 | static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed) |
75 | { |
76 | struct rtw_dev *rtwdev = hw->priv; |
77 | int ret = 0; |
78 | |
79 | /* let previous ips work finish to ensure we don't leave ips twice */ |
80 | cancel_work_sync(work: &rtwdev->ips_work); |
81 | |
82 | mutex_lock(&rtwdev->mutex); |
83 | |
84 | rtw_leave_lps_deep(rtwdev); |
85 | |
86 | if ((changed & IEEE80211_CONF_CHANGE_IDLE) && |
87 | !(hw->conf.flags & IEEE80211_CONF_IDLE)) { |
88 | ret = rtw_leave_ips(rtwdev); |
89 | if (ret) { |
90 | rtw_err(rtwdev, "failed to leave idle state\n" ); |
91 | goto out; |
92 | } |
93 | } |
94 | |
95 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) |
96 | rtw_set_channel(rtwdev); |
97 | |
98 | if ((changed & IEEE80211_CONF_CHANGE_IDLE) && |
99 | (hw->conf.flags & IEEE80211_CONF_IDLE) && |
100 | !test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) |
101 | rtw_enter_ips(rtwdev); |
102 | |
103 | out: |
104 | mutex_unlock(lock: &rtwdev->mutex); |
105 | return ret; |
106 | } |
107 | |
108 | static const struct rtw_vif_port rtw_vif_port[] = { |
109 | [0] = { |
110 | .mac_addr = {.addr = 0x0610}, |
111 | .bssid = {.addr = 0x0618}, |
112 | .net_type = {.addr = 0x0100, .mask = 0x30000}, |
113 | .aid = {.addr = 0x06a8, .mask = 0x7ff}, |
114 | .bcn_ctrl = {.addr = 0x0550, .mask = 0xff}, |
115 | }, |
116 | [1] = { |
117 | .mac_addr = {.addr = 0x0700}, |
118 | .bssid = {.addr = 0x0708}, |
119 | .net_type = {.addr = 0x0100, .mask = 0xc0000}, |
120 | .aid = {.addr = 0x0710, .mask = 0x7ff}, |
121 | .bcn_ctrl = {.addr = 0x0551, .mask = 0xff}, |
122 | }, |
123 | [2] = { |
124 | .mac_addr = {.addr = 0x1620}, |
125 | .bssid = {.addr = 0x1628}, |
126 | .net_type = {.addr = 0x1100, .mask = 0x3}, |
127 | .aid = {.addr = 0x1600, .mask = 0x7ff}, |
128 | .bcn_ctrl = {.addr = 0x0578, .mask = 0xff}, |
129 | }, |
130 | [3] = { |
131 | .mac_addr = {.addr = 0x1630}, |
132 | .bssid = {.addr = 0x1638}, |
133 | .net_type = {.addr = 0x1100, .mask = 0xc}, |
134 | .aid = {.addr = 0x1604, .mask = 0x7ff}, |
135 | .bcn_ctrl = {.addr = 0x0579, .mask = 0xff}, |
136 | }, |
137 | [4] = { |
138 | .mac_addr = {.addr = 0x1640}, |
139 | .bssid = {.addr = 0x1648}, |
140 | .net_type = {.addr = 0x1100, .mask = 0x30}, |
141 | .aid = {.addr = 0x1608, .mask = 0x7ff}, |
142 | .bcn_ctrl = {.addr = 0x057a, .mask = 0xff}, |
143 | }, |
144 | }; |
145 | |
146 | static int rtw_ops_add_interface(struct ieee80211_hw *hw, |
147 | struct ieee80211_vif *vif) |
148 | { |
149 | struct rtw_dev *rtwdev = hw->priv; |
150 | struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; |
151 | enum rtw_net_type net_type; |
152 | u32 config = 0; |
153 | u8 port; |
154 | u8 bcn_ctrl = 0; |
155 | |
156 | if (rtw_fw_feature_check(fw: &rtwdev->fw, feature: FW_FEATURE_BCN_FILTER)) |
157 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | |
158 | IEEE80211_VIF_SUPPORTS_CQM_RSSI; |
159 | rtwvif->stats.tx_unicast = 0; |
160 | rtwvif->stats.rx_unicast = 0; |
161 | rtwvif->stats.tx_cnt = 0; |
162 | rtwvif->stats.rx_cnt = 0; |
163 | rtwvif->scan_req = NULL; |
164 | memset(&rtwvif->bfee, 0, sizeof(struct rtw_bfee)); |
165 | rtw_txq_init(rtwdev, txq: vif->txq); |
166 | INIT_LIST_HEAD(list: &rtwvif->rsvd_page_list); |
167 | |
168 | mutex_lock(&rtwdev->mutex); |
169 | |
170 | port = find_first_zero_bit(addr: rtwdev->hw_port, size: RTW_PORT_NUM); |
171 | if (port >= RTW_PORT_NUM) { |
172 | mutex_unlock(lock: &rtwdev->mutex); |
173 | return -EINVAL; |
174 | } |
175 | set_bit(nr: port, addr: rtwdev->hw_port); |
176 | |
177 | rtwvif->port = port; |
178 | rtwvif->conf = &rtw_vif_port[port]; |
179 | rtw_leave_lps_deep(rtwdev); |
180 | |
181 | switch (vif->type) { |
182 | case NL80211_IFTYPE_AP: |
183 | case NL80211_IFTYPE_MESH_POINT: |
184 | rtw_add_rsvd_page_bcn(rtwdev, rtwvif); |
185 | net_type = RTW_NET_AP_MODE; |
186 | bcn_ctrl = BIT_EN_BCN_FUNCTION | BIT_DIS_TSF_UDT; |
187 | break; |
188 | case NL80211_IFTYPE_ADHOC: |
189 | rtw_add_rsvd_page_bcn(rtwdev, rtwvif); |
190 | net_type = RTW_NET_AD_HOC; |
191 | bcn_ctrl = BIT_EN_BCN_FUNCTION | BIT_DIS_TSF_UDT; |
192 | break; |
193 | case NL80211_IFTYPE_STATION: |
194 | rtw_add_rsvd_page_sta(rtwdev, rtwvif); |
195 | net_type = RTW_NET_NO_LINK; |
196 | bcn_ctrl = BIT_EN_BCN_FUNCTION; |
197 | break; |
198 | default: |
199 | WARN_ON(1); |
200 | clear_bit(nr: rtwvif->port, addr: rtwdev->hw_port); |
201 | mutex_unlock(lock: &rtwdev->mutex); |
202 | return -EINVAL; |
203 | } |
204 | |
205 | ether_addr_copy(dst: rtwvif->mac_addr, src: vif->addr); |
206 | config |= PORT_SET_MAC_ADDR; |
207 | rtwvif->net_type = net_type; |
208 | config |= PORT_SET_NET_TYPE; |
209 | rtwvif->bcn_ctrl = bcn_ctrl; |
210 | config |= PORT_SET_BCN_CTRL; |
211 | rtw_vif_port_config(rtwdev, rtwvif, config); |
212 | rtw_core_port_switch(rtwdev, vif); |
213 | rtw_recalc_lps(rtwdev, new_vif: vif); |
214 | |
215 | mutex_unlock(lock: &rtwdev->mutex); |
216 | |
217 | rtw_dbg(rtwdev, mask: RTW_DBG_STATE, fmt: "start vif %pM on port %d\n" , vif->addr, rtwvif->port); |
218 | return 0; |
219 | } |
220 | |
221 | static void rtw_ops_remove_interface(struct ieee80211_hw *hw, |
222 | struct ieee80211_vif *vif) |
223 | { |
224 | struct rtw_dev *rtwdev = hw->priv; |
225 | struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; |
226 | u32 config = 0; |
227 | |
228 | rtw_dbg(rtwdev, mask: RTW_DBG_STATE, fmt: "stop vif %pM on port %d\n" , vif->addr, rtwvif->port); |
229 | |
230 | mutex_lock(&rtwdev->mutex); |
231 | |
232 | rtw_leave_lps_deep(rtwdev); |
233 | |
234 | rtw_txq_cleanup(rtwdev, txq: vif->txq); |
235 | rtw_remove_rsvd_page(rtwdev, rtwvif); |
236 | |
237 | eth_zero_addr(addr: rtwvif->mac_addr); |
238 | config |= PORT_SET_MAC_ADDR; |
239 | rtwvif->net_type = RTW_NET_NO_LINK; |
240 | config |= PORT_SET_NET_TYPE; |
241 | rtwvif->bcn_ctrl = 0; |
242 | config |= PORT_SET_BCN_CTRL; |
243 | rtw_vif_port_config(rtwdev, rtwvif, config); |
244 | clear_bit(nr: rtwvif->port, addr: rtwdev->hw_port); |
245 | rtw_recalc_lps(rtwdev, NULL); |
246 | |
247 | mutex_unlock(lock: &rtwdev->mutex); |
248 | } |
249 | |
250 | static int rtw_ops_change_interface(struct ieee80211_hw *hw, |
251 | struct ieee80211_vif *vif, |
252 | enum nl80211_iftype type, bool p2p) |
253 | { |
254 | struct rtw_dev *rtwdev = hw->priv; |
255 | |
256 | rtw_dbg(rtwdev, mask: RTW_DBG_STATE, fmt: "change vif %pM (%d)->(%d), p2p (%d)->(%d)\n" , |
257 | vif->addr, vif->type, type, vif->p2p, p2p); |
258 | |
259 | rtw_ops_remove_interface(hw, vif); |
260 | |
261 | vif->type = type; |
262 | vif->p2p = p2p; |
263 | |
264 | return rtw_ops_add_interface(hw, vif); |
265 | } |
266 | |
267 | static void rtw_ops_configure_filter(struct ieee80211_hw *hw, |
268 | unsigned int changed_flags, |
269 | unsigned int *new_flags, |
270 | u64 multicast) |
271 | { |
272 | struct rtw_dev *rtwdev = hw->priv; |
273 | |
274 | *new_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_FCSFAIL | |
275 | FIF_BCN_PRBRESP_PROMISC; |
276 | |
277 | mutex_lock(&rtwdev->mutex); |
278 | |
279 | rtw_leave_lps_deep(rtwdev); |
280 | |
281 | if (changed_flags & FIF_ALLMULTI) { |
282 | if (*new_flags & FIF_ALLMULTI) |
283 | rtwdev->hal.rcr |= BIT_AM; |
284 | else |
285 | rtwdev->hal.rcr &= ~(BIT_AM); |
286 | } |
287 | if (changed_flags & FIF_FCSFAIL) { |
288 | if (*new_flags & FIF_FCSFAIL) |
289 | rtwdev->hal.rcr |= BIT_ACRC32; |
290 | else |
291 | rtwdev->hal.rcr &= ~(BIT_ACRC32); |
292 | } |
293 | if (changed_flags & FIF_OTHER_BSS) { |
294 | if (*new_flags & FIF_OTHER_BSS) |
295 | rtwdev->hal.rcr |= BIT_AAP; |
296 | else |
297 | rtwdev->hal.rcr &= ~(BIT_AAP); |
298 | } |
299 | if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { |
300 | if (*new_flags & FIF_BCN_PRBRESP_PROMISC) |
301 | rtwdev->hal.rcr &= ~(BIT_CBSSID_BCN | BIT_CBSSID_DATA); |
302 | else |
303 | rtwdev->hal.rcr |= BIT_CBSSID_BCN; |
304 | } |
305 | |
306 | rtw_dbg(rtwdev, mask: RTW_DBG_RX, |
307 | fmt: "config rx filter, changed=0x%08x, new=0x%08x, rcr=0x%08x\n" , |
308 | changed_flags, *new_flags, rtwdev->hal.rcr); |
309 | |
310 | rtw_write32(rtwdev, REG_RCR, val: rtwdev->hal.rcr); |
311 | |
312 | mutex_unlock(lock: &rtwdev->mutex); |
313 | } |
314 | |
315 | /* Only have one group of EDCA parameters now */ |
316 | static const u32 ac_to_edca_param[IEEE80211_NUM_ACS] = { |
317 | [IEEE80211_AC_VO] = REG_EDCA_VO_PARAM, |
318 | [IEEE80211_AC_VI] = REG_EDCA_VI_PARAM, |
319 | [IEEE80211_AC_BE] = REG_EDCA_BE_PARAM, |
320 | [IEEE80211_AC_BK] = REG_EDCA_BK_PARAM, |
321 | }; |
322 | |
323 | static u8 rtw_aifsn_to_aifs(struct rtw_dev *rtwdev, |
324 | struct rtw_vif *rtwvif, u8 aifsn) |
325 | { |
326 | struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); |
327 | u8 slot_time; |
328 | u8 sifs; |
329 | |
330 | slot_time = vif->bss_conf.use_short_slot ? 9 : 20; |
331 | sifs = rtwdev->hal.current_band_type == RTW_BAND_5G ? 16 : 10; |
332 | |
333 | return aifsn * slot_time + sifs; |
334 | } |
335 | |
336 | static void __rtw_conf_tx(struct rtw_dev *rtwdev, |
337 | struct rtw_vif *rtwvif, u16 ac) |
338 | { |
339 | struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac]; |
340 | u32 edca_param = ac_to_edca_param[ac]; |
341 | u8 ecw_max, ecw_min; |
342 | u8 aifs; |
343 | |
344 | /* 2^ecw - 1 = cw; ecw = log2(cw + 1) */ |
345 | ecw_max = ilog2(params->cw_max + 1); |
346 | ecw_min = ilog2(params->cw_min + 1); |
347 | aifs = rtw_aifsn_to_aifs(rtwdev, rtwvif, aifsn: params->aifs); |
348 | rtw_write32_mask(rtwdev, addr: edca_param, BIT_MASK_TXOP_LMT, data: params->txop); |
349 | rtw_write32_mask(rtwdev, addr: edca_param, BIT_MASK_CWMAX, data: ecw_max); |
350 | rtw_write32_mask(rtwdev, addr: edca_param, BIT_MASK_CWMIN, data: ecw_min); |
351 | rtw_write32_mask(rtwdev, addr: edca_param, BIT_MASK_AIFS, data: aifs); |
352 | } |
353 | |
354 | static void rtw_conf_tx(struct rtw_dev *rtwdev, |
355 | struct rtw_vif *rtwvif) |
356 | { |
357 | u16 ac; |
358 | |
359 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
360 | __rtw_conf_tx(rtwdev, rtwvif, ac); |
361 | } |
362 | |
363 | static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, |
364 | struct ieee80211_vif *vif, |
365 | struct ieee80211_bss_conf *conf, |
366 | u64 changed) |
367 | { |
368 | struct rtw_dev *rtwdev = hw->priv; |
369 | struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; |
370 | struct rtw_coex *coex = &rtwdev->coex; |
371 | struct rtw_coex_stat *coex_stat = &coex->stat; |
372 | u32 config = 0; |
373 | |
374 | mutex_lock(&rtwdev->mutex); |
375 | |
376 | rtw_leave_lps_deep(rtwdev); |
377 | |
378 | if (changed & BSS_CHANGED_ASSOC) { |
379 | rtw_vif_assoc_changed(rtwvif, conf); |
380 | if (vif->cfg.assoc) { |
381 | rtw_coex_connect_notify(rtwdev, type: COEX_ASSOCIATE_FINISH); |
382 | |
383 | rtw_fw_download_rsvd_page(rtwdev); |
384 | rtw_send_rsvd_page_h2c(rtwdev); |
385 | rtw_fw_default_port(rtwdev, rtwvif); |
386 | rtw_coex_media_status_notify(rtwdev, type: vif->cfg.assoc); |
387 | if (rtw_bf_support) |
388 | rtw_bf_assoc(rtwdev, vif, bss_conf: conf); |
389 | } else { |
390 | rtw_leave_lps(rtwdev); |
391 | rtw_bf_disassoc(rtwdev, vif, bss_conf: conf); |
392 | /* Abort ongoing scan if cancel_scan isn't issued |
393 | * when disconnected by peer |
394 | */ |
395 | if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) |
396 | rtw_hw_scan_abort(rtwdev); |
397 | |
398 | } |
399 | |
400 | config |= PORT_SET_NET_TYPE; |
401 | config |= PORT_SET_AID; |
402 | } |
403 | |
404 | if (changed & BSS_CHANGED_BSSID) { |
405 | ether_addr_copy(dst: rtwvif->bssid, src: conf->bssid); |
406 | config |= PORT_SET_BSSID; |
407 | if (!rtw_core_check_sta_active(rtwdev)) |
408 | rtw_clear_op_chan(rtwdev); |
409 | else |
410 | rtw_store_op_chan(rtwdev, backup: true); |
411 | } |
412 | |
413 | if (changed & BSS_CHANGED_BEACON_INT) { |
414 | if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION) |
415 | coex_stat->wl_beacon_interval = conf->beacon_int; |
416 | } |
417 | |
418 | if (changed & BSS_CHANGED_BEACON) { |
419 | rtw_set_dtim_period(rtwdev, dtim_period: conf->dtim_period); |
420 | rtw_fw_download_rsvd_page(rtwdev); |
421 | rtw_send_rsvd_page_h2c(rtwdev); |
422 | } |
423 | |
424 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
425 | if (conf->enable_beacon) |
426 | rtw_write32_set(rtwdev, REG_FWHW_TXQ_CTRL, |
427 | BIT_EN_BCNQ_DL); |
428 | else |
429 | rtw_write32_clr(rtwdev, REG_FWHW_TXQ_CTRL, |
430 | BIT_EN_BCNQ_DL); |
431 | } |
432 | if (changed & BSS_CHANGED_CQM) |
433 | rtw_fw_beacon_filter_config(rtwdev, connect: true, vif); |
434 | |
435 | if (changed & BSS_CHANGED_MU_GROUPS) |
436 | rtw_chip_set_gid_table(rtwdev, vif, conf); |
437 | |
438 | if (changed & BSS_CHANGED_ERP_SLOT) |
439 | rtw_conf_tx(rtwdev, rtwvif); |
440 | |
441 | if (changed & BSS_CHANGED_PS) |
442 | rtw_recalc_lps(rtwdev, NULL); |
443 | |
444 | rtw_vif_port_config(rtwdev, rtwvif, config); |
445 | |
446 | mutex_unlock(lock: &rtwdev->mutex); |
447 | } |
448 | |
449 | static int rtw_ops_start_ap(struct ieee80211_hw *hw, |
450 | struct ieee80211_vif *vif, |
451 | struct ieee80211_bss_conf *link_conf) |
452 | { |
453 | struct rtw_dev *rtwdev = hw->priv; |
454 | const struct rtw_chip_info *chip = rtwdev->chip; |
455 | |
456 | mutex_lock(&rtwdev->mutex); |
457 | rtw_write32_set(rtwdev, REG_TCR, BIT_TCR_UPDATE_HGQMD); |
458 | rtwdev->ap_active = true; |
459 | rtw_store_op_chan(rtwdev, backup: true); |
460 | chip->ops->phy_calibration(rtwdev); |
461 | mutex_unlock(lock: &rtwdev->mutex); |
462 | |
463 | return 0; |
464 | } |
465 | |
466 | static void rtw_ops_stop_ap(struct ieee80211_hw *hw, |
467 | struct ieee80211_vif *vif, |
468 | struct ieee80211_bss_conf *link_conf) |
469 | { |
470 | struct rtw_dev *rtwdev = hw->priv; |
471 | |
472 | mutex_lock(&rtwdev->mutex); |
473 | rtw_write32_clr(rtwdev, REG_TCR, BIT_TCR_UPDATE_HGQMD); |
474 | rtwdev->ap_active = false; |
475 | if (!rtw_core_check_sta_active(rtwdev)) |
476 | rtw_clear_op_chan(rtwdev); |
477 | mutex_unlock(lock: &rtwdev->mutex); |
478 | } |
479 | |
480 | static int rtw_ops_conf_tx(struct ieee80211_hw *hw, |
481 | struct ieee80211_vif *vif, |
482 | unsigned int link_id, u16 ac, |
483 | const struct ieee80211_tx_queue_params *params) |
484 | { |
485 | struct rtw_dev *rtwdev = hw->priv; |
486 | struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; |
487 | |
488 | mutex_lock(&rtwdev->mutex); |
489 | |
490 | rtw_leave_lps_deep(rtwdev); |
491 | |
492 | rtwvif->tx_params[ac] = *params; |
493 | __rtw_conf_tx(rtwdev, rtwvif, ac); |
494 | |
495 | mutex_unlock(lock: &rtwdev->mutex); |
496 | |
497 | return 0; |
498 | } |
499 | |
500 | static int rtw_ops_sta_add(struct ieee80211_hw *hw, |
501 | struct ieee80211_vif *vif, |
502 | struct ieee80211_sta *sta) |
503 | { |
504 | struct rtw_dev *rtwdev = hw->priv; |
505 | int ret = 0; |
506 | |
507 | mutex_lock(&rtwdev->mutex); |
508 | ret = rtw_sta_add(rtwdev, sta, vif); |
509 | mutex_unlock(lock: &rtwdev->mutex); |
510 | |
511 | return ret; |
512 | } |
513 | |
514 | static int rtw_ops_sta_remove(struct ieee80211_hw *hw, |
515 | struct ieee80211_vif *vif, |
516 | struct ieee80211_sta *sta) |
517 | { |
518 | struct rtw_dev *rtwdev = hw->priv; |
519 | |
520 | mutex_lock(&rtwdev->mutex); |
521 | rtw_fw_beacon_filter_config(rtwdev, connect: false, vif); |
522 | rtw_sta_remove(rtwdev, sta, fw_exist: true); |
523 | mutex_unlock(lock: &rtwdev->mutex); |
524 | |
525 | return 0; |
526 | } |
527 | |
528 | static int rtw_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
529 | bool set) |
530 | { |
531 | struct rtw_dev *rtwdev = hw->priv; |
532 | |
533 | ieee80211_queue_work(hw, work: &rtwdev->update_beacon_work); |
534 | |
535 | return 0; |
536 | } |
537 | |
538 | static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
539 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, |
540 | struct ieee80211_key_conf *key) |
541 | { |
542 | struct rtw_dev *rtwdev = hw->priv; |
543 | struct rtw_sec_desc *sec = &rtwdev->sec; |
544 | u8 hw_key_type; |
545 | u8 hw_key_idx; |
546 | int ret = 0; |
547 | |
548 | switch (key->cipher) { |
549 | case WLAN_CIPHER_SUITE_WEP40: |
550 | hw_key_type = RTW_CAM_WEP40; |
551 | break; |
552 | case WLAN_CIPHER_SUITE_WEP104: |
553 | hw_key_type = RTW_CAM_WEP104; |
554 | break; |
555 | case WLAN_CIPHER_SUITE_TKIP: |
556 | hw_key_type = RTW_CAM_TKIP; |
557 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
558 | break; |
559 | case WLAN_CIPHER_SUITE_CCMP: |
560 | hw_key_type = RTW_CAM_AES; |
561 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; |
562 | break; |
563 | case WLAN_CIPHER_SUITE_AES_CMAC: |
564 | case WLAN_CIPHER_SUITE_BIP_CMAC_256: |
565 | case WLAN_CIPHER_SUITE_BIP_GMAC_128: |
566 | case WLAN_CIPHER_SUITE_BIP_GMAC_256: |
567 | case WLAN_CIPHER_SUITE_CCMP_256: |
568 | case WLAN_CIPHER_SUITE_GCMP: |
569 | case WLAN_CIPHER_SUITE_GCMP_256: |
570 | /* suppress error messages */ |
571 | return -EOPNOTSUPP; |
572 | default: |
573 | return -ENOTSUPP; |
574 | } |
575 | |
576 | mutex_lock(&rtwdev->mutex); |
577 | |
578 | rtw_leave_lps_deep(rtwdev); |
579 | |
580 | if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { |
581 | hw_key_idx = rtw_sec_get_free_cam(sec); |
582 | } else { |
583 | /* multiple interfaces? */ |
584 | hw_key_idx = key->keyidx; |
585 | } |
586 | |
587 | if (hw_key_idx > sec->total_cam_num) { |
588 | ret = -ENOSPC; |
589 | goto out; |
590 | } |
591 | |
592 | switch (cmd) { |
593 | case SET_KEY: |
594 | /* need sw generated IV */ |
595 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
596 | key->hw_key_idx = hw_key_idx; |
597 | rtw_sec_write_cam(rtwdev, sec, sta, key, |
598 | hw_key_type, hw_key_idx); |
599 | break; |
600 | case DISABLE_KEY: |
601 | rtw_hci_flush_all_queues(rtwdev, drop: false); |
602 | rtw_mac_flush_all_queues(rtwdev, drop: false); |
603 | rtw_sec_clear_cam(rtwdev, sec, hw_key_idx: key->hw_key_idx); |
604 | break; |
605 | } |
606 | |
607 | /* download new cam settings for PG to backup */ |
608 | if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG) |
609 | rtw_fw_download_rsvd_page(rtwdev); |
610 | |
611 | out: |
612 | mutex_unlock(lock: &rtwdev->mutex); |
613 | |
614 | return ret; |
615 | } |
616 | |
617 | static int rtw_ops_ampdu_action(struct ieee80211_hw *hw, |
618 | struct ieee80211_vif *vif, |
619 | struct ieee80211_ampdu_params *params) |
620 | { |
621 | struct ieee80211_sta *sta = params->sta; |
622 | u16 tid = params->tid; |
623 | struct ieee80211_txq *txq = sta->txq[tid]; |
624 | struct rtw_txq *rtwtxq = (struct rtw_txq *)txq->drv_priv; |
625 | |
626 | switch (params->action) { |
627 | case IEEE80211_AMPDU_TX_START: |
628 | return IEEE80211_AMPDU_TX_START_IMMEDIATE; |
629 | case IEEE80211_AMPDU_TX_STOP_CONT: |
630 | case IEEE80211_AMPDU_TX_STOP_FLUSH: |
631 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: |
632 | clear_bit(nr: RTW_TXQ_AMPDU, addr: &rtwtxq->flags); |
633 | ieee80211_stop_tx_ba_cb_irqsafe(vif, ra: sta->addr, tid); |
634 | break; |
635 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
636 | set_bit(nr: RTW_TXQ_AMPDU, addr: &rtwtxq->flags); |
637 | break; |
638 | case IEEE80211_AMPDU_RX_START: |
639 | case IEEE80211_AMPDU_RX_STOP: |
640 | break; |
641 | default: |
642 | WARN_ON(1); |
643 | return -ENOTSUPP; |
644 | } |
645 | |
646 | return 0; |
647 | } |
648 | |
649 | static bool rtw_ops_can_aggregate_in_amsdu(struct ieee80211_hw *hw, |
650 | struct sk_buff *head, |
651 | struct sk_buff *skb) |
652 | { |
653 | struct rtw_dev *rtwdev = hw->priv; |
654 | struct rtw_hal *hal = &rtwdev->hal; |
655 | |
656 | /* we don't want to enable TX AMSDU on 2.4G */ |
657 | if (hal->current_band_type == RTW_BAND_2G) |
658 | return false; |
659 | |
660 | return true; |
661 | } |
662 | |
663 | static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw, |
664 | struct ieee80211_vif *vif, |
665 | const u8 *mac_addr) |
666 | { |
667 | struct rtw_dev *rtwdev = hw->priv; |
668 | struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; |
669 | |
670 | mutex_lock(&rtwdev->mutex); |
671 | rtw_core_scan_start(rtwdev, rtwvif, mac_addr, hw_scan: false); |
672 | mutex_unlock(lock: &rtwdev->mutex); |
673 | } |
674 | |
675 | static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw, |
676 | struct ieee80211_vif *vif) |
677 | { |
678 | struct rtw_dev *rtwdev = hw->priv; |
679 | |
680 | mutex_lock(&rtwdev->mutex); |
681 | rtw_core_scan_complete(rtwdev, vif, hw_scan: false); |
682 | mutex_unlock(lock: &rtwdev->mutex); |
683 | } |
684 | |
685 | static void rtw_ops_mgd_prepare_tx(struct ieee80211_hw *hw, |
686 | struct ieee80211_vif *vif, |
687 | struct ieee80211_prep_tx_info *info) |
688 | { |
689 | struct rtw_dev *rtwdev = hw->priv; |
690 | |
691 | mutex_lock(&rtwdev->mutex); |
692 | rtw_leave_lps_deep(rtwdev); |
693 | rtw_coex_connect_notify(rtwdev, type: COEX_ASSOCIATE_START); |
694 | rtw_chip_prepare_tx(rtwdev); |
695 | mutex_unlock(lock: &rtwdev->mutex); |
696 | } |
697 | |
698 | static int rtw_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
699 | { |
700 | struct rtw_dev *rtwdev = hw->priv; |
701 | |
702 | mutex_lock(&rtwdev->mutex); |
703 | rtwdev->rts_threshold = value; |
704 | mutex_unlock(lock: &rtwdev->mutex); |
705 | |
706 | return 0; |
707 | } |
708 | |
709 | static void rtw_ops_sta_statistics(struct ieee80211_hw *hw, |
710 | struct ieee80211_vif *vif, |
711 | struct ieee80211_sta *sta, |
712 | struct station_info *sinfo) |
713 | { |
714 | struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; |
715 | |
716 | sinfo->txrate = si->ra_report.txrate; |
717 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); |
718 | } |
719 | |
720 | static void rtw_ops_flush(struct ieee80211_hw *hw, |
721 | struct ieee80211_vif *vif, |
722 | u32 queues, bool drop) |
723 | { |
724 | struct rtw_dev *rtwdev = hw->priv; |
725 | |
726 | mutex_lock(&rtwdev->mutex); |
727 | rtw_leave_lps_deep(rtwdev); |
728 | |
729 | rtw_hci_flush_queues(rtwdev, queues, drop); |
730 | rtw_mac_flush_queues(rtwdev, queues, drop); |
731 | mutex_unlock(lock: &rtwdev->mutex); |
732 | } |
733 | |
734 | struct rtw_iter_bitrate_mask_data { |
735 | struct rtw_dev *rtwdev; |
736 | struct ieee80211_vif *vif; |
737 | const struct cfg80211_bitrate_mask *mask; |
738 | }; |
739 | |
740 | static void rtw_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta) |
741 | { |
742 | struct rtw_iter_bitrate_mask_data *br_data = data; |
743 | struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; |
744 | |
745 | if (si->vif != br_data->vif) |
746 | return; |
747 | |
748 | /* free previous mask setting */ |
749 | kfree(objp: si->mask); |
750 | si->mask = kmemdup(p: br_data->mask, size: sizeof(struct cfg80211_bitrate_mask), |
751 | GFP_ATOMIC); |
752 | if (!si->mask) { |
753 | si->use_cfg_mask = false; |
754 | return; |
755 | } |
756 | |
757 | si->use_cfg_mask = true; |
758 | rtw_update_sta_info(rtwdev: br_data->rtwdev, si, reset_ra_mask: true); |
759 | } |
760 | |
761 | static void rtw_ra_mask_info_update(struct rtw_dev *rtwdev, |
762 | struct ieee80211_vif *vif, |
763 | const struct cfg80211_bitrate_mask *mask) |
764 | { |
765 | struct rtw_iter_bitrate_mask_data br_data; |
766 | |
767 | br_data.rtwdev = rtwdev; |
768 | br_data.vif = vif; |
769 | br_data.mask = mask; |
770 | rtw_iterate_stas(rtwdev, iterator: rtw_ra_mask_info_update_iter, data: &br_data); |
771 | } |
772 | |
773 | static int rtw_ops_set_bitrate_mask(struct ieee80211_hw *hw, |
774 | struct ieee80211_vif *vif, |
775 | const struct cfg80211_bitrate_mask *mask) |
776 | { |
777 | struct rtw_dev *rtwdev = hw->priv; |
778 | |
779 | mutex_lock(&rtwdev->mutex); |
780 | rtw_ra_mask_info_update(rtwdev, vif, mask); |
781 | mutex_unlock(lock: &rtwdev->mutex); |
782 | |
783 | return 0; |
784 | } |
785 | |
786 | static int rtw_ops_set_antenna(struct ieee80211_hw *hw, |
787 | u32 tx_antenna, |
788 | u32 rx_antenna) |
789 | { |
790 | struct rtw_dev *rtwdev = hw->priv; |
791 | const struct rtw_chip_info *chip = rtwdev->chip; |
792 | int ret; |
793 | |
794 | if (!chip->ops->set_antenna) |
795 | return -EOPNOTSUPP; |
796 | |
797 | mutex_lock(&rtwdev->mutex); |
798 | ret = chip->ops->set_antenna(rtwdev, tx_antenna, rx_antenna); |
799 | mutex_unlock(lock: &rtwdev->mutex); |
800 | |
801 | return ret; |
802 | } |
803 | |
804 | static int rtw_ops_get_antenna(struct ieee80211_hw *hw, |
805 | u32 *tx_antenna, |
806 | u32 *rx_antenna) |
807 | { |
808 | struct rtw_dev *rtwdev = hw->priv; |
809 | struct rtw_hal *hal = &rtwdev->hal; |
810 | |
811 | *tx_antenna = hal->antenna_tx; |
812 | *rx_antenna = hal->antenna_rx; |
813 | |
814 | return 0; |
815 | } |
816 | |
817 | #ifdef CONFIG_PM |
818 | static int rtw_ops_suspend(struct ieee80211_hw *hw, |
819 | struct cfg80211_wowlan *wowlan) |
820 | { |
821 | struct rtw_dev *rtwdev = hw->priv; |
822 | int ret; |
823 | |
824 | mutex_lock(&rtwdev->mutex); |
825 | ret = rtw_wow_suspend(rtwdev, wowlan); |
826 | if (ret) |
827 | rtw_err(rtwdev, "failed to suspend for wow %d\n" , ret); |
828 | mutex_unlock(lock: &rtwdev->mutex); |
829 | |
830 | return ret ? 1 : 0; |
831 | } |
832 | |
833 | static int rtw_ops_resume(struct ieee80211_hw *hw) |
834 | { |
835 | struct rtw_dev *rtwdev = hw->priv; |
836 | int ret; |
837 | |
838 | mutex_lock(&rtwdev->mutex); |
839 | ret = rtw_wow_resume(rtwdev); |
840 | if (ret) |
841 | rtw_err(rtwdev, "failed to resume for wow %d\n" , ret); |
842 | mutex_unlock(lock: &rtwdev->mutex); |
843 | |
844 | return ret ? 1 : 0; |
845 | } |
846 | |
847 | static void rtw_ops_set_wakeup(struct ieee80211_hw *hw, bool enabled) |
848 | { |
849 | struct rtw_dev *rtwdev = hw->priv; |
850 | |
851 | device_set_wakeup_enable(dev: rtwdev->dev, enable: enabled); |
852 | } |
853 | #endif |
854 | |
855 | static void rtw_reconfig_complete(struct ieee80211_hw *hw, |
856 | enum ieee80211_reconfig_type reconfig_type) |
857 | { |
858 | struct rtw_dev *rtwdev = hw->priv; |
859 | |
860 | mutex_lock(&rtwdev->mutex); |
861 | if (reconfig_type == IEEE80211_RECONFIG_TYPE_RESTART) |
862 | clear_bit(nr: RTW_FLAG_RESTARTING, addr: rtwdev->flags); |
863 | mutex_unlock(lock: &rtwdev->mutex); |
864 | } |
865 | |
866 | static int rtw_ops_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
867 | struct ieee80211_scan_request *req) |
868 | { |
869 | struct rtw_dev *rtwdev = hw->priv; |
870 | int ret; |
871 | |
872 | if (!rtw_fw_feature_check(fw: &rtwdev->fw, feature: FW_FEATURE_SCAN_OFFLOAD)) |
873 | return 1; |
874 | |
875 | if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) |
876 | return -EBUSY; |
877 | |
878 | mutex_lock(&rtwdev->mutex); |
879 | rtw_hw_scan_start(rtwdev, vif, req); |
880 | ret = rtw_hw_scan_offload(rtwdev, vif, enable: true); |
881 | if (ret) { |
882 | rtw_hw_scan_abort(rtwdev); |
883 | rtw_err(rtwdev, "HW scan failed with status: %d\n" , ret); |
884 | } |
885 | mutex_unlock(lock: &rtwdev->mutex); |
886 | |
887 | return ret; |
888 | } |
889 | |
890 | static void rtw_ops_cancel_hw_scan(struct ieee80211_hw *hw, |
891 | struct ieee80211_vif *vif) |
892 | { |
893 | struct rtw_dev *rtwdev = hw->priv; |
894 | |
895 | if (!rtw_fw_feature_check(fw: &rtwdev->fw, feature: FW_FEATURE_SCAN_OFFLOAD)) |
896 | return; |
897 | |
898 | if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) |
899 | return; |
900 | |
901 | mutex_lock(&rtwdev->mutex); |
902 | rtw_hw_scan_abort(rtwdev); |
903 | mutex_unlock(lock: &rtwdev->mutex); |
904 | } |
905 | |
906 | static int rtw_ops_set_sar_specs(struct ieee80211_hw *hw, |
907 | const struct cfg80211_sar_specs *sar) |
908 | { |
909 | struct rtw_dev *rtwdev = hw->priv; |
910 | |
911 | mutex_lock(&rtwdev->mutex); |
912 | rtw_set_sar_specs(rtwdev, sar); |
913 | mutex_unlock(lock: &rtwdev->mutex); |
914 | |
915 | return 0; |
916 | } |
917 | |
918 | static void rtw_ops_sta_rc_update(struct ieee80211_hw *hw, |
919 | struct ieee80211_vif *vif, |
920 | struct ieee80211_sta *sta, u32 changed) |
921 | { |
922 | struct rtw_dev *rtwdev = hw->priv; |
923 | struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; |
924 | |
925 | if (changed & IEEE80211_RC_BW_CHANGED) |
926 | ieee80211_queue_work(hw: rtwdev->hw, work: &si->rc_work); |
927 | } |
928 | |
929 | const struct ieee80211_ops rtw_ops = { |
930 | .add_chanctx = ieee80211_emulate_add_chanctx, |
931 | .remove_chanctx = ieee80211_emulate_remove_chanctx, |
932 | .change_chanctx = ieee80211_emulate_change_chanctx, |
933 | .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx, |
934 | .tx = rtw_ops_tx, |
935 | .wake_tx_queue = rtw_ops_wake_tx_queue, |
936 | .start = rtw_ops_start, |
937 | .stop = rtw_ops_stop, |
938 | .config = rtw_ops_config, |
939 | .add_interface = rtw_ops_add_interface, |
940 | .remove_interface = rtw_ops_remove_interface, |
941 | .change_interface = rtw_ops_change_interface, |
942 | .configure_filter = rtw_ops_configure_filter, |
943 | .bss_info_changed = rtw_ops_bss_info_changed, |
944 | .start_ap = rtw_ops_start_ap, |
945 | .stop_ap = rtw_ops_stop_ap, |
946 | .conf_tx = rtw_ops_conf_tx, |
947 | .sta_add = rtw_ops_sta_add, |
948 | .sta_remove = rtw_ops_sta_remove, |
949 | .set_tim = rtw_ops_set_tim, |
950 | .set_key = rtw_ops_set_key, |
951 | .ampdu_action = rtw_ops_ampdu_action, |
952 | .can_aggregate_in_amsdu = rtw_ops_can_aggregate_in_amsdu, |
953 | .sw_scan_start = rtw_ops_sw_scan_start, |
954 | .sw_scan_complete = rtw_ops_sw_scan_complete, |
955 | .mgd_prepare_tx = rtw_ops_mgd_prepare_tx, |
956 | .set_rts_threshold = rtw_ops_set_rts_threshold, |
957 | .sta_statistics = rtw_ops_sta_statistics, |
958 | .flush = rtw_ops_flush, |
959 | .set_bitrate_mask = rtw_ops_set_bitrate_mask, |
960 | .set_antenna = rtw_ops_set_antenna, |
961 | .get_antenna = rtw_ops_get_antenna, |
962 | .reconfig_complete = rtw_reconfig_complete, |
963 | .hw_scan = rtw_ops_hw_scan, |
964 | .cancel_hw_scan = rtw_ops_cancel_hw_scan, |
965 | .sta_rc_update = rtw_ops_sta_rc_update, |
966 | .set_sar_specs = rtw_ops_set_sar_specs, |
967 | #ifdef CONFIG_PM |
968 | .suspend = rtw_ops_suspend, |
969 | .resume = rtw_ops_resume, |
970 | .set_wakeup = rtw_ops_set_wakeup, |
971 | #endif |
972 | }; |
973 | EXPORT_SYMBOL(rtw_ops); |
974 | |