linux/drivers/net/wireless/rtlwifi/core.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2009-2012  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
  30#include "wifi.h"
  31#include "core.h"
  32#include "cam.h"
  33#include "base.h"
  34#include "pci.h"
  35#include "ps.h"
  36
  37#include <linux/export.h>
  38
  39void rtl_fw_cb(const struct firmware *firmware, void *context)
  40{
  41        struct ieee80211_hw *hw = context;
  42        struct rtl_priv *rtlpriv = rtl_priv(hw);
  43        int err;
  44
  45        RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
  46                         "Firmware callback routine entered!\n");
  47        complete(&rtlpriv->firmware_loading_complete);
  48        if (!firmware) {
  49                pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name);
  50                rtlpriv->max_fw_size = 0;
  51                return;
  52        }
  53        if (firmware->size > rtlpriv->max_fw_size) {
  54                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  55                         "Firmware is too big!\n");
  56                release_firmware(firmware);
  57                return;
  58        }
  59        memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
  60        rtlpriv->rtlhal.fwsize = firmware->size;
  61        release_firmware(firmware);
  62
  63        err = ieee80211_register_hw(hw);
  64        if (err) {
  65                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  66                         "Can't register mac80211 hw\n");
  67                return;
  68        } else {
  69                rtlpriv->mac80211.mac80211_registered = 1;
  70        }
  71        set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
  72
  73        /*init rfkill */
  74        rtl_init_rfkill(hw);
  75}
  76EXPORT_SYMBOL(rtl_fw_cb);
  77
  78/*mutex for start & stop is must here. */
  79static int rtl_op_start(struct ieee80211_hw *hw)
  80{
  81        int err;
  82        struct rtl_priv *rtlpriv = rtl_priv(hw);
  83        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  84
  85        if (!is_hal_stop(rtlhal))
  86                return 0;
  87        if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status))
  88                return 0;
  89        mutex_lock(&rtlpriv->locks.conf_mutex);
  90        err = rtlpriv->intf_ops->adapter_start(hw);
  91        if (!err)
  92                rtl_watch_dog_timer_callback((unsigned long)hw);
  93        mutex_unlock(&rtlpriv->locks.conf_mutex);
  94        return err;
  95}
  96
  97static void rtl_op_stop(struct ieee80211_hw *hw)
  98{
  99        struct rtl_priv *rtlpriv = rtl_priv(hw);
 100        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 101        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 102        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 103
 104        if (is_hal_stop(rtlhal))
 105                return;
 106
 107        /* here is must, because adhoc do stop and start,
 108         * but stop with RFOFF may cause something wrong,
 109         * like adhoc TP
 110         */
 111        if (unlikely(ppsc->rfpwr_state == ERFOFF)) {
 112                rtl_ips_nic_on(hw);
 113        }
 114
 115        mutex_lock(&rtlpriv->locks.conf_mutex);
 116
 117        mac->link_state = MAC80211_NOLINK;
 118        memset(mac->bssid, 0, 6);
 119        mac->vendor = PEER_UNKNOWN;
 120
 121        /*reset sec info */
 122        rtl_cam_reset_sec_info(hw);
 123
 124        rtl_deinit_deferred_work(hw);
 125        rtlpriv->intf_ops->adapter_stop(hw);
 126
 127        mutex_unlock(&rtlpriv->locks.conf_mutex);
 128}
 129
 130static void rtl_op_tx(struct ieee80211_hw *hw,
 131                      struct ieee80211_tx_control *control,
 132                      struct sk_buff *skb)
 133{
 134        struct rtl_priv *rtlpriv = rtl_priv(hw);
 135        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 136        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 137        struct rtl_tcb_desc tcb_desc;
 138        memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
 139
 140        if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON))
 141                goto err_free;
 142
 143        if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status))
 144                goto err_free;
 145
 146        if (!rtlpriv->intf_ops->waitq_insert(hw, control->sta, skb))
 147                rtlpriv->intf_ops->adapter_tx(hw, control->sta, skb, &tcb_desc);
 148
 149        return;
 150
 151err_free:
 152        dev_kfree_skb_any(skb);
 153}
 154
 155static int rtl_op_add_interface(struct ieee80211_hw *hw,
 156                struct ieee80211_vif *vif)
 157{
 158        struct rtl_priv *rtlpriv = rtl_priv(hw);
 159        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 160        int err = 0;
 161
 162        vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
 163
 164        if (mac->vif) {
 165                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 166                         "vif has been set!! mac->vif = 0x%p\n", mac->vif);
 167                return -EOPNOTSUPP;
 168        }
 169
 170        rtl_ips_nic_on(hw);
 171
 172        mutex_lock(&rtlpriv->locks.conf_mutex);
 173
 174        switch (ieee80211_vif_type_p2p(vif)) {
 175        case NL80211_IFTYPE_P2P_CLIENT:
 176                mac->p2p = P2P_ROLE_CLIENT;
 177                /*fall through*/
 178        case NL80211_IFTYPE_STATION:
 179                if (mac->beacon_enabled == 1) {
 180                        RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 181                                 "NL80211_IFTYPE_STATION\n");
 182                        mac->beacon_enabled = 0;
 183                        rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
 184                                        rtlpriv->cfg->maps
 185                                        [RTL_IBSS_INT_MASKS]);
 186                }
 187                break;
 188        case NL80211_IFTYPE_ADHOC:
 189                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 190                         "NL80211_IFTYPE_ADHOC\n");
 191
 192                mac->link_state = MAC80211_LINKED;
 193                rtlpriv->cfg->ops->set_bcn_reg(hw);
 194                if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G)
 195                        mac->basic_rates = 0xfff;
 196                else
 197                        mac->basic_rates = 0xff0;
 198                rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
 199                                (u8 *) (&mac->basic_rates));
 200
 201                break;
 202        case NL80211_IFTYPE_P2P_GO:
 203                mac->p2p = P2P_ROLE_GO;
 204                /*fall through*/
 205        case NL80211_IFTYPE_AP:
 206                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 207                         "NL80211_IFTYPE_AP\n");
 208
 209                mac->link_state = MAC80211_LINKED;
 210                rtlpriv->cfg->ops->set_bcn_reg(hw);
 211                if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G)
 212                        mac->basic_rates = 0xfff;
 213                else
 214                        mac->basic_rates = 0xff0;
 215                rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
 216                                (u8 *) (&mac->basic_rates));
 217                break;
 218        case NL80211_IFTYPE_MESH_POINT:
 219                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 220                         "NL80211_IFTYPE_MESH_POINT\n");
 221
 222                mac->link_state = MAC80211_LINKED;
 223                rtlpriv->cfg->ops->set_bcn_reg(hw);
 224                if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G)
 225                        mac->basic_rates = 0xfff;
 226                else
 227                        mac->basic_rates = 0xff0;
 228                rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
 229                                (u8 *)(&mac->basic_rates));
 230                break;
 231        default:
 232                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 233                         "operation mode %d is not supported!\n", vif->type);
 234                err = -EOPNOTSUPP;
 235                goto out;
 236        }
 237
 238        if (mac->p2p) {
 239                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 240                         "p2p role %x\n", vif->type);
 241                mac->basic_rates = 0xff0;/*disable cck rate for p2p*/
 242                rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
 243                                (u8 *)(&mac->basic_rates));
 244        }
 245        mac->vif = vif;
 246        mac->opmode = vif->type;
 247        rtlpriv->cfg->ops->set_network_type(hw, vif->type);
 248        memcpy(mac->mac_addr, vif->addr, ETH_ALEN);
 249        rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
 250
 251out:
 252        mutex_unlock(&rtlpriv->locks.conf_mutex);
 253        return err;
 254}
 255
 256static void rtl_op_remove_interface(struct ieee80211_hw *hw,
 257                struct ieee80211_vif *vif)
 258{
 259        struct rtl_priv *rtlpriv = rtl_priv(hw);
 260        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 261
 262        mutex_lock(&rtlpriv->locks.conf_mutex);
 263
 264        /* Free beacon resources */
 265        if ((vif->type == NL80211_IFTYPE_AP) ||
 266            (vif->type == NL80211_IFTYPE_ADHOC) ||
 267            (vif->type == NL80211_IFTYPE_MESH_POINT)) {
 268                if (mac->beacon_enabled == 1) {
 269                        mac->beacon_enabled = 0;
 270                        rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
 271                                        rtlpriv->cfg->maps
 272                                        [RTL_IBSS_INT_MASKS]);
 273                }
 274        }
 275
 276        /*
 277         *Note: We assume NL80211_IFTYPE_UNSPECIFIED as
 278         *NO LINK for our hardware.
 279         */
 280        mac->p2p = 0;
 281        mac->vif = NULL;
 282        mac->link_state = MAC80211_NOLINK;
 283        memset(mac->bssid, 0, 6);
 284        mac->vendor = PEER_UNKNOWN;
 285        mac->opmode = NL80211_IFTYPE_UNSPECIFIED;
 286        rtlpriv->cfg->ops->set_network_type(hw, mac->opmode);
 287        mutex_unlock(&rtlpriv->locks.conf_mutex);
 288}
 289
 290static int rtl_op_change_interface(struct ieee80211_hw *hw,
 291                                      struct ieee80211_vif *vif,
 292                                      enum nl80211_iftype new_type, bool p2p)
 293{
 294        struct rtl_priv *rtlpriv = rtl_priv(hw);
 295        int ret;
 296        rtl_op_remove_interface(hw, vif);
 297
 298        vif->type = new_type;
 299        vif->p2p = p2p;
 300        ret = rtl_op_add_interface(hw, vif);
 301        RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 302                 "p2p %x\n", p2p);
 303        return ret;
 304}
 305
 306static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
 307{
 308        struct rtl_priv *rtlpriv = rtl_priv(hw);
 309        struct rtl_phy *rtlphy = &(rtlpriv->phy);
 310        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 311        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 312        struct ieee80211_conf *conf = &hw->conf;
 313
 314        if (mac->skip_scan)
 315                return 1;
 316
 317        mutex_lock(&rtlpriv->locks.conf_mutex);
 318        if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {  /*BIT(2)*/
 319                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 320                         "IEEE80211_CONF_CHANGE_LISTEN_INTERVAL\n");
 321        }
 322
 323        /*For IPS */
 324        if (changed & IEEE80211_CONF_CHANGE_IDLE) {
 325                if (hw->conf.flags & IEEE80211_CONF_IDLE)
 326                        rtl_ips_nic_off(hw);
 327                else
 328                        rtl_ips_nic_on(hw);
 329        } else {
 330                /*
 331                 *although rfoff may not cause by ips, but we will
 332                 *check the reason in set_rf_power_state function
 333                 */
 334                if (unlikely(ppsc->rfpwr_state == ERFOFF))
 335                        rtl_ips_nic_on(hw);
 336        }
 337
 338        /*For LPS */
 339        if (changed & IEEE80211_CONF_CHANGE_PS) {
 340                cancel_delayed_work(&rtlpriv->works.ps_work);
 341                cancel_delayed_work(&rtlpriv->works.ps_rfon_wq);
 342                if (conf->flags & IEEE80211_CONF_PS) {
 343                        rtlpriv->psc.sw_ps_enabled = true;
 344                        /* sleep here is must, or we may recv the beacon and
 345                         * cause mac80211 into wrong ps state, this will cause
 346                         * power save nullfunc send fail, and further cause
 347                         * pkt loss, So sleep must quickly but not immediatly
 348                         * because that will cause nullfunc send by mac80211
 349                         * fail, and cause pkt loss, we have tested that 5mA
 350                         * is worked very well */
 351                        if (!rtlpriv->psc.multi_buffered)
 352                                queue_delayed_work(rtlpriv->works.rtl_wq,
 353                                                &rtlpriv->works.ps_work,
 354                                                MSECS(5));
 355                } else {
 356                        rtl_swlps_rf_awake(hw);
 357                        rtlpriv->psc.sw_ps_enabled = false;
 358                }
 359        }
 360
 361        if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
 362                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 363                         "IEEE80211_CONF_CHANGE_RETRY_LIMITS %x\n",
 364                         hw->conf.long_frame_max_tx_count);
 365                mac->retry_long = hw->conf.long_frame_max_tx_count;
 366                mac->retry_short = hw->conf.long_frame_max_tx_count;
 367                rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT,
 368                                              (u8 *) (&hw->conf.
 369                                                      long_frame_max_tx_count));
 370        }
 371
 372        if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
 373                struct ieee80211_channel *channel = hw->conf.chandef.chan;
 374                u8 wide_chan = (u8) channel->hw_value;
 375
 376                if (mac->act_scanning)
 377                        mac->n_channels++;
 378
 379                if (rtlpriv->dm.supp_phymode_switch &&
 380                    mac->link_state < MAC80211_LINKED &&
 381                    !mac->act_scanning) {
 382                        if (rtlpriv->cfg->ops->chk_switch_dmdp)
 383                                rtlpriv->cfg->ops->chk_switch_dmdp(hw);
 384                }
 385
 386                /*
 387                 *because we should back channel to
 388                 *current_network.chan in in scanning,
 389                 *So if set_chan == current_network.chan
 390                 *we should set it.
 391                 *because mac80211 tell us wrong bw40
 392                 *info for cisco1253 bw20, so we modify
 393                 *it here based on UPPER & LOWER
 394                 */
 395                switch (cfg80211_get_chandef_type(&hw->conf.chandef)) {
 396                case NL80211_CHAN_HT20:
 397                case NL80211_CHAN_NO_HT:
 398                        /* SC */
 399                        mac->cur_40_prime_sc =
 400                                PRIME_CHNL_OFFSET_DONT_CARE;
 401                        rtlphy->current_chan_bw = HT_CHANNEL_WIDTH_20;
 402                        mac->bw_40 = false;
 403                        break;
 404                case NL80211_CHAN_HT40MINUS:
 405                        /* SC */
 406                        mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_UPPER;
 407                        rtlphy->current_chan_bw =
 408                                HT_CHANNEL_WIDTH_20_40;
 409                        mac->bw_40 = true;
 410
 411                        /*wide channel */
 412                        wide_chan -= 2;
 413
 414                        break;
 415                case NL80211_CHAN_HT40PLUS:
 416                        /* SC */
 417                        mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_LOWER;
 418                        rtlphy->current_chan_bw =
 419                                HT_CHANNEL_WIDTH_20_40;
 420                        mac->bw_40 = true;
 421
 422                        /*wide channel */
 423                        wide_chan += 2;
 424
 425                        break;
 426                default:
 427                        mac->bw_40 = false;
 428                        RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 429                                 "switch case not processed\n");
 430                        break;
 431                }
 432
 433                if (wide_chan <= 0)
 434                        wide_chan = 1;
 435
 436                /* In scanning, before we go offchannel we may send a ps = 1
 437                 * null to AP, and then we may send a ps = 0 null to AP quickly,
 438                 * but first null may have caused AP to put lots of packet to
 439                 * hw tx buffer. These packets must be tx'd before we go off
 440                 * channel so we must delay more time to let AP flush these
 441                 * packets before going offchannel, or dis-association or
 442                 * delete BA will be caused by AP
 443                 */
 444                if (rtlpriv->mac80211.offchan_delay) {
 445                        rtlpriv->mac80211.offchan_delay = false;
 446                        mdelay(50);
 447                }
 448                rtlphy->current_channel = wide_chan;
 449
 450                rtlpriv->cfg->ops->switch_channel(hw);
 451                rtlpriv->cfg->ops->set_channel_access(hw);
 452                rtlpriv->cfg->ops->set_bw_mode(hw,
 453                                cfg80211_get_chandef_type(&hw->conf.chandef));
 454        }
 455
 456        mutex_unlock(&rtlpriv->locks.conf_mutex);
 457
 458        return 0;
 459}
 460
 461static void rtl_op_configure_filter(struct ieee80211_hw *hw,
 462                             unsigned int changed_flags,
 463                             unsigned int *new_flags, u64 multicast)
 464{
 465        struct rtl_priv *rtlpriv = rtl_priv(hw);
 466        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 467
 468        *new_flags &= RTL_SUPPORTED_FILTERS;
 469        if (!changed_flags)
 470                return;
 471
 472        /*TODO: we disable broadcase now, so enable here */
 473        if (changed_flags & FIF_ALLMULTI) {
 474                if (*new_flags & FIF_ALLMULTI) {
 475                        mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AM] |
 476                            rtlpriv->cfg->maps[MAC_RCR_AB];
 477                        RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 478                                 "Enable receive multicast frame\n");
 479                } else {
 480                        mac->rx_conf &= ~(rtlpriv->cfg->maps[MAC_RCR_AM] |
 481                                          rtlpriv->cfg->maps[MAC_RCR_AB]);
 482                        RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 483                                 "Disable receive multicast frame\n");
 484                }
 485        }
 486
 487        if (changed_flags & FIF_FCSFAIL) {
 488                if (*new_flags & FIF_FCSFAIL) {
 489                        mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACRC32];
 490                        RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 491                                 "Enable receive FCS error frame\n");
 492                } else {
 493                        mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACRC32];
 494                        RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 495                                 "Disable receive FCS error frame\n");
 496                }
 497        }
 498
 499        /* if ssid not set to hw don't check bssid
 500         * here just used for linked scanning, & linked
 501         * and nolink check bssid is set in set network_type */
 502        if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) &&
 503                (mac->link_state >= MAC80211_LINKED)) {
 504                if (mac->opmode != NL80211_IFTYPE_AP &&
 505                    mac->opmode != NL80211_IFTYPE_MESH_POINT) {
 506                        if (*new_flags & FIF_BCN_PRBRESP_PROMISC) {
 507                                rtlpriv->cfg->ops->set_chk_bssid(hw, false);
 508                        } else {
 509                                rtlpriv->cfg->ops->set_chk_bssid(hw, true);
 510                        }
 511                }
 512        }
 513
 514        if (changed_flags & FIF_CONTROL) {
 515                if (*new_flags & FIF_CONTROL) {
 516                        mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACF];
 517
 518                        RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 519                                 "Enable receive control frame\n");
 520                } else {
 521                        mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACF];
 522                        RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 523                                 "Disable receive control frame\n");
 524                }
 525        }
 526
 527        if (changed_flags & FIF_OTHER_BSS) {
 528                if (*new_flags & FIF_OTHER_BSS) {
 529                        mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AAP];
 530                        RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 531                                 "Enable receive other BSS's frame\n");
 532                } else {
 533                        mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_AAP];
 534                        RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 535                                 "Disable receive other BSS's frame\n");
 536                }
 537        }
 538}
 539static int rtl_op_sta_add(struct ieee80211_hw *hw,
 540                         struct ieee80211_vif *vif,
 541                         struct ieee80211_sta *sta)
 542{
 543        struct rtl_priv *rtlpriv = rtl_priv(hw);
 544        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 545        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 546        struct rtl_sta_info *sta_entry;
 547
 548        if (sta) {
 549                sta_entry = (struct rtl_sta_info *) sta->drv_priv;
 550                spin_lock_bh(&rtlpriv->locks.entry_list_lock);
 551                list_add_tail(&sta_entry->list, &rtlpriv->entry_list);
 552                spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
 553                if (rtlhal->current_bandtype == BAND_ON_2_4G) {
 554                        sta_entry->wireless_mode = WIRELESS_MODE_G;
 555                        if (sta->supp_rates[0] <= 0xf)
 556                                sta_entry->wireless_mode = WIRELESS_MODE_B;
 557                        if (sta->ht_cap.ht_supported == true)
 558                                sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
 559
 560                        if (vif->type == NL80211_IFTYPE_ADHOC)
 561                                sta_entry->wireless_mode = WIRELESS_MODE_G;
 562                } else if (rtlhal->current_bandtype == BAND_ON_5G) {
 563                        sta_entry->wireless_mode = WIRELESS_MODE_A;
 564                        if (sta->ht_cap.ht_supported == true)
 565                                sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
 566
 567                        if (vif->type == NL80211_IFTYPE_ADHOC)
 568                                sta_entry->wireless_mode = WIRELESS_MODE_A;
 569                }
 570                /*disable cck rate for p2p*/
 571                if (mac->p2p)
 572                        sta->supp_rates[0] &= 0xfffffff0;
 573
 574                memcpy(sta_entry->mac_addr, sta->addr, ETH_ALEN);
 575                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
 576                         "Add sta addr is %pM\n", sta->addr);
 577                rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);
 578        }
 579        return 0;
 580}
 581
 582static int rtl_op_sta_remove(struct ieee80211_hw *hw,
 583                                struct ieee80211_vif *vif,
 584                                struct ieee80211_sta *sta)
 585{
 586        struct rtl_priv *rtlpriv = rtl_priv(hw);
 587        struct rtl_sta_info *sta_entry;
 588        if (sta) {
 589                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
 590                         "Remove sta addr is %pM\n", sta->addr);
 591                sta_entry = (struct rtl_sta_info *) sta->drv_priv;
 592                sta_entry->wireless_mode = 0;
 593                sta_entry->ratr_index = 0;
 594
 595                spin_lock_bh(&rtlpriv->locks.entry_list_lock);
 596                list_del(&sta_entry->list);
 597                spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
 598        }
 599        return 0;
 600}
 601
 602static int _rtl_get_hal_qnum(u16 queue)
 603{
 604        int qnum;
 605
 606        switch (queue) {
 607        case 0:
 608                qnum = AC3_VO;
 609                break;
 610        case 1:
 611                qnum = AC2_VI;
 612                break;
 613        case 2:
 614                qnum = AC0_BE;
 615                break;
 616        case 3:
 617                qnum = AC1_BK;
 618                break;
 619        default:
 620                qnum = AC0_BE;
 621                break;
 622        }
 623        return qnum;
 624}
 625
 626/*
 627 *for mac80211 VO = 0, VI = 1, BE = 2, BK = 3
 628 *for rtl819x  BE = 0, BK = 1, VI = 2, VO = 3
 629 */
 630static int rtl_op_conf_tx(struct ieee80211_hw *hw,
 631                   struct ieee80211_vif *vif, u16 queue,
 632                   const struct ieee80211_tx_queue_params *param)
 633{
 634        struct rtl_priv *rtlpriv = rtl_priv(hw);
 635        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 636        int aci;
 637
 638        if (queue >= AC_MAX) {
 639                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 640                         "queue number %d is incorrect!\n", queue);
 641                return -EINVAL;
 642        }
 643
 644        aci = _rtl_get_hal_qnum(queue);
 645        mac->ac[aci].aifs = param->aifs;
 646        mac->ac[aci].cw_min = cpu_to_le16(param->cw_min);
 647        mac->ac[aci].cw_max = cpu_to_le16(param->cw_max);
 648        mac->ac[aci].tx_op = cpu_to_le16(param->txop);
 649        memcpy(&mac->edca_param[aci], param, sizeof(*param));
 650        rtlpriv->cfg->ops->set_qos(hw, aci);
 651        return 0;
 652}
 653
 654static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 655                             struct ieee80211_vif *vif,
 656                             struct ieee80211_bss_conf *bss_conf, u32 changed)
 657{
 658        struct rtl_priv *rtlpriv = rtl_priv(hw);
 659        struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
 660        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 661        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 662        struct ieee80211_sta *sta = NULL;
 663
 664        mutex_lock(&rtlpriv->locks.conf_mutex);
 665        if ((vif->type == NL80211_IFTYPE_ADHOC) ||
 666            (vif->type == NL80211_IFTYPE_AP) ||
 667            (vif->type == NL80211_IFTYPE_MESH_POINT)) {
 668                if ((changed & BSS_CHANGED_BEACON) ||
 669                    (changed & BSS_CHANGED_BEACON_ENABLED &&
 670                     bss_conf->enable_beacon)) {
 671                        if (mac->beacon_enabled == 0) {
 672                                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
 673                                         "BSS_CHANGED_BEACON_ENABLED\n");
 674
 675                                /*start hw beacon interrupt. */
 676                                /*rtlpriv->cfg->ops->set_bcn_reg(hw); */
 677                                mac->beacon_enabled = 1;
 678                                rtlpriv->cfg->ops->update_interrupt_mask(hw,
 679                                                rtlpriv->cfg->maps
 680                                                [RTL_IBSS_INT_MASKS],
 681                                                0);
 682
 683                                if (rtlpriv->cfg->ops->linked_set_reg)
 684                                        rtlpriv->cfg->ops->linked_set_reg(hw);
 685                        }
 686                }
 687                if ((changed & BSS_CHANGED_BEACON_ENABLED &&
 688                        !bss_conf->enable_beacon)) {
 689                        if (mac->beacon_enabled == 1) {
 690                                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
 691                                         "ADHOC DISABLE BEACON\n");
 692
 693                                mac->beacon_enabled = 0;
 694                                rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
 695                                                rtlpriv->cfg->maps
 696                                                [RTL_IBSS_INT_MASKS]);
 697                        }
 698                }
 699                if (changed & BSS_CHANGED_BEACON_INT) {
 700                        RT_TRACE(rtlpriv, COMP_BEACON, DBG_TRACE,
 701                                 "BSS_CHANGED_BEACON_INT\n");
 702                        mac->beacon_interval = bss_conf->beacon_int;
 703                        rtlpriv->cfg->ops->set_bcn_intv(hw);
 704                }
 705        }
 706
 707        /*TODO: reference to enum ieee80211_bss_change */
 708        if (changed & BSS_CHANGED_ASSOC) {
 709                if (bss_conf->assoc) {
 710                        struct ieee80211_sta *sta = NULL;
 711                        /* we should reset all sec info & cam
 712                         * before set cam after linked, we should not
 713                         * reset in disassoc, that will cause tkip->wep
 714                         * fail because some flag will be wrong */
 715                        /* reset sec info */
 716                        rtl_cam_reset_sec_info(hw);
 717                        /* reset cam to fix wep fail issue
 718                         * when change from wpa to wep */
 719                        rtl_cam_reset_all_entry(hw);
 720
 721                        mac->link_state = MAC80211_LINKED;
 722                        mac->cnt_after_linked = 0;
 723                        mac->assoc_id = bss_conf->aid;
 724                        memcpy(mac->bssid, bss_conf->bssid, 6);
 725
 726                        if (rtlpriv->cfg->ops->linked_set_reg)
 727                                rtlpriv->cfg->ops->linked_set_reg(hw);
 728                        rcu_read_lock();
 729                        sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid);
 730
 731                        if (vif->type == NL80211_IFTYPE_STATION && sta)
 732                                rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);
 733                        RT_TRACE(rtlpriv, COMP_EASY_CONCURRENT, DBG_LOUD,
 734                                 "send PS STATIC frame\n");
 735                        if (rtlpriv->dm.supp_phymode_switch) {
 736                                if (sta->ht_cap.ht_supported)
 737                                        rtl_send_smps_action(hw, sta,
 738                                                 IEEE80211_SMPS_STATIC);
 739                        }
 740                        rcu_read_unlock();
 741
 742                        RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
 743                                 "BSS_CHANGED_ASSOC\n");
 744                } else {
 745                        if (mac->link_state == MAC80211_LINKED) {
 746                                rtlpriv->enter_ps = false;
 747                                schedule_work(&rtlpriv->works.lps_change_work);
 748                        }
 749
 750                        if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE)
 751                                rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
 752                        mac->link_state = MAC80211_NOLINK;
 753                        memset(mac->bssid, 0, 6);
 754                        mac->vendor = PEER_UNKNOWN;
 755
 756                        if (rtlpriv->dm.supp_phymode_switch) {
 757                                if (rtlpriv->cfg->ops->chk_switch_dmdp)
 758                                        rtlpriv->cfg->ops->chk_switch_dmdp(hw);
 759                        }
 760
 761                        RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
 762                                 "BSS_CHANGED_UN_ASSOC\n");
 763                }
 764        }
 765
 766        if (changed & BSS_CHANGED_ERP_CTS_PROT) {
 767                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 768                         "BSS_CHANGED_ERP_CTS_PROT\n");
 769                mac->use_cts_protect = bss_conf->use_cts_prot;
 770        }
 771
 772        if (changed & BSS_CHANGED_ERP_PREAMBLE) {
 773                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
 774                         "BSS_CHANGED_ERP_PREAMBLE use short preamble:%x\n",
 775                         bss_conf->use_short_preamble);
 776
 777                mac->short_preamble = bss_conf->use_short_preamble;
 778                rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACK_PREAMBLE,
 779                                              &mac->short_preamble);
 780        }
 781
 782        if (changed & BSS_CHANGED_ERP_SLOT) {
 783                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 784                         "BSS_CHANGED_ERP_SLOT\n");
 785
 786                if (bss_conf->use_short_slot)
 787                        mac->slot_time = RTL_SLOT_TIME_9;
 788                else
 789                        mac->slot_time = RTL_SLOT_TIME_20;
 790
 791                rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME,
 792                                              &mac->slot_time);
 793        }
 794
 795        if (changed & BSS_CHANGED_HT) {
 796                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, "BSS_CHANGED_HT\n");
 797                rcu_read_lock();
 798                sta = get_sta(hw, vif, bss_conf->bssid);
 799                if (sta) {
 800                        if (sta->ht_cap.ampdu_density >
 801                            mac->current_ampdu_density)
 802                                mac->current_ampdu_density =
 803                                    sta->ht_cap.ampdu_density;
 804                        if (sta->ht_cap.ampdu_factor <
 805                            mac->current_ampdu_factor)
 806                                mac->current_ampdu_factor =
 807                                    sta->ht_cap.ampdu_factor;
 808                }
 809                rcu_read_unlock();
 810
 811                rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SHORTGI_DENSITY,
 812                                              &mac->max_mss_density);
 813                rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_FACTOR,
 814                                              &mac->current_ampdu_factor);
 815                rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_MIN_SPACE,
 816                                              &mac->current_ampdu_density);
 817        }
 818
 819        if (changed & BSS_CHANGED_BSSID) {
 820                u32 basic_rates;
 821
 822                rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BSSID,
 823                                              (u8 *) bss_conf->bssid);
 824
 825                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, "%pM\n",
 826                         bss_conf->bssid);
 827
 828                mac->vendor = PEER_UNKNOWN;
 829                memcpy(mac->bssid, bss_conf->bssid, 6);
 830                rtlpriv->cfg->ops->set_network_type(hw, vif->type);
 831
 832                rcu_read_lock();
 833                sta = get_sta(hw, vif, bss_conf->bssid);
 834                if (!sta) {
 835                        rcu_read_unlock();
 836                        goto out;
 837                }
 838
 839                if (rtlhal->current_bandtype == BAND_ON_5G) {
 840                        mac->mode = WIRELESS_MODE_A;
 841                } else {
 842                        if (sta->supp_rates[0] <= 0xf)
 843                                mac->mode = WIRELESS_MODE_B;
 844                        else
 845                                mac->mode = WIRELESS_MODE_G;
 846                }
 847
 848                if (sta->ht_cap.ht_supported) {
 849                        if (rtlhal->current_bandtype == BAND_ON_2_4G)
 850                                mac->mode = WIRELESS_MODE_N_24G;
 851                        else
 852                                mac->mode = WIRELESS_MODE_N_5G;
 853                }
 854
 855                /* just station need it, because ibss & ap mode will
 856                 * set in sta_add, and will be NULL here */
 857                if (mac->opmode == NL80211_IFTYPE_STATION) {
 858                        struct rtl_sta_info *sta_entry;
 859                        sta_entry = (struct rtl_sta_info *) sta->drv_priv;
 860                        sta_entry->wireless_mode = mac->mode;
 861                }
 862
 863                if (sta->ht_cap.ht_supported) {
 864                        mac->ht_enable = true;
 865
 866                        /*
 867                         * for cisco 1252 bw20 it's wrong
 868                         * if (ht_cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
 869                         *      mac->bw_40 = true;
 870                         * }
 871                         * */
 872                }
 873
 874                if (changed & BSS_CHANGED_BASIC_RATES) {
 875                        /* for 5G must << RATE_6M_INDEX = 4,
 876                         * because 5G have no cck rate*/
 877                        if (rtlhal->current_bandtype == BAND_ON_5G)
 878                                basic_rates = sta->supp_rates[1] << 4;
 879                        else
 880                                basic_rates = sta->supp_rates[0];
 881
 882                        mac->basic_rates = basic_rates;
 883                        rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
 884                                        (u8 *) (&basic_rates));
 885                }
 886                rcu_read_unlock();
 887        }
 888
 889        /*
 890         * For FW LPS:
 891         * To tell firmware we have connected
 892         * to an AP. For 92SE/CE power save v2.
 893         */
 894        if (changed & BSS_CHANGED_ASSOC) {
 895                if (bss_conf->assoc) {
 896                        if (ppsc->fwctrl_lps) {
 897                                u8 mstatus = RT_MEDIA_CONNECT;
 898                                rtlpriv->cfg->ops->set_hw_reg(hw,
 899                                                      HW_VAR_H2C_FW_JOINBSSRPT,
 900                                                      &mstatus);
 901                                ppsc->report_linked = true;
 902                        }
 903                } else {
 904                        if (ppsc->fwctrl_lps) {
 905                                u8 mstatus = RT_MEDIA_DISCONNECT;
 906                                rtlpriv->cfg->ops->set_hw_reg(hw,
 907                                                      HW_VAR_H2C_FW_JOINBSSRPT,
 908                                                      &mstatus);
 909                                ppsc->report_linked = false;
 910                        }
 911                }
 912                if (rtlpriv->cfg->ops->bt_wifi_media_status_notify)
 913                        rtlpriv->cfg->ops->bt_wifi_media_status_notify(hw,
 914                                                         ppsc->report_linked);
 915        }
 916
 917out:
 918        mutex_unlock(&rtlpriv->locks.conf_mutex);
 919}
 920
 921static u64 rtl_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 922{
 923        struct rtl_priv *rtlpriv = rtl_priv(hw);
 924        u64 tsf;
 925
 926        rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&tsf));
 927        return tsf;
 928}
 929
 930static void rtl_op_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 931                           u64 tsf)
 932{
 933        struct rtl_priv *rtlpriv = rtl_priv(hw);
 934        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 935        u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0;
 936
 937        mac->tsf = tsf;
 938        rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CORRECT_TSF, &bibss);
 939}
 940
 941static void rtl_op_reset_tsf(struct ieee80211_hw *hw,
 942                             struct ieee80211_vif *vif)
 943{
 944        struct rtl_priv *rtlpriv = rtl_priv(hw);
 945        u8 tmp = 0;
 946
 947        rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_DUAL_TSF_RST, &tmp);
 948}
 949
 950static void rtl_op_sta_notify(struct ieee80211_hw *hw,
 951                              struct ieee80211_vif *vif,
 952                              enum sta_notify_cmd cmd,
 953                              struct ieee80211_sta *sta)
 954{
 955        switch (cmd) {
 956        case STA_NOTIFY_SLEEP:
 957                break;
 958        case STA_NOTIFY_AWAKE:
 959                break;
 960        default:
 961                break;
 962        }
 963}
 964
 965static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
 966                               struct ieee80211_vif *vif,
 967                               enum ieee80211_ampdu_mlme_action action,
 968                               struct ieee80211_sta *sta, u16 tid, u16 *ssn,
 969                               u8 buf_size)
 970{
 971        struct rtl_priv *rtlpriv = rtl_priv(hw);
 972
 973        switch (action) {
 974        case IEEE80211_AMPDU_TX_START:
 975                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 976                         "IEEE80211_AMPDU_TX_START: TID:%d\n", tid);
 977                return rtl_tx_agg_start(hw, sta, tid, ssn);
 978                break;
 979        case IEEE80211_AMPDU_TX_STOP_CONT:
 980        case IEEE80211_AMPDU_TX_STOP_FLUSH:
 981        case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
 982                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 983                         "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid);
 984                return rtl_tx_agg_stop(hw, sta, tid);
 985        case IEEE80211_AMPDU_TX_OPERATIONAL:
 986                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 987                         "IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid);
 988                rtl_tx_agg_oper(hw, sta, tid);
 989                break;
 990        case IEEE80211_AMPDU_RX_START:
 991                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 992                         "IEEE80211_AMPDU_RX_START:TID:%d\n", tid);
 993                return rtl_rx_agg_start(hw, sta, tid);
 994        case IEEE80211_AMPDU_RX_STOP:
 995                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 996                         "IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid);
 997                return rtl_rx_agg_stop(hw, sta, tid);
 998        default:
 999                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
1000                         "IEEE80211_AMPDU_ERR!!!!:\n");
1001                return -EOPNOTSUPP;
1002        }
1003        return 0;
1004}
1005
1006static void rtl_op_sw_scan_start(struct ieee80211_hw *hw)
1007{
1008        struct rtl_priv *rtlpriv = rtl_priv(hw);
1009        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1010
1011        RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n");
1012        mac->act_scanning = true;
1013        if (rtlpriv->link_info.higher_busytraffic) {
1014                mac->skip_scan = true;
1015                return;
1016        }
1017
1018        if (rtlpriv->dm.supp_phymode_switch) {
1019                if (rtlpriv->cfg->ops->chk_switch_dmdp)
1020                        rtlpriv->cfg->ops->chk_switch_dmdp(hw);
1021        }
1022        if (mac->link_state == MAC80211_LINKED) {
1023                rtlpriv->enter_ps = false;
1024                schedule_work(&rtlpriv->works.lps_change_work);
1025                mac->link_state = MAC80211_LINKED_SCANNING;
1026        } else {
1027                rtl_ips_nic_on(hw);
1028        }
1029
1030        /* Dual mac */
1031        rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false;
1032
1033        rtlpriv->cfg->ops->led_control(hw, LED_CTL_SITE_SURVEY);
1034        rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP);
1035}
1036
1037static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw)
1038{
1039        struct rtl_priv *rtlpriv = rtl_priv(hw);
1040        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1041
1042        RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n");
1043        mac->act_scanning = false;
1044        mac->skip_scan = false;
1045        if (rtlpriv->link_info.higher_busytraffic)
1046                return;
1047
1048        /*p2p will use 1/6/11 to scan */
1049        if (mac->n_channels == 3)
1050                mac->p2p_in_use = true;
1051        else
1052                mac->p2p_in_use = false;
1053        mac->n_channels = 0;
1054        /* Dual mac */
1055        rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false;
1056
1057        if (mac->link_state == MAC80211_LINKED_SCANNING) {
1058                mac->link_state = MAC80211_LINKED;
1059                if (mac->opmode == NL80211_IFTYPE_STATION) {
1060                        /* fix fwlps issue */
1061                        rtlpriv->cfg->ops->set_network_type(hw, mac->opmode);
1062                }
1063        }
1064
1065        rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE);
1066}
1067
1068static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
1069                          struct ieee80211_vif *vif, struct ieee80211_sta *sta,
1070                          struct ieee80211_key_conf *key)
1071{
1072        struct rtl_priv *rtlpriv = rtl_priv(hw);
1073        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1074        u8 key_type = NO_ENCRYPTION;
1075        u8 key_idx;
1076        bool group_key = false;
1077        bool wep_only = false;
1078        int err = 0;
1079        u8 mac_addr[ETH_ALEN];
1080        u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1081
1082        if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
1083                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
1084                         "not open hw encryption\n");
1085                return -ENOSPC; /*User disabled HW-crypto */
1086        }
1087        /* To support IBSS, use sw-crypto for GTK */
1088        if (((vif->type == NL80211_IFTYPE_ADHOC) ||
1089             (vif->type == NL80211_IFTYPE_MESH_POINT)) &&
1090              !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
1091                return -ENOSPC;
1092        RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
1093                 "%s hardware based encryption for keyidx: %d, mac: %pM\n",
1094                 cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
1095                 sta ? sta->addr : bcast_addr);
1096        rtlpriv->sec.being_setkey = true;
1097        rtl_ips_nic_on(hw);
1098        mutex_lock(&rtlpriv->locks.conf_mutex);
1099        /* <1> get encryption alg */
1100
1101        switch (key->cipher) {
1102        case WLAN_CIPHER_SUITE_WEP40:
1103                key_type = WEP40_ENCRYPTION;
1104                RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:WEP40\n");
1105                break;
1106        case WLAN_CIPHER_SUITE_WEP104:
1107                RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:WEP104\n");
1108                key_type = WEP104_ENCRYPTION;
1109                break;
1110        case WLAN_CIPHER_SUITE_TKIP:
1111                key_type = TKIP_ENCRYPTION;
1112                RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:TKIP\n");
1113                break;
1114        case WLAN_CIPHER_SUITE_CCMP:
1115                key_type = AESCCMP_ENCRYPTION;
1116                RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n");
1117                break;
1118        case WLAN_CIPHER_SUITE_AES_CMAC:
1119                /*HW doesn't support CMAC encryption, use software CMAC */
1120                key_type = AESCMAC_ENCRYPTION;
1121                RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CMAC\n");
1122                RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
1123                         "HW don't support CMAC encryption, use software CMAC\n");
1124                err = -EOPNOTSUPP;
1125                goto out_unlock;
1126        default:
1127                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "alg_err:%x!!!!\n",
1128                         key->cipher);
1129                goto out_unlock;
1130        }
1131        if (key_type == WEP40_ENCRYPTION ||
1132                        key_type == WEP104_ENCRYPTION ||
1133                        mac->opmode == NL80211_IFTYPE_ADHOC)
1134                rtlpriv->sec.use_defaultkey = true;
1135
1136        /* <2> get key_idx */
1137        key_idx = (u8) (key->keyidx);
1138        if (key_idx > 3)
1139                goto out_unlock;
1140        /* <3> if pairwise key enable_hw_sec */
1141        group_key = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE);
1142
1143        /* wep always be group key, but there are two conditions:
1144         * 1) wep only: is just for wep enc, in this condition
1145         * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION
1146         * will be true & enable_hw_sec will be set when wep
1147         * key setting.
1148         * 2) wep(group) + AES(pairwise): some AP like cisco
1149         * may use it, in this condition enable_hw_sec will not
1150         * be set when wep key setting */
1151        /* we must reset sec_info after lingked before set key,
1152         * or some flag will be wrong*/
1153        if (vif->type == NL80211_IFTYPE_AP ||
1154            vif->type == NL80211_IFTYPE_MESH_POINT) {
1155                if (!group_key || key_type == WEP40_ENCRYPTION ||
1156                        key_type == WEP104_ENCRYPTION) {
1157                        if (group_key)
1158                                wep_only = true;
1159                        rtlpriv->cfg->ops->enable_hw_sec(hw);
1160                }
1161        } else {
1162                if ((!group_key) || (mac->opmode == NL80211_IFTYPE_ADHOC) ||
1163                     rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) {
1164                        if (rtlpriv->sec.pairwise_enc_algorithm ==
1165                            NO_ENCRYPTION &&
1166                            (key_type == WEP40_ENCRYPTION ||
1167                            key_type == WEP104_ENCRYPTION))
1168                                wep_only = true;
1169                        rtlpriv->sec.pairwise_enc_algorithm = key_type;
1170                        RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
1171                                 "set enable_hw_sec, key_type:%x(OPEN:0 WEP40:1 TKIP:2 AES:4 WEP104:5)\n",
1172                                 key_type);
1173                        rtlpriv->cfg->ops->enable_hw_sec(hw);
1174                }
1175        }
1176        /* <4> set key based on cmd */
1177        switch (cmd) {
1178        case SET_KEY:
1179                if (wep_only) {
1180                        RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
1181                                 "set WEP(group/pairwise) key\n");
1182                        /* Pairwise key with an assigned MAC address. */
1183                        rtlpriv->sec.pairwise_enc_algorithm = key_type;
1184                        rtlpriv->sec.group_enc_algorithm = key_type;
1185                        /*set local buf about wep key. */
1186                        memcpy(rtlpriv->sec.key_buf[key_idx],
1187                               key->key, key->keylen);
1188                        rtlpriv->sec.key_len[key_idx] = key->keylen;
1189                        eth_zero_addr(mac_addr);
1190                } else if (group_key) { /* group key */
1191                        RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
1192                                 "set group key\n");
1193                        /* group key */
1194                        rtlpriv->sec.group_enc_algorithm = key_type;
1195                        /*set local buf about group key. */
1196                        memcpy(rtlpriv->sec.key_buf[key_idx],
1197                               key->key, key->keylen);
1198                        rtlpriv->sec.key_len[key_idx] = key->keylen;
1199                        memcpy(mac_addr, bcast_addr, ETH_ALEN);
1200                } else {        /* pairwise key */
1201                        RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
1202                                 "set pairwise key\n");
1203                        if (!sta) {
1204                                RT_ASSERT(false,
1205                                          "pairwise key without mac_addr\n");
1206
1207                                err = -EOPNOTSUPP;
1208                                goto out_unlock;
1209                        }
1210                        /* Pairwise key with an assigned MAC address. */
1211                        rtlpriv->sec.pairwise_enc_algorithm = key_type;
1212                        /*set local buf about pairwise key. */
1213                        memcpy(rtlpriv->sec.key_buf[PAIRWISE_KEYIDX],
1214                               key->key, key->keylen);
1215                        rtlpriv->sec.key_len[PAIRWISE_KEYIDX] = key->keylen;
1216                        rtlpriv->sec.pairwise_key =
1217                            rtlpriv->sec.key_buf[PAIRWISE_KEYIDX];
1218                        memcpy(mac_addr, sta->addr, ETH_ALEN);
1219                }
1220                rtlpriv->cfg->ops->set_key(hw, key_idx, mac_addr,
1221                                           group_key, key_type, wep_only,
1222                                           false);
1223                /* <5> tell mac80211 do something: */
1224                /*must use sw generate IV, or can not work !!!!. */
1225                key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
1226                key->hw_key_idx = key_idx;
1227                if (key_type == TKIP_ENCRYPTION)
1228                        key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
1229                /*use software CCMP encryption for management frames (MFP) */
1230                if (key_type == AESCCMP_ENCRYPTION)
1231                        key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
1232                break;
1233        case DISABLE_KEY:
1234                RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
1235                         "disable key delete one entry\n");
1236                /*set local buf about wep key. */
1237                if (vif->type == NL80211_IFTYPE_AP ||
1238                    vif->type == NL80211_IFTYPE_MESH_POINT) {
1239                        if (sta)
1240                                rtl_cam_del_entry(hw, sta->addr);
1241                }
1242                memset(rtlpriv->sec.key_buf[key_idx], 0, key->keylen);
1243                rtlpriv->sec.key_len[key_idx] = 0;
1244                eth_zero_addr(mac_addr);
1245                /*
1246                 *mac80211 will delete entrys one by one,
1247                 *so don't use rtl_cam_reset_all_entry
1248                 *or clear all entry here.
1249                 */
1250                rtl_cam_delete_one_entry(hw, mac_addr, key_idx);
1251
1252                rtl_cam_reset_sec_info(hw);
1253
1254                break;
1255        default:
1256                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
1257                         "cmd_err:%x!!!!\n", cmd);
1258        }
1259out_unlock:
1260        mutex_unlock(&rtlpriv->locks.conf_mutex);
1261        rtlpriv->sec.being_setkey = false;
1262        return err;
1263}
1264
1265static void rtl_op_rfkill_poll(struct ieee80211_hw *hw)
1266{
1267        struct rtl_priv *rtlpriv = rtl_priv(hw);
1268
1269        bool radio_state;
1270        bool blocked;
1271        u8 valid = 0;
1272
1273        if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status))
1274                return;
1275
1276        mutex_lock(&rtlpriv->locks.conf_mutex);
1277
1278        /*if Radio On return true here */
1279        radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid);
1280
1281        if (valid) {
1282                if (unlikely(radio_state != rtlpriv->rfkill.rfkill_state)) {
1283                        rtlpriv->rfkill.rfkill_state = radio_state;
1284
1285                        RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
1286                                 "wireless radio switch turned %s\n",
1287                                 radio_state ? "on" : "off");
1288
1289                        blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1;
1290                        wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
1291                }
1292        }
1293
1294        mutex_unlock(&rtlpriv->locks.conf_mutex);
1295}
1296
1297/* this function is called by mac80211 to flush tx buffer
1298 * before switch channel or power save, or tx buffer packet
1299 * maybe send after offchannel or rf sleep, this may cause
1300 * dis-association by AP */
1301static void rtl_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
1302{
1303        struct rtl_priv *rtlpriv = rtl_priv(hw);
1304
1305        if (rtlpriv->intf_ops->flush)
1306                rtlpriv->intf_ops->flush(hw, drop);
1307}
1308
1309const struct ieee80211_ops rtl_ops = {
1310        .start = rtl_op_start,
1311        .stop = rtl_op_stop,
1312        .tx = rtl_op_tx,
1313        .add_interface = rtl_op_add_interface,
1314        .remove_interface = rtl_op_remove_interface,
1315        .change_interface = rtl_op_change_interface,
1316        .config = rtl_op_config,
1317        .configure_filter = rtl_op_configure_filter,
1318        .sta_add = rtl_op_sta_add,
1319        .sta_remove = rtl_op_sta_remove,
1320        .set_key = rtl_op_set_key,
1321        .conf_tx = rtl_op_conf_tx,
1322        .bss_info_changed = rtl_op_bss_info_changed,
1323        .get_tsf = rtl_op_get_tsf,
1324        .set_tsf = rtl_op_set_tsf,
1325        .reset_tsf = rtl_op_reset_tsf,
1326        .sta_notify = rtl_op_sta_notify,
1327        .ampdu_action = rtl_op_ampdu_action,
1328        .sw_scan_start = rtl_op_sw_scan_start,
1329        .sw_scan_complete = rtl_op_sw_scan_complete,
1330        .rfkill_poll = rtl_op_rfkill_poll,
1331        .flush = rtl_op_flush,
1332};
1333EXPORT_SYMBOL_GPL(rtl_ops);
1334