Merge branch 'for-linus/2639/i2c-1' of git://git.fluff.org/bjdooks/linux
[deliverable/linux.git] / drivers / net / wireless / rtlwifi / core.c
1 /******************************************************************************
2 *
3 * Copyright(c) 2009-2010 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17 *
18 * The full GNU General Public License is included in this distribution in the
19 * file called LICENSE.
20 *
21 * Contact Information:
22 * wlanfae <wlanfae@realtek.com>
23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24 * Hsinchu 300, Taiwan.
25 *
26 * Larry Finger <Larry.Finger@lwfinger.net>
27 *****************************************************************************/
28
29 #include "wifi.h"
30 #include "core.h"
31 #include "cam.h"
32 #include "base.h"
33 #include "ps.h"
34
35 /*mutex for start & stop is must here. */
36 static int rtl_op_start(struct ieee80211_hw *hw)
37 {
38 int err = 0;
39 struct rtl_priv *rtlpriv = rtl_priv(hw);
40 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
41
42 if (!is_hal_stop(rtlhal))
43 return 0;
44 if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status))
45 return 0;
46 mutex_lock(&rtlpriv->locks.conf_mutex);
47 err = rtlpriv->intf_ops->adapter_start(hw);
48 if (err)
49 goto out;
50 rtl_watch_dog_timer_callback((unsigned long)hw);
51 out:
52 mutex_unlock(&rtlpriv->locks.conf_mutex);
53 return err;
54 }
55
56 static void rtl_op_stop(struct ieee80211_hw *hw)
57 {
58 struct rtl_priv *rtlpriv = rtl_priv(hw);
59 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
60 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
61 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
62
63 if (is_hal_stop(rtlhal))
64 return;
65
66 if (unlikely(ppsc->rfpwr_state == ERFOFF)) {
67 rtl_ips_nic_on(hw);
68 mdelay(1);
69 }
70
71 mutex_lock(&rtlpriv->locks.conf_mutex);
72
73 mac->link_state = MAC80211_NOLINK;
74 memset(mac->bssid, 0, 6);
75
76 /*reset sec info */
77 rtl_cam_reset_sec_info(hw);
78
79 rtl_deinit_deferred_work(hw);
80 rtlpriv->intf_ops->adapter_stop(hw);
81
82 mutex_unlock(&rtlpriv->locks.conf_mutex);
83 }
84
85 static void rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
86 {
87 struct rtl_priv *rtlpriv = rtl_priv(hw);
88 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
89 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
90
91 if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON))
92 goto err_free;
93
94 if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status))
95 goto err_free;
96
97
98 rtlpriv->intf_ops->adapter_tx(hw, skb);
99
100 return;
101
102 err_free:
103 dev_kfree_skb_any(skb);
104 }
105
106 static int rtl_op_add_interface(struct ieee80211_hw *hw,
107 struct ieee80211_vif *vif)
108 {
109 struct rtl_priv *rtlpriv = rtl_priv(hw);
110 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
111 int err = 0;
112
113 if (mac->vif) {
114 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
115 ("vif has been set!! mac->vif = 0x%p\n", mac->vif));
116 return -EOPNOTSUPP;
117 }
118
119 rtl_ips_nic_on(hw);
120
121 mutex_lock(&rtlpriv->locks.conf_mutex);
122 switch (vif->type) {
123 case NL80211_IFTYPE_STATION:
124 if (mac->beacon_enabled == 1) {
125 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
126 ("NL80211_IFTYPE_STATION\n"));
127 mac->beacon_enabled = 0;
128 rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
129 rtlpriv->cfg->maps
130 [RTL_IBSS_INT_MASKS]);
131 }
132 break;
133 case NL80211_IFTYPE_ADHOC:
134 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
135 ("NL80211_IFTYPE_ADHOC\n"));
136
137 mac->link_state = MAC80211_LINKED;
138 rtlpriv->cfg->ops->set_bcn_reg(hw);
139 break;
140 case NL80211_IFTYPE_AP:
141 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
142 ("NL80211_IFTYPE_AP\n"));
143 break;
144 default:
145 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
146 ("operation mode %d is not support!\n", vif->type));
147 err = -EOPNOTSUPP;
148 goto out;
149 }
150
151 mac->vif = vif;
152 mac->opmode = vif->type;
153 rtlpriv->cfg->ops->set_network_type(hw, vif->type);
154 memcpy(mac->mac_addr, vif->addr, ETH_ALEN);
155 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
156
157 out:
158 mutex_unlock(&rtlpriv->locks.conf_mutex);
159 return err;
160 }
161
162 static void rtl_op_remove_interface(struct ieee80211_hw *hw,
163 struct ieee80211_vif *vif)
164 {
165 struct rtl_priv *rtlpriv = rtl_priv(hw);
166 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
167
168 mutex_lock(&rtlpriv->locks.conf_mutex);
169
170 /* Free beacon resources */
171 if ((mac->opmode == NL80211_IFTYPE_AP) ||
172 (mac->opmode == NL80211_IFTYPE_ADHOC) ||
173 (mac->opmode == NL80211_IFTYPE_MESH_POINT)) {
174 if (mac->beacon_enabled == 1) {
175 mac->beacon_enabled = 0;
176 rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
177 rtlpriv->cfg->maps
178 [RTL_IBSS_INT_MASKS]);
179 }
180 }
181
182 /*
183 *Note: We assume NL80211_IFTYPE_UNSPECIFIED as
184 *NO LINK for our hardware.
185 */
186 mac->vif = NULL;
187 mac->link_state = MAC80211_NOLINK;
188 memset(mac->bssid, 0, 6);
189 mac->opmode = NL80211_IFTYPE_UNSPECIFIED;
190 rtlpriv->cfg->ops->set_network_type(hw, mac->opmode);
191
192 mutex_unlock(&rtlpriv->locks.conf_mutex);
193 }
194
195
196 static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
197 {
198 struct rtl_priv *rtlpriv = rtl_priv(hw);
199 struct rtl_phy *rtlphy = &(rtlpriv->phy);
200 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
201 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
202 struct ieee80211_conf *conf = &hw->conf;
203
204 mutex_lock(&rtlpriv->locks.conf_mutex);
205 if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /*BIT(2)*/
206 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
207 ("IEEE80211_CONF_CHANGE_LISTEN_INTERVAL\n"));
208 }
209
210 /*For IPS */
211 if (changed & IEEE80211_CONF_CHANGE_IDLE) {
212 if (hw->conf.flags & IEEE80211_CONF_IDLE)
213 rtl_ips_nic_off(hw);
214 else
215 rtl_ips_nic_on(hw);
216 } else {
217 /*
218 *although rfoff may not cause by ips, but we will
219 *check the reason in set_rf_power_state function
220 */
221 if (unlikely(ppsc->rfpwr_state == ERFOFF))
222 rtl_ips_nic_on(hw);
223 }
224
225 /*For LPS */
226 if (changed & IEEE80211_CONF_CHANGE_PS) {
227 if (conf->flags & IEEE80211_CONF_PS)
228 rtl_lps_enter(hw);
229 else
230 rtl_lps_leave(hw);
231 }
232
233 if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
234 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
235 ("IEEE80211_CONF_CHANGE_RETRY_LIMITS %x\n",
236 hw->conf.long_frame_max_tx_count));
237 mac->retry_long = hw->conf.long_frame_max_tx_count;
238 mac->retry_short = hw->conf.long_frame_max_tx_count;
239 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT,
240 (u8 *) (&hw->conf.
241 long_frame_max_tx_count));
242 }
243
244 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
245 struct ieee80211_channel *channel = hw->conf.channel;
246 u8 wide_chan = (u8) channel->hw_value;
247
248 /*
249 *because we should back channel to
250 *current_network.chan in in scanning,
251 *So if set_chan == current_network.chan
252 *we should set it.
253 *because mac80211 tell us wrong bw40
254 *info for cisco1253 bw20, so we modify
255 *it here based on UPPER & LOWER
256 */
257 switch (hw->conf.channel_type) {
258 case NL80211_CHAN_HT20:
259 case NL80211_CHAN_NO_HT:
260 /* SC */
261 mac->cur_40_prime_sc =
262 PRIME_CHNL_OFFSET_DONT_CARE;
263 rtlphy->current_chan_bw = HT_CHANNEL_WIDTH_20;
264 mac->bw_40 = false;
265 break;
266 case NL80211_CHAN_HT40MINUS:
267 /* SC */
268 mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_UPPER;
269 rtlphy->current_chan_bw =
270 HT_CHANNEL_WIDTH_20_40;
271 mac->bw_40 = true;
272
273 /*wide channel */
274 wide_chan -= 2;
275
276 break;
277 case NL80211_CHAN_HT40PLUS:
278 /* SC */
279 mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_LOWER;
280 rtlphy->current_chan_bw =
281 HT_CHANNEL_WIDTH_20_40;
282 mac->bw_40 = true;
283
284 /*wide channel */
285 wide_chan += 2;
286
287 break;
288 default:
289 mac->bw_40 = false;
290 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
291 ("switch case not processed\n"));
292 break;
293 }
294
295 if (wide_chan <= 0)
296 wide_chan = 1;
297 rtlphy->current_channel = wide_chan;
298
299 rtlpriv->cfg->ops->set_channel_access(hw);
300 rtlpriv->cfg->ops->switch_channel(hw);
301 rtlpriv->cfg->ops->set_bw_mode(hw,
302 hw->conf.channel_type);
303 }
304
305 mutex_unlock(&rtlpriv->locks.conf_mutex);
306
307 return 0;
308 }
309
310 static void rtl_op_configure_filter(struct ieee80211_hw *hw,
311 unsigned int changed_flags,
312 unsigned int *new_flags, u64 multicast)
313 {
314 struct rtl_priv *rtlpriv = rtl_priv(hw);
315 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
316
317 *new_flags &= RTL_SUPPORTED_FILTERS;
318 if (!changed_flags)
319 return;
320
321 /*TODO: we disable broadcase now, so enable here */
322 if (changed_flags & FIF_ALLMULTI) {
323 if (*new_flags & FIF_ALLMULTI) {
324 mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AM] |
325 rtlpriv->cfg->maps[MAC_RCR_AB];
326 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
327 ("Enable receive multicast frame.\n"));
328 } else {
329 mac->rx_conf &= ~(rtlpriv->cfg->maps[MAC_RCR_AM] |
330 rtlpriv->cfg->maps[MAC_RCR_AB]);
331 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
332 ("Disable receive multicast frame.\n"));
333 }
334 }
335
336 if (changed_flags & FIF_FCSFAIL) {
337 if (*new_flags & FIF_FCSFAIL) {
338 mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACRC32];
339 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
340 ("Enable receive FCS error frame.\n"));
341 } else {
342 mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACRC32];
343 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
344 ("Disable receive FCS error frame.\n"));
345 }
346 }
347
348 if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
349 /*
350 *TODO: BIT(5) is probe response BIT(8) is beacon
351 *TODO: Use define for BIT(5) and BIT(8)
352 */
353 if (*new_flags & FIF_BCN_PRBRESP_PROMISC)
354 mac->rx_mgt_filter |= (BIT(5) | BIT(8));
355 else
356 mac->rx_mgt_filter &= ~(BIT(5) | BIT(8));
357 }
358
359 if (changed_flags & FIF_CONTROL) {
360 if (*new_flags & FIF_CONTROL) {
361 mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACF];
362 mac->rx_ctrl_filter |= RTL_SUPPORTED_CTRL_FILTER;
363
364 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
365 ("Enable receive control frame.\n"));
366 } else {
367 mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACF];
368 mac->rx_ctrl_filter &= ~RTL_SUPPORTED_CTRL_FILTER;
369 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
370 ("Disable receive control frame.\n"));
371 }
372 }
373
374 if (changed_flags & FIF_OTHER_BSS) {
375 if (*new_flags & FIF_OTHER_BSS) {
376 mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AAP];
377 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
378 ("Enable receive other BSS's frame.\n"));
379 } else {
380 mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_AAP];
381 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
382 ("Disable receive other BSS's frame.\n"));
383 }
384 }
385
386 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf));
387 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MGT_FILTER,
388 (u8 *) (&mac->rx_mgt_filter));
389 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CTRL_FILTER,
390 (u8 *) (&mac->rx_ctrl_filter));
391 }
392
393 static int _rtl_get_hal_qnum(u16 queue)
394 {
395 int qnum;
396
397 switch (queue) {
398 case 0:
399 qnum = AC3_VO;
400 break;
401 case 1:
402 qnum = AC2_VI;
403 break;
404 case 2:
405 qnum = AC0_BE;
406 break;
407 case 3:
408 qnum = AC1_BK;
409 break;
410 default:
411 qnum = AC0_BE;
412 break;
413 }
414 return qnum;
415 }
416
417 /*
418 *for mac80211 VO=0, VI=1, BE=2, BK=3
419 *for rtl819x BE=0, BK=1, VI=2, VO=3
420 */
421 static int rtl_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
422 const struct ieee80211_tx_queue_params *param)
423 {
424 struct rtl_priv *rtlpriv = rtl_priv(hw);
425 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
426 int aci;
427
428 if (queue >= AC_MAX) {
429 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
430 ("queue number %d is incorrect!\n", queue));
431 return -EINVAL;
432 }
433
434 aci = _rtl_get_hal_qnum(queue);
435 mac->ac[aci].aifs = param->aifs;
436 mac->ac[aci].cw_min = cpu_to_le16(param->cw_min);
437 mac->ac[aci].cw_max = cpu_to_le16(param->cw_max);
438 mac->ac[aci].tx_op = cpu_to_le16(param->txop);
439 memcpy(&mac->edca_param[aci], param, sizeof(*param));
440 rtlpriv->cfg->ops->set_qos(hw, aci);
441 return 0;
442 }
443
444 static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
445 struct ieee80211_vif *vif,
446 struct ieee80211_bss_conf *bss_conf, u32 changed)
447 {
448 struct rtl_priv *rtlpriv = rtl_priv(hw);
449 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
450 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
451
452 mutex_lock(&rtlpriv->locks.conf_mutex);
453
454 if ((vif->type == NL80211_IFTYPE_ADHOC) ||
455 (vif->type == NL80211_IFTYPE_AP) ||
456 (vif->type == NL80211_IFTYPE_MESH_POINT)) {
457
458 if ((changed & BSS_CHANGED_BEACON) ||
459 (changed & BSS_CHANGED_BEACON_ENABLED &&
460 bss_conf->enable_beacon)) {
461
462 if (mac->beacon_enabled == 0) {
463 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
464 ("BSS_CHANGED_BEACON_ENABLED\n"));
465
466 /*start hw beacon interrupt. */
467 /*rtlpriv->cfg->ops->set_bcn_reg(hw); */
468 mac->beacon_enabled = 1;
469 rtlpriv->cfg->ops->update_interrupt_mask(hw,
470 rtlpriv->cfg->maps
471 [RTL_IBSS_INT_MASKS],
472 0);
473 }
474 } else {
475 if (mac->beacon_enabled == 1) {
476 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
477 ("ADHOC DISABLE BEACON\n"));
478
479 mac->beacon_enabled = 0;
480 rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
481 rtlpriv->cfg->maps
482 [RTL_IBSS_INT_MASKS]);
483 }
484 }
485
486 if (changed & BSS_CHANGED_BEACON_INT) {
487 RT_TRACE(rtlpriv, COMP_BEACON, DBG_TRACE,
488 ("BSS_CHANGED_BEACON_INT\n"));
489 mac->beacon_interval = bss_conf->beacon_int;
490 rtlpriv->cfg->ops->set_bcn_intv(hw);
491 }
492 }
493
494 /*TODO: reference to enum ieee80211_bss_change */
495 if (changed & BSS_CHANGED_ASSOC) {
496 if (bss_conf->assoc) {
497 mac->link_state = MAC80211_LINKED;
498 mac->cnt_after_linked = 0;
499 mac->assoc_id = bss_conf->aid;
500 memcpy(mac->bssid, bss_conf->bssid, 6);
501
502 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
503 ("BSS_CHANGED_ASSOC\n"));
504 } else {
505 if (mac->link_state == MAC80211_LINKED)
506 rtl_lps_leave(hw);
507
508 mac->link_state = MAC80211_NOLINK;
509 memset(mac->bssid, 0, 6);
510
511 /* reset sec info */
512 rtl_cam_reset_sec_info(hw);
513
514 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
515 ("BSS_CHANGED_UN_ASSOC\n"));
516 }
517 }
518
519 if (changed & BSS_CHANGED_ERP_CTS_PROT) {
520 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
521 ("BSS_CHANGED_ERP_CTS_PROT\n"));
522 mac->use_cts_protect = bss_conf->use_cts_prot;
523 }
524
525 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
526 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
527 ("BSS_CHANGED_ERP_PREAMBLE use short preamble:%x\n",
528 bss_conf->use_short_preamble));
529
530 mac->short_preamble = bss_conf->use_short_preamble;
531 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACK_PREAMBLE,
532 (u8 *) (&mac->short_preamble));
533 }
534
535 if (changed & BSS_CHANGED_ERP_SLOT) {
536 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
537 ("BSS_CHANGED_ERP_SLOT\n"));
538
539 if (bss_conf->use_short_slot)
540 mac->slot_time = RTL_SLOT_TIME_9;
541 else
542 mac->slot_time = RTL_SLOT_TIME_20;
543
544 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME,
545 (u8 *) (&mac->slot_time));
546 }
547
548 if (changed & BSS_CHANGED_HT) {
549 struct ieee80211_sta *sta = NULL;
550
551 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
552 ("BSS_CHANGED_HT\n"));
553
554 rcu_read_lock();
555 sta = ieee80211_find_sta(mac->vif, mac->bssid);
556
557 if (sta) {
558 if (sta->ht_cap.ampdu_density >
559 mac->current_ampdu_density)
560 mac->current_ampdu_density =
561 sta->ht_cap.ampdu_density;
562 if (sta->ht_cap.ampdu_factor <
563 mac->current_ampdu_factor)
564 mac->current_ampdu_factor =
565 sta->ht_cap.ampdu_factor;
566 }
567 rcu_read_unlock();
568
569 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SHORTGI_DENSITY,
570 (u8 *) (&mac->max_mss_density));
571 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_FACTOR,
572 &mac->current_ampdu_factor);
573 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_MIN_SPACE,
574 &mac->current_ampdu_density);
575 }
576
577 if (changed & BSS_CHANGED_BSSID) {
578 struct ieee80211_sta *sta = NULL;
579 u32 basic_rates;
580 u8 i;
581
582 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BSSID,
583 (u8 *) bss_conf->bssid);
584
585 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
586 (MAC_FMT "\n", MAC_ARG(bss_conf->bssid)));
587
588 memcpy(mac->bssid, bss_conf->bssid, 6);
589 if (is_valid_ether_addr(bss_conf->bssid)) {
590 switch (vif->type) {
591 case NL80211_IFTYPE_UNSPECIFIED:
592 break;
593 case NL80211_IFTYPE_ADHOC:
594 break;
595 case NL80211_IFTYPE_STATION:
596 break;
597 case NL80211_IFTYPE_AP:
598 break;
599 default:
600 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
601 ("switch case not process\n"));
602 break;
603 }
604 rtlpriv->cfg->ops->set_network_type(hw, vif->type);
605 } else
606 rtlpriv->cfg->ops->set_network_type(hw,
607 NL80211_IFTYPE_UNSPECIFIED);
608
609 memset(mac->mcs, 0, 16);
610 mac->ht_enable = false;
611 mac->sgi_40 = false;
612 mac->sgi_20 = false;
613
614 if (!bss_conf->use_short_slot)
615 mac->mode = WIRELESS_MODE_B;
616 else
617 mac->mode = WIRELESS_MODE_G;
618
619 rcu_read_lock();
620 sta = ieee80211_find_sta(mac->vif, mac->bssid);
621
622 if (sta) {
623 if (sta->ht_cap.ht_supported) {
624 mac->mode = WIRELESS_MODE_N_24G;
625 mac->ht_enable = true;
626 }
627
628 if (mac->ht_enable) {
629 u16 ht_cap = sta->ht_cap.cap;
630 memcpy(mac->mcs, (u8 *) (&sta->ht_cap.mcs), 16);
631
632 for (i = 0; i < 16; i++)
633 RT_TRACE(rtlpriv, COMP_MAC80211,
634 DBG_LOUD, ("%x ",
635 mac->mcs[i]));
636 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
637 ("\n"));
638
639 if (ht_cap & IEEE80211_HT_CAP_SGI_40)
640 mac->sgi_40 = true;
641
642 if (ht_cap & IEEE80211_HT_CAP_SGI_20)
643 mac->sgi_20 = true;
644
645 /*
646 * for cisco 1252 bw20 it's wrong
647 * if (ht_cap &
648 * IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
649 * mac->bw_40 = true;
650 * }
651 */
652 }
653 }
654 rcu_read_unlock();
655
656 /*mac80211 just give us CCK rates any time
657 *So we add G rate in basic rates when
658 not in B mode*/
659 if (changed & BSS_CHANGED_BASIC_RATES) {
660 if (mac->mode == WIRELESS_MODE_B)
661 basic_rates = bss_conf->basic_rates | 0x00f;
662 else
663 basic_rates = bss_conf->basic_rates | 0xff0;
664
665 if (!vif)
666 goto out;
667
668 mac->basic_rates = basic_rates;
669 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
670 (u8 *) (&basic_rates));
671
672 if (rtlpriv->dm.useramask)
673 rtlpriv->cfg->ops->update_rate_mask(hw, 0);
674 else
675 rtlpriv->cfg->ops->update_rate_table(hw);
676
677 }
678 }
679
680 /*
681 * For FW LPS:
682 * To tell firmware we have connected
683 * to an AP. For 92SE/CE power save v2.
684 */
685 if (changed & BSS_CHANGED_ASSOC) {
686 if (bss_conf->assoc) {
687 if (ppsc->fwctrl_lps) {
688 u8 mstatus = RT_MEDIA_CONNECT;
689 rtlpriv->cfg->ops->set_hw_reg(hw,
690 HW_VAR_H2C_FW_JOINBSSRPT,
691 (u8 *) (&mstatus));
692 ppsc->report_linked = true;
693 }
694 } else {
695 if (ppsc->fwctrl_lps) {
696 u8 mstatus = RT_MEDIA_DISCONNECT;
697 rtlpriv->cfg->ops->set_hw_reg(hw,
698 HW_VAR_H2C_FW_JOINBSSRPT,
699 (u8 *)(&mstatus));
700 ppsc->report_linked = false;
701 }
702 }
703 }
704
705 out:
706 mutex_unlock(&rtlpriv->locks.conf_mutex);
707 }
708
709 static u64 rtl_op_get_tsf(struct ieee80211_hw *hw)
710 {
711 struct rtl_priv *rtlpriv = rtl_priv(hw);
712 u64 tsf;
713
714 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&tsf));
715 return tsf;
716 }
717
718 static void rtl_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
719 {
720 struct rtl_priv *rtlpriv = rtl_priv(hw);
721 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
722 u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0;;
723
724 mac->tsf = tsf;
725 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&bibss));
726 }
727
728 static void rtl_op_reset_tsf(struct ieee80211_hw *hw)
729 {
730 struct rtl_priv *rtlpriv = rtl_priv(hw);
731 u8 tmp = 0;
732
733 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_DUAL_TSF_RST, (u8 *) (&tmp));
734 }
735
736 static void rtl_op_sta_notify(struct ieee80211_hw *hw,
737 struct ieee80211_vif *vif,
738 enum sta_notify_cmd cmd,
739 struct ieee80211_sta *sta)
740 {
741 switch (cmd) {
742 case STA_NOTIFY_SLEEP:
743 break;
744 case STA_NOTIFY_AWAKE:
745 break;
746 default:
747 break;
748 }
749 }
750
751 static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
752 struct ieee80211_vif *vif,
753 enum ieee80211_ampdu_mlme_action action,
754 struct ieee80211_sta *sta, u16 tid, u16 *ssn,
755 u8 buf_size)
756 {
757 struct rtl_priv *rtlpriv = rtl_priv(hw);
758
759 switch (action) {
760 case IEEE80211_AMPDU_TX_START:
761 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
762 ("IEEE80211_AMPDU_TX_START: TID:%d\n", tid));
763 return rtl_tx_agg_start(hw, sta->addr, tid, ssn);
764 break;
765 case IEEE80211_AMPDU_TX_STOP:
766 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
767 ("IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid));
768 return rtl_tx_agg_stop(hw, sta->addr, tid);
769 break;
770 case IEEE80211_AMPDU_TX_OPERATIONAL:
771 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
772 ("IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid));
773 break;
774 case IEEE80211_AMPDU_RX_START:
775 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
776 ("IEEE80211_AMPDU_RX_START:TID:%d\n", tid));
777 break;
778 case IEEE80211_AMPDU_RX_STOP:
779 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
780 ("IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid));
781 break;
782 default:
783 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
784 ("IEEE80211_AMPDU_ERR!!!!:\n"));
785 return -EOPNOTSUPP;
786 }
787 return 0;
788 }
789
790 static void rtl_op_sw_scan_start(struct ieee80211_hw *hw)
791 {
792 struct rtl_priv *rtlpriv = rtl_priv(hw);
793 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
794
795 mac->act_scanning = true;
796
797 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("\n"));
798
799 if (mac->link_state == MAC80211_LINKED) {
800 rtl_lps_leave(hw);
801 mac->link_state = MAC80211_LINKED_SCANNING;
802 } else
803 rtl_ips_nic_on(hw);
804
805 rtlpriv->cfg->ops->led_control(hw, LED_CTL_SITE_SURVEY);
806 rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP);
807 }
808
809 static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw)
810 {
811 struct rtl_priv *rtlpriv = rtl_priv(hw);
812 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
813
814 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("\n"));
815
816 rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE);
817 mac->act_scanning = false;
818 if (mac->link_state == MAC80211_LINKED_SCANNING) {
819 mac->link_state = MAC80211_LINKED;
820
821 /* fix fwlps issue */
822 rtlpriv->cfg->ops->set_network_type(hw, mac->opmode);
823
824 if (rtlpriv->dm.useramask)
825 rtlpriv->cfg->ops->update_rate_mask(hw, 0);
826 else
827 rtlpriv->cfg->ops->update_rate_table(hw);
828
829 }
830
831 }
832
833 static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
834 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
835 struct ieee80211_key_conf *key)
836 {
837 struct rtl_priv *rtlpriv = rtl_priv(hw);
838 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
839 u8 key_type = NO_ENCRYPTION;
840 u8 key_idx;
841 bool group_key = false;
842 bool wep_only = false;
843 int err = 0;
844 u8 mac_addr[ETH_ALEN];
845 u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
846 u8 zero_addr[ETH_ALEN] = { 0 };
847
848 if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
849 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
850 ("not open hw encryption\n"));
851 return -ENOSPC; /*User disabled HW-crypto */
852 }
853 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
854 ("%s hardware based encryption for keyidx: %d, mac: %pM\n",
855 cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
856 sta ? sta->addr : bcast_addr));
857 rtlpriv->sec.being_setkey = true;
858 rtl_ips_nic_on(hw);
859 mutex_lock(&rtlpriv->locks.conf_mutex);
860 /* <1> get encryption alg */
861 switch (key->cipher) {
862 case WLAN_CIPHER_SUITE_WEP40:
863 key_type = WEP40_ENCRYPTION;
864 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:WEP40\n"));
865 rtlpriv->sec.use_defaultkey = true;
866 break;
867 case WLAN_CIPHER_SUITE_WEP104:
868 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
869 ("alg:WEP104\n"));
870 key_type = WEP104_ENCRYPTION;
871 rtlpriv->sec.use_defaultkey = true;
872 break;
873 case WLAN_CIPHER_SUITE_TKIP:
874 key_type = TKIP_ENCRYPTION;
875 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:TKIP\n"));
876 if (mac->opmode == NL80211_IFTYPE_ADHOC)
877 rtlpriv->sec.use_defaultkey = true;
878 break;
879 case WLAN_CIPHER_SUITE_CCMP:
880 key_type = AESCCMP_ENCRYPTION;
881 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:CCMP\n"));
882 if (mac->opmode == NL80211_IFTYPE_ADHOC)
883 rtlpriv->sec.use_defaultkey = true;
884 break;
885 default:
886 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
887 ("alg_err:%x!!!!:\n", key->cipher));
888 goto out_unlock;
889 }
890 /* <2> get key_idx */
891 key_idx = (u8) (key->keyidx);
892 if (key_idx > 3)
893 goto out_unlock;
894 /* <3> if pairwise key enable_hw_sec */
895 group_key = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE);
896 if ((!group_key) || (mac->opmode == NL80211_IFTYPE_ADHOC) ||
897 rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) {
898 if (rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION &&
899 (key_type == WEP40_ENCRYPTION ||
900 key_type == WEP104_ENCRYPTION))
901 wep_only = true;
902 rtlpriv->sec.pairwise_enc_algorithm = key_type;
903 rtlpriv->cfg->ops->enable_hw_sec(hw);
904 }
905 /* <4> set key based on cmd */
906 switch (cmd) {
907 case SET_KEY:
908 if (wep_only) {
909 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
910 ("set WEP(group/pairwise) key\n"));
911 /* Pairwise key with an assigned MAC address. */
912 rtlpriv->sec.pairwise_enc_algorithm = key_type;
913 rtlpriv->sec.group_enc_algorithm = key_type;
914 /*set local buf about wep key. */
915 memcpy(rtlpriv->sec.key_buf[key_idx],
916 key->key, key->keylen);
917 rtlpriv->sec.key_len[key_idx] = key->keylen;
918 memcpy(mac_addr, zero_addr, ETH_ALEN);
919 } else if (group_key) { /* group key */
920 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
921 ("set group key\n"));
922 /* group key */
923 rtlpriv->sec.group_enc_algorithm = key_type;
924 /*set local buf about group key. */
925 memcpy(rtlpriv->sec.key_buf[key_idx],
926 key->key, key->keylen);
927 rtlpriv->sec.key_len[key_idx] = key->keylen;
928 memcpy(mac_addr, bcast_addr, ETH_ALEN);
929 } else { /* pairwise key */
930 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
931 ("set pairwise key\n"));
932 if (!sta) {
933 RT_ASSERT(false, ("pairwise key withnot"
934 "mac_addr\n"));
935 err = -EOPNOTSUPP;
936 goto out_unlock;
937 }
938 /* Pairwise key with an assigned MAC address. */
939 rtlpriv->sec.pairwise_enc_algorithm = key_type;
940 /*set local buf about pairwise key. */
941 memcpy(rtlpriv->sec.key_buf[PAIRWISE_KEYIDX],
942 key->key, key->keylen);
943 rtlpriv->sec.key_len[PAIRWISE_KEYIDX] = key->keylen;
944 rtlpriv->sec.pairwise_key =
945 rtlpriv->sec.key_buf[PAIRWISE_KEYIDX];
946 memcpy(mac_addr, sta->addr, ETH_ALEN);
947 }
948 rtlpriv->cfg->ops->set_key(hw, key_idx, mac_addr,
949 group_key, key_type, wep_only,
950 false);
951 /* <5> tell mac80211 do something: */
952 /*must use sw generate IV, or can not work !!!!. */
953 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
954 key->hw_key_idx = key_idx;
955 if (key_type == TKIP_ENCRYPTION)
956 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
957 break;
958 case DISABLE_KEY:
959 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
960 ("disable key delete one entry\n"));
961 /*set local buf about wep key. */
962 memset(rtlpriv->sec.key_buf[key_idx], 0, key->keylen);
963 rtlpriv->sec.key_len[key_idx] = 0;
964 memcpy(mac_addr, zero_addr, ETH_ALEN);
965 /*
966 *mac80211 will delete entrys one by one,
967 *so don't use rtl_cam_reset_all_entry
968 *or clear all entry here.
969 */
970 rtl_cam_delete_one_entry(hw, mac_addr, key_idx);
971 break;
972 default:
973 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
974 ("cmd_err:%x!!!!:\n", cmd));
975 }
976 out_unlock:
977 mutex_unlock(&rtlpriv->locks.conf_mutex);
978 rtlpriv->sec.being_setkey = false;
979 return err;
980 }
981
982 static void rtl_op_rfkill_poll(struct ieee80211_hw *hw)
983 {
984 struct rtl_priv *rtlpriv = rtl_priv(hw);
985
986 bool radio_state;
987 bool blocked;
988 u8 valid = 0;
989
990 if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status))
991 return;
992
993 mutex_lock(&rtlpriv->locks.conf_mutex);
994
995 /*if Radio On return true here */
996 radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid);
997
998 if (valid) {
999 if (unlikely(radio_state != rtlpriv->rfkill.rfkill_state)) {
1000 rtlpriv->rfkill.rfkill_state = radio_state;
1001
1002 RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
1003 (KERN_INFO "wireless radio switch turned %s\n",
1004 radio_state ? "on" : "off"));
1005
1006 blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1;
1007 wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
1008 }
1009 }
1010
1011 mutex_unlock(&rtlpriv->locks.conf_mutex);
1012 }
1013
1014 const struct ieee80211_ops rtl_ops = {
1015 .start = rtl_op_start,
1016 .stop = rtl_op_stop,
1017 .tx = rtl_op_tx,
1018 .add_interface = rtl_op_add_interface,
1019 .remove_interface = rtl_op_remove_interface,
1020 .config = rtl_op_config,
1021 .configure_filter = rtl_op_configure_filter,
1022 .set_key = rtl_op_set_key,
1023 .conf_tx = rtl_op_conf_tx,
1024 .bss_info_changed = rtl_op_bss_info_changed,
1025 .get_tsf = rtl_op_get_tsf,
1026 .set_tsf = rtl_op_set_tsf,
1027 .reset_tsf = rtl_op_reset_tsf,
1028 .sta_notify = rtl_op_sta_notify,
1029 .ampdu_action = rtl_op_ampdu_action,
1030 .sw_scan_start = rtl_op_sw_scan_start,
1031 .sw_scan_complete = rtl_op_sw_scan_complete,
1032 .rfkill_poll = rtl_op_rfkill_poll,
1033 };
This page took 0.052186 seconds and 5 git commands to generate.