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_sig_qual
  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                                if (mac->opmode == NL80211_IFTYPE_AP ||
 293                                    mac->opmode == NL80211_IFTYPE_MESH_POINT) {
 294                                        entry_id = rtl_cam_get_free_entry(hw,
 295                                                                 p_macaddr);
 296                                        if (entry_id >=  TOTAL_CAM_ENTRY) {
 297                                                RT_TRACE(rtlpriv, COMP_SEC,
 298                                                         DBG_EMERG,
 299                                                         "Can not find free hw security cam entry\n");
 300                                                return;
 301                                        }
 302                                } else {
 303                                        entry_id = CAM_PAIRWISE_KEY_POSITION;
 304                                }
 305
 306                                key_index = PAIRWISE_KEYIDX;
 307                                is_pairwise = true;
 308                        }
 309                }
 310                if (rtlpriv->sec.key_len[key_index] == 0) {
 311                        RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 312                                 "delete one entry\n");
 313                        if (mac->opmode == NL80211_IFTYPE_AP ||
 314                            mac->opmode == NL80211_IFTYPE_MESH_POINT)
 315                                rtl_cam_del_entry(hw, p_macaddr);
 316                        rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
 317                } else {
 318                        RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
 319                                 "The insert KEY length is %d\n",
 320                                 rtlpriv->sec.key_len[PAIRWISE_KEYIDX]);
 321                        RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
 322                                 "The insert KEY is %x %x\n",
 323                                 rtlpriv->sec.key_buf[0][0],
 324                                 rtlpriv->sec.key_buf[0][1]);
 325                        RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 326                                 "add one entry\n");
 327                        if (is_pairwise) {
 328                                RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD,
 329                                              "Pairwise Key content",
 330                                              rtlpriv->sec.pairwise_key,
 331                                              rtlpriv->sec.
 332                                              key_len[PAIRWISE_KEYIDX]);
 333                                RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 334                                         "set Pairwise key\n");
 335
 336                                rtl_cam_add_one_entry(hw, macaddr, key_index,
 337                                                entry_id, enc_algo,
 338                                                CAM_CONFIG_NO_USEDK,
 339                                                rtlpriv->sec.
 340                                                key_buf[key_index]);
 341                        } else {
 342                                RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 343                                         "set group key\n");
 344                                if (mac->opmode == NL80211_IFTYPE_ADHOC) {
 345                                        rtl_cam_add_one_entry(hw,
 346                                                rtlefuse->dev_addr,
 347                                                PAIRWISE_KEYIDX,
 348                                                CAM_PAIRWISE_KEY_POSITION,
 349                                                enc_algo,
 350                                                CAM_CONFIG_NO_USEDK,
 351                                                rtlpriv->sec.key_buf
 352                                                [entry_id]);
 353                                }
 354                                rtl_cam_add_one_entry(hw, macaddr, key_index,
 355                                                entry_id, enc_algo,
 356                                                CAM_CONFIG_NO_USEDK,
 357                                                rtlpriv->sec.key_buf[entry_id]);
 358                        }
 359                }
 360        }
 361}
 362
 363u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw)
 364{
 365        struct rtl_priv *rtlpriv = rtl_priv(hw);
 366
 367        return rtl_read_dword(rtlpriv, REG_TXDMA_STATUS);
 368}
 369
 370void rtl92c_enable_interrupt(struct ieee80211_hw *hw)
 371{
 372        struct rtl_priv *rtlpriv = rtl_priv(hw);
 373        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 374        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 375        struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
 376
 377        if (IS_HARDWARE_TYPE_8192CE(rtlhal)) {
 378                rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] &
 379                                0xFFFFFFFF);
 380                rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] &
 381                                0xFFFFFFFF);
 382        } else {
 383                rtl_write_dword(rtlpriv, REG_HIMR, rtlusb->irq_mask[0] &
 384                                0xFFFFFFFF);
 385                rtl_write_dword(rtlpriv, REG_HIMRE, rtlusb->irq_mask[1] &
 386                                0xFFFFFFFF);
 387        }
 388}
 389
 390void rtl92c_init_interrupt(struct ieee80211_hw *hw)
 391{
 392         rtl92c_enable_interrupt(hw);
 393}
 394
 395void rtl92c_disable_interrupt(struct ieee80211_hw *hw)
 396{
 397        struct rtl_priv *rtlpriv = rtl_priv(hw);
 398
 399        rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
 400        rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
 401}
 402
 403void rtl92c_set_qos(struct ieee80211_hw *hw, int aci)
 404{
 405        struct rtl_priv *rtlpriv = rtl_priv(hw);
 406        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 407        u32 u4b_ac_param;
 408
 409        rtl92c_dm_init_edca_turbo(hw);
 410        u4b_ac_param = (u32) mac->ac[aci].aifs;
 411        u4b_ac_param |=
 412            ((u32) le16_to_cpu(mac->ac[aci].cw_min) & 0xF) <<
 413            AC_PARAM_ECW_MIN_OFFSET;
 414        u4b_ac_param |=
 415            ((u32) le16_to_cpu(mac->ac[aci].cw_max) & 0xF) <<
 416            AC_PARAM_ECW_MAX_OFFSET;
 417        u4b_ac_param |= (u32) le16_to_cpu(mac->ac[aci].tx_op) <<
 418                         AC_PARAM_TXOP_OFFSET;
 419        RT_TRACE(rtlpriv, COMP_QOS, DBG_LOUD, "queue:%x, ac_param:%x\n",
 420                 aci, u4b_ac_param);
 421        switch (aci) {
 422        case AC1_BK:
 423                rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, u4b_ac_param);
 424                break;
 425        case AC0_BE:
 426                rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param);
 427                break;
 428        case AC2_VI:
 429                rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, u4b_ac_param);
 430                break;
 431        case AC3_VO:
 432                rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, u4b_ac_param);
 433                break;
 434        default:
 435                RT_ASSERT(false, "invalid aci: %d !\n", aci);
 436                break;
 437        }
 438}
 439
 440/*-------------------------------------------------------------------------
 441 * HW MAC Address
 442 *-------------------------------------------------------------------------*/
 443void rtl92c_set_mac_addr(struct ieee80211_hw *hw, const u8 *addr)
 444{
 445        u32 i;
 446        struct rtl_priv *rtlpriv = rtl_priv(hw);
 447
 448        for (i = 0 ; i < ETH_ALEN ; i++)
 449                rtl_write_byte(rtlpriv, (REG_MACID + i), *(addr+i));
 450
 451        RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG,
 452                 "MAC Address: %02X-%02X-%02X-%02X-%02X-%02X\n",
 453                 rtl_read_byte(rtlpriv, REG_MACID),
 454                 rtl_read_byte(rtlpriv, REG_MACID+1),
 455                 rtl_read_byte(rtlpriv, REG_MACID+2),
 456                 rtl_read_byte(rtlpriv, REG_MACID+3),
 457                 rtl_read_byte(rtlpriv, REG_MACID+4),
 458                 rtl_read_byte(rtlpriv, REG_MACID+5));
 459}
 460
 461void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size)
 462{
 463        struct rtl_priv *rtlpriv = rtl_priv(hw);
 464        rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, size);
 465}
 466
 467int rtl92c_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
 468{
 469        u8 value;
 470        struct rtl_priv *rtlpriv = rtl_priv(hw);
 471
 472        switch (type) {
 473        case NL80211_IFTYPE_UNSPECIFIED:
 474                value = NT_NO_LINK;
 475                RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 476                         "Set Network type to NO LINK!\n");
 477                break;
 478        case NL80211_IFTYPE_ADHOC:
 479                value = NT_LINK_AD_HOC;
 480                RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 481                         "Set Network type to Ad Hoc!\n");
 482                break;
 483        case NL80211_IFTYPE_STATION:
 484                value = NT_LINK_AP;
 485                RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 486                         "Set Network type to STA!\n");
 487                break;
 488        case NL80211_IFTYPE_AP:
 489                value = NT_AS_AP;
 490                RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 491                         "Set Network type to AP!\n");
 492                break;
 493        default:
 494                RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 495                         "Network type %d not supported!\n", type);
 496                return -EOPNOTSUPP;
 497        }
 498        rtl_write_byte(rtlpriv, (REG_CR + 2), value);
 499        return 0;
 500}
 501
 502void rtl92c_init_network_type(struct ieee80211_hw *hw)
 503{
 504        rtl92c_set_network_type(hw, NL80211_IFTYPE_UNSPECIFIED);
 505}
 506
 507void rtl92c_init_adaptive_ctrl(struct ieee80211_hw *hw)
 508{
 509        u16     value16;
 510        u32     value32;
 511        struct rtl_priv *rtlpriv = rtl_priv(hw);
 512
 513        /* Response Rate Set */
 514        value32 = rtl_read_dword(rtlpriv, REG_RRSR);
 515        value32 &= ~RATE_BITMAP_ALL;
 516        value32 |= RATE_RRSR_CCK_ONLY_1M;
 517        rtl_write_dword(rtlpriv, REG_RRSR, value32);
 518        /* SIFS (used in NAV) */
 519        value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10);
 520        rtl_write_word(rtlpriv,  REG_SPEC_SIFS, value16);
 521        /* Retry Limit */
 522        value16 = _LRL(0x30) | _SRL(0x30);
 523        rtl_write_dword(rtlpriv,  REG_RL, value16);
 524}
 525
 526void rtl92c_init_rate_fallback(struct ieee80211_hw *hw)
 527{
 528        struct rtl_priv *rtlpriv = rtl_priv(hw);
 529
 530        /* Set Data Auto Rate Fallback Retry Count register. */
 531        rtl_write_dword(rtlpriv,  REG_DARFRC, 0x00000000);
 532        rtl_write_dword(rtlpriv,  REG_DARFRC+4, 0x10080404);
 533        rtl_write_dword(rtlpriv,  REG_RARFRC, 0x04030201);
 534        rtl_write_dword(rtlpriv,  REG_RARFRC+4, 0x08070605);
 535}
 536
 537static void rtl92c_set_cck_sifs(struct ieee80211_hw *hw, u8 trx_sifs,
 538                                u8 ctx_sifs)
 539{
 540        struct rtl_priv *rtlpriv = rtl_priv(hw);
 541
 542        rtl_write_byte(rtlpriv, REG_SIFS_CCK, trx_sifs);
 543        rtl_write_byte(rtlpriv, (REG_SIFS_CCK + 1), ctx_sifs);
 544}
 545
 546static void rtl92c_set_ofdm_sifs(struct ieee80211_hw *hw, u8 trx_sifs,
 547                                 u8 ctx_sifs)
 548{
 549        struct rtl_priv *rtlpriv = rtl_priv(hw);
 550
 551        rtl_write_byte(rtlpriv, REG_SIFS_OFDM, trx_sifs);
 552        rtl_write_byte(rtlpriv, (REG_SIFS_OFDM + 1), ctx_sifs);
 553}
 554
 555void rtl92c_init_edca_param(struct ieee80211_hw *hw,
 556                            u16 queue, u16 txop, u8 cw_min, u8 cw_max, u8 aifs)
 557{
 558        /* sequence: VO, VI, BE, BK ==> the same as 92C hardware design.
 559         * referenc : enum nl80211_txq_q or ieee80211_set_wmm_default function.
 560         */
 561        u32 value;
 562        struct rtl_priv *rtlpriv = rtl_priv(hw);
 563
 564        value = (u32)aifs;
 565        value |= ((u32)cw_min & 0xF) << 8;
 566        value |= ((u32)cw_max & 0xF) << 12;
 567        value |= (u32)txop << 16;
 568        /* 92C hardware register sequence is the same as queue number. */
 569        rtl_write_dword(rtlpriv, (REG_EDCA_VO_PARAM + (queue * 4)), value);
 570}
 571
 572void rtl92c_init_edca(struct ieee80211_hw *hw)
 573{
 574        u16 value16;
 575        struct rtl_priv *rtlpriv = rtl_priv(hw);
 576
 577        /* disable EDCCA count down, to reduce collison and retry */
 578        value16 = rtl_read_word(rtlpriv, REG_RD_CTRL);
 579        value16 |= DIS_EDCA_CNT_DWN;
 580        rtl_write_word(rtlpriv, REG_RD_CTRL, value16);
 581        /* Update SIFS timing.  ??????????
 582         * pHalData->SifsTime = 0x0e0e0a0a; */
 583        rtl92c_set_cck_sifs(hw, 0xa, 0xa);
 584        rtl92c_set_ofdm_sifs(hw, 0xe, 0xe);
 585        /* Set CCK/OFDM SIFS to be 10us. */
 586        rtl_write_word(rtlpriv, REG_SIFS_CCK, 0x0a0a);
 587        rtl_write_word(rtlpriv, REG_SIFS_OFDM, 0x1010);
 588        rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0204);
 589        rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x014004);
 590        /* TXOP */
 591        rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, 0x005EA42B);
 592        rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0x0000A44F);
 593        rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x005EA324);
 594        rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x002FA226);
 595        /* PIFS */
 596        rtl_write_byte(rtlpriv, REG_PIFS, 0x1C);
 597        /* AGGR BREAK TIME Register */
 598        rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
 599        rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040);
 600        rtl_write_byte(rtlpriv, REG_BCNDMATIM, 0x02);
 601        rtl_write_byte(rtlpriv, REG_ATIMWND, 0x02);
 602}
 603
 604void rtl92c_init_ampdu_aggregation(struct ieee80211_hw *hw)
 605{
 606        struct rtl_priv *rtlpriv = rtl_priv(hw);
 607
 608        rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x99997631);
 609        rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
 610        /* init AMPDU aggregation number, tuning for Tx's TP, */
 611        rtl_write_word(rtlpriv, 0x4CA, 0x0708);
 612}
 613
 614void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw, bool infra_mode)
 615{
 616        struct rtl_priv *rtlpriv = rtl_priv(hw);
 617
 618        rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xFF);
 619}
 620
 621void rtl92c_init_rdg_setting(struct ieee80211_hw *hw)
 622{
 623        struct rtl_priv *rtlpriv = rtl_priv(hw);
 624
 625        rtl_write_byte(rtlpriv, REG_RD_CTRL, 0xFF);
 626        rtl_write_word(rtlpriv, REG_RD_NAV_NXT, 0x200);
 627        rtl_write_byte(rtlpriv, REG_RD_RESP_PKT_TH, 0x05);
 628}
 629
 630void rtl92c_init_retry_function(struct ieee80211_hw *hw)
 631{
 632        u8      value8;
 633        struct rtl_priv *rtlpriv = rtl_priv(hw);
 634
 635        value8 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL);
 636        value8 |= EN_AMPDU_RTY_NEW;
 637        rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL, value8);
 638        /* Set ACK timeout */
 639        rtl_write_byte(rtlpriv, REG_ACKTO, 0x40);
 640}
 641
 642void rtl92c_init_beacon_parameters(struct ieee80211_hw *hw,
 643                                   enum version_8192c version)
 644{
 645        struct rtl_priv *rtlpriv = rtl_priv(hw);
 646        struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
 647
 648        rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);/* ms */
 649        rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/*ms*/
 650        rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
 651        if (IS_NORMAL_CHIP(rtlhal->version))
 652                rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F);
 653        else
 654                rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF);
 655}
 656
 657void rtl92c_disable_fast_edca(struct ieee80211_hw *hw)
 658{
 659        struct rtl_priv *rtlpriv = rtl_priv(hw);
 660
 661        rtl_write_word(rtlpriv, REG_FAST_EDCA_CTRL, 0);
 662}
 663
 664void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T)
 665{
 666        struct rtl_priv *rtlpriv = rtl_priv(hw);
 667        u8 value = is2T ? MAX_MSS_DENSITY_2T : MAX_MSS_DENSITY_1T;
 668
 669        rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, value);
 670}
 671
 672u16 rtl92c_get_mgt_filter(struct ieee80211_hw *hw)
 673{
 674        struct rtl_priv *rtlpriv = rtl_priv(hw);
 675
 676        return rtl_read_word(rtlpriv, REG_RXFLTMAP0);
 677}
 678
 679void rtl92c_set_mgt_filter(struct ieee80211_hw *hw, u16 filter)
 680{
 681        struct rtl_priv *rtlpriv = rtl_priv(hw);
 682
 683        rtl_write_word(rtlpriv, REG_RXFLTMAP0, filter);
 684}
 685
 686u16 rtl92c_get_ctrl_filter(struct ieee80211_hw *hw)
 687{
 688        struct rtl_priv *rtlpriv = rtl_priv(hw);
 689
 690        return rtl_read_word(rtlpriv, REG_RXFLTMAP1);
 691}
 692
 693void rtl92c_set_ctrl_filter(struct ieee80211_hw *hw, u16 filter)
 694{
 695        struct rtl_priv *rtlpriv = rtl_priv(hw);
 696
 697        rtl_write_word(rtlpriv, REG_RXFLTMAP1, filter);
 698}
 699
 700u16 rtl92c_get_data_filter(struct ieee80211_hw *hw)
 701{
 702        struct rtl_priv *rtlpriv = rtl_priv(hw);
 703
 704        return rtl_read_word(rtlpriv,  REG_RXFLTMAP2);
 705}
 706
 707void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter)
 708{
 709        struct rtl_priv *rtlpriv = rtl_priv(hw);
 710
 711        rtl_write_word(rtlpriv, REG_RXFLTMAP2, filter);
 712}
 713/*==============================================================*/
 714
 715static u8 _rtl92c_query_rxpwrpercentage(char antpower)
 716{
 717        if ((antpower <= -100) || (antpower >= 20))
 718                return 0;
 719        else if (antpower >= 0)
 720                return 100;
 721        else
 722                return 100 + antpower;
 723}
 724
 725static u8 _rtl92c_evm_db_to_percentage(char value)
 726{
 727        char ret_val;
 728
 729        ret_val = value;
 730        if (ret_val >= 0)
 731                ret_val = 0;
 732        if (ret_val <= -33)
 733                ret_val = -33;
 734        ret_val = 0 - ret_val;
 735        ret_val *= 3;
 736        if (ret_val == 99)
 737                ret_val = 100;
 738        return ret_val;
 739}
 740
 741static long _rtl92c_translate_todbm(struct ieee80211_hw *hw,
 742                                     u8 signal_strength_index)
 743{
 744        long signal_power;
 745
 746        signal_power = (long)((signal_strength_index + 1) >> 1);
 747        signal_power -= 95;
 748        return signal_power;
 749}
 750
 751static long _rtl92c_signal_scale_mapping(struct ieee80211_hw *hw,
 752                long currsig)
 753{
 754        long retsig;
 755
 756        if (currsig >= 61 && currsig <= 100)
 757                retsig = 90 + ((currsig - 60) / 4);
 758        else if (currsig >= 41 && currsig <= 60)
 759                retsig = 78 + ((currsig - 40) / 2);
 760        else if (currsig >= 31 && currsig <= 40)
 761                retsig = 66 + (currsig - 30);
 762        else if (currsig >= 21 && currsig <= 30)
 763                retsig = 54 + (currsig - 20);
 764        else if (currsig >= 5 && currsig <= 20)
 765                retsig = 42 + (((currsig - 5) * 2) / 3);
 766        else if (currsig == 4)
 767                retsig = 36;
 768        else if (currsig == 3)
 769                retsig = 27;
 770        else if (currsig == 2)
 771                retsig = 18;
 772        else if (currsig == 1)
 773                retsig = 9;
 774        else
 775                retsig = currsig;
 776        return retsig;
 777}
 778
 779static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
 780                                      struct rtl_stats *pstats,
 781                                      struct rx_desc_92c *pdesc,
 782                                      struct rx_fwinfo_92c *p_drvinfo,
 783                                      bool packet_match_bssid,
 784                                      bool packet_toself,
 785                                      bool packet_beacon)
 786{
 787        struct rtl_priv *rtlpriv = rtl_priv(hw);
 788        struct rtl_phy *rtlphy = &(rtlpriv->phy);
 789        struct phy_sts_cck_8192s_t *cck_buf;
 790        s8 rx_pwr_all = 0, rx_pwr[4];
 791        u8 rf_rx_num = 0, evm, pwdb_all;
 792        u8 i, max_spatial_stream;
 793        u32 rssi, total_rssi = 0;
 794        bool in_powersavemode = false;
 795        bool is_cck_rate;
 796
 797        is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
 798        pstats->packet_matchbssid = packet_match_bssid;
 799        pstats->packet_toself = packet_toself;
 800        pstats->is_cck = is_cck_rate;
 801        pstats->packet_beacon = packet_beacon;
 802        pstats->is_cck = is_cck_rate;
 803        pstats->RX_SIGQ[0] = -1;
 804        pstats->RX_SIGQ[1] = -1;
 805        if (is_cck_rate) {
 806                u8 report, cck_highpwr;
 807                cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
 808                if (!in_powersavemode)
 809                        cck_highpwr = rtlphy->cck_high_power;
 810                else
 811                        cck_highpwr = false;
 812                if (!cck_highpwr) {
 813                        u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
 814                        report = cck_buf->cck_agc_rpt & 0xc0;
 815                        report = report >> 6;
 816                        switch (report) {
 817                        case 0x3:
 818                                rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
 819                                break;
 820                        case 0x2:
 821                                rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
 822                                break;
 823                        case 0x1:
 824                                rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
 825                                break;
 826                        case 0x0:
 827                                rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
 828                                break;
 829                        }
 830                } else {
 831                        u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
 832                        report = p_drvinfo->cfosho[0] & 0x60;
 833                        report = report >> 5;
 834                        switch (report) {
 835                        case 0x3:
 836                                rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
 837                                break;
 838                        case 0x2:
 839                                rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
 840                                break;
 841                        case 0x1:
 842                                rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
 843                                break;
 844                        case 0x0:
 845                                rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
 846                                break;
 847                        }
 848                }
 849                pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
 850                pstats->rx_pwdb_all = pwdb_all;
 851                pstats->recvsignalpower = rx_pwr_all;
 852                if (packet_match_bssid) {
 853                        u8 sq;
 854                        if (pstats->rx_pwdb_all > 40)
 855                                sq = 100;
 856                        else {
 857                                sq = cck_buf->sq_rpt;
 858                                if (sq > 64)
 859                                        sq = 0;
 860                                else if (sq < 20)
 861                                        sq = 100;
 862                                else
 863                                        sq = ((64 - sq) * 100) / 44;
 864                        }
 865                        pstats->signalquality = sq;
 866                        pstats->RX_SIGQ[0] = sq;
 867                        pstats->RX_SIGQ[1] = -1;
 868                }
 869        } else {
 870                rtlpriv->dm.rfpath_rxenable[0] =
 871                    rtlpriv->dm.rfpath_rxenable[1] = true;
 872                for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
 873                        if (rtlpriv->dm.rfpath_rxenable[i])
 874                                rf_rx_num++;
 875                        rx_pwr[i] =
 876                            ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110;
 877                        rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]);
 878                        total_rssi += rssi;
 879                        rtlpriv->stats.rx_snr_db[i] =
 880                            (long)(p_drvinfo->rxsnr[i] / 2);
 881
 882                        if (packet_match_bssid)
 883                                pstats->rx_mimo_signalstrength[i] = (u8) rssi;
 884                }
 885                rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
 886                pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
 887                pstats->rx_pwdb_all = pwdb_all;
 888                pstats->rxpower = rx_pwr_all;
 889                pstats->recvsignalpower = rx_pwr_all;
 890                if (GET_RX_DESC_RX_MCS(pdesc) &&
 891                    GET_RX_DESC_RX_MCS(pdesc) >= DESC92_RATEMCS8 &&
 892                    GET_RX_DESC_RX_MCS(pdesc) <= DESC92_RATEMCS15)
 893                        max_spatial_stream = 2;
 894                else
 895                        max_spatial_stream = 1;
 896                for (i = 0; i < max_spatial_stream; i++) {
 897                        evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]);
 898                        if (packet_match_bssid) {
 899                                if (i == 0)
 900                                        pstats->signalquality =
 901                                            (u8) (evm & 0xff);
 902                                pstats->RX_SIGQ[i] =
 903                                    (u8) (evm & 0xff);
 904                        }
 905                }
 906        }
 907        if (is_cck_rate)
 908                pstats->signalstrength =
 909                    (u8) (_rtl92c_signal_scale_mapping(hw, pwdb_all));
 910        else if (rf_rx_num != 0)
 911                pstats->signalstrength =
 912                    (u8) (_rtl92c_signal_scale_mapping
 913                          (hw, total_rssi /= rf_rx_num));
 914}
 915
 916static void _rtl92c_process_ui_rssi(struct ieee80211_hw *hw,
 917                struct rtl_stats *pstats)
 918{
 919        struct rtl_priv *rtlpriv = rtl_priv(hw);
 920        struct rtl_phy *rtlphy = &(rtlpriv->phy);
 921        u8 rfpath;
 922        u32 last_rssi, tmpval;
 923
 924        if (pstats->packet_toself || pstats->packet_beacon) {
 925                rtlpriv->stats.rssi_calculate_cnt++;
 926                if (rtlpriv->stats.ui_rssi.total_num++ >=
 927                    PHY_RSSI_SLID_WIN_MAX) {
 928                        rtlpriv->stats.ui_rssi.total_num =
 929                            PHY_RSSI_SLID_WIN_MAX;
 930                        last_rssi =
 931                            rtlpriv->stats.ui_rssi.elements[rtlpriv->
 932                                                           stats.ui_rssi.index];
 933                        rtlpriv->stats.ui_rssi.total_val -= last_rssi;
 934                }
 935                rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength;
 936                rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.
 937                                        index++] = pstats->signalstrength;
 938                if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
 939                        rtlpriv->stats.ui_rssi.index = 0;
 940                tmpval = rtlpriv->stats.ui_rssi.total_val /
 941                    rtlpriv->stats.ui_rssi.total_num;
 942                rtlpriv->stats.signal_strength =
 943                    _rtl92c_translate_todbm(hw, (u8) tmpval);
 944                pstats->rssi = rtlpriv->stats.signal_strength;
 945        }
 946        if (!pstats->is_cck && pstats->packet_toself) {
 947                for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
 948                     rfpath++) {
 949                        if (!rtl8192_phy_check_is_legal_rfpath(hw, rfpath))
 950                                continue;
 951                        if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
 952                                rtlpriv->stats.rx_rssi_percentage[rfpath] =
 953                                    pstats->rx_mimo_signalstrength[rfpath];
 954                        }
 955                        if (pstats->rx_mimo_signalstrength[rfpath] >
 956                            rtlpriv->stats.rx_rssi_percentage[rfpath]) {
 957                                rtlpriv->stats.rx_rssi_percentage[rfpath] =
 958                                    ((rtlpriv->stats.
 959                                      rx_rssi_percentage[rfpath] *
 960                                      (RX_SMOOTH_FACTOR - 1)) +
 961                                     (pstats->rx_mimo_signalstrength[rfpath])) /
 962                                    (RX_SMOOTH_FACTOR);
 963
 964                                rtlpriv->stats.rx_rssi_percentage[rfpath] =
 965                                    rtlpriv->stats.rx_rssi_percentage[rfpath] +
 966                                    1;
 967                        } else {
 968                                rtlpriv->stats.rx_rssi_percentage[rfpath] =
 969                                    ((rtlpriv->stats.
 970                                      rx_rssi_percentage[rfpath] *
 971                                      (RX_SMOOTH_FACTOR - 1)) +
 972                                     (pstats->rx_mimo_signalstrength[rfpath])) /
 973                                    (RX_SMOOTH_FACTOR);
 974                        }
 975                }
 976        }
 977}
 978
 979static void _rtl92c_update_rxsignalstatistics(struct ieee80211_hw *hw,
 980                                               struct rtl_stats *pstats)
 981{
 982        struct rtl_priv *rtlpriv = rtl_priv(hw);
 983        int weighting = 0;
 984
 985        if (rtlpriv->stats.recv_signal_power == 0)
 986                rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
 987        if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power)
 988                weighting = 5;
 989        else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power)
 990                weighting = (-5);
 991        rtlpriv->stats.recv_signal_power =
 992            (rtlpriv->stats.recv_signal_power * 5 +
 993             pstats->recvsignalpower + weighting) / 6;
 994}
 995
 996static void _rtl92c_process_pwdb(struct ieee80211_hw *hw,
 997                struct rtl_stats *pstats)
 998{
 999        struct rtl_priv *rtlpriv = rtl_priv(hw);
1000        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1001        long undec_sm_pwdb = 0;
1002
1003        if (mac->opmode == NL80211_IFTYPE_ADHOC) {
1004                return;
1005        } else {
1006                undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
1007        }
1008        if (pstats->packet_toself || pstats->packet_beacon) {
1009                if (undec_sm_pwdb < 0)
1010                        undec_sm_pwdb = pstats->rx_pwdb_all;
1011                if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) {
1012                        undec_sm_pwdb = (((undec_sm_pwdb) *
1013                              (RX_SMOOTH_FACTOR - 1)) +
1014                             (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
1015                        undec_sm_pwdb += 1;
1016                } else {
1017                        undec_sm_pwdb = (((undec_sm_pwdb) *
1018                              (RX_SMOOTH_FACTOR - 1)) +
1019                             (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
1020                }
1021                rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
1022                _rtl92c_update_rxsignalstatistics(hw, pstats);
1023        }
1024}
1025
1026static void _rtl92c_process_LINK_Q(struct ieee80211_hw *hw,
1027                                             struct rtl_stats *pstats)
1028{
1029        struct rtl_priv *rtlpriv = rtl_priv(hw);
1030        u32 last_evm = 0, n_stream, tmpval;
1031
1032        if (pstats->signalquality != 0) {
1033                if (pstats->packet_toself || pstats->packet_beacon) {
1034                        if (rtlpriv->stats.LINK_Q.total_num++ >=
1035                            PHY_LINKQUALITY_SLID_WIN_MAX) {
1036                                rtlpriv->stats.LINK_Q.total_num =
1037                                    PHY_LINKQUALITY_SLID_WIN_MAX;
1038                                last_evm =
1039                                    rtlpriv->stats.LINK_Q.elements
1040                                    [rtlpriv->stats.LINK_Q.index];
1041                                rtlpriv->stats.LINK_Q.total_val -=
1042                                    last_evm;
1043                        }
1044                        rtlpriv->stats.LINK_Q.total_val +=
1045                            pstats->signalquality;
1046                        rtlpriv->stats.LINK_Q.elements
1047                           [rtlpriv->stats.LINK_Q.index++] =
1048                            pstats->signalquality;
1049                        if (rtlpriv->stats.LINK_Q.index >=
1050                            PHY_LINKQUALITY_SLID_WIN_MAX)
1051                                rtlpriv->stats.LINK_Q.index = 0;
1052                        tmpval = rtlpriv->stats.LINK_Q.total_val /
1053                            rtlpriv->stats.LINK_Q.total_num;
1054                        rtlpriv->stats.signal_quality = tmpval;
1055                        rtlpriv->stats.last_sigstrength_inpercent = tmpval;
1056                        for (n_stream = 0; n_stream < 2;
1057                             n_stream++) {
1058                                if (pstats->RX_SIGQ[n_stream] != -1) {
1059                                        if (!rtlpriv->stats.RX_EVM[n_stream]) {
1060                                                rtlpriv->stats.RX_EVM[n_stream]
1061                                                 = pstats->RX_SIGQ[n_stream];
1062                                        }
1063                                        rtlpriv->stats.RX_EVM[n_stream] =
1064                                            ((rtlpriv->stats.RX_EVM
1065                                            [n_stream] *
1066                                            (RX_SMOOTH_FACTOR - 1)) +
1067                                            (pstats->RX_SIGQ
1068                                            [n_stream] * 1)) /
1069                                            (RX_SMOOTH_FACTOR);
1070                                }
1071                        }
1072                }
1073        } else {
1074                ;
1075        }
1076}
1077
1078static void _rtl92c_process_phyinfo(struct ieee80211_hw *hw,
1079                                     u8 *buffer,
1080                                     struct rtl_stats *pcurrent_stats)
1081{
1082        if (!pcurrent_stats->packet_matchbssid &&
1083            !pcurrent_stats->packet_beacon)
1084                return;
1085        _rtl92c_process_ui_rssi(hw, pcurrent_stats);
1086        _rtl92c_process_pwdb(hw, pcurrent_stats);
1087        _rtl92c_process_LINK_Q(hw, pcurrent_stats);
1088}
1089
1090void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
1091                                               struct sk_buff *skb,
1092                                               struct rtl_stats *pstats,
1093                                               struct rx_desc_92c *pdesc,
1094                                               struct rx_fwinfo_92c *p_drvinfo)
1095{
1096        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1097        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1098        struct ieee80211_hdr *hdr;
1099        u8 *tmp_buf;
1100        u8 *praddr;
1101        __le16 fc;
1102        u16 type, cpu_fc;
1103        bool packet_matchbssid, packet_toself, packet_beacon = false;
1104
1105        tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
1106        hdr = (struct ieee80211_hdr *)tmp_buf;
1107        fc = hdr->frame_control;
1108        cpu_fc = le16_to_cpu(fc);
1109        type = WLAN_FC_GET_TYPE(fc);
1110        praddr = hdr->addr1;
1111        packet_matchbssid =
1112            ((IEEE80211_FTYPE_CTL != type) &&
1113             ether_addr_equal(mac->bssid,
1114                              (cpu_fc & IEEE80211_FCTL_TODS) ? hdr->addr1 :
1115                              (cpu_fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 :
1116                              hdr->addr3) &&
1117             (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv));
1118
1119        packet_toself = packet_matchbssid &&
1120            ether_addr_equal(praddr, rtlefuse->dev_addr);
1121        if (ieee80211_is_beacon(fc))
1122                packet_beacon = true;
1123        _rtl92c_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
1124                                   packet_matchbssid, packet_toself,
1125                                   packet_beacon);
1126        _rtl92c_process_phyinfo(hw, tmp_buf, pstats);
1127}
1128