Branch data Line data Source code
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 : :
17 : 0 : static void rtw_ops_tx(struct ieee80211_hw *hw,
18 : : struct ieee80211_tx_control *control,
19 : : struct sk_buff *skb)
20 : : {
21 : 0 : struct rtw_dev *rtwdev = hw->priv;
22 : :
23 [ # # ]: 0 : if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags)) {
24 : 0 : ieee80211_free_txskb(hw, skb);
25 : 0 : return;
26 : : }
27 : :
28 : 0 : rtw_tx(rtwdev, control, skb);
29 : : }
30 : :
31 : 0 : static void rtw_ops_wake_tx_queue(struct ieee80211_hw *hw,
32 : : struct ieee80211_txq *txq)
33 : : {
34 : 0 : struct rtw_dev *rtwdev = hw->priv;
35 : 0 : struct rtw_txq *rtwtxq = (struct rtw_txq *)txq->drv_priv;
36 : :
37 [ # # ]: 0 : if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
38 : : return;
39 : :
40 : 0 : spin_lock_bh(&rtwdev->txq_lock);
41 [ # # ]: 0 : if (list_empty(&rtwtxq->list))
42 : 0 : list_add_tail(&rtwtxq->list, &rtwdev->txqs);
43 : 0 : spin_unlock_bh(&rtwdev->txq_lock);
44 : :
45 : 0 : tasklet_schedule(&rtwdev->tx_tasklet);
46 : : }
47 : :
48 : 0 : static int rtw_ops_start(struct ieee80211_hw *hw)
49 : : {
50 : 0 : struct rtw_dev *rtwdev = hw->priv;
51 : 0 : int ret;
52 : :
53 : 0 : mutex_lock(&rtwdev->mutex);
54 : 0 : ret = rtw_core_start(rtwdev);
55 : 0 : mutex_unlock(&rtwdev->mutex);
56 : :
57 : 0 : return ret;
58 : : }
59 : :
60 : 0 : static void rtw_ops_stop(struct ieee80211_hw *hw)
61 : : {
62 : 0 : struct rtw_dev *rtwdev = hw->priv;
63 : :
64 : 0 : mutex_lock(&rtwdev->mutex);
65 : 0 : rtw_core_stop(rtwdev);
66 : 0 : mutex_unlock(&rtwdev->mutex);
67 : 0 : }
68 : :
69 : 0 : static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed)
70 : : {
71 : 0 : struct rtw_dev *rtwdev = hw->priv;
72 : 0 : int ret = 0;
73 : :
74 : 0 : mutex_lock(&rtwdev->mutex);
75 : :
76 : 0 : rtw_leave_lps_deep(rtwdev);
77 : :
78 [ # # ]: 0 : if (changed & IEEE80211_CONF_CHANGE_IDLE) {
79 [ # # ]: 0 : if (hw->conf.flags & IEEE80211_CONF_IDLE) {
80 : 0 : rtw_enter_ips(rtwdev);
81 : : } else {
82 : 0 : ret = rtw_leave_ips(rtwdev);
83 [ # # ]: 0 : if (ret) {
84 : 0 : rtw_err(rtwdev, "failed to leave idle state\n");
85 : 0 : goto out;
86 : : }
87 : : }
88 : : }
89 : :
90 [ # # ]: 0 : if (changed & IEEE80211_CONF_CHANGE_PS) {
91 [ # # ]: 0 : if (hw->conf.flags & IEEE80211_CONF_PS) {
92 : 0 : rtwdev->ps_enabled = true;
93 : : } else {
94 : 0 : rtwdev->ps_enabled = false;
95 : 0 : rtw_leave_lps(rtwdev);
96 : : }
97 : : }
98 : :
99 [ # # ]: 0 : if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
100 : 0 : rtw_set_channel(rtwdev);
101 : :
102 : 0 : out:
103 : 0 : mutex_unlock(&rtwdev->mutex);
104 : 0 : return ret;
105 : : }
106 : :
107 : : static const struct rtw_vif_port rtw_vif_port[] = {
108 : : [0] = {
109 : : .mac_addr = {.addr = 0x0610},
110 : : .bssid = {.addr = 0x0618},
111 : : .net_type = {.addr = 0x0100, .mask = 0x30000},
112 : : .aid = {.addr = 0x06a8, .mask = 0x7ff},
113 : : .bcn_ctrl = {.addr = 0x0550, .mask = 0xff},
114 : : },
115 : : [1] = {
116 : : .mac_addr = {.addr = 0x0700},
117 : : .bssid = {.addr = 0x0708},
118 : : .net_type = {.addr = 0x0100, .mask = 0xc0000},
119 : : .aid = {.addr = 0x0710, .mask = 0x7ff},
120 : : .bcn_ctrl = {.addr = 0x0551, .mask = 0xff},
121 : : },
122 : : [2] = {
123 : : .mac_addr = {.addr = 0x1620},
124 : : .bssid = {.addr = 0x1628},
125 : : .net_type = {.addr = 0x1100, .mask = 0x3},
126 : : .aid = {.addr = 0x1600, .mask = 0x7ff},
127 : : .bcn_ctrl = {.addr = 0x0578, .mask = 0xff},
128 : : },
129 : : [3] = {
130 : : .mac_addr = {.addr = 0x1630},
131 : : .bssid = {.addr = 0x1638},
132 : : .net_type = {.addr = 0x1100, .mask = 0xc},
133 : : .aid = {.addr = 0x1604, .mask = 0x7ff},
134 : : .bcn_ctrl = {.addr = 0x0579, .mask = 0xff},
135 : : },
136 : : [4] = {
137 : : .mac_addr = {.addr = 0x1640},
138 : : .bssid = {.addr = 0x1648},
139 : : .net_type = {.addr = 0x1100, .mask = 0x30},
140 : : .aid = {.addr = 0x1608, .mask = 0x7ff},
141 : : .bcn_ctrl = {.addr = 0x057a, .mask = 0xff},
142 : : },
143 : : };
144 : :
145 : 0 : static int rtw_ops_add_interface(struct ieee80211_hw *hw,
146 : : struct ieee80211_vif *vif)
147 : : {
148 : 0 : struct rtw_dev *rtwdev = hw->priv;
149 : 0 : struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
150 : 0 : enum rtw_net_type net_type;
151 : 0 : u32 config = 0;
152 : 0 : u8 port = 0;
153 : 0 : u8 bcn_ctrl = 0;
154 : :
155 : 0 : rtwvif->port = port;
156 : 0 : rtwvif->stats.tx_unicast = 0;
157 : 0 : rtwvif->stats.rx_unicast = 0;
158 : 0 : rtwvif->stats.tx_cnt = 0;
159 : 0 : rtwvif->stats.rx_cnt = 0;
160 : 0 : memset(&rtwvif->bfee, 0, sizeof(struct rtw_bfee));
161 : 0 : rtwvif->conf = &rtw_vif_port[port];
162 : 0 : rtw_txq_init(rtwdev, vif->txq);
163 : :
164 : 0 : mutex_lock(&rtwdev->mutex);
165 : :
166 : 0 : rtw_leave_lps_deep(rtwdev);
167 : :
168 [ # # # ]: 0 : switch (vif->type) {
169 : : case NL80211_IFTYPE_AP:
170 : : case NL80211_IFTYPE_MESH_POINT:
171 : : net_type = RTW_NET_AP_MODE;
172 : : bcn_ctrl = BIT_EN_BCN_FUNCTION | BIT_DIS_TSF_UDT;
173 : : break;
174 : 0 : case NL80211_IFTYPE_ADHOC:
175 : 0 : net_type = RTW_NET_AD_HOC;
176 : 0 : bcn_ctrl = BIT_EN_BCN_FUNCTION | BIT_DIS_TSF_UDT;
177 : 0 : break;
178 : 0 : case NL80211_IFTYPE_STATION:
179 : : default:
180 : 0 : net_type = RTW_NET_NO_LINK;
181 : 0 : bcn_ctrl = BIT_EN_BCN_FUNCTION;
182 : 0 : break;
183 : : }
184 : :
185 : 0 : ether_addr_copy(rtwvif->mac_addr, vif->addr);
186 : 0 : config |= PORT_SET_MAC_ADDR;
187 : 0 : rtwvif->net_type = net_type;
188 : 0 : config |= PORT_SET_NET_TYPE;
189 : 0 : rtwvif->bcn_ctrl = bcn_ctrl;
190 : 0 : config |= PORT_SET_BCN_CTRL;
191 : 0 : rtw_vif_port_config(rtwdev, rtwvif, config);
192 : :
193 : 0 : mutex_unlock(&rtwdev->mutex);
194 : :
195 : 0 : rtw_info(rtwdev, "start vif %pM on port %d\n", vif->addr, rtwvif->port);
196 : 0 : return 0;
197 : : }
198 : :
199 : 0 : static void rtw_ops_remove_interface(struct ieee80211_hw *hw,
200 : : struct ieee80211_vif *vif)
201 : : {
202 : 0 : struct rtw_dev *rtwdev = hw->priv;
203 : 0 : struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
204 : 0 : u32 config = 0;
205 : :
206 : 0 : rtw_info(rtwdev, "stop vif %pM on port %d\n", vif->addr, rtwvif->port);
207 : :
208 : 0 : mutex_lock(&rtwdev->mutex);
209 : :
210 : 0 : rtw_leave_lps_deep(rtwdev);
211 : :
212 : 0 : rtw_txq_cleanup(rtwdev, vif->txq);
213 : :
214 : 0 : eth_zero_addr(rtwvif->mac_addr);
215 : 0 : config |= PORT_SET_MAC_ADDR;
216 : 0 : rtwvif->net_type = RTW_NET_NO_LINK;
217 : 0 : config |= PORT_SET_NET_TYPE;
218 : 0 : rtwvif->bcn_ctrl = 0;
219 : 0 : config |= PORT_SET_BCN_CTRL;
220 : 0 : rtw_vif_port_config(rtwdev, rtwvif, config);
221 : :
222 : 0 : mutex_unlock(&rtwdev->mutex);
223 : 0 : }
224 : :
225 : 0 : static void rtw_ops_configure_filter(struct ieee80211_hw *hw,
226 : : unsigned int changed_flags,
227 : : unsigned int *new_flags,
228 : : u64 multicast)
229 : : {
230 : 0 : struct rtw_dev *rtwdev = hw->priv;
231 : :
232 : 0 : *new_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_FCSFAIL |
233 : : FIF_BCN_PRBRESP_PROMISC;
234 : :
235 : 0 : mutex_lock(&rtwdev->mutex);
236 : :
237 : 0 : rtw_leave_lps_deep(rtwdev);
238 : :
239 [ # # ]: 0 : if (changed_flags & FIF_ALLMULTI) {
240 [ # # ]: 0 : if (*new_flags & FIF_ALLMULTI)
241 : 0 : rtwdev->hal.rcr |= BIT_AM | BIT_AB;
242 : : else
243 : 0 : rtwdev->hal.rcr &= ~(BIT_AM | BIT_AB);
244 : : }
245 [ # # ]: 0 : if (changed_flags & FIF_FCSFAIL) {
246 [ # # ]: 0 : if (*new_flags & FIF_FCSFAIL)
247 : 0 : rtwdev->hal.rcr |= BIT_ACRC32;
248 : : else
249 : 0 : rtwdev->hal.rcr &= ~(BIT_ACRC32);
250 : : }
251 [ # # ]: 0 : if (changed_flags & FIF_OTHER_BSS) {
252 [ # # ]: 0 : if (*new_flags & FIF_OTHER_BSS)
253 : 0 : rtwdev->hal.rcr |= BIT_AAP;
254 : : else
255 : 0 : rtwdev->hal.rcr &= ~(BIT_AAP);
256 : : }
257 [ # # ]: 0 : if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
258 [ # # ]: 0 : if (*new_flags & FIF_BCN_PRBRESP_PROMISC)
259 : 0 : rtwdev->hal.rcr &= ~(BIT_CBSSID_BCN | BIT_CBSSID_DATA);
260 : : else
261 : 0 : rtwdev->hal.rcr |= BIT_CBSSID_BCN;
262 : : }
263 : :
264 : 0 : rtw_dbg(rtwdev, RTW_DBG_RX,
265 : : "config rx filter, changed=0x%08x, new=0x%08x, rcr=0x%08x\n",
266 : : changed_flags, *new_flags, rtwdev->hal.rcr);
267 : :
268 : 0 : rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr);
269 : :
270 : 0 : mutex_unlock(&rtwdev->mutex);
271 : 0 : }
272 : :
273 : : /* Only have one group of EDCA parameters now */
274 : : static const u32 ac_to_edca_param[IEEE80211_NUM_ACS] = {
275 : : [IEEE80211_AC_VO] = REG_EDCA_VO_PARAM,
276 : : [IEEE80211_AC_VI] = REG_EDCA_VI_PARAM,
277 : : [IEEE80211_AC_BE] = REG_EDCA_BE_PARAM,
278 : : [IEEE80211_AC_BK] = REG_EDCA_BK_PARAM,
279 : : };
280 : :
281 : 0 : static u8 rtw_aifsn_to_aifs(struct rtw_dev *rtwdev,
282 : : struct rtw_vif *rtwvif, u8 aifsn)
283 : : {
284 : 0 : struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
285 : 0 : u8 slot_time;
286 : 0 : u8 sifs;
287 : :
288 [ # # ]: 0 : slot_time = vif->bss_conf.use_short_slot ? 9 : 20;
289 [ # # ]: 0 : sifs = rtwdev->hal.current_band_type == RTW_BAND_5G ? 16 : 10;
290 : :
291 : 0 : return aifsn * slot_time + sifs;
292 : : }
293 : :
294 : 0 : static void __rtw_conf_tx(struct rtw_dev *rtwdev,
295 : : struct rtw_vif *rtwvif, u16 ac)
296 : : {
297 : 0 : struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac];
298 : 0 : u32 edca_param = ac_to_edca_param[ac];
299 : 0 : u8 ecw_max, ecw_min;
300 : 0 : u8 aifs;
301 : :
302 : : /* 2^ecw - 1 = cw; ecw = log2(cw + 1) */
303 [ # # # # : 0 : ecw_max = ilog2(params->cw_max + 1);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ]
304 [ # # # # : 0 : ecw_min = ilog2(params->cw_min + 1);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ]
305 [ # # ]: 0 : aifs = rtw_aifsn_to_aifs(rtwdev, rtwvif, params->aifs);
306 : 0 : rtw_write32_mask(rtwdev, edca_param, BIT_MASK_TXOP_LMT, params->txop);
307 : 0 : rtw_write32_mask(rtwdev, edca_param, BIT_MASK_CWMAX, ecw_max);
308 : 0 : rtw_write32_mask(rtwdev, edca_param, BIT_MASK_CWMIN, ecw_min);
309 : 0 : rtw_write32_mask(rtwdev, edca_param, BIT_MASK_AIFS, aifs);
310 : 0 : }
311 : :
312 : : static void rtw_conf_tx(struct rtw_dev *rtwdev,
313 : : struct rtw_vif *rtwvif)
314 : : {
315 : : u16 ac;
316 : :
317 [ # # ]: 0 : for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
318 : 0 : __rtw_conf_tx(rtwdev, rtwvif, ac);
319 : : }
320 : :
321 : 0 : static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
322 : : struct ieee80211_vif *vif,
323 : : struct ieee80211_bss_conf *conf,
324 : : u32 changed)
325 : : {
326 : 0 : struct rtw_dev *rtwdev = hw->priv;
327 : 0 : struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
328 : 0 : u32 config = 0;
329 : :
330 : 0 : mutex_lock(&rtwdev->mutex);
331 : :
332 : 0 : rtw_leave_lps_deep(rtwdev);
333 : :
334 [ # # ]: 0 : if (changed & BSS_CHANGED_ASSOC) {
335 : 0 : struct rtw_chip_info *chip = rtwdev->chip;
336 : 0 : enum rtw_net_type net_type;
337 : :
338 [ # # ]: 0 : if (conf->assoc) {
339 : 0 : rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_FINISH);
340 : 0 : net_type = RTW_NET_MGD_LINKED;
341 : 0 : chip->ops->phy_calibration(rtwdev);
342 : :
343 : 0 : rtwvif->aid = conf->aid;
344 : 0 : rtw_add_rsvd_page(rtwdev, RSVD_PS_POLL, true);
345 : 0 : rtw_add_rsvd_page(rtwdev, RSVD_QOS_NULL, true);
346 : 0 : rtw_add_rsvd_page(rtwdev, RSVD_NULL, true);
347 : 0 : rtw_add_rsvd_page(rtwdev, RSVD_LPS_PG_DPK, true);
348 : 0 : rtw_add_rsvd_page(rtwdev, RSVD_LPS_PG_INFO, true);
349 : 0 : rtw_fw_download_rsvd_page(rtwdev, vif);
350 : 0 : rtw_send_rsvd_page_h2c(rtwdev);
351 : 0 : rtw_coex_media_status_notify(rtwdev, conf->assoc);
352 [ # # ]: 0 : if (rtw_bf_support)
353 : 0 : rtw_bf_assoc(rtwdev, vif, conf);
354 : : } else {
355 : 0 : rtw_leave_lps(rtwdev);
356 : 0 : net_type = RTW_NET_NO_LINK;
357 : 0 : rtwvif->aid = 0;
358 : 0 : rtw_reset_rsvd_page(rtwdev);
359 : 0 : rtw_bf_disassoc(rtwdev, vif, conf);
360 : : }
361 : :
362 : 0 : rtwvif->net_type = net_type;
363 : 0 : config |= PORT_SET_NET_TYPE;
364 : 0 : config |= PORT_SET_AID;
365 : : }
366 : :
367 [ # # ]: 0 : if (changed & BSS_CHANGED_BSSID) {
368 : 0 : ether_addr_copy(rtwvif->bssid, conf->bssid);
369 : 0 : config |= PORT_SET_BSSID;
370 : : }
371 : :
372 [ # # ]: 0 : if (changed & BSS_CHANGED_BEACON)
373 : 0 : rtw_fw_download_rsvd_page(rtwdev, vif);
374 : :
375 [ # # ]: 0 : if (changed & BSS_CHANGED_MU_GROUPS) {
376 : 0 : struct rtw_chip_info *chip = rtwdev->chip;
377 : :
378 : 0 : chip->ops->set_gid_table(rtwdev, vif, conf);
379 : : }
380 : :
381 [ # # ]: 0 : if (changed & BSS_CHANGED_ERP_SLOT)
382 : : rtw_conf_tx(rtwdev, rtwvif);
383 : :
384 : 0 : rtw_vif_port_config(rtwdev, rtwvif, config);
385 : :
386 : 0 : mutex_unlock(&rtwdev->mutex);
387 : 0 : }
388 : :
389 : 0 : static int rtw_ops_conf_tx(struct ieee80211_hw *hw,
390 : : struct ieee80211_vif *vif, u16 ac,
391 : : const struct ieee80211_tx_queue_params *params)
392 : : {
393 : 0 : struct rtw_dev *rtwdev = hw->priv;
394 : 0 : struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
395 : :
396 : 0 : mutex_lock(&rtwdev->mutex);
397 : :
398 : 0 : rtw_leave_lps_deep(rtwdev);
399 : :
400 : 0 : rtwvif->tx_params[ac] = *params;
401 : 0 : __rtw_conf_tx(rtwdev, rtwvif, ac);
402 : :
403 : 0 : mutex_unlock(&rtwdev->mutex);
404 : :
405 : 0 : return 0;
406 : : }
407 : :
408 : 0 : static u8 rtw_acquire_macid(struct rtw_dev *rtwdev)
409 : : {
410 : 0 : unsigned long mac_id;
411 : :
412 : 0 : mac_id = find_first_zero_bit(rtwdev->mac_id_map, RTW_MAX_MAC_ID_NUM);
413 [ # # ]: 0 : if (mac_id < RTW_MAX_MAC_ID_NUM)
414 : 0 : set_bit(mac_id, rtwdev->mac_id_map);
415 : :
416 : 0 : return mac_id;
417 : : }
418 : :
419 : 0 : static void rtw_release_macid(struct rtw_dev *rtwdev, u8 mac_id)
420 : : {
421 : 0 : clear_bit(mac_id, rtwdev->mac_id_map);
422 : : }
423 : :
424 : 0 : static int rtw_ops_sta_add(struct ieee80211_hw *hw,
425 : : struct ieee80211_vif *vif,
426 : : struct ieee80211_sta *sta)
427 : : {
428 : 0 : struct rtw_dev *rtwdev = hw->priv;
429 : 0 : struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
430 : 0 : int i;
431 : 0 : int ret = 0;
432 : :
433 : 0 : mutex_lock(&rtwdev->mutex);
434 : :
435 : 0 : si->mac_id = rtw_acquire_macid(rtwdev);
436 [ # # ]: 0 : if (si->mac_id >= RTW_MAX_MAC_ID_NUM) {
437 : 0 : ret = -ENOSPC;
438 : 0 : goto out;
439 : : }
440 : :
441 : 0 : si->sta = sta;
442 : 0 : si->vif = vif;
443 : 0 : si->init_ra_lv = 1;
444 : 0 : ewma_rssi_init(&si->avg_rssi);
445 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
446 : 0 : rtw_txq_init(rtwdev, sta->txq[i]);
447 : :
448 : 0 : rtw_update_sta_info(rtwdev, si);
449 : 0 : rtw_fw_media_status_report(rtwdev, si->mac_id, true);
450 : :
451 : 0 : rtwdev->sta_cnt++;
452 : :
453 : 0 : rtw_info(rtwdev, "sta %pM joined with macid %d\n",
454 : : sta->addr, si->mac_id);
455 : :
456 : 0 : out:
457 : 0 : mutex_unlock(&rtwdev->mutex);
458 : 0 : return ret;
459 : : }
460 : :
461 : 0 : static int rtw_ops_sta_remove(struct ieee80211_hw *hw,
462 : : struct ieee80211_vif *vif,
463 : : struct ieee80211_sta *sta)
464 : : {
465 : 0 : struct rtw_dev *rtwdev = hw->priv;
466 : 0 : struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
467 : 0 : int i;
468 : :
469 : 0 : mutex_lock(&rtwdev->mutex);
470 : :
471 : 0 : rtw_release_macid(rtwdev, si->mac_id);
472 : 0 : rtw_fw_media_status_report(rtwdev, si->mac_id, false);
473 : :
474 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
475 : 0 : rtw_txq_cleanup(rtwdev, sta->txq[i]);
476 : :
477 : 0 : kfree(si->mask);
478 : :
479 : 0 : rtwdev->sta_cnt--;
480 : :
481 : 0 : rtw_info(rtwdev, "sta %pM with macid %d left\n",
482 : : sta->addr, si->mac_id);
483 : :
484 : 0 : mutex_unlock(&rtwdev->mutex);
485 : 0 : return 0;
486 : : }
487 : :
488 : 0 : static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
489 : : struct ieee80211_vif *vif, struct ieee80211_sta *sta,
490 : : struct ieee80211_key_conf *key)
491 : : {
492 : 0 : struct rtw_dev *rtwdev = hw->priv;
493 : 0 : struct rtw_sec_desc *sec = &rtwdev->sec;
494 : 0 : u8 hw_key_type;
495 : 0 : u8 hw_key_idx;
496 : 0 : int ret = 0;
497 : :
498 [ # # # # : 0 : switch (key->cipher) {
# # ]
499 : : case WLAN_CIPHER_SUITE_WEP40:
500 : : hw_key_type = RTW_CAM_WEP40;
501 : : break;
502 : 0 : case WLAN_CIPHER_SUITE_WEP104:
503 : 0 : hw_key_type = RTW_CAM_WEP104;
504 : 0 : break;
505 : 0 : case WLAN_CIPHER_SUITE_TKIP:
506 : 0 : hw_key_type = RTW_CAM_TKIP;
507 : 0 : key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
508 : 0 : break;
509 : 0 : case WLAN_CIPHER_SUITE_CCMP:
510 : 0 : hw_key_type = RTW_CAM_AES;
511 : 0 : key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
512 : 0 : break;
513 : : case WLAN_CIPHER_SUITE_AES_CMAC:
514 : : case WLAN_CIPHER_SUITE_BIP_CMAC_256:
515 : : case WLAN_CIPHER_SUITE_BIP_GMAC_128:
516 : : case WLAN_CIPHER_SUITE_BIP_GMAC_256:
517 : : /* suppress error messages */
518 : : return -EOPNOTSUPP;
519 : 0 : default:
520 : 0 : return -ENOTSUPP;
521 : : }
522 : :
523 : 0 : mutex_lock(&rtwdev->mutex);
524 : :
525 : 0 : rtw_leave_lps_deep(rtwdev);
526 : :
527 [ # # ]: 0 : if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
528 : 0 : hw_key_idx = rtw_sec_get_free_cam(sec);
529 : : } else {
530 : : /* multiple interfaces? */
531 : 0 : hw_key_idx = key->keyidx;
532 : : }
533 : :
534 [ # # ]: 0 : if (hw_key_idx > sec->total_cam_num) {
535 : 0 : ret = -ENOSPC;
536 : 0 : goto out;
537 : : }
538 : :
539 [ # # # ]: 0 : switch (cmd) {
540 : 0 : case SET_KEY:
541 : : /* need sw generated IV */
542 : 0 : key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
543 : 0 : key->hw_key_idx = hw_key_idx;
544 : 0 : rtw_sec_write_cam(rtwdev, sec, sta, key,
545 : : hw_key_type, hw_key_idx);
546 : 0 : break;
547 : : case DISABLE_KEY:
548 : 0 : rtw_mac_flush_all_queues(rtwdev, false);
549 : 0 : rtw_sec_clear_cam(rtwdev, sec, key->hw_key_idx);
550 : 0 : break;
551 : : }
552 : :
553 : : /* download new cam settings for PG to backup */
554 [ # # ]: 0 : if (rtw_fw_lps_deep_mode == LPS_DEEP_MODE_PG)
555 : 0 : rtw_fw_download_rsvd_page(rtwdev, vif);
556 : :
557 : 0 : out:
558 : 0 : mutex_unlock(&rtwdev->mutex);
559 : :
560 : 0 : return ret;
561 : : }
562 : :
563 : 0 : static int rtw_ops_ampdu_action(struct ieee80211_hw *hw,
564 : : struct ieee80211_vif *vif,
565 : : struct ieee80211_ampdu_params *params)
566 : : {
567 : 0 : struct ieee80211_sta *sta = params->sta;
568 : 0 : u16 tid = params->tid;
569 : 0 : struct ieee80211_txq *txq = sta->txq[tid];
570 : 0 : struct rtw_txq *rtwtxq = (struct rtw_txq *)txq->drv_priv;
571 : :
572 [ # # # # : 0 : switch (params->action) {
# ]
573 : : case IEEE80211_AMPDU_TX_START:
574 : : return IEEE80211_AMPDU_TX_START_IMMEDIATE;
575 : 0 : case IEEE80211_AMPDU_TX_STOP_CONT:
576 : : case IEEE80211_AMPDU_TX_STOP_FLUSH:
577 : : case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
578 : 0 : clear_bit(RTW_TXQ_AMPDU, &rtwtxq->flags);
579 : 0 : ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
580 : 0 : break;
581 : 0 : case IEEE80211_AMPDU_TX_OPERATIONAL:
582 : 0 : set_bit(RTW_TXQ_AMPDU, &rtwtxq->flags);
583 : 0 : break;
584 : : case IEEE80211_AMPDU_RX_START:
585 : : case IEEE80211_AMPDU_RX_STOP:
586 : : break;
587 : : default:
588 : 0 : WARN_ON(1);
589 : 0 : return -ENOTSUPP;
590 : : }
591 : :
592 : : return 0;
593 : : }
594 : :
595 : 0 : static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw,
596 : : struct ieee80211_vif *vif,
597 : : const u8 *mac_addr)
598 : : {
599 : 0 : struct rtw_dev *rtwdev = hw->priv;
600 : 0 : struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
601 : 0 : u32 config = 0;
602 : :
603 : 0 : mutex_lock(&rtwdev->mutex);
604 : :
605 : 0 : rtw_leave_lps(rtwdev);
606 : :
607 : 0 : ether_addr_copy(rtwvif->mac_addr, mac_addr);
608 : 0 : config |= PORT_SET_MAC_ADDR;
609 : 0 : rtw_vif_port_config(rtwdev, rtwvif, config);
610 : :
611 : 0 : rtw_coex_scan_notify(rtwdev, COEX_SCAN_START);
612 : :
613 : 0 : set_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags);
614 : 0 : set_bit(RTW_FLAG_SCANNING, rtwdev->flags);
615 : :
616 : 0 : mutex_unlock(&rtwdev->mutex);
617 : 0 : }
618 : :
619 : 0 : static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw,
620 : : struct ieee80211_vif *vif)
621 : : {
622 : 0 : struct rtw_dev *rtwdev = hw->priv;
623 : 0 : struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
624 : 0 : u32 config = 0;
625 : :
626 : 0 : mutex_lock(&rtwdev->mutex);
627 : :
628 : 0 : clear_bit(RTW_FLAG_SCANNING, rtwdev->flags);
629 : 0 : clear_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags);
630 : :
631 : 0 : ether_addr_copy(rtwvif->mac_addr, vif->addr);
632 : 0 : config |= PORT_SET_MAC_ADDR;
633 : 0 : rtw_vif_port_config(rtwdev, rtwvif, config);
634 : :
635 : 0 : rtw_coex_scan_notify(rtwdev, COEX_SCAN_FINISH);
636 : :
637 : 0 : mutex_unlock(&rtwdev->mutex);
638 : 0 : }
639 : :
640 : 0 : static void rtw_ops_mgd_prepare_tx(struct ieee80211_hw *hw,
641 : : struct ieee80211_vif *vif,
642 : : u16 duration)
643 : : {
644 : 0 : struct rtw_dev *rtwdev = hw->priv;
645 : :
646 : 0 : mutex_lock(&rtwdev->mutex);
647 : 0 : rtw_leave_lps_deep(rtwdev);
648 : 0 : rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_START);
649 : 0 : mutex_unlock(&rtwdev->mutex);
650 : 0 : }
651 : :
652 : 0 : static int rtw_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
653 : : {
654 : 0 : struct rtw_dev *rtwdev = hw->priv;
655 : :
656 : 0 : mutex_lock(&rtwdev->mutex);
657 : 0 : rtwdev->rts_threshold = value;
658 : 0 : mutex_unlock(&rtwdev->mutex);
659 : :
660 : 0 : return 0;
661 : : }
662 : :
663 : 0 : static void rtw_ops_sta_statistics(struct ieee80211_hw *hw,
664 : : struct ieee80211_vif *vif,
665 : : struct ieee80211_sta *sta,
666 : : struct station_info *sinfo)
667 : : {
668 : 0 : struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
669 : :
670 : 0 : sinfo->txrate = si->ra_report.txrate;
671 : 0 : sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
672 : 0 : }
673 : :
674 : 0 : static void rtw_ops_flush(struct ieee80211_hw *hw,
675 : : struct ieee80211_vif *vif,
676 : : u32 queues, bool drop)
677 : : {
678 : 0 : struct rtw_dev *rtwdev = hw->priv;
679 : :
680 : 0 : mutex_lock(&rtwdev->mutex);
681 : 0 : rtw_leave_lps_deep(rtwdev);
682 : :
683 : 0 : rtw_mac_flush_queues(rtwdev, queues, drop);
684 : 0 : mutex_unlock(&rtwdev->mutex);
685 : 0 : }
686 : :
687 : : struct rtw_iter_bitrate_mask_data {
688 : : struct rtw_dev *rtwdev;
689 : : struct ieee80211_vif *vif;
690 : : const struct cfg80211_bitrate_mask *mask;
691 : : };
692 : :
693 : 0 : static void rtw_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta)
694 : : {
695 : 0 : struct rtw_iter_bitrate_mask_data *br_data = data;
696 : 0 : struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
697 : :
698 [ # # ]: 0 : if (si->vif != br_data->vif)
699 : : return;
700 : :
701 : : /* free previous mask setting */
702 : 0 : kfree(si->mask);
703 : 0 : si->mask = kmemdup(br_data->mask, sizeof(struct cfg80211_bitrate_mask),
704 : : GFP_ATOMIC);
705 [ # # ]: 0 : if (!si->mask) {
706 : 0 : si->use_cfg_mask = false;
707 : 0 : return;
708 : : }
709 : :
710 : 0 : si->use_cfg_mask = true;
711 : 0 : rtw_update_sta_info(br_data->rtwdev, si);
712 : : }
713 : :
714 : 0 : static void rtw_ra_mask_info_update(struct rtw_dev *rtwdev,
715 : : struct ieee80211_vif *vif,
716 : : const struct cfg80211_bitrate_mask *mask)
717 : : {
718 : 0 : struct rtw_iter_bitrate_mask_data br_data;
719 : :
720 : 0 : br_data.rtwdev = rtwdev;
721 : 0 : br_data.vif = vif;
722 : 0 : br_data.mask = mask;
723 : 0 : rtw_iterate_stas_atomic(rtwdev, rtw_ra_mask_info_update_iter, &br_data);
724 : : }
725 : :
726 : 0 : static int rtw_ops_set_bitrate_mask(struct ieee80211_hw *hw,
727 : : struct ieee80211_vif *vif,
728 : : const struct cfg80211_bitrate_mask *mask)
729 : : {
730 : 0 : struct rtw_dev *rtwdev = hw->priv;
731 : :
732 : 0 : rtw_ra_mask_info_update(rtwdev, vif, mask);
733 : :
734 : 0 : return 0;
735 : : }
736 : :
737 : : #ifdef CONFIG_PM
738 : 0 : static int rtw_ops_suspend(struct ieee80211_hw *hw,
739 : : struct cfg80211_wowlan *wowlan)
740 : : {
741 : 0 : struct rtw_dev *rtwdev = hw->priv;
742 : 0 : int ret;
743 : :
744 : 0 : mutex_lock(&rtwdev->mutex);
745 : 0 : ret = rtw_wow_suspend(rtwdev, wowlan);
746 [ # # ]: 0 : if (ret)
747 : 0 : rtw_err(rtwdev, "failed to suspend for wow %d\n", ret);
748 : 0 : mutex_unlock(&rtwdev->mutex);
749 : :
750 : 0 : return ret ? 1 : 0;
751 : : }
752 : :
753 : 0 : static int rtw_ops_resume(struct ieee80211_hw *hw)
754 : : {
755 : 0 : struct rtw_dev *rtwdev = hw->priv;
756 : 0 : int ret;
757 : :
758 : 0 : mutex_lock(&rtwdev->mutex);
759 : 0 : ret = rtw_wow_resume(rtwdev);
760 [ # # ]: 0 : if (ret)
761 : 0 : rtw_err(rtwdev, "failed to resume for wow %d\n", ret);
762 : 0 : mutex_unlock(&rtwdev->mutex);
763 : :
764 : 0 : return ret ? 1 : 0;
765 : : }
766 : :
767 : 0 : static void rtw_ops_set_wakeup(struct ieee80211_hw *hw, bool enabled)
768 : : {
769 : 0 : struct rtw_dev *rtwdev = hw->priv;
770 : :
771 : 0 : device_set_wakeup_enable(rtwdev->dev, enabled);
772 : 0 : }
773 : : #endif
774 : :
775 : : const struct ieee80211_ops rtw_ops = {
776 : : .tx = rtw_ops_tx,
777 : : .wake_tx_queue = rtw_ops_wake_tx_queue,
778 : : .start = rtw_ops_start,
779 : : .stop = rtw_ops_stop,
780 : : .config = rtw_ops_config,
781 : : .add_interface = rtw_ops_add_interface,
782 : : .remove_interface = rtw_ops_remove_interface,
783 : : .configure_filter = rtw_ops_configure_filter,
784 : : .bss_info_changed = rtw_ops_bss_info_changed,
785 : : .conf_tx = rtw_ops_conf_tx,
786 : : .sta_add = rtw_ops_sta_add,
787 : : .sta_remove = rtw_ops_sta_remove,
788 : : .set_key = rtw_ops_set_key,
789 : : .ampdu_action = rtw_ops_ampdu_action,
790 : : .sw_scan_start = rtw_ops_sw_scan_start,
791 : : .sw_scan_complete = rtw_ops_sw_scan_complete,
792 : : .mgd_prepare_tx = rtw_ops_mgd_prepare_tx,
793 : : .set_rts_threshold = rtw_ops_set_rts_threshold,
794 : : .sta_statistics = rtw_ops_sta_statistics,
795 : : .flush = rtw_ops_flush,
796 : : .set_bitrate_mask = rtw_ops_set_bitrate_mask,
797 : : #ifdef CONFIG_PM
798 : : .suspend = rtw_ops_suspend,
799 : : .resume = rtw_ops_resume,
800 : : .set_wakeup = rtw_ops_set_wakeup,
801 : : #endif
802 : : };
803 : : EXPORT_SYMBOL(rtw_ops);
|