1 /******************************************************************************
3 * Copyright(c) 2009-2010 Realtek Corporation.
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.
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
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
18 * The full GNU General Public License is included in this distribution in the
19 * file called LICENSE.
21 * Contact Information:
22 * wlanfae <wlanfae@realtek.com>
23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24 * Hsinchu 300, Taiwan.
26 * Larry Finger <Larry.Finger@lwfinger.net>
27 *****************************************************************************/
35 /*mutex for start & stop is must here. */
36 static int rtl_op_start(struct ieee80211_hw *hw)
39 struct rtl_priv *rtlpriv = rtl_priv(hw);
40 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
42 if (!is_hal_stop(rtlhal))
44 if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status))
46 mutex_lock(&rtlpriv->locks.conf_mutex);
47 err = rtlpriv->intf_ops->adapter_start(hw);
49 rtl_watch_dog_timer_callback((unsigned long)hw);
50 mutex_unlock(&rtlpriv->locks.conf_mutex);
54 static void rtl_op_stop(struct ieee80211_hw *hw)
56 struct rtl_priv *rtlpriv = rtl_priv(hw);
57 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
58 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
59 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
61 if (is_hal_stop(rtlhal))
64 if (unlikely(ppsc->rfpwr_state == ERFOFF)) {
69 mutex_lock(&rtlpriv->locks.conf_mutex);
71 mac->link_state = MAC80211_NOLINK;
72 memset(mac->bssid, 0, 6);
75 rtl_cam_reset_sec_info(hw);
77 rtl_deinit_deferred_work(hw);
78 rtlpriv->intf_ops->adapter_stop(hw);
80 mutex_unlock(&rtlpriv->locks.conf_mutex);
83 static void rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
85 struct rtl_priv *rtlpriv = rtl_priv(hw);
86 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
87 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
89 if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON))
92 if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status))
96 rtlpriv->intf_ops->adapter_tx(hw, skb);
101 dev_kfree_skb_any(skb);
104 static int rtl_op_add_interface(struct ieee80211_hw *hw,
105 struct ieee80211_vif *vif)
107 struct rtl_priv *rtlpriv = rtl_priv(hw);
108 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
112 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
113 ("vif has been set!! mac->vif = 0x%p\n", mac->vif));
119 mutex_lock(&rtlpriv->locks.conf_mutex);
121 case NL80211_IFTYPE_STATION:
122 if (mac->beacon_enabled == 1) {
123 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
124 ("NL80211_IFTYPE_STATION\n"));
125 mac->beacon_enabled = 0;
126 rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
128 [RTL_IBSS_INT_MASKS]);
131 case NL80211_IFTYPE_ADHOC:
132 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
133 ("NL80211_IFTYPE_ADHOC\n"));
135 mac->link_state = MAC80211_LINKED;
136 rtlpriv->cfg->ops->set_bcn_reg(hw);
138 case NL80211_IFTYPE_AP:
139 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
140 ("NL80211_IFTYPE_AP\n"));
143 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
144 ("operation mode %d is not support!\n", vif->type));
150 mac->opmode = vif->type;
151 rtlpriv->cfg->ops->set_network_type(hw, vif->type);
152 memcpy(mac->mac_addr, vif->addr, ETH_ALEN);
153 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
156 mutex_unlock(&rtlpriv->locks.conf_mutex);
160 static void rtl_op_remove_interface(struct ieee80211_hw *hw,
161 struct ieee80211_vif *vif)
163 struct rtl_priv *rtlpriv = rtl_priv(hw);
164 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
166 mutex_lock(&rtlpriv->locks.conf_mutex);
168 /* Free beacon resources */
169 if ((mac->opmode == NL80211_IFTYPE_AP) ||
170 (mac->opmode == NL80211_IFTYPE_ADHOC) ||
171 (mac->opmode == NL80211_IFTYPE_MESH_POINT)) {
172 if (mac->beacon_enabled == 1) {
173 mac->beacon_enabled = 0;
174 rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
176 [RTL_IBSS_INT_MASKS]);
181 *Note: We assume NL80211_IFTYPE_UNSPECIFIED as
182 *NO LINK for our hardware.
185 mac->link_state = MAC80211_NOLINK;
186 memset(mac->bssid, 0, 6);
187 mac->opmode = NL80211_IFTYPE_UNSPECIFIED;
188 rtlpriv->cfg->ops->set_network_type(hw, mac->opmode);
190 mutex_unlock(&rtlpriv->locks.conf_mutex);
194 static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
196 struct rtl_priv *rtlpriv = rtl_priv(hw);
197 struct rtl_phy *rtlphy = &(rtlpriv->phy);
198 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
199 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
200 struct ieee80211_conf *conf = &hw->conf;
202 mutex_lock(&rtlpriv->locks.conf_mutex);
203 if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /*BIT(2)*/
204 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
205 ("IEEE80211_CONF_CHANGE_LISTEN_INTERVAL\n"));
209 if (changed & IEEE80211_CONF_CHANGE_IDLE) {
210 if (hw->conf.flags & IEEE80211_CONF_IDLE)
216 *although rfoff may not cause by ips, but we will
217 *check the reason in set_rf_power_state function
219 if (unlikely(ppsc->rfpwr_state == ERFOFF))
224 if (changed & IEEE80211_CONF_CHANGE_PS) {
225 if (conf->flags & IEEE80211_CONF_PS)
231 if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
232 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
233 ("IEEE80211_CONF_CHANGE_RETRY_LIMITS %x\n",
234 hw->conf.long_frame_max_tx_count));
235 mac->retry_long = hw->conf.long_frame_max_tx_count;
236 mac->retry_short = hw->conf.long_frame_max_tx_count;
237 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT,
239 long_frame_max_tx_count));
242 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
243 struct ieee80211_channel *channel = hw->conf.channel;
244 u8 wide_chan = (u8) channel->hw_value;
247 *because we should back channel to
248 *current_network.chan in in scanning,
249 *So if set_chan == current_network.chan
251 *because mac80211 tell us wrong bw40
252 *info for cisco1253 bw20, so we modify
253 *it here based on UPPER & LOWER
255 switch (hw->conf.channel_type) {
256 case NL80211_CHAN_HT20:
257 case NL80211_CHAN_NO_HT:
259 mac->cur_40_prime_sc =
260 PRIME_CHNL_OFFSET_DONT_CARE;
261 rtlphy->current_chan_bw = HT_CHANNEL_WIDTH_20;
264 case NL80211_CHAN_HT40MINUS:
266 mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_UPPER;
267 rtlphy->current_chan_bw =
268 HT_CHANNEL_WIDTH_20_40;
275 case NL80211_CHAN_HT40PLUS:
277 mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_LOWER;
278 rtlphy->current_chan_bw =
279 HT_CHANNEL_WIDTH_20_40;
288 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
289 ("switch case not processed\n"));
295 rtlphy->current_channel = wide_chan;
297 rtlpriv->cfg->ops->set_channel_access(hw);
298 rtlpriv->cfg->ops->switch_channel(hw);
299 rtlpriv->cfg->ops->set_bw_mode(hw,
300 hw->conf.channel_type);
303 mutex_unlock(&rtlpriv->locks.conf_mutex);
308 static void rtl_op_configure_filter(struct ieee80211_hw *hw,
309 unsigned int changed_flags,
310 unsigned int *new_flags, u64 multicast)
312 struct rtl_priv *rtlpriv = rtl_priv(hw);
313 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
315 *new_flags &= RTL_SUPPORTED_FILTERS;
319 /*TODO: we disable broadcase now, so enable here */
320 if (changed_flags & FIF_ALLMULTI) {
321 if (*new_flags & FIF_ALLMULTI) {
322 mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AM] |
323 rtlpriv->cfg->maps[MAC_RCR_AB];
324 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
325 ("Enable receive multicast frame.\n"));
327 mac->rx_conf &= ~(rtlpriv->cfg->maps[MAC_RCR_AM] |
328 rtlpriv->cfg->maps[MAC_RCR_AB]);
329 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
330 ("Disable receive multicast frame.\n"));
334 if (changed_flags & FIF_FCSFAIL) {
335 if (*new_flags & FIF_FCSFAIL) {
336 mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACRC32];
337 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
338 ("Enable receive FCS error frame.\n"));
340 mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACRC32];
341 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
342 ("Disable receive FCS error frame.\n"));
346 if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
348 *TODO: BIT(5) is probe response BIT(8) is beacon
349 *TODO: Use define for BIT(5) and BIT(8)
351 if (*new_flags & FIF_BCN_PRBRESP_PROMISC)
352 mac->rx_mgt_filter |= (BIT(5) | BIT(8));
354 mac->rx_mgt_filter &= ~(BIT(5) | BIT(8));
357 if (changed_flags & FIF_CONTROL) {
358 if (*new_flags & FIF_CONTROL) {
359 mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACF];
360 mac->rx_ctrl_filter |= RTL_SUPPORTED_CTRL_FILTER;
362 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
363 ("Enable receive control frame.\n"));
365 mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACF];
366 mac->rx_ctrl_filter &= ~RTL_SUPPORTED_CTRL_FILTER;
367 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
368 ("Disable receive control frame.\n"));
372 if (changed_flags & FIF_OTHER_BSS) {
373 if (*new_flags & FIF_OTHER_BSS) {
374 mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AAP];
375 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
376 ("Enable receive other BSS's frame.\n"));
378 mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_AAP];
379 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
380 ("Disable receive other BSS's frame.\n"));
384 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf));
385 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MGT_FILTER,
386 (u8 *) (&mac->rx_mgt_filter));
387 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CTRL_FILTER,
388 (u8 *) (&mac->rx_ctrl_filter));
391 static int _rtl_get_hal_qnum(u16 queue)
416 *for mac80211 VO=0, VI=1, BE=2, BK=3
417 *for rtl819x BE=0, BK=1, VI=2, VO=3
419 static int rtl_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
420 const struct ieee80211_tx_queue_params *param)
422 struct rtl_priv *rtlpriv = rtl_priv(hw);
423 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
426 if (queue >= AC_MAX) {
427 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
428 ("queue number %d is incorrect!\n", queue));
432 aci = _rtl_get_hal_qnum(queue);
433 mac->ac[aci].aifs = param->aifs;
434 mac->ac[aci].cw_min = cpu_to_le16(param->cw_min);
435 mac->ac[aci].cw_max = cpu_to_le16(param->cw_max);
436 mac->ac[aci].tx_op = cpu_to_le16(param->txop);
437 memcpy(&mac->edca_param[aci], param, sizeof(*param));
438 rtlpriv->cfg->ops->set_qos(hw, aci);
442 static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
443 struct ieee80211_vif *vif,
444 struct ieee80211_bss_conf *bss_conf, u32 changed)
446 struct rtl_priv *rtlpriv = rtl_priv(hw);
447 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
448 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
450 mutex_lock(&rtlpriv->locks.conf_mutex);
452 if ((vif->type == NL80211_IFTYPE_ADHOC) ||
453 (vif->type == NL80211_IFTYPE_AP) ||
454 (vif->type == NL80211_IFTYPE_MESH_POINT)) {
456 if ((changed & BSS_CHANGED_BEACON) ||
457 (changed & BSS_CHANGED_BEACON_ENABLED &&
458 bss_conf->enable_beacon)) {
460 if (mac->beacon_enabled == 0) {
461 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
462 ("BSS_CHANGED_BEACON_ENABLED\n"));
464 /*start hw beacon interrupt. */
465 /*rtlpriv->cfg->ops->set_bcn_reg(hw); */
466 mac->beacon_enabled = 1;
467 rtlpriv->cfg->ops->update_interrupt_mask(hw,
469 [RTL_IBSS_INT_MASKS],
473 if (mac->beacon_enabled == 1) {
474 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
475 ("ADHOC DISABLE BEACON\n"));
477 mac->beacon_enabled = 0;
478 rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
480 [RTL_IBSS_INT_MASKS]);
484 if (changed & BSS_CHANGED_BEACON_INT) {
485 RT_TRACE(rtlpriv, COMP_BEACON, DBG_TRACE,
486 ("BSS_CHANGED_BEACON_INT\n"));
487 mac->beacon_interval = bss_conf->beacon_int;
488 rtlpriv->cfg->ops->set_bcn_intv(hw);
492 /*TODO: reference to enum ieee80211_bss_change */
493 if (changed & BSS_CHANGED_ASSOC) {
494 if (bss_conf->assoc) {
495 mac->link_state = MAC80211_LINKED;
496 mac->cnt_after_linked = 0;
497 mac->assoc_id = bss_conf->aid;
498 memcpy(mac->bssid, bss_conf->bssid, 6);
500 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
501 ("BSS_CHANGED_ASSOC\n"));
503 if (mac->link_state == MAC80211_LINKED)
506 mac->link_state = MAC80211_NOLINK;
507 memset(mac->bssid, 0, 6);
510 rtl_cam_reset_sec_info(hw);
512 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
513 ("BSS_CHANGED_UN_ASSOC\n"));
517 if (changed & BSS_CHANGED_ERP_CTS_PROT) {
518 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
519 ("BSS_CHANGED_ERP_CTS_PROT\n"));
520 mac->use_cts_protect = bss_conf->use_cts_prot;
523 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
524 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
525 ("BSS_CHANGED_ERP_PREAMBLE use short preamble:%x\n",
526 bss_conf->use_short_preamble));
528 mac->short_preamble = bss_conf->use_short_preamble;
529 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACK_PREAMBLE,
530 (u8 *) (&mac->short_preamble));
533 if (changed & BSS_CHANGED_ERP_SLOT) {
534 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
535 ("BSS_CHANGED_ERP_SLOT\n"));
537 if (bss_conf->use_short_slot)
538 mac->slot_time = RTL_SLOT_TIME_9;
540 mac->slot_time = RTL_SLOT_TIME_20;
542 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME,
543 (u8 *) (&mac->slot_time));
546 if (changed & BSS_CHANGED_HT) {
547 struct ieee80211_sta *sta = NULL;
549 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
550 ("BSS_CHANGED_HT\n"));
553 sta = ieee80211_find_sta(mac->vif, mac->bssid);
556 if (sta->ht_cap.ampdu_density >
557 mac->current_ampdu_density)
558 mac->current_ampdu_density =
559 sta->ht_cap.ampdu_density;
560 if (sta->ht_cap.ampdu_factor <
561 mac->current_ampdu_factor)
562 mac->current_ampdu_factor =
563 sta->ht_cap.ampdu_factor;
567 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SHORTGI_DENSITY,
568 (u8 *) (&mac->max_mss_density));
569 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_FACTOR,
570 &mac->current_ampdu_factor);
571 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_MIN_SPACE,
572 &mac->current_ampdu_density);
575 if (changed & BSS_CHANGED_BSSID) {
576 struct ieee80211_sta *sta = NULL;
580 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BSSID,
581 (u8 *) bss_conf->bssid);
583 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
584 (MAC_FMT "\n", MAC_ARG(bss_conf->bssid)));
586 memcpy(mac->bssid, bss_conf->bssid, 6);
587 if (is_valid_ether_addr(bss_conf->bssid)) {
589 case NL80211_IFTYPE_UNSPECIFIED:
591 case NL80211_IFTYPE_ADHOC:
593 case NL80211_IFTYPE_STATION:
595 case NL80211_IFTYPE_AP:
598 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
599 ("switch case not process\n"));
602 rtlpriv->cfg->ops->set_network_type(hw, vif->type);
604 rtlpriv->cfg->ops->set_network_type(hw,
605 NL80211_IFTYPE_UNSPECIFIED);
607 memset(mac->mcs, 0, 16);
608 mac->ht_enable = false;
612 if (!bss_conf->use_short_slot)
613 mac->mode = WIRELESS_MODE_B;
615 mac->mode = WIRELESS_MODE_G;
618 sta = ieee80211_find_sta(mac->vif, mac->bssid);
621 if (sta->ht_cap.ht_supported) {
622 mac->mode = WIRELESS_MODE_N_24G;
623 mac->ht_enable = true;
626 if (mac->ht_enable) {
627 u16 ht_cap = sta->ht_cap.cap;
628 memcpy(mac->mcs, (u8 *) (&sta->ht_cap.mcs), 16);
630 for (i = 0; i < 16; i++)
631 RT_TRACE(rtlpriv, COMP_MAC80211,
634 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
637 if (ht_cap & IEEE80211_HT_CAP_SGI_40)
640 if (ht_cap & IEEE80211_HT_CAP_SGI_20)
644 * for cisco 1252 bw20 it's wrong
646 * IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
654 /*mac80211 just give us CCK rates any time
655 *So we add G rate in basic rates when
657 if (changed & BSS_CHANGED_BASIC_RATES) {
658 if (mac->mode == WIRELESS_MODE_B)
659 basic_rates = bss_conf->basic_rates | 0x00f;
661 basic_rates = bss_conf->basic_rates | 0xff0;
666 mac->basic_rates = basic_rates;
667 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
668 (u8 *) (&basic_rates));
670 if (rtlpriv->dm.useramask)
671 rtlpriv->cfg->ops->update_rate_mask(hw, 0);
673 rtlpriv->cfg->ops->update_rate_table(hw);
680 * To tell firmware we have connected
681 * to an AP. For 92SE/CE power save v2.
683 if (changed & BSS_CHANGED_ASSOC) {
684 if (bss_conf->assoc) {
685 if (ppsc->fwctrl_lps) {
686 u8 mstatus = RT_MEDIA_CONNECT;
687 rtlpriv->cfg->ops->set_hw_reg(hw,
688 HW_VAR_H2C_FW_JOINBSSRPT,
690 ppsc->report_linked = true;
693 if (ppsc->fwctrl_lps) {
694 u8 mstatus = RT_MEDIA_DISCONNECT;
695 rtlpriv->cfg->ops->set_hw_reg(hw,
696 HW_VAR_H2C_FW_JOINBSSRPT,
698 ppsc->report_linked = false;
704 mutex_unlock(&rtlpriv->locks.conf_mutex);
707 static u64 rtl_op_get_tsf(struct ieee80211_hw *hw)
709 struct rtl_priv *rtlpriv = rtl_priv(hw);
712 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&tsf));
716 static void rtl_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
718 struct rtl_priv *rtlpriv = rtl_priv(hw);
719 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
720 u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0;;
723 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&bibss));
726 static void rtl_op_reset_tsf(struct ieee80211_hw *hw)
728 struct rtl_priv *rtlpriv = rtl_priv(hw);
731 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_DUAL_TSF_RST, (u8 *) (&tmp));
734 static void rtl_op_sta_notify(struct ieee80211_hw *hw,
735 struct ieee80211_vif *vif,
736 enum sta_notify_cmd cmd,
737 struct ieee80211_sta *sta)
740 case STA_NOTIFY_SLEEP:
742 case STA_NOTIFY_AWAKE:
749 static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
750 struct ieee80211_vif *vif,
751 enum ieee80211_ampdu_mlme_action action,
752 struct ieee80211_sta *sta, u16 tid, u16 *ssn,
755 struct rtl_priv *rtlpriv = rtl_priv(hw);
758 case IEEE80211_AMPDU_TX_START:
759 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
760 ("IEEE80211_AMPDU_TX_START: TID:%d\n", tid));
761 return rtl_tx_agg_start(hw, sta->addr, tid, ssn);
763 case IEEE80211_AMPDU_TX_STOP:
764 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
765 ("IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid));
766 return rtl_tx_agg_stop(hw, sta->addr, tid);
768 case IEEE80211_AMPDU_TX_OPERATIONAL:
769 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
770 ("IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid));
772 case IEEE80211_AMPDU_RX_START:
773 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
774 ("IEEE80211_AMPDU_RX_START:TID:%d\n", tid));
776 case IEEE80211_AMPDU_RX_STOP:
777 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
778 ("IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid));
781 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
782 ("IEEE80211_AMPDU_ERR!!!!:\n"));
788 static void rtl_op_sw_scan_start(struct ieee80211_hw *hw)
790 struct rtl_priv *rtlpriv = rtl_priv(hw);
791 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
793 mac->act_scanning = true;
795 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("\n"));
797 if (mac->link_state == MAC80211_LINKED) {
799 mac->link_state = MAC80211_LINKED_SCANNING;
803 rtlpriv->cfg->ops->led_control(hw, LED_CTL_SITE_SURVEY);
804 rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP);
807 static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw)
809 struct rtl_priv *rtlpriv = rtl_priv(hw);
810 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
812 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("\n"));
814 rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE);
815 mac->act_scanning = false;
816 if (mac->link_state == MAC80211_LINKED_SCANNING) {
817 mac->link_state = MAC80211_LINKED;
819 /* fix fwlps issue */
820 rtlpriv->cfg->ops->set_network_type(hw, mac->opmode);
822 if (rtlpriv->dm.useramask)
823 rtlpriv->cfg->ops->update_rate_mask(hw, 0);
825 rtlpriv->cfg->ops->update_rate_table(hw);
831 static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
832 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
833 struct ieee80211_key_conf *key)
835 struct rtl_priv *rtlpriv = rtl_priv(hw);
836 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
837 u8 key_type = NO_ENCRYPTION;
839 bool group_key = false;
840 bool wep_only = false;
842 u8 mac_addr[ETH_ALEN];
843 u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
844 u8 zero_addr[ETH_ALEN] = { 0 };
846 if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
847 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
848 ("not open hw encryption\n"));
849 return -ENOSPC; /*User disabled HW-crypto */
851 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
852 ("%s hardware based encryption for keyidx: %d, mac: %pM\n",
853 cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
854 sta ? sta->addr : bcast_addr));
855 rtlpriv->sec.being_setkey = true;
857 mutex_lock(&rtlpriv->locks.conf_mutex);
858 /* <1> get encryption alg */
859 switch (key->cipher) {
860 case WLAN_CIPHER_SUITE_WEP40:
861 key_type = WEP40_ENCRYPTION;
862 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:WEP40\n"));
863 rtlpriv->sec.use_defaultkey = true;
865 case WLAN_CIPHER_SUITE_WEP104:
866 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
868 key_type = WEP104_ENCRYPTION;
869 rtlpriv->sec.use_defaultkey = true;
871 case WLAN_CIPHER_SUITE_TKIP:
872 key_type = TKIP_ENCRYPTION;
873 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:TKIP\n"));
874 if (mac->opmode == NL80211_IFTYPE_ADHOC)
875 rtlpriv->sec.use_defaultkey = true;
877 case WLAN_CIPHER_SUITE_CCMP:
878 key_type = AESCCMP_ENCRYPTION;
879 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:CCMP\n"));
880 if (mac->opmode == NL80211_IFTYPE_ADHOC)
881 rtlpriv->sec.use_defaultkey = true;
884 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
885 ("alg_err:%x!!!!:\n", key->cipher));
888 /* <2> get key_idx */
889 key_idx = (u8) (key->keyidx);
892 /* <3> if pairwise key enable_hw_sec */
893 group_key = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE);
894 if ((!group_key) || (mac->opmode == NL80211_IFTYPE_ADHOC) ||
895 rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) {
896 if (rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION &&
897 (key_type == WEP40_ENCRYPTION ||
898 key_type == WEP104_ENCRYPTION))
900 rtlpriv->sec.pairwise_enc_algorithm = key_type;
901 rtlpriv->cfg->ops->enable_hw_sec(hw);
903 /* <4> set key based on cmd */
907 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
908 ("set WEP(group/pairwise) key\n"));
909 /* Pairwise key with an assigned MAC address. */
910 rtlpriv->sec.pairwise_enc_algorithm = key_type;
911 rtlpriv->sec.group_enc_algorithm = key_type;
912 /*set local buf about wep key. */
913 memcpy(rtlpriv->sec.key_buf[key_idx],
914 key->key, key->keylen);
915 rtlpriv->sec.key_len[key_idx] = key->keylen;
916 memcpy(mac_addr, zero_addr, ETH_ALEN);
917 } else if (group_key) { /* group key */
918 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
919 ("set group key\n"));
921 rtlpriv->sec.group_enc_algorithm = key_type;
922 /*set local buf about group key. */
923 memcpy(rtlpriv->sec.key_buf[key_idx],
924 key->key, key->keylen);
925 rtlpriv->sec.key_len[key_idx] = key->keylen;
926 memcpy(mac_addr, bcast_addr, ETH_ALEN);
927 } else { /* pairwise key */
928 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
929 ("set pairwise key\n"));
931 RT_ASSERT(false, ("pairwise key withnot"
936 /* Pairwise key with an assigned MAC address. */
937 rtlpriv->sec.pairwise_enc_algorithm = key_type;
938 /*set local buf about pairwise key. */
939 memcpy(rtlpriv->sec.key_buf[PAIRWISE_KEYIDX],
940 key->key, key->keylen);
941 rtlpriv->sec.key_len[PAIRWISE_KEYIDX] = key->keylen;
942 rtlpriv->sec.pairwise_key =
943 rtlpriv->sec.key_buf[PAIRWISE_KEYIDX];
944 memcpy(mac_addr, sta->addr, ETH_ALEN);
946 rtlpriv->cfg->ops->set_key(hw, key_idx, mac_addr,
947 group_key, key_type, wep_only,
949 /* <5> tell mac80211 do something: */
950 /*must use sw generate IV, or can not work !!!!. */
951 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
952 key->hw_key_idx = key_idx;
953 if (key_type == TKIP_ENCRYPTION)
954 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
957 RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
958 ("disable key delete one entry\n"));
959 /*set local buf about wep key. */
960 memset(rtlpriv->sec.key_buf[key_idx], 0, key->keylen);
961 rtlpriv->sec.key_len[key_idx] = 0;
962 memcpy(mac_addr, zero_addr, ETH_ALEN);
964 *mac80211 will delete entrys one by one,
965 *so don't use rtl_cam_reset_all_entry
966 *or clear all entry here.
968 rtl_cam_delete_one_entry(hw, mac_addr, key_idx);
971 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
972 ("cmd_err:%x!!!!:\n", cmd));
975 mutex_unlock(&rtlpriv->locks.conf_mutex);
976 rtlpriv->sec.being_setkey = false;
980 static void rtl_op_rfkill_poll(struct ieee80211_hw *hw)
982 struct rtl_priv *rtlpriv = rtl_priv(hw);
988 if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status))
991 mutex_lock(&rtlpriv->locks.conf_mutex);
993 /*if Radio On return true here */
994 radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid);
997 if (unlikely(radio_state != rtlpriv->rfkill.rfkill_state)) {
998 rtlpriv->rfkill.rfkill_state = radio_state;
1000 RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
1001 (KERN_INFO "wireless radio switch turned %s\n",
1002 radio_state ? "on" : "off"));
1004 blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1;
1005 wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
1009 mutex_unlock(&rtlpriv->locks.conf_mutex);
1012 const struct ieee80211_ops rtl_ops = {
1013 .start = rtl_op_start,
1014 .stop = rtl_op_stop,
1016 .add_interface = rtl_op_add_interface,
1017 .remove_interface = rtl_op_remove_interface,
1018 .config = rtl_op_config,
1019 .configure_filter = rtl_op_configure_filter,
1020 .set_key = rtl_op_set_key,
1021 .conf_tx = rtl_op_conf_tx,
1022 .bss_info_changed = rtl_op_bss_info_changed,
1023 .get_tsf = rtl_op_get_tsf,
1024 .set_tsf = rtl_op_set_tsf,
1025 .reset_tsf = rtl_op_reset_tsf,
1026 .sta_notify = rtl_op_sta_notify,
1027 .ampdu_action = rtl_op_ampdu_action,
1028 .sw_scan_start = rtl_op_sw_scan_start,
1029 .sw_scan_complete = rtl_op_sw_scan_complete,
1030 .rfkill_poll = rtl_op_rfkill_poll,