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