Linux Audio

Check our new training course

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