linux/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2009-2012  Realtek Corporation. All rights reserved.
   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 "../pci.h"
  32#include "../usb.h"
  33#include "../ps.h"
  34#include "../cam.h"
  35#include "reg.h"
  36#include "def.h"
  37#include "phy.h"
  38#include "rf.h"
  39#include "dm.h"
  40#include "mac.h"
  41#include "trx.h"
  42
  43#include <linux/module.h>
  44
  45/* macro to shorten lines */
  46
  47#define LINK_Q  ui_link_quality
  48#define RX_EVM  rx_evm_percentage
  49#define RX_SIGQ rx_mimo_signalquality
  50
  51
  52void rtl92c_read_chip_version(struct ieee80211_hw *hw)
  53{
  54        struct rtl_priv *rtlpriv = rtl_priv(hw);
  55        struct rtl_phy *rtlphy = &(rtlpriv->phy);
  56        struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
  57        enum version_8192c chip_version = VERSION_UNKNOWN;
  58        const char *versionid;
  59        u32 value32;
  60
  61        value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG);
  62        if (value32 & TRP_VAUX_EN) {
  63                chip_version = (value32 & TYPE_ID) ? VERSION_TEST_CHIP_92C :
  64                               VERSION_TEST_CHIP_88C;
  65        } else {
  66                /* Normal mass production chip. */
  67                chip_version = NORMAL_CHIP;
  68                chip_version |= ((value32 & TYPE_ID) ? CHIP_92C : 0);
  69                chip_version |= ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0);
  70                /* RTL8723 with BT function. */
  71                chip_version |= ((value32 & BT_FUNC) ? CHIP_8723 : 0);
  72                if (IS_VENDOR_UMC(chip_version))
  73                        chip_version |= ((value32 & CHIP_VER_RTL_MASK) ?
  74                                         CHIP_VENDOR_UMC_B_CUT : 0);
  75                if (IS_92C_SERIAL(chip_version)) {
  76                        value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM);
  77                        chip_version |= ((CHIP_BONDING_IDENTIFIER(value32) ==
  78                                 CHIP_BONDING_92C_1T2R) ? CHIP_92C_1T2R : 0);
  79                } else if (IS_8723_SERIES(chip_version)) {
  80                        value32 = rtl_read_dword(rtlpriv, REG_GPIO_OUTSTS);
  81                        chip_version |= ((value32 & RF_RL_ID) ?
  82                                          CHIP_8723_DRV_REV : 0);
  83                }
  84        }
  85        rtlhal->version  = (enum version_8192c)chip_version;
  86        pr_info("Chip version 0x%x\n", chip_version);
  87        switch (rtlhal->version) {
  88        case VERSION_NORMAL_TSMC_CHIP_92C_1T2R:
  89                versionid = "NORMAL_B_CHIP_92C";
  90                break;
  91        case VERSION_NORMAL_TSMC_CHIP_92C:
  92                versionid = "NORMAL_TSMC_CHIP_92C";
  93                break;
  94        case VERSION_NORMAL_TSMC_CHIP_88C:
  95                versionid = "NORMAL_TSMC_CHIP_88C";
  96                break;
  97        case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT:
  98                versionid = "NORMAL_UMC_CHIP_i92C_1T2R_A_CUT";
  99                break;
 100        case VERSION_NORMAL_UMC_CHIP_92C_A_CUT:
 101                versionid = "NORMAL_UMC_CHIP_92C_A_CUT";
 102                break;
 103        case VERSION_NORMAL_UMC_CHIP_88C_A_CUT:
 104                versionid = "NORMAL_UMC_CHIP_88C_A_CUT";
 105                break;
 106        case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT:
 107                versionid = "NORMAL_UMC_CHIP_92C_1T2R_B_CUT";
 108                break;
 109        case VERSION_NORMAL_UMC_CHIP_92C_B_CUT:
 110                versionid = "NORMAL_UMC_CHIP_92C_B_CUT";
 111                break;
 112        case VERSION_NORMAL_UMC_CHIP_88C_B_CUT:
 113                versionid = "NORMAL_UMC_CHIP_88C_B_CUT";
 114                break;
 115        case VERSION_NORMA_UMC_CHIP_8723_1T1R_A_CUT:
 116                versionid = "NORMAL_UMC_CHIP_8723_1T1R_A_CUT";
 117                break;
 118        case VERSION_NORMA_UMC_CHIP_8723_1T1R_B_CUT:
 119                versionid = "NORMAL_UMC_CHIP_8723_1T1R_B_CUT";
 120                break;
 121        case VERSION_TEST_CHIP_92C:
 122                versionid = "TEST_CHIP_92C";
 123                break;
 124        case VERSION_TEST_CHIP_88C:
 125                versionid = "TEST_CHIP_88C";
 126                break;
 127        default:
 128                versionid = "UNKNOWN";
 129                break;
 130        }
 131        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 132                 "Chip Version ID: %s\n", versionid);
 133
 134        if (IS_92C_SERIAL(rtlhal->version))
 135                rtlphy->rf_type =
 136                         (IS_92C_1T2R(rtlhal->version)) ? RF_1T2R : RF_2T2R;
 137        else
 138                rtlphy->rf_type = RF_1T1R;
 139        RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
 140                 "Chip RF Type: %s\n",
 141                 rtlphy->rf_type == RF_2T2R ? "RF_2T2R" : "RF_1T1R");
 142        if (get_rf_type(rtlphy) == RF_1T1R)
 143                rtlpriv->dm.rfpath_rxenable[0] = true;
 144        else
 145                rtlpriv->dm.rfpath_rxenable[0] =
 146                    rtlpriv->dm.rfpath_rxenable[1] = true;
 147        RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n",
 148                 rtlhal->version);
 149}
 150
 151/**
 152 * writeLLT - LLT table write access
 153 * @io: io callback
 154 * @address: LLT logical address.
 155 * @data: LLT data content
 156 *
 157 * Realtek hardware access function.
 158 *
 159 */
 160bool rtl92c_llt_write(struct ieee80211_hw *hw, u32 address, u32 data)
 161{
 162        struct rtl_priv *rtlpriv = rtl_priv(hw);
 163        bool status = true;
 164        long count = 0;
 165        u32 value = _LLT_INIT_ADDR(address) |
 166            _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS);
 167
 168        rtl_write_dword(rtlpriv, REG_LLT_INIT, value);
 169        do {
 170                value = rtl_read_dword(rtlpriv, REG_LLT_INIT);
 171                if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value))
 172                        break;
 173                if (count > POLLING_LLT_THRESHOLD) {
 174                        RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 175                                 "Failed to polling write LLT done at address %d! _LLT_OP_VALUE(%x)\n",
 176                                 address, _LLT_OP_VALUE(value));
 177                        status = false;
 178                        break;
 179                }
 180        } while (++count);
 181        return status;
 182}
 183/**
 184 * rtl92c_init_LLT_table - Init LLT table
 185 * @io: io callback
 186 * @boundary:
 187 *
 188 * Realtek hardware access function.
 189 *
 190 */
 191bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary)
 192{
 193        bool rst = true;
 194        u32     i;
 195
 196        for (i = 0; i < (boundary - 1); i++) {
 197                rst = rtl92c_llt_write(hw, i , i + 1);
 198                if (true != rst) {
 199                        pr_err("===> %s #1 fail\n", __func__);
 200                        return rst;
 201                }
 202        }
 203        /* end of list */
 204        rst = rtl92c_llt_write(hw, (boundary - 1), 0xFF);
 205        if (true != rst) {
 206                pr_err("===> %s #2 fail\n", __func__);
 207                return rst;
 208        }
 209        /* Make the other pages as ring buffer
 210         * This ring buffer is used as beacon buffer if we config this MAC
 211         *  as two MAC transfer.
 212         * Otherwise used as local loopback buffer.
 213         */
 214        for (i = boundary; i < LLT_LAST_ENTRY_OF_TX_PKT_BUFFER; i++) {
 215                rst = rtl92c_llt_write(hw, i, (i + 1));
 216                if (true != rst) {
 217                        pr_err("===> %s #3 fail\n", __func__);
 218                        return rst;
 219                }
 220        }
 221        /* Let last entry point to the start entry of ring buffer */
 222        rst = rtl92c_llt_write(hw, LLT_LAST_ENTRY_OF_TX_PKT_BUFFER, boundary);
 223        if (true != rst) {
 224                pr_err("===> %s #4 fail\n", __func__);
 225                return rst;
 226        }
 227        return rst;
 228}
 229void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index,
 230                     u8 *p_macaddr, bool is_group, u8 enc_algo,
 231                     bool is_wepkey, bool clear_all)
 232{
 233        struct rtl_priv *rtlpriv = rtl_priv(hw);
 234        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 235        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 236        u8 *macaddr = p_macaddr;
 237        u32 entry_id = 0;
 238        bool is_pairwise = false;
 239        static u8 cam_const_addr[4][6] = {
 240                {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
 241                {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
 242                {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
 243                {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
 244        };
 245        static u8 cam_const_broad[] = {
 246                0xff, 0xff, 0xff, 0xff, 0xff, 0xff
 247        };
 248
 249        if (clear_all) {
 250                u8 idx = 0;
 251                u8 cam_offset = 0;
 252                u8 clear_number = 5;
 253
 254                RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n");
 255                for (idx = 0; idx < clear_number; idx++) {
 256                        rtl_cam_mark_invalid(hw, cam_offset + idx);
 257                        rtl_cam_empty_entry(hw, cam_offset + idx);
 258                        if (idx < 5) {
 259                                memset(rtlpriv->sec.key_buf[idx], 0,
 260                                       MAX_KEY_LEN);
 261                                rtlpriv->sec.key_len[idx] = 0;
 262                        }
 263                }
 264        } else {
 265                switch (enc_algo) {
 266                case WEP40_ENCRYPTION:
 267                        enc_algo = CAM_WEP40;
 268                        break;
 269                case WEP104_ENCRYPTION:
 270                        enc_algo = CAM_WEP104;
 271                        break;
 272                case TKIP_ENCRYPTION:
 273                        enc_algo = CAM_TKIP;
 274                        break;
 275                case AESCCMP_ENCRYPTION:
 276                        enc_algo = CAM_AES;
 277                        break;
 278                default:
 279                        RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 280                                 "illegal switch case\n");
 281                        enc_algo = CAM_TKIP;
 282                        break;
 283                }
 284                if (is_wepkey || rtlpriv->sec.use_defaultkey) {
 285                        macaddr = cam_const_addr[key_index];
 286                        entry_id = key_index;
 287                } else {
 288                        if (is_group) {
 289                                macaddr = cam_const_broad;
 290                                entry_id = key_index;
 291                        } else {
 292                                key_index = PAIRWISE_KEYIDX;
 293                                entry_id = CAM_PAIRWISE_KEY_POSITION;
 294                                is_pairwise = true;
 295                        }
 296                }
 297                if (rtlpriv->sec.key_len[key_index] == 0) {
 298                        RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 299                                 "delete one entry\n");
 300                        rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
 301                } else {
 302                        RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
 303                                 "The insert KEY length is %d\n",
 304                                 rtlpriv->sec.key_len[PAIRWISE_KEYIDX]);
 305                        RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
 306                                 "The insert KEY is %x %x\n",
 307                                 rtlpriv->sec.key_buf[0][0],
 308                                 rtlpriv->sec.key_buf[0][1]);
 309                        RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 310                                 "add one entry\n");
 311                        if (is_pairwise) {
 312                                RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD,
 313                                              "Pairwise Key content",
 314                                              rtlpriv->sec.pairwise_key,
 315                                              rtlpriv->sec.
 316                                              key_len[PAIRWISE_KEYIDX]);
 317                                RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 318                                         "set Pairwise key\n");
 319
 320                                rtl_cam_add_one_entry(hw, macaddr, key_index,
 321                                                entry_id, enc_algo,
 322                                                CAM_CONFIG_NO_USEDK,
 323                                                rtlpriv->sec.
 324                                                key_buf[key_index]);
 325                        } else {
 326                                RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 327                                         "set group key\n");
 328                                if (mac->opmode == NL80211_IFTYPE_ADHOC) {
 329                                        rtl_cam_add_one_entry(hw,
 330                                                rtlefuse->dev_addr,
 331                                                PAIRWISE_KEYIDX,
 332                                                CAM_PAIRWISE_KEY_POSITION,
 333                                                enc_algo,
 334                                                CAM_CONFIG_NO_USEDK,
 335                                                rtlpriv->sec.key_buf
 336                                                [entry_id]);
 337                                }
 338                                rtl_cam_add_one_entry(hw, macaddr, key_index,
 339                                                entry_id, enc_algo,
 340                                                CAM_CONFIG_NO_USEDK,
 341                                                rtlpriv->sec.key_buf[entry_id]);
 342                        }
 343                }
 344        }
 345}
 346
 347u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw)
 348{
 349        struct rtl_priv *rtlpriv = rtl_priv(hw);
 350
 351        return rtl_read_dword(rtlpriv, REG_TXDMA_STATUS);
 352}
 353
 354void rtl92c_enable_interrupt(struct ieee80211_hw *hw)
 355{
 356        struct rtl_priv *rtlpriv = rtl_priv(hw);
 357        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 358        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 359        struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
 360
 361        if (IS_HARDWARE_TYPE_8192CE(rtlhal)) {
 362                rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] &
 363                                0xFFFFFFFF);
 364                rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] &
 365                                0xFFFFFFFF);
 366        } else {
 367                rtl_write_dword(rtlpriv, REG_HIMR, rtlusb->irq_mask[0] &
 368                                0xFFFFFFFF);
 369                rtl_write_dword(rtlpriv, REG_HIMRE, rtlusb->irq_mask[1] &
 370                                0xFFFFFFFF);
 371        }
 372}
 373
 374void rtl92c_init_interrupt(struct ieee80211_hw *hw)
 375{
 376         rtl92c_enable_interrupt(hw);
 377}
 378
 379void rtl92c_disable_interrupt(struct ieee80211_hw *hw)
 380{
 381        struct rtl_priv *rtlpriv = rtl_priv(hw);
 382
 383        rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
 384        rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
 385}
 386
 387void rtl92c_set_qos(struct ieee80211_hw *hw, int aci)
 388{
 389        struct rtl_priv *rtlpriv = rtl_priv(hw);
 390        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 391        u32 u4b_ac_param;
 392
 393        rtl92c_dm_init_edca_turbo(hw);
 394        u4b_ac_param = (u32) mac->ac[aci].aifs;
 395        u4b_ac_param |=
 396            ((u32) le16_to_cpu(mac->ac[aci].cw_min) & 0xF) <<
 397            AC_PARAM_ECW_MIN_OFFSET;
 398        u4b_ac_param |=
 399            ((u32) le16_to_cpu(mac->ac[aci].cw_max) & 0xF) <<
 400            AC_PARAM_ECW_MAX_OFFSET;
 401        u4b_ac_param |= (u32) le16_to_cpu(mac->ac[aci].tx_op) <<
 402                         AC_PARAM_TXOP_OFFSET;
 403        RT_TRACE(rtlpriv, COMP_QOS, DBG_LOUD, "queue:%x, ac_param:%x\n",
 404                 aci, u4b_ac_param);
 405        switch (aci) {
 406        case AC1_BK:
 407                rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, u4b_ac_param);
 408                break;
 409        case AC0_BE:
 410                rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param);
 411                break;
 412        case AC2_VI:
 413                rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, u4b_ac_param);
 414                break;
 415        case AC3_VO:
 416                rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, u4b_ac_param);
 417                break;
 418        default:
 419                RT_ASSERT(false, "invalid aci: %d !\n", aci);
 420                break;
 421        }
 422}
 423
 424/*-------------------------------------------------------------------------
 425 * HW MAC Address
 426 *-------------------------------------------------------------------------*/
 427void rtl92c_set_mac_addr(struct ieee80211_hw *hw, const u8 *addr)
 428{
 429        u32 i;
 430        struct rtl_priv *rtlpriv = rtl_priv(hw);
 431
 432        for (i = 0 ; i < ETH_ALEN ; i++)
 433                rtl_write_byte(rtlpriv, (REG_MACID + i), *(addr+i));
 434
 435        RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG,
 436                 "MAC Address: %02X-%02X-%02X-%02X-%02X-%02X\n",
 437                 rtl_read_byte(rtlpriv, REG_MACID),
 438                 rtl_read_byte(rtlpriv, REG_MACID+1),
 439                 rtl_read_byte(rtlpriv, REG_MACID+2),
 440                 rtl_read_byte(rtlpriv, REG_MACID+3),
 441                 rtl_read_byte(rtlpriv, REG_MACID+4),
 442                 rtl_read_byte(rtlpriv, REG_MACID+5));
 443}
 444
 445void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size)
 446{
 447        struct rtl_priv *rtlpriv = rtl_priv(hw);
 448        rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, size);
 449}
 450
 451int rtl92c_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
 452{
 453        u8 value;
 454        struct rtl_priv *rtlpriv = rtl_priv(hw);
 455
 456        switch (type) {
 457        case NL80211_IFTYPE_UNSPECIFIED:
 458                value = NT_NO_LINK;
 459                RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 460                         "Set Network type to NO LINK!\n");
 461                break;
 462        case NL80211_IFTYPE_ADHOC:
 463                value = NT_LINK_AD_HOC;
 464                RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 465                         "Set Network type to Ad Hoc!\n");
 466                break;
 467        case NL80211_IFTYPE_STATION:
 468                value = NT_LINK_AP;
 469                RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 470                         "Set Network type to STA!\n");
 471                break;
 472        case NL80211_IFTYPE_AP:
 473                value = NT_AS_AP;
 474                RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 475                         "Set Network type to AP!\n");
 476                break;
 477        default:
 478                RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 479                         "Network type %d not supported!\n", type);
 480                return -EOPNOTSUPP;
 481        }
 482        rtl_write_byte(rtlpriv, (REG_CR + 2), value);
 483        return 0;
 484}
 485
 486void rtl92c_init_network_type(struct ieee80211_hw *hw)
 487{
 488        rtl92c_set_network_type(hw, NL80211_IFTYPE_UNSPECIFIED);
 489}
 490
 491void rtl92c_init_adaptive_ctrl(struct ieee80211_hw *hw)
 492{
 493        u16     value16;
 494        u32     value32;
 495        struct rtl_priv *rtlpriv = rtl_priv(hw);
 496
 497        /* Response Rate Set */
 498        value32 = rtl_read_dword(rtlpriv, REG_RRSR);
 499        value32 &= ~RATE_BITMAP_ALL;
 500        value32 |= RATE_RRSR_CCK_ONLY_1M;
 501        rtl_write_dword(rtlpriv, REG_RRSR, value32);
 502        /* SIFS (used in NAV) */
 503        value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10);
 504        rtl_write_word(rtlpriv,  REG_SPEC_SIFS, value16);
 505        /* Retry Limit */
 506        value16 = _LRL(0x30) | _SRL(0x30);
 507        rtl_write_dword(rtlpriv,  REG_RL, value16);
 508}
 509
 510void rtl92c_init_rate_fallback(struct ieee80211_hw *hw)
 511{
 512        struct rtl_priv *rtlpriv = rtl_priv(hw);
 513
 514        /* Set Data Auto Rate Fallback Retry Count register. */
 515        rtl_write_dword(rtlpriv,  REG_DARFRC, 0x00000000);
 516        rtl_write_dword(rtlpriv,  REG_DARFRC+4, 0x10080404);
 517        rtl_write_dword(rtlpriv,  REG_RARFRC, 0x04030201);
 518        rtl_write_dword(rtlpriv,  REG_RARFRC+4, 0x08070605);
 519}
 520
 521static void rtl92c_set_cck_sifs(struct ieee80211_hw *hw, u8 trx_sifs,
 522                                u8 ctx_sifs)
 523{
 524        struct rtl_priv *rtlpriv = rtl_priv(hw);
 525
 526        rtl_write_byte(rtlpriv, REG_SIFS_CCK, trx_sifs);
 527        rtl_write_byte(rtlpriv, (REG_SIFS_CCK + 1), ctx_sifs);
 528}
 529
 530static void rtl92c_set_ofdm_sifs(struct ieee80211_hw *hw, u8 trx_sifs,
 531                                 u8 ctx_sifs)
 532{
 533        struct rtl_priv *rtlpriv = rtl_priv(hw);
 534
 535        rtl_write_byte(rtlpriv, REG_SIFS_OFDM, trx_sifs);
 536        rtl_write_byte(rtlpriv, (REG_SIFS_OFDM + 1), ctx_sifs);
 537}
 538
 539void rtl92c_init_edca_param(struct ieee80211_hw *hw,
 540                            u16 queue, u16 txop, u8 cw_min, u8 cw_max, u8 aifs)
 541{
 542        /* sequence: VO, VI, BE, BK ==> the same as 92C hardware design.
 543         * referenc : enum nl80211_txq_q or ieee80211_set_wmm_default function.
 544         */
 545        u32 value;
 546        struct rtl_priv *rtlpriv = rtl_priv(hw);
 547
 548        value = (u32)aifs;
 549        value |= ((u32)cw_min & 0xF) << 8;
 550        value |= ((u32)cw_max & 0xF) << 12;
 551        value |= (u32)txop << 16;
 552        /* 92C hardware register sequence is the same as queue number. */
 553        rtl_write_dword(rtlpriv, (REG_EDCA_VO_PARAM + (queue * 4)), value);
 554}
 555
 556void rtl92c_init_edca(struct ieee80211_hw *hw)
 557{
 558        u16 value16;
 559        struct rtl_priv *rtlpriv = rtl_priv(hw);
 560
 561        /* disable EDCCA count down, to reduce collison and retry */
 562        value16 = rtl_read_word(rtlpriv, REG_RD_CTRL);
 563        value16 |= DIS_EDCA_CNT_DWN;
 564        rtl_write_word(rtlpriv, REG_RD_CTRL, value16);
 565        /* Update SIFS timing.  ??????????
 566         * pHalData->SifsTime = 0x0e0e0a0a; */
 567        rtl92c_set_cck_sifs(hw, 0xa, 0xa);
 568        rtl92c_set_ofdm_sifs(hw, 0xe, 0xe);
 569        /* Set CCK/OFDM SIFS to be 10us. */
 570        rtl_write_word(rtlpriv, REG_SIFS_CCK, 0x0a0a);
 571        rtl_write_word(rtlpriv, REG_SIFS_OFDM, 0x1010);
 572        rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0204);
 573        rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x014004);
 574        /* TXOP */
 575        rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, 0x005EA42B);
 576        rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0x0000A44F);
 577        rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x005EA324);
 578        rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x002FA226);
 579        /* PIFS */
 580        rtl_write_byte(rtlpriv, REG_PIFS, 0x1C);
 581        /* AGGR BREAK TIME Register */
 582        rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
 583        rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040);
 584        rtl_write_byte(rtlpriv, REG_BCNDMATIM, 0x02);
 585        rtl_write_byte(rtlpriv, REG_ATIMWND, 0x02);
 586}
 587
 588void rtl92c_init_ampdu_aggregation(struct ieee80211_hw *hw)
 589{
 590        struct rtl_priv *rtlpriv = rtl_priv(hw);
 591
 592        rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x99997631);
 593        rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
 594        /* init AMPDU aggregation number, tuning for Tx's TP, */
 595        rtl_write_word(rtlpriv, 0x4CA, 0x0708);
 596}
 597
 598void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw, bool infra_mode)
 599{
 600        struct rtl_priv *rtlpriv = rtl_priv(hw);
 601
 602        rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xFF);
 603}
 604
 605void rtl92c_init_rdg_setting(struct ieee80211_hw *hw)
 606{
 607        struct rtl_priv *rtlpriv = rtl_priv(hw);
 608
 609        rtl_write_byte(rtlpriv, REG_RD_CTRL, 0xFF);
 610        rtl_write_word(rtlpriv, REG_RD_NAV_NXT, 0x200);
 611        rtl_write_byte(rtlpriv, REG_RD_RESP_PKT_TH, 0x05);
 612}
 613
 614void rtl92c_init_retry_function(struct ieee80211_hw *hw)
 615{
 616        u8      value8;
 617        struct rtl_priv *rtlpriv = rtl_priv(hw);
 618
 619        value8 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL);
 620        value8 |= EN_AMPDU_RTY_NEW;
 621        rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL, value8);
 622        /* Set ACK timeout */
 623        rtl_write_byte(rtlpriv, REG_ACKTO, 0x40);
 624}
 625
 626void rtl92c_init_beacon_parameters(struct ieee80211_hw *hw,
 627                                   enum version_8192c version)
 628{
 629        struct rtl_priv *rtlpriv = rtl_priv(hw);
 630        struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
 631
 632        rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);/* ms */
 633        rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/*ms*/
 634        rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
 635        if (IS_NORMAL_CHIP(rtlhal->version))
 636                rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F);
 637        else
 638                rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF);
 639}
 640
 641void rtl92c_disable_fast_edca(struct ieee80211_hw *hw)
 642{
 643        struct rtl_priv *rtlpriv = rtl_priv(hw);
 644
 645        rtl_write_word(rtlpriv, REG_FAST_EDCA_CTRL, 0);
 646}
 647
 648void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T)
 649{
 650        struct rtl_priv *rtlpriv = rtl_priv(hw);
 651        u8 value = is2T ? MAX_MSS_DENSITY_2T : MAX_MSS_DENSITY_1T;
 652
 653        rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, value);
 654}
 655
 656u16 rtl92c_get_mgt_filter(struct ieee80211_hw *hw)
 657{
 658        struct rtl_priv *rtlpriv = rtl_priv(hw);
 659
 660        return rtl_read_word(rtlpriv, REG_RXFLTMAP0);
 661}
 662
 663void rtl92c_set_mgt_filter(struct ieee80211_hw *hw, u16 filter)
 664{
 665        struct rtl_priv *rtlpriv = rtl_priv(hw);
 666
 667        rtl_write_word(rtlpriv, REG_RXFLTMAP0, filter);
 668}
 669
 670u16 rtl92c_get_ctrl_filter(struct ieee80211_hw *hw)
 671{
 672        struct rtl_priv *rtlpriv = rtl_priv(hw);
 673
 674        return rtl_read_word(rtlpriv, REG_RXFLTMAP1);
 675}
 676
 677void rtl92c_set_ctrl_filter(struct ieee80211_hw *hw, u16 filter)
 678{
 679        struct rtl_priv *rtlpriv = rtl_priv(hw);
 680
 681        rtl_write_word(rtlpriv, REG_RXFLTMAP1, filter);
 682}
 683
 684u16 rtl92c_get_data_filter(struct ieee80211_hw *hw)
 685{
 686        struct rtl_priv *rtlpriv = rtl_priv(hw);
 687
 688        return rtl_read_word(rtlpriv,  REG_RXFLTMAP2);
 689}
 690
 691void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter)
 692{
 693        struct rtl_priv *rtlpriv = rtl_priv(hw);
 694
 695        rtl_write_word(rtlpriv, REG_RXFLTMAP2, filter);
 696}
 697/*==============================================================*/
 698
 699static u8 _rtl92c_query_rxpwrpercentage(char antpower)
 700{
 701        if ((antpower <= -100) || (antpower >= 20))
 702                return 0;
 703        else if (antpower >= 0)
 704                return 100;
 705        else
 706                return 100 + antpower;
 707}
 708
 709static u8 _rtl92c_evm_db_to_percentage(char value)
 710{
 711        char ret_val;
 712
 713        ret_val = value;
 714        if (ret_val >= 0)
 715                ret_val = 0;
 716        if (ret_val <= -33)
 717                ret_val = -33;
 718        ret_val = 0 - ret_val;
 719        ret_val *= 3;
 720        if (ret_val == 99)
 721                ret_val = 100;
 722        return ret_val;
 723}
 724
 725static long _rtl92c_translate_todbm(struct ieee80211_hw *hw,
 726                                     u8 signal_strength_index)
 727{
 728        long signal_power;
 729
 730        signal_power = (long)((signal_strength_index + 1) >> 1);
 731        signal_power -= 95;
 732        return signal_power;
 733}
 734
 735static long _rtl92c_signal_scale_mapping(struct ieee80211_hw *hw,
 736                long currsig)
 737{
 738        long retsig;
 739
 740        if (currsig >= 61 && currsig <= 100)
 741                retsig = 90 + ((currsig - 60) / 4);
 742        else if (currsig >= 41 && currsig <= 60)
 743                retsig = 78 + ((currsig - 40) / 2);
 744        else if (currsig >= 31 && currsig <= 40)
 745                retsig = 66 + (currsig - 30);
 746        else if (currsig >= 21 && currsig <= 30)
 747                retsig = 54 + (currsig - 20);
 748        else if (currsig >= 5 && currsig <= 20)
 749                retsig = 42 + (((currsig - 5) * 2) / 3);
 750        else if (currsig == 4)
 751                retsig = 36;
 752        else if (currsig == 3)
 753                retsig = 27;
 754        else if (currsig == 2)
 755                retsig = 18;
 756        else if (currsig == 1)
 757                retsig = 9;
 758        else
 759                retsig = currsig;
 760        return retsig;
 761}
 762
 763static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
 764                                      struct rtl_stats *pstats,
 765                                      struct rx_desc_92c *pdesc,
 766                                      struct rx_fwinfo_92c *p_drvinfo,
 767                                      bool packet_match_bssid,
 768                                      bool packet_toself,
 769                                      bool packet_beacon)
 770{
 771        struct rtl_priv *rtlpriv = rtl_priv(hw);
 772        struct rtl_phy *rtlphy = &(rtlpriv->phy);
 773        struct phy_sts_cck_8192s_t *cck_buf;
 774        s8 rx_pwr_all = 0, rx_pwr[4];
 775        u8 rf_rx_num = 0, evm, pwdb_all;
 776        u8 i, max_spatial_stream;
 777        u32 rssi, total_rssi = 0;
 778        bool in_powersavemode = false;
 779        bool is_cck_rate;
 780
 781        is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
 782        pstats->packet_matchbssid = packet_match_bssid;
 783        pstats->packet_toself = packet_toself;
 784        pstats->is_cck = is_cck_rate;
 785        pstats->packet_beacon = packet_beacon;
 786        pstats->is_cck = is_cck_rate;
 787        pstats->RX_SIGQ[0] = -1;
 788        pstats->RX_SIGQ[1] = -1;
 789        if (is_cck_rate) {
 790                u8 report, cck_highpwr;
 791                cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
 792                if (!in_powersavemode)
 793                        cck_highpwr = rtlphy->cck_high_power;
 794                else
 795                        cck_highpwr = false;
 796                if (!cck_highpwr) {
 797                        u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
 798                        report = cck_buf->cck_agc_rpt & 0xc0;
 799                        report = report >> 6;
 800                        switch (report) {
 801                        case 0x3:
 802                                rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
 803                                break;
 804                        case 0x2:
 805                                rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
 806                                break;
 807                        case 0x1:
 808                                rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
 809                                break;
 810                        case 0x0:
 811                                rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
 812                                break;
 813                        }
 814                } else {
 815                        u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
 816                        report = p_drvinfo->cfosho[0] & 0x60;
 817                        report = report >> 5;
 818                        switch (report) {
 819                        case 0x3:
 820                                rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
 821                                break;
 822                        case 0x2:
 823                                rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
 824                                break;
 825                        case 0x1:
 826                                rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
 827                                break;
 828                        case 0x0:
 829                                rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
 830                                break;
 831                        }
 832                }
 833                pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
 834                pstats->rx_pwdb_all = pwdb_all;
 835                pstats->recvsignalpower = rx_pwr_all;
 836                if (packet_match_bssid) {
 837                        u8 sq;
 838                        if (pstats->rx_pwdb_all > 40)
 839                                sq = 100;
 840                        else {
 841                                sq = cck_buf->sq_rpt;
 842                                if (sq > 64)
 843                                        sq = 0;
 844                                else if (sq < 20)
 845                                        sq = 100;
 846                                else
 847                                        sq = ((64 - sq) * 100) / 44;
 848                        }
 849                        pstats->signalquality = sq;
 850                        pstats->RX_SIGQ[0] = sq;
 851                        pstats->RX_SIGQ[1] = -1;
 852                }
 853        } else {
 854                rtlpriv->dm.rfpath_rxenable[0] =
 855                    rtlpriv->dm.rfpath_rxenable[1] = true;
 856                for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
 857                        if (rtlpriv->dm.rfpath_rxenable[i])
 858                                rf_rx_num++;
 859                        rx_pwr[i] =
 860                            ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110;
 861                        rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]);
 862                        total_rssi += rssi;
 863                        rtlpriv->stats.rx_snr_db[i] =
 864                            (long)(p_drvinfo->rxsnr[i] / 2);
 865
 866                        if (packet_match_bssid)
 867                                pstats->rx_mimo_signalstrength[i] = (u8) rssi;
 868                }
 869                rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
 870                pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
 871                pstats->rx_pwdb_all = pwdb_all;
 872                pstats->rxpower = rx_pwr_all;
 873                pstats->recvsignalpower = rx_pwr_all;
 874                if (GET_RX_DESC_RX_MCS(pdesc) &&
 875                    GET_RX_DESC_RX_MCS(pdesc) >= DESC92_RATEMCS8 &&
 876                    GET_RX_DESC_RX_MCS(pdesc) <= DESC92_RATEMCS15)
 877                        max_spatial_stream = 2;
 878                else
 879                        max_spatial_stream = 1;
 880                for (i = 0; i < max_spatial_stream; i++) {
 881                        evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]);
 882                        if (packet_match_bssid) {
 883                                if (i == 0)
 884                                        pstats->signalquality =
 885                                            (u8) (evm & 0xff);
 886                                pstats->RX_SIGQ[i] =
 887                                    (u8) (evm & 0xff);
 888                        }
 889                }
 890        }
 891        if (is_cck_rate)
 892                pstats->signalstrength =
 893                    (u8) (_rtl92c_signal_scale_mapping(hw, pwdb_all));
 894        else if (rf_rx_num != 0)
 895                pstats->signalstrength =
 896                    (u8) (_rtl92c_signal_scale_mapping
 897                          (hw, total_rssi /= rf_rx_num));
 898}
 899
 900static void _rtl92c_process_ui_rssi(struct ieee80211_hw *hw,
 901                struct rtl_stats *pstats)
 902{
 903        struct rtl_priv *rtlpriv = rtl_priv(hw);
 904        struct rtl_phy *rtlphy = &(rtlpriv->phy);
 905        u8 rfpath;
 906        u32 last_rssi, tmpval;
 907
 908        if (pstats->packet_toself || pstats->packet_beacon) {
 909                rtlpriv->stats.rssi_calculate_cnt++;
 910                if (rtlpriv->stats.ui_rssi.total_num++ >=
 911                    PHY_RSSI_SLID_WIN_MAX) {
 912                        rtlpriv->stats.ui_rssi.total_num =
 913                            PHY_RSSI_SLID_WIN_MAX;
 914                        last_rssi =
 915                            rtlpriv->stats.ui_rssi.elements[rtlpriv->
 916                                                           stats.ui_rssi.index];
 917                        rtlpriv->stats.ui_rssi.total_val -= last_rssi;
 918                }
 919                rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength;
 920                rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.
 921                                        index++] = pstats->signalstrength;
 922                if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
 923                        rtlpriv->stats.ui_rssi.index = 0;
 924                tmpval = rtlpriv->stats.ui_rssi.total_val /
 925                    rtlpriv->stats.ui_rssi.total_num;
 926                rtlpriv->stats.signal_strength =
 927                    _rtl92c_translate_todbm(hw, (u8) tmpval);
 928                pstats->rssi = rtlpriv->stats.signal_strength;
 929        }
 930        if (!pstats->is_cck && pstats->packet_toself) {
 931                for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
 932                     rfpath++) {
 933                        if (!rtl8192_phy_check_is_legal_rfpath(hw, rfpath))
 934                                continue;
 935                        if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
 936                                rtlpriv->stats.rx_rssi_percentage[rfpath] =
 937                                    pstats->rx_mimo_signalstrength[rfpath];
 938                        }
 939                        if (pstats->rx_mimo_signalstrength[rfpath] >
 940                            rtlpriv->stats.rx_rssi_percentage[rfpath]) {
 941                                rtlpriv->stats.rx_rssi_percentage[rfpath] =
 942                                    ((rtlpriv->stats.
 943                                      rx_rssi_percentage[rfpath] *
 944                                      (RX_SMOOTH_FACTOR - 1)) +
 945                                     (pstats->rx_mimo_signalstrength[rfpath])) /
 946                                    (RX_SMOOTH_FACTOR);
 947
 948                                rtlpriv->stats.rx_rssi_percentage[rfpath] =
 949                                    rtlpriv->stats.rx_rssi_percentage[rfpath] +
 950                                    1;
 951                        } else {
 952                                rtlpriv->stats.rx_rssi_percentage[rfpath] =
 953                                    ((rtlpriv->stats.
 954                                      rx_rssi_percentage[rfpath] *
 955                                      (RX_SMOOTH_FACTOR - 1)) +
 956                                     (pstats->rx_mimo_signalstrength[rfpath])) /
 957                                    (RX_SMOOTH_FACTOR);
 958                        }
 959                }
 960        }
 961}
 962
 963static void _rtl92c_update_rxsignalstatistics(struct ieee80211_hw *hw,
 964                                               struct rtl_stats *pstats)
 965{
 966        struct rtl_priv *rtlpriv = rtl_priv(hw);
 967        int weighting = 0;
 968
 969        if (rtlpriv->stats.recv_signal_power == 0)
 970                rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
 971        if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power)
 972                weighting = 5;
 973        else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power)
 974                weighting = (-5);
 975        rtlpriv->stats.recv_signal_power =
 976            (rtlpriv->stats.recv_signal_power * 5 +
 977             pstats->recvsignalpower + weighting) / 6;
 978}
 979
 980static void _rtl92c_process_pwdb(struct ieee80211_hw *hw,
 981                struct rtl_stats *pstats)
 982{
 983        struct rtl_priv *rtlpriv = rtl_priv(hw);
 984        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 985        long undecorated_smoothed_pwdb = 0;
 986
 987        if (mac->opmode == NL80211_IFTYPE_ADHOC) {
 988                return;
 989        } else {
 990                undecorated_smoothed_pwdb =
 991                    rtlpriv->dm.undecorated_smoothed_pwdb;
 992        }
 993        if (pstats->packet_toself || pstats->packet_beacon) {
 994                if (undecorated_smoothed_pwdb < 0)
 995                        undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
 996                if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
 997                        undecorated_smoothed_pwdb =
 998                            (((undecorated_smoothed_pwdb) *
 999                              (RX_SMOOTH_FACTOR - 1)) +
1000                             (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
1001                        undecorated_smoothed_pwdb = undecorated_smoothed_pwdb
1002                            + 1;
1003                } else {
1004                        undecorated_smoothed_pwdb =
1005                            (((undecorated_smoothed_pwdb) *
1006                              (RX_SMOOTH_FACTOR - 1)) +
1007                             (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
1008                }
1009                rtlpriv->dm.undecorated_smoothed_pwdb =
1010                    undecorated_smoothed_pwdb;
1011                _rtl92c_update_rxsignalstatistics(hw, pstats);
1012        }
1013}
1014
1015static void _rtl92c_process_LINK_Q(struct ieee80211_hw *hw,
1016                                             struct rtl_stats *pstats)
1017{
1018        struct rtl_priv *rtlpriv = rtl_priv(hw);
1019        u32 last_evm = 0, n_stream, tmpval;
1020
1021        if (pstats->signalquality != 0) {
1022                if (pstats->packet_toself || pstats->packet_beacon) {
1023                        if (rtlpriv->stats.LINK_Q.total_num++ >=
1024                            PHY_LINKQUALITY_SLID_WIN_MAX) {
1025                                rtlpriv->stats.LINK_Q.total_num =
1026                                    PHY_LINKQUALITY_SLID_WIN_MAX;
1027                                last_evm =
1028                                    rtlpriv->stats.LINK_Q.elements
1029                                    [rtlpriv->stats.LINK_Q.index];
1030                                rtlpriv->stats.LINK_Q.total_val -=
1031                                    last_evm;
1032                        }
1033                        rtlpriv->stats.LINK_Q.total_val +=
1034                            pstats->signalquality;
1035                        rtlpriv->stats.LINK_Q.elements
1036                           [rtlpriv->stats.LINK_Q.index++] =
1037                            pstats->signalquality;
1038                        if (rtlpriv->stats.LINK_Q.index >=
1039                            PHY_LINKQUALITY_SLID_WIN_MAX)
1040                                rtlpriv->stats.LINK_Q.index = 0;
1041                        tmpval = rtlpriv->stats.LINK_Q.total_val /
1042                            rtlpriv->stats.LINK_Q.total_num;
1043                        rtlpriv->stats.signal_quality = tmpval;
1044                        rtlpriv->stats.last_sigstrength_inpercent = tmpval;
1045                        for (n_stream = 0; n_stream < 2;
1046                             n_stream++) {
1047                                if (pstats->RX_SIGQ[n_stream] != -1) {
1048                                        if (!rtlpriv->stats.RX_EVM[n_stream]) {
1049                                                rtlpriv->stats.RX_EVM[n_stream]
1050                                                 = pstats->RX_SIGQ[n_stream];
1051                                        }
1052                                        rtlpriv->stats.RX_EVM[n_stream] =
1053                                            ((rtlpriv->stats.RX_EVM
1054                                            [n_stream] *
1055                                            (RX_SMOOTH_FACTOR - 1)) +
1056                                            (pstats->RX_SIGQ
1057                                            [n_stream] * 1)) /
1058                                            (RX_SMOOTH_FACTOR);
1059                                }
1060                        }
1061                }
1062        } else {
1063                ;
1064        }
1065}
1066
1067static void _rtl92c_process_phyinfo(struct ieee80211_hw *hw,
1068                                     u8 *buffer,
1069                                     struct rtl_stats *pcurrent_stats)
1070{
1071        if (!pcurrent_stats->packet_matchbssid &&
1072            !pcurrent_stats->packet_beacon)
1073                return;
1074        _rtl92c_process_ui_rssi(hw, pcurrent_stats);
1075        _rtl92c_process_pwdb(hw, pcurrent_stats);
1076        _rtl92c_process_LINK_Q(hw, pcurrent_stats);
1077}
1078
1079void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
1080                                               struct sk_buff *skb,
1081                                               struct rtl_stats *pstats,
1082                                               struct rx_desc_92c *pdesc,
1083                                               struct rx_fwinfo_92c *p_drvinfo)
1084{
1085        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1086        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1087        struct ieee80211_hdr *hdr;
1088        u8 *tmp_buf;
1089        u8 *praddr;
1090        __le16 fc;
1091        u16 type, cpu_fc;
1092        bool packet_matchbssid, packet_toself, packet_beacon;
1093
1094        tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
1095        hdr = (struct ieee80211_hdr *)tmp_buf;
1096        fc = hdr->frame_control;
1097        cpu_fc = le16_to_cpu(fc);
1098        type = WLAN_FC_GET_TYPE(fc);
1099        praddr = hdr->addr1;
1100        packet_matchbssid =
1101            ((IEEE80211_FTYPE_CTL != type) &&
1102             (!compare_ether_addr(mac->bssid,
1103                          (cpu_fc & IEEE80211_FCTL_TODS) ?
1104                          hdr->addr1 : (cpu_fc & IEEE80211_FCTL_FROMDS) ?
1105                          hdr->addr2 : hdr->addr3)) &&
1106             (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv));
1107
1108        packet_toself = packet_matchbssid &&
1109            (!compare_ether_addr(praddr, rtlefuse->dev_addr));
1110        if (ieee80211_is_beacon(fc))
1111                packet_beacon = true;
1112        _rtl92c_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
1113                                   packet_matchbssid, packet_toself,
1114                                   packet_beacon);
1115        _rtl92c_process_phyinfo(hw, tmp_buf, pstats);
1116}
1117