Linux Audio

Check our new training course

Embedded Linux training

Mar 10-20, 2025, special US time zones
Register
Loading...
Note: File does not exist in v5.4.
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2009-2010  Realtek Corporation.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of version 2 of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  12 * more details.
  13 *
  14 * You should have received a copy of the GNU General Public License along with
  15 * this program; if not, write to the Free Software Foundation, Inc.,
  16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17 *
  18 * The full GNU General Public License is included in this distribution in the
  19 * file called LICENSE.
  20 *
  21 * Contact Information:
  22 * wlanfae <wlanfae@realtek.com>
  23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
  24 * Hsinchu 300, Taiwan.
  25 *
  26 * Larry Finger <Larry.Finger@lwfinger.net>
  27 *
  28 *****************************************************************************/
  29
  30#include "../wifi.h"
  31#include "../pci.h"
  32#include "../base.h"
  33#include "reg.h"
  34#include "def.h"
  35#include "phy.h"
  36#include "trx.h"
  37#include "led.h"
  38
  39static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
  40{
  41	__le16 fc = rtl_get_fc(skb);
  42
  43	if (unlikely(ieee80211_is_beacon(fc)))
  44		return QSLT_BEACON;
  45	if (ieee80211_is_mgmt(fc))
  46		return QSLT_MGNT;
  47
  48	return skb->priority;
  49}
  50
  51static int _rtl92ce_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu)
  52{
  53	int rate_idx;
  54
  55	if (first_ampdu) {
  56		if (false == isht) {
  57			switch (desc_rate) {
  58			case DESC92C_RATE1M:
  59				rate_idx = 0;
  60				break;
  61			case DESC92C_RATE2M:
  62				rate_idx = 1;
  63				break;
  64			case DESC92C_RATE5_5M:
  65				rate_idx = 2;
  66				break;
  67			case DESC92C_RATE11M:
  68				rate_idx = 3;
  69				break;
  70			case DESC92C_RATE6M:
  71				rate_idx = 4;
  72				break;
  73			case DESC92C_RATE9M:
  74				rate_idx = 5;
  75				break;
  76			case DESC92C_RATE12M:
  77				rate_idx = 6;
  78				break;
  79			case DESC92C_RATE18M:
  80				rate_idx = 7;
  81				break;
  82			case DESC92C_RATE24M:
  83				rate_idx = 8;
  84				break;
  85			case DESC92C_RATE36M:
  86				rate_idx = 9;
  87				break;
  88			case DESC92C_RATE48M:
  89				rate_idx = 10;
  90				break;
  91			case DESC92C_RATE54M:
  92				rate_idx = 11;
  93				break;
  94			default:
  95				rate_idx = 0;
  96				break;
  97			}
  98		} else {
  99			rate_idx = 11;
 100		}
 101
 102		return rate_idx;
 103	}
 104
 105	switch (desc_rate) {
 106	case DESC92C_RATE1M:
 107		rate_idx = 0;
 108		break;
 109	case DESC92C_RATE2M:
 110		rate_idx = 1;
 111		break;
 112	case DESC92C_RATE5_5M:
 113		rate_idx = 2;
 114		break;
 115	case DESC92C_RATE11M:
 116		rate_idx = 3;
 117		break;
 118	case DESC92C_RATE6M:
 119		rate_idx = 4;
 120		break;
 121	case DESC92C_RATE9M:
 122		rate_idx = 5;
 123		break;
 124	case DESC92C_RATE12M:
 125		rate_idx = 6;
 126		break;
 127	case DESC92C_RATE18M:
 128		rate_idx = 7;
 129		break;
 130	case DESC92C_RATE24M:
 131		rate_idx = 8;
 132		break;
 133	case DESC92C_RATE36M:
 134		rate_idx = 9;
 135		break;
 136	case DESC92C_RATE48M:
 137		rate_idx = 10;
 138		break;
 139	case DESC92C_RATE54M:
 140		rate_idx = 11;
 141		break;
 142	default:
 143		rate_idx = 11;
 144		break;
 145	}
 146	return rate_idx;
 147}
 148
 149static u8 _rtl92c_query_rxpwrpercentage(char antpower)
 150{
 151	if ((antpower <= -100) || (antpower >= 20))
 152		return 0;
 153	else if (antpower >= 0)
 154		return 100;
 155	else
 156		return 100 + antpower;
 157}
 158
 159static u8 _rtl92c_evm_db_to_percentage(char value)
 160{
 161	char ret_val;
 162	ret_val = value;
 163
 164	if (ret_val >= 0)
 165		ret_val = 0;
 166
 167	if (ret_val <= -33)
 168		ret_val = -33;
 169
 170	ret_val = 0 - ret_val;
 171	ret_val *= 3;
 172
 173	if (ret_val == 99)
 174		ret_val = 100;
 175
 176	return ret_val;
 177}
 178
 179static long _rtl92ce_translate_todbm(struct ieee80211_hw *hw,
 180				     u8 signal_strength_index)
 181{
 182	long signal_power;
 183
 184	signal_power = (long)((signal_strength_index + 1) >> 1);
 185	signal_power -= 95;
 186	return signal_power;
 187}
 188
 189static long _rtl92ce_signal_scale_mapping(struct ieee80211_hw *hw,
 190		long currsig)
 191{
 192	long retsig;
 193
 194	if (currsig >= 61 && currsig <= 100)
 195		retsig = 90 + ((currsig - 60) / 4);
 196	else if (currsig >= 41 && currsig <= 60)
 197		retsig = 78 + ((currsig - 40) / 2);
 198	else if (currsig >= 31 && currsig <= 40)
 199		retsig = 66 + (currsig - 30);
 200	else if (currsig >= 21 && currsig <= 30)
 201		retsig = 54 + (currsig - 20);
 202	else if (currsig >= 5 && currsig <= 20)
 203		retsig = 42 + (((currsig - 5) * 2) / 3);
 204	else if (currsig == 4)
 205		retsig = 36;
 206	else if (currsig == 3)
 207		retsig = 27;
 208	else if (currsig == 2)
 209		retsig = 18;
 210	else if (currsig == 1)
 211		retsig = 9;
 212	else
 213		retsig = currsig;
 214
 215	return retsig;
 216}
 217
 218static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 219				       struct rtl_stats *pstats,
 220				       struct rx_desc_92c *pdesc,
 221				       struct rx_fwinfo_92c *p_drvinfo,
 222				       bool packet_match_bssid,
 223				       bool packet_toself,
 224				       bool packet_beacon)
 225{
 226	struct rtl_priv *rtlpriv = rtl_priv(hw);
 227	struct phy_sts_cck_8192s_t *cck_buf;
 228	s8 rx_pwr_all = 0, rx_pwr[4];
 229	u8 evm, pwdb_all, rf_rx_num = 0;
 230	u8 i, max_spatial_stream;
 231	u32 rssi, total_rssi = 0;
 232	bool in_powersavemode = false;
 233	bool is_cck_rate;
 234
 235	is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
 236	pstats->packet_matchbssid = packet_match_bssid;
 237	pstats->packet_toself = packet_toself;
 238	pstats->is_cck = is_cck_rate;
 239	pstats->packet_beacon = packet_beacon;
 240	pstats->is_cck = is_cck_rate;
 241	pstats->rx_mimo_signalquality[0] = -1;
 242	pstats->rx_mimo_signalquality[1] = -1;
 243
 244	if (is_cck_rate) {
 245		u8 report, cck_highpwr;
 246		cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
 247
 248		if (!in_powersavemode)
 249			cck_highpwr = (u8) rtl_get_bbreg(hw,
 250						 RFPGA0_XA_HSSIPARAMETER2,
 251						 BIT(9));
 252		else
 253			cck_highpwr = false;
 254
 255		if (!cck_highpwr) {
 256			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
 257			report = cck_buf->cck_agc_rpt & 0xc0;
 258			report = report >> 6;
 259			switch (report) {
 260			case 0x3:
 261				rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
 262				break;
 263			case 0x2:
 264				rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
 265				break;
 266			case 0x1:
 267				rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
 268				break;
 269			case 0x0:
 270				rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
 271				break;
 272			}
 273		} else {
 274			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
 275			report = p_drvinfo->cfosho[0] & 0x60;
 276			report = report >> 5;
 277			switch (report) {
 278			case 0x3:
 279				rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
 280				break;
 281			case 0x2:
 282				rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
 283				break;
 284			case 0x1:
 285				rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
 286				break;
 287			case 0x0:
 288				rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
 289				break;
 290			}
 291		}
 292
 293		pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
 294		pstats->rx_pwdb_all = pwdb_all;
 295		pstats->recvsignalpower = rx_pwr_all;
 296
 297		if (packet_match_bssid) {
 298			u8 sq;
 299			if (pstats->rx_pwdb_all > 40)
 300				sq = 100;
 301			else {
 302				sq = cck_buf->sq_rpt;
 303				if (sq > 64)
 304					sq = 0;
 305				else if (sq < 20)
 306					sq = 100;
 307				else
 308					sq = ((64 - sq) * 100) / 44;
 309			}
 310
 311			pstats->signalquality = sq;
 312			pstats->rx_mimo_signalquality[0] = sq;
 313			pstats->rx_mimo_signalquality[1] = -1;
 314		}
 315	} else {
 316		rtlpriv->dm.rfpath_rxenable[0] =
 317		    rtlpriv->dm.rfpath_rxenable[1] = true;
 318		for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
 319			if (rtlpriv->dm.rfpath_rxenable[i])
 320				rf_rx_num++;
 321
 322			rx_pwr[i] =
 323			    ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110;
 324			rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]);
 325			total_rssi += rssi;
 326			rtlpriv->stats.rx_snr_db[i] =
 327			    (long)(p_drvinfo->rxsnr[i] / 2);
 328
 329			if (packet_match_bssid)
 330				pstats->rx_mimo_signalstrength[i] = (u8) rssi;
 331		}
 332
 333		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
 334		pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
 335		pstats->rx_pwdb_all = pwdb_all;
 336		pstats->rxpower = rx_pwr_all;
 337		pstats->recvsignalpower = rx_pwr_all;
 338
 339		if (pdesc->rxht && pdesc->rxmcs >= DESC92C_RATEMCS8 &&
 340		    pdesc->rxmcs <= DESC92C_RATEMCS15)
 341			max_spatial_stream = 2;
 342		else
 343			max_spatial_stream = 1;
 344
 345		for (i = 0; i < max_spatial_stream; i++) {
 346			evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]);
 347
 348			if (packet_match_bssid) {
 349				if (i == 0)
 350					pstats->signalquality =
 351					    (u8) (evm & 0xff);
 352				pstats->rx_mimo_signalquality[i] =
 353				    (u8) (evm & 0xff);
 354			}
 355		}
 356	}
 357
 358	if (is_cck_rate)
 359		pstats->signalstrength =
 360		    (u8) (_rtl92ce_signal_scale_mapping(hw, pwdb_all));
 361	else if (rf_rx_num != 0)
 362		pstats->signalstrength =
 363		    (u8) (_rtl92ce_signal_scale_mapping
 364			  (hw, total_rssi /= rf_rx_num));
 365}
 366
 367static void _rtl92ce_process_ui_rssi(struct ieee80211_hw *hw,
 368		struct rtl_stats *pstats)
 369{
 370	struct rtl_priv *rtlpriv = rtl_priv(hw);
 371	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 372	u8 rfpath;
 373	u32 last_rssi, tmpval;
 374
 375	if (pstats->packet_toself || pstats->packet_beacon) {
 376		rtlpriv->stats.rssi_calculate_cnt++;
 377
 378		if (rtlpriv->stats.ui_rssi.total_num++ >=
 379		    PHY_RSSI_SLID_WIN_MAX) {
 380
 381			rtlpriv->stats.ui_rssi.total_num =
 382			    PHY_RSSI_SLID_WIN_MAX;
 383			last_rssi =
 384			    rtlpriv->stats.ui_rssi.elements[rtlpriv->
 385						    stats.ui_rssi.index];
 386			rtlpriv->stats.ui_rssi.total_val -= last_rssi;
 387		}
 388
 389		rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength;
 390		rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.
 391						index++] =
 392		    pstats->signalstrength;
 393
 394		if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
 395			rtlpriv->stats.ui_rssi.index = 0;
 396
 397		tmpval = rtlpriv->stats.ui_rssi.total_val /
 398		    rtlpriv->stats.ui_rssi.total_num;
 399		rtlpriv->stats.signal_strength =
 400		    _rtl92ce_translate_todbm(hw, (u8) tmpval);
 401		pstats->rssi = rtlpriv->stats.signal_strength;
 402	}
 403
 404	if (!pstats->is_cck && pstats->packet_toself) {
 405		for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
 406		     rfpath++) {
 407			if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
 408				rtlpriv->stats.rx_rssi_percentage[rfpath] =
 409				    pstats->rx_mimo_signalstrength[rfpath];
 410
 411			}
 412
 413			if (pstats->rx_mimo_signalstrength[rfpath] >
 414			    rtlpriv->stats.rx_rssi_percentage[rfpath]) {
 415				rtlpriv->stats.rx_rssi_percentage[rfpath] =
 416				    ((rtlpriv->stats.
 417				      rx_rssi_percentage[rfpath] *
 418				      (RX_SMOOTH_FACTOR - 1)) +
 419				     (pstats->rx_mimo_signalstrength[rfpath])) /
 420				    (RX_SMOOTH_FACTOR);
 421
 422				rtlpriv->stats.rx_rssi_percentage[rfpath] =
 423				    rtlpriv->stats.rx_rssi_percentage[rfpath] +
 424				    1;
 425			} else {
 426				rtlpriv->stats.rx_rssi_percentage[rfpath] =
 427				    ((rtlpriv->stats.
 428				      rx_rssi_percentage[rfpath] *
 429				      (RX_SMOOTH_FACTOR - 1)) +
 430				     (pstats->rx_mimo_signalstrength[rfpath])) /
 431				    (RX_SMOOTH_FACTOR);
 432			}
 433
 434		}
 435	}
 436}
 437
 438static void _rtl92ce_update_rxsignalstatistics(struct ieee80211_hw *hw,
 439					       struct rtl_stats *pstats)
 440{
 441	struct rtl_priv *rtlpriv = rtl_priv(hw);
 442	int weighting = 0;
 443
 444	if (rtlpriv->stats.recv_signal_power == 0)
 445		rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
 446
 447	if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power)
 448		weighting = 5;
 449
 450	else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power)
 451		weighting = (-5);
 452
 453	rtlpriv->stats.recv_signal_power =
 454	    (rtlpriv->stats.recv_signal_power * 5 +
 455	     pstats->recvsignalpower + weighting) / 6;
 456}
 457
 458static void _rtl92ce_process_pwdb(struct ieee80211_hw *hw,
 459		struct rtl_stats *pstats)
 460{
 461	struct rtl_priv *rtlpriv = rtl_priv(hw);
 462	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 463	long undecorated_smoothed_pwdb;
 464
 465	if (mac->opmode == NL80211_IFTYPE_ADHOC) {
 466		return;
 467	} else {
 468		undecorated_smoothed_pwdb =
 469		    rtlpriv->dm.undecorated_smoothed_pwdb;
 470	}
 471
 472	if (pstats->packet_toself || pstats->packet_beacon) {
 473		if (undecorated_smoothed_pwdb < 0)
 474			undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
 475
 476		if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
 477			undecorated_smoothed_pwdb =
 478			    (((undecorated_smoothed_pwdb) *
 479			      (RX_SMOOTH_FACTOR - 1)) +
 480			     (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
 481
 482			undecorated_smoothed_pwdb = undecorated_smoothed_pwdb
 483			    + 1;
 484		} else {
 485			undecorated_smoothed_pwdb =
 486			    (((undecorated_smoothed_pwdb) *
 487			      (RX_SMOOTH_FACTOR - 1)) +
 488			     (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
 489		}
 490
 491		rtlpriv->dm.undecorated_smoothed_pwdb =
 492		    undecorated_smoothed_pwdb;
 493		_rtl92ce_update_rxsignalstatistics(hw, pstats);
 494	}
 495}
 496
 497static void _rtl92ce_process_ui_link_quality(struct ieee80211_hw *hw,
 498					     struct rtl_stats *pstats)
 499{
 500	struct rtl_priv *rtlpriv = rtl_priv(hw);
 501	u32 last_evm, n_spatialstream, tmpval;
 502
 503	if (pstats->signalquality != 0) {
 504		if (pstats->packet_toself || pstats->packet_beacon) {
 505
 506			if (rtlpriv->stats.ui_link_quality.total_num++ >=
 507			    PHY_LINKQUALITY_SLID_WIN_MAX) {
 508				rtlpriv->stats.ui_link_quality.total_num =
 509				    PHY_LINKQUALITY_SLID_WIN_MAX;
 510				last_evm =
 511				    rtlpriv->stats.
 512				    ui_link_quality.elements[rtlpriv->
 513							  stats.ui_link_quality.
 514							  index];
 515				rtlpriv->stats.ui_link_quality.total_val -=
 516				    last_evm;
 517			}
 518
 519			rtlpriv->stats.ui_link_quality.total_val +=
 520			    pstats->signalquality;
 521			rtlpriv->stats.ui_link_quality.elements[rtlpriv->stats.
 522								ui_link_quality.
 523								index++] =
 524			    pstats->signalquality;
 525
 526			if (rtlpriv->stats.ui_link_quality.index >=
 527			    PHY_LINKQUALITY_SLID_WIN_MAX)
 528				rtlpriv->stats.ui_link_quality.index = 0;
 529
 530			tmpval = rtlpriv->stats.ui_link_quality.total_val /
 531			    rtlpriv->stats.ui_link_quality.total_num;
 532			rtlpriv->stats.signal_quality = tmpval;
 533
 534			rtlpriv->stats.last_sigstrength_inpercent = tmpval;
 535
 536			for (n_spatialstream = 0; n_spatialstream < 2;
 537			     n_spatialstream++) {
 538				if (pstats->
 539				    rx_mimo_signalquality[n_spatialstream] !=
 540				    -1) {
 541					if (rtlpriv->stats.
 542					    rx_evm_percentage[n_spatialstream]
 543					    == 0) {
 544						rtlpriv->stats.
 545						   rx_evm_percentage
 546						   [n_spatialstream] =
 547						   pstats->rx_mimo_signalquality
 548						   [n_spatialstream];
 549					}
 550
 551					rtlpriv->stats.
 552					    rx_evm_percentage[n_spatialstream] =
 553					    ((rtlpriv->
 554					      stats.rx_evm_percentage
 555					      [n_spatialstream] *
 556					      (RX_SMOOTH_FACTOR - 1)) +
 557					     (pstats->
 558					      rx_mimo_signalquality
 559					      [n_spatialstream] * 1)) /
 560					    (RX_SMOOTH_FACTOR);
 561				}
 562			}
 563		}
 564	} else {
 565		;
 566	}
 567}
 568
 569static void _rtl92ce_process_phyinfo(struct ieee80211_hw *hw,
 570				     u8 *buffer,
 571				     struct rtl_stats *pcurrent_stats)
 572{
 573
 574	if (!pcurrent_stats->packet_matchbssid &&
 575	    !pcurrent_stats->packet_beacon)
 576		return;
 577
 578	_rtl92ce_process_ui_rssi(hw, pcurrent_stats);
 579	_rtl92ce_process_pwdb(hw, pcurrent_stats);
 580	_rtl92ce_process_ui_link_quality(hw, pcurrent_stats);
 581}
 582
 583static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw,
 584					       struct sk_buff *skb,
 585					       struct rtl_stats *pstats,
 586					       struct rx_desc_92c *pdesc,
 587					       struct rx_fwinfo_92c *p_drvinfo)
 588{
 589	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 590	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 591
 592	struct ieee80211_hdr *hdr;
 593	u8 *tmp_buf;
 594	u8 *praddr;
 595	__le16 fc;
 596	u16 type, c_fc;
 597	bool packet_matchbssid, packet_toself, packet_beacon;
 598
 599	tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
 600
 601	hdr = (struct ieee80211_hdr *)tmp_buf;
 602	fc = hdr->frame_control;
 603	c_fc = le16_to_cpu(fc);
 604	type = WLAN_FC_GET_TYPE(fc);
 605	praddr = hdr->addr1;
 606
 607	packet_matchbssid =
 608	    ((IEEE80211_FTYPE_CTL != type) &&
 609	     (!compare_ether_addr(mac->bssid,
 610				  (c_fc & IEEE80211_FCTL_TODS) ?
 611				  hdr->addr1 : (c_fc & IEEE80211_FCTL_FROMDS) ?
 612				  hdr->addr2 : hdr->addr3)) &&
 613	     (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv));
 614
 615	packet_toself = packet_matchbssid &&
 616	    (!compare_ether_addr(praddr, rtlefuse->dev_addr));
 617
 618	if (ieee80211_is_beacon(fc))
 619		packet_beacon = true;
 620
 621	_rtl92ce_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
 622				   packet_matchbssid, packet_toself,
 623				   packet_beacon);
 624
 625	_rtl92ce_process_phyinfo(hw, tmp_buf, pstats);
 626}
 627
 628bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
 629			   struct rtl_stats *stats,
 630			   struct ieee80211_rx_status *rx_status,
 631			   u8 *p_desc, struct sk_buff *skb)
 632{
 633	struct rx_fwinfo_92c *p_drvinfo;
 634	struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
 635
 636	u32 phystatus = GET_RX_DESC_PHYST(pdesc);
 637	stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
 638	stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) *
 639	    RX_DRV_INFO_SIZE_UNIT;
 640	stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03);
 641	stats->icv = (u16) GET_RX_DESC_ICV(pdesc);
 642	stats->crc = (u16) GET_RX_DESC_CRC32(pdesc);
 643	stats->hwerror = (stats->crc | stats->icv);
 644	stats->decrypted = !GET_RX_DESC_SWDEC(pdesc);
 645	stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc);
 646	stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
 647	stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
 648	stats->isampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
 649				   && (GET_RX_DESC_FAGGR(pdesc) == 1));
 650	stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
 651	stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
 652
 653	rx_status->freq = hw->conf.channel->center_freq;
 654	rx_status->band = hw->conf.channel->band;
 655
 656	if (GET_RX_DESC_CRC32(pdesc))
 657		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
 658
 659	if (!GET_RX_DESC_SWDEC(pdesc))
 660		rx_status->flag |= RX_FLAG_DECRYPTED;
 661
 662	if (GET_RX_DESC_BW(pdesc))
 663		rx_status->flag |= RX_FLAG_40MHZ;
 664
 665	if (GET_RX_DESC_RXHT(pdesc))
 666		rx_status->flag |= RX_FLAG_HT;
 667
 668	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
 669
 670	if (stats->decrypted)
 671		rx_status->flag |= RX_FLAG_DECRYPTED;
 672
 673	rx_status->rate_idx = _rtl92ce_rate_mapping((bool)
 674						    GET_RX_DESC_RXHT(pdesc),
 675						    (u8)
 676						    GET_RX_DESC_RXMCS(pdesc),
 677						    (bool)
 678						    GET_RX_DESC_PAGGR(pdesc));
 679
 680	rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
 681	if (phystatus) {
 682		p_drvinfo = (struct rx_fwinfo_92c *)(skb->data +
 683						     stats->rx_bufshift);
 684
 685		_rtl92ce_translate_rx_signal_stuff(hw,
 686						   skb, stats, pdesc,
 687						   p_drvinfo);
 688	}
 689
 690	/*rx_status->qual = stats->signal; */
 691	rx_status->signal = stats->rssi + 10;
 692	/*rx_status->noise = -stats->noise; */
 693
 694	return true;
 695}
 696
 697void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
 698			  struct ieee80211_hdr *hdr, u8 *pdesc_tx,
 699			  struct ieee80211_tx_info *info, struct sk_buff *skb,
 700			  u8 hw_queue, struct rtl_tcb_desc *tcb_desc)
 701{
 702	struct rtl_priv *rtlpriv = rtl_priv(hw);
 703	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 704	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 705	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 706	bool defaultadapter = true;
 707	struct ieee80211_sta *sta;
 708	u8 *pdesc = (u8 *) pdesc_tx;
 709	u16 seq_number;
 710	__le16 fc = hdr->frame_control;
 711	u8 fw_qsel = _rtl92ce_map_hwqueue_to_fwqueue(skb, hw_queue);
 712	bool firstseg = ((hdr->seq_ctrl &
 713			  cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
 714
 715	bool lastseg = ((hdr->frame_control &
 716			 cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
 717
 718	dma_addr_t mapping = pci_map_single(rtlpci->pdev,
 719					    skb->data, skb->len,
 720					    PCI_DMA_TODEVICE);
 721	u8 bw_40 = 0;
 722
 723	rcu_read_lock();
 724	sta = get_sta(hw, mac->vif, mac->bssid);
 725	if (mac->opmode == NL80211_IFTYPE_STATION) {
 726		bw_40 = mac->bw_40;
 727	} else if (mac->opmode == NL80211_IFTYPE_AP ||
 728		mac->opmode == NL80211_IFTYPE_ADHOC) {
 729		if (sta)
 730			bw_40 = sta->ht_cap.cap &
 731				IEEE80211_HT_CAP_SUP_WIDTH_20_40;
 732	}
 733
 734	seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
 735
 736	rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc);
 737
 738	CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92c));
 739
 740	if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) {
 741		firstseg = true;
 742		lastseg = true;
 743	}
 744	if (firstseg) {
 745		SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
 746
 747		SET_TX_DESC_TX_RATE(pdesc, tcb_desc->hw_rate);
 748
 749		if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble)
 750			SET_TX_DESC_DATA_SHORTGI(pdesc, 1);
 751
 752		if (info->flags & IEEE80211_TX_CTL_AMPDU) {
 753			SET_TX_DESC_AGG_BREAK(pdesc, 1);
 754			SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14);
 755		}
 756		SET_TX_DESC_SEQ(pdesc, seq_number);
 757
 758		SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc->rts_enable &&
 759						!tcb_desc->
 760						cts_enable) ? 1 : 0));
 761		SET_TX_DESC_HW_RTS_ENABLE(pdesc,
 762					  ((tcb_desc->rts_enable
 763					    || tcb_desc->cts_enable) ? 1 : 0));
 764		SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc->cts_enable) ? 1 : 0));
 765		SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc->rts_stbc) ? 1 : 0));
 766
 767		SET_TX_DESC_RTS_RATE(pdesc, tcb_desc->rts_rate);
 768		SET_TX_DESC_RTS_BW(pdesc, 0);
 769		SET_TX_DESC_RTS_SC(pdesc, tcb_desc->rts_sc);
 770		SET_TX_DESC_RTS_SHORT(pdesc,
 771				      ((tcb_desc->rts_rate <= DESC92C_RATE54M) ?
 772				       (tcb_desc->rts_use_shortpreamble ? 1 : 0)
 773				       : (tcb_desc->rts_use_shortgi ? 1 : 0)));
 774
 775		if (bw_40) {
 776			if (tcb_desc->packet_bw) {
 777				SET_TX_DESC_DATA_BW(pdesc, 1);
 778				SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3);
 779			} else {
 780				SET_TX_DESC_DATA_BW(pdesc, 0);
 781				SET_TX_DESC_TX_SUB_CARRIER(pdesc,
 782						 mac->cur_40_prime_sc);
 783			}
 784		} else {
 785			SET_TX_DESC_DATA_BW(pdesc, 0);
 786			SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0);
 787		}
 788
 789		SET_TX_DESC_LINIP(pdesc, 0);
 790		SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len);
 791
 792		if (sta) {
 793			u8 ampdu_density = sta->ht_cap.ampdu_density;
 794			SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density);
 795		}
 796
 797		if (info->control.hw_key) {
 798			struct ieee80211_key_conf *keyconf =
 799			    info->control.hw_key;
 800
 801			switch (keyconf->cipher) {
 802			case WLAN_CIPHER_SUITE_WEP40:
 803			case WLAN_CIPHER_SUITE_WEP104:
 804			case WLAN_CIPHER_SUITE_TKIP:
 805				SET_TX_DESC_SEC_TYPE(pdesc, 0x1);
 806				break;
 807			case WLAN_CIPHER_SUITE_CCMP:
 808				SET_TX_DESC_SEC_TYPE(pdesc, 0x3);
 809				break;
 810			default:
 811				SET_TX_DESC_SEC_TYPE(pdesc, 0x0);
 812				break;
 813
 814			}
 815		}
 816
 817		SET_TX_DESC_PKT_ID(pdesc, 0);
 818		SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel);
 819
 820		SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F);
 821		SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF);
 822		SET_TX_DESC_DISABLE_FB(pdesc, 0);
 823		SET_TX_DESC_USE_RATE(pdesc, tcb_desc->use_driver_rate ? 1 : 0);
 824
 825		if (ieee80211_is_data_qos(fc)) {
 826			if (mac->rdg_en) {
 827				RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
 828					 ("Enable RDG function.\n"));
 829				SET_TX_DESC_RDG_ENABLE(pdesc, 1);
 830				SET_TX_DESC_HTC(pdesc, 1);
 831			}
 832		}
 833	}
 834	rcu_read_unlock();
 835
 836	SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0));
 837	SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0));
 838
 839	SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len);
 840
 841	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
 842
 843	if (rtlpriv->dm.useramask) {
 844		SET_TX_DESC_RATE_ID(pdesc, tcb_desc->ratr_index);
 845		SET_TX_DESC_MACID(pdesc, tcb_desc->mac_id);
 846	} else {
 847		SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc->ratr_index);
 848		SET_TX_DESC_MACID(pdesc, tcb_desc->ratr_index);
 849	}
 850
 851	if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) {
 852		SET_TX_DESC_HWSEQ_EN(pdesc, 1);
 853		SET_TX_DESC_PKT_ID(pdesc, 8);
 854
 855		if (!defaultadapter)
 856			SET_TX_DESC_QOS(pdesc, 1);
 857	}
 858
 859	SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1));
 860
 861	if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
 862	    is_broadcast_ether_addr(ieee80211_get_DA(hdr))) {
 863		SET_TX_DESC_BMC(pdesc, 1);
 864	}
 865
 866	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, ("\n"));
 867}
 868
 869void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
 870			     u8 *pdesc, bool firstseg,
 871			     bool lastseg, struct sk_buff *skb)
 872{
 873	struct rtl_priv *rtlpriv = rtl_priv(hw);
 874	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 875	u8 fw_queue = QSLT_BEACON;
 876
 877	dma_addr_t mapping = pci_map_single(rtlpci->pdev,
 878					    skb->data, skb->len,
 879					    PCI_DMA_TODEVICE);
 880
 881	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
 882	__le16 fc = hdr->frame_control;
 883
 884	CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE);
 885
 886	if (firstseg)
 887		SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
 888
 889	SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M);
 890
 891	SET_TX_DESC_SEQ(pdesc, 0);
 892
 893	SET_TX_DESC_LINIP(pdesc, 0);
 894
 895	SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue);
 896
 897	SET_TX_DESC_FIRST_SEG(pdesc, 1);
 898	SET_TX_DESC_LAST_SEG(pdesc, 1);
 899
 900	SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len));
 901
 902	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
 903
 904	SET_TX_DESC_RATE_ID(pdesc, 7);
 905	SET_TX_DESC_MACID(pdesc, 0);
 906
 907	SET_TX_DESC_OWN(pdesc, 1);
 908
 909	SET_TX_DESC_PKT_SIZE((u8 *) pdesc, (u16) (skb->len));
 910
 911	SET_TX_DESC_FIRST_SEG(pdesc, 1);
 912	SET_TX_DESC_LAST_SEG(pdesc, 1);
 913
 914	SET_TX_DESC_OFFSET(pdesc, 0x20);
 915
 916	SET_TX_DESC_USE_RATE(pdesc, 1);
 917
 918	if (!ieee80211_is_data_qos(fc)) {
 919		SET_TX_DESC_HWSEQ_EN(pdesc, 1);
 920		SET_TX_DESC_PKT_ID(pdesc, 8);
 921	}
 922
 923	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
 924		      "H2C Tx Cmd Content\n",
 925		      pdesc, TX_DESC_SIZE);
 926}
 927
 928void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
 929{
 930	if (istx) {
 931		switch (desc_name) {
 932		case HW_DESC_OWN:
 933			wmb();
 934			SET_TX_DESC_OWN(pdesc, 1);
 935			break;
 936		case HW_DESC_TX_NEXTDESC_ADDR:
 937			SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val);
 938			break;
 939		default:
 940			RT_ASSERT(false, ("ERR txdesc :%d"
 941					  " not process\n", desc_name));
 942			break;
 943		}
 944	} else {
 945		switch (desc_name) {
 946		case HW_DESC_RXOWN:
 947			wmb();
 948			SET_RX_DESC_OWN(pdesc, 1);
 949			break;
 950		case HW_DESC_RXBUFF_ADDR:
 951			SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val);
 952			break;
 953		case HW_DESC_RXPKT_LEN:
 954			SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val);
 955			break;
 956		case HW_DESC_RXERO:
 957			SET_RX_DESC_EOR(pdesc, 1);
 958			break;
 959		default:
 960			RT_ASSERT(false, ("ERR rxdesc :%d "
 961					  "not process\n", desc_name));
 962			break;
 963		}
 964	}
 965}
 966
 967u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name)
 968{
 969	u32 ret = 0;
 970
 971	if (istx) {
 972		switch (desc_name) {
 973		case HW_DESC_OWN:
 974			ret = GET_TX_DESC_OWN(p_desc);
 975			break;
 976		case HW_DESC_TXBUFF_ADDR:
 977			ret = GET_TX_DESC_TX_BUFFER_ADDRESS(p_desc);
 978			break;
 979		default:
 980			RT_ASSERT(false, ("ERR txdesc :%d "
 981					  "not process\n", desc_name));
 982			break;
 983		}
 984	} else {
 985		struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
 986		switch (desc_name) {
 987		case HW_DESC_OWN:
 988			ret = GET_RX_DESC_OWN(pdesc);
 989			break;
 990		case HW_DESC_RXPKT_LEN:
 991			ret = GET_RX_DESC_PKT_LEN(pdesc);
 992			break;
 993		default:
 994			RT_ASSERT(false, ("ERR rxdesc :%d "
 995					  "not process\n", desc_name));
 996			break;
 997		}
 998	}
 999	return ret;
1000}
1001
1002void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
1003{
1004	struct rtl_priv *rtlpriv = rtl_priv(hw);
1005	if (hw_queue == BEACON_QUEUE) {
1006		rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4));
1007	} else {
1008		rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG,
1009			       BIT(0) << (hw_queue));
1010	}
1011}
1012