1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /* Copyright(c) 2009-2014 Realtek Corporation.*/
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun #include "../wifi.h"
5*4882a593Smuzhiyun #include "../pci.h"
6*4882a593Smuzhiyun #include "../base.h"
7*4882a593Smuzhiyun #include "../stats.h"
8*4882a593Smuzhiyun #include "reg.h"
9*4882a593Smuzhiyun #include "def.h"
10*4882a593Smuzhiyun #include "phy.h"
11*4882a593Smuzhiyun #include "trx.h"
12*4882a593Smuzhiyun #include "led.h"
13*4882a593Smuzhiyun #include "dm.h"
14*4882a593Smuzhiyun #include "fw.h"
15*4882a593Smuzhiyun
_rtl92ee_map_hwqueue_to_fwqueue(struct sk_buff * skb,u8 hw_queue)16*4882a593Smuzhiyun static u8 _rtl92ee_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
17*4882a593Smuzhiyun {
18*4882a593Smuzhiyun __le16 fc = rtl_get_fc(skb);
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun if (unlikely(ieee80211_is_beacon(fc)))
21*4882a593Smuzhiyun return QSLT_BEACON;
22*4882a593Smuzhiyun if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))
23*4882a593Smuzhiyun return QSLT_MGNT;
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun return skb->priority;
26*4882a593Smuzhiyun }
27*4882a593Smuzhiyun
_rtl92ee_query_rxphystatus(struct ieee80211_hw * hw,struct rtl_stats * pstatus,u8 * pdesc,struct rx_fwinfo * p_drvinfo,bool bpacket_match_bssid,bool bpacket_toself,bool packet_beacon)28*4882a593Smuzhiyun static void _rtl92ee_query_rxphystatus(struct ieee80211_hw *hw,
29*4882a593Smuzhiyun struct rtl_stats *pstatus, u8 *pdesc,
30*4882a593Smuzhiyun struct rx_fwinfo *p_drvinfo,
31*4882a593Smuzhiyun bool bpacket_match_bssid,
32*4882a593Smuzhiyun bool bpacket_toself,
33*4882a593Smuzhiyun bool packet_beacon)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
36*4882a593Smuzhiyun struct phy_status_rpt *p_phystrpt = (struct phy_status_rpt *)p_drvinfo;
37*4882a593Smuzhiyun s8 rx_pwr_all, rx_pwr[4];
38*4882a593Smuzhiyun u8 rf_rx_num = 0, evm, pwdb_all;
39*4882a593Smuzhiyun u8 i, max_spatial_stream;
40*4882a593Smuzhiyun u32 rssi, total_rssi = 0;
41*4882a593Smuzhiyun bool is_cck = pstatus->is_cck;
42*4882a593Smuzhiyun u8 lan_idx, vga_idx;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun /* Record it for next packet processing */
45*4882a593Smuzhiyun pstatus->packet_matchbssid = bpacket_match_bssid;
46*4882a593Smuzhiyun pstatus->packet_toself = bpacket_toself;
47*4882a593Smuzhiyun pstatus->packet_beacon = packet_beacon;
48*4882a593Smuzhiyun pstatus->rx_mimo_signalquality[0] = -1;
49*4882a593Smuzhiyun pstatus->rx_mimo_signalquality[1] = -1;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun if (is_cck) {
52*4882a593Smuzhiyun u8 cck_highpwr;
53*4882a593Smuzhiyun u8 cck_agc_rpt;
54*4882a593Smuzhiyun /* CCK Driver info Structure is not the same as OFDM packet. */
55*4882a593Smuzhiyun cck_agc_rpt = p_phystrpt->cck_agc_rpt_ofdm_cfosho_a;
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun /* (1)Hardware does not provide RSSI for CCK
58*4882a593Smuzhiyun * (2)PWDB, Average PWDB cacluated by
59*4882a593Smuzhiyun * hardware (for rate adaptive)
60*4882a593Smuzhiyun */
61*4882a593Smuzhiyun cck_highpwr = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2,
62*4882a593Smuzhiyun BIT(9));
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun lan_idx = ((cck_agc_rpt & 0xE0) >> 5);
65*4882a593Smuzhiyun vga_idx = (cck_agc_rpt & 0x1f);
66*4882a593Smuzhiyun switch (lan_idx) {
67*4882a593Smuzhiyun case 7: /*VGA_idx = 27~2*/
68*4882a593Smuzhiyun if (vga_idx <= 27)
69*4882a593Smuzhiyun rx_pwr_all = -100 + 2 * (27 - vga_idx);
70*4882a593Smuzhiyun else
71*4882a593Smuzhiyun rx_pwr_all = -100;
72*4882a593Smuzhiyun break;
73*4882a593Smuzhiyun case 6: /*VGA_idx = 2~0*/
74*4882a593Smuzhiyun rx_pwr_all = -48 + 2 * (2 - vga_idx);
75*4882a593Smuzhiyun break;
76*4882a593Smuzhiyun case 5: /*VGA_idx = 7~5*/
77*4882a593Smuzhiyun rx_pwr_all = -42 + 2 * (7 - vga_idx);
78*4882a593Smuzhiyun break;
79*4882a593Smuzhiyun case 4: /*VGA_idx = 7~4*/
80*4882a593Smuzhiyun rx_pwr_all = -36 + 2 * (7 - vga_idx);
81*4882a593Smuzhiyun break;
82*4882a593Smuzhiyun case 3: /*VGA_idx = 7~0*/
83*4882a593Smuzhiyun rx_pwr_all = -24 + 2 * (7 - vga_idx);
84*4882a593Smuzhiyun break;
85*4882a593Smuzhiyun case 2: /*VGA_idx = 5~0*/
86*4882a593Smuzhiyun if (cck_highpwr)
87*4882a593Smuzhiyun rx_pwr_all = -12 + 2 * (5 - vga_idx);
88*4882a593Smuzhiyun else
89*4882a593Smuzhiyun rx_pwr_all = -6 + 2 * (5 - vga_idx);
90*4882a593Smuzhiyun break;
91*4882a593Smuzhiyun case 1:
92*4882a593Smuzhiyun rx_pwr_all = 8 - 2 * vga_idx;
93*4882a593Smuzhiyun break;
94*4882a593Smuzhiyun case 0:
95*4882a593Smuzhiyun rx_pwr_all = 14 - 2 * vga_idx;
96*4882a593Smuzhiyun break;
97*4882a593Smuzhiyun default:
98*4882a593Smuzhiyun rx_pwr_all = 0;
99*4882a593Smuzhiyun break;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun rx_pwr_all += 16;
102*4882a593Smuzhiyun pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun if (!cck_highpwr) {
105*4882a593Smuzhiyun if (pwdb_all >= 80)
106*4882a593Smuzhiyun pwdb_all = ((pwdb_all - 80) << 1) +
107*4882a593Smuzhiyun ((pwdb_all - 80) >> 1) + 80;
108*4882a593Smuzhiyun else if ((pwdb_all <= 78) && (pwdb_all >= 20))
109*4882a593Smuzhiyun pwdb_all += 3;
110*4882a593Smuzhiyun if (pwdb_all > 100)
111*4882a593Smuzhiyun pwdb_all = 100;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun pstatus->rx_pwdb_all = pwdb_all;
115*4882a593Smuzhiyun pstatus->bt_rx_rssi_percentage = pwdb_all;
116*4882a593Smuzhiyun pstatus->recvsignalpower = rx_pwr_all;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /* (3) Get Signal Quality (EVM) */
119*4882a593Smuzhiyun if (bpacket_match_bssid) {
120*4882a593Smuzhiyun u8 sq, sq_rpt;
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun if (pstatus->rx_pwdb_all > 40) {
123*4882a593Smuzhiyun sq = 100;
124*4882a593Smuzhiyun } else {
125*4882a593Smuzhiyun sq_rpt = p_phystrpt->cck_sig_qual_ofdm_pwdb_all;
126*4882a593Smuzhiyun if (sq_rpt > 64)
127*4882a593Smuzhiyun sq = 0;
128*4882a593Smuzhiyun else if (sq_rpt < 20)
129*4882a593Smuzhiyun sq = 100;
130*4882a593Smuzhiyun else
131*4882a593Smuzhiyun sq = ((64 - sq_rpt) * 100) / 44;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun pstatus->signalquality = sq;
135*4882a593Smuzhiyun pstatus->rx_mimo_signalquality[0] = sq;
136*4882a593Smuzhiyun pstatus->rx_mimo_signalquality[1] = -1;
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun } else {
139*4882a593Smuzhiyun /* (1)Get RSSI for HT rate */
140*4882a593Smuzhiyun for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) {
141*4882a593Smuzhiyun /* we will judge RF RX path now. */
142*4882a593Smuzhiyun if (rtlpriv->dm.rfpath_rxenable[i])
143*4882a593Smuzhiyun rf_rx_num++;
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun rx_pwr[i] = ((p_phystrpt->path_agc[i].gain & 0x3f) * 2)
146*4882a593Smuzhiyun - 110;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun pstatus->rx_pwr[i] = rx_pwr[i];
149*4882a593Smuzhiyun /* Translate DBM to percentage. */
150*4882a593Smuzhiyun rssi = rtl_query_rxpwrpercentage(rx_pwr[i]);
151*4882a593Smuzhiyun total_rssi += rssi;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun pstatus->rx_mimo_signalstrength[i] = (u8)rssi;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun /* (2)PWDB, Average PWDB cacluated by
157*4882a593Smuzhiyun * hardware (for rate adaptive)
158*4882a593Smuzhiyun */
159*4882a593Smuzhiyun rx_pwr_all = ((p_phystrpt->cck_sig_qual_ofdm_pwdb_all >> 1)
160*4882a593Smuzhiyun & 0x7f) - 110;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
163*4882a593Smuzhiyun pstatus->rx_pwdb_all = pwdb_all;
164*4882a593Smuzhiyun pstatus->bt_rx_rssi_percentage = pwdb_all;
165*4882a593Smuzhiyun pstatus->rxpower = rx_pwr_all;
166*4882a593Smuzhiyun pstatus->recvsignalpower = rx_pwr_all;
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun /* (3)EVM of HT rate */
169*4882a593Smuzhiyun if (pstatus->rate >= DESC_RATEMCS8 &&
170*4882a593Smuzhiyun pstatus->rate <= DESC_RATEMCS15)
171*4882a593Smuzhiyun max_spatial_stream = 2;
172*4882a593Smuzhiyun else
173*4882a593Smuzhiyun max_spatial_stream = 1;
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun for (i = 0; i < max_spatial_stream; i++) {
176*4882a593Smuzhiyun evm = rtl_evm_db_to_percentage(
177*4882a593Smuzhiyun p_phystrpt->stream_rxevm[i]);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun if (bpacket_match_bssid) {
180*4882a593Smuzhiyun /* Fill value in RFD, Get the first
181*4882a593Smuzhiyun * spatial stream only
182*4882a593Smuzhiyun */
183*4882a593Smuzhiyun if (i == 0)
184*4882a593Smuzhiyun pstatus->signalquality = (u8)(evm &
185*4882a593Smuzhiyun 0xff);
186*4882a593Smuzhiyun pstatus->rx_mimo_signalquality[i] = (u8)(evm &
187*4882a593Smuzhiyun 0xff);
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun if (bpacket_match_bssid) {
192*4882a593Smuzhiyun for (i = RF90_PATH_A; i <= RF90_PATH_B; i++)
193*4882a593Smuzhiyun rtl_priv(hw)->dm.cfo_tail[i] =
194*4882a593Smuzhiyun (int)p_phystrpt->path_cfotail[i];
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun if (rtl_priv(hw)->dm.packet_count == 0xffffffff)
197*4882a593Smuzhiyun rtl_priv(hw)->dm.packet_count = 0;
198*4882a593Smuzhiyun else
199*4882a593Smuzhiyun rtl_priv(hw)->dm.packet_count++;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun /* UI BSS List signal strength(in percentage),
204*4882a593Smuzhiyun * make it good looking, from 0~100.
205*4882a593Smuzhiyun */
206*4882a593Smuzhiyun if (is_cck)
207*4882a593Smuzhiyun pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw,
208*4882a593Smuzhiyun pwdb_all));
209*4882a593Smuzhiyun else if (rf_rx_num != 0)
210*4882a593Smuzhiyun pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw,
211*4882a593Smuzhiyun total_rssi /= rf_rx_num));
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
_rtl92ee_translate_rx_signal_stuff(struct ieee80211_hw * hw,struct sk_buff * skb,struct rtl_stats * pstatus,u8 * pdesc,struct rx_fwinfo * p_drvinfo)214*4882a593Smuzhiyun static void _rtl92ee_translate_rx_signal_stuff(struct ieee80211_hw *hw,
215*4882a593Smuzhiyun struct sk_buff *skb,
216*4882a593Smuzhiyun struct rtl_stats *pstatus,
217*4882a593Smuzhiyun u8 *pdesc,
218*4882a593Smuzhiyun struct rx_fwinfo *p_drvinfo)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
221*4882a593Smuzhiyun struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
222*4882a593Smuzhiyun struct ieee80211_hdr *hdr;
223*4882a593Smuzhiyun u8 *tmp_buf;
224*4882a593Smuzhiyun u8 *praddr;
225*4882a593Smuzhiyun u8 *psaddr;
226*4882a593Smuzhiyun __le16 fc;
227*4882a593Smuzhiyun bool packet_matchbssid, packet_toself, packet_beacon;
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun tmp_buf = skb->data + pstatus->rx_drvinfo_size +
230*4882a593Smuzhiyun pstatus->rx_bufshift + 24;
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun hdr = (struct ieee80211_hdr *)tmp_buf;
233*4882a593Smuzhiyun fc = hdr->frame_control;
234*4882a593Smuzhiyun praddr = hdr->addr1;
235*4882a593Smuzhiyun psaddr = ieee80211_get_SA(hdr);
236*4882a593Smuzhiyun ether_addr_copy(pstatus->psaddr, psaddr);
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun packet_matchbssid = (!ieee80211_is_ctl(fc) &&
239*4882a593Smuzhiyun (ether_addr_equal(mac->bssid,
240*4882a593Smuzhiyun ieee80211_has_tods(fc) ?
241*4882a593Smuzhiyun hdr->addr1 :
242*4882a593Smuzhiyun ieee80211_has_fromds(fc) ?
243*4882a593Smuzhiyun hdr->addr2 : hdr->addr3)) &&
244*4882a593Smuzhiyun (!pstatus->hwerror) && (!pstatus->crc) &&
245*4882a593Smuzhiyun (!pstatus->icv));
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun packet_toself = packet_matchbssid &&
248*4882a593Smuzhiyun (ether_addr_equal(praddr, rtlefuse->dev_addr));
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun if (ieee80211_is_beacon(fc))
251*4882a593Smuzhiyun packet_beacon = true;
252*4882a593Smuzhiyun else
253*4882a593Smuzhiyun packet_beacon = false;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun if (packet_beacon && packet_matchbssid)
256*4882a593Smuzhiyun rtl_priv(hw)->dm.dbginfo.num_qry_beacon_pkt++;
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun if (packet_matchbssid && ieee80211_is_data_qos(hdr->frame_control) &&
259*4882a593Smuzhiyun !is_multicast_ether_addr(ieee80211_get_DA(hdr))) {
260*4882a593Smuzhiyun struct ieee80211_qos_hdr *hdr_qos =
261*4882a593Smuzhiyun (struct ieee80211_qos_hdr *)tmp_buf;
262*4882a593Smuzhiyun u16 tid = le16_to_cpu(hdr_qos->qos_ctrl) & 0xf;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun if (tid != 0 && tid != 3)
265*4882a593Smuzhiyun rtl_priv(hw)->dm.dbginfo.num_non_be_pkt++;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun _rtl92ee_query_rxphystatus(hw, pstatus, pdesc, p_drvinfo,
269*4882a593Smuzhiyun packet_matchbssid, packet_toself,
270*4882a593Smuzhiyun packet_beacon);
271*4882a593Smuzhiyun rtl_process_phyinfo(hw, tmp_buf, pstatus);
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun
_rtl92ee_insert_emcontent(struct rtl_tcb_desc * ptcb_desc,u8 * virtualaddress8)274*4882a593Smuzhiyun static void _rtl92ee_insert_emcontent(struct rtl_tcb_desc *ptcb_desc,
275*4882a593Smuzhiyun u8 *virtualaddress8)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun u32 dwtmp;
278*4882a593Smuzhiyun __le32 *virtualaddress = (__le32 *)virtualaddress8;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun memset(virtualaddress, 0, 8);
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun set_earlymode_pktnum(virtualaddress, ptcb_desc->empkt_num);
283*4882a593Smuzhiyun if (ptcb_desc->empkt_num == 1) {
284*4882a593Smuzhiyun dwtmp = ptcb_desc->empkt_len[0];
285*4882a593Smuzhiyun } else {
286*4882a593Smuzhiyun dwtmp = ptcb_desc->empkt_len[0];
287*4882a593Smuzhiyun dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
288*4882a593Smuzhiyun dwtmp += ptcb_desc->empkt_len[1];
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun set_earlymode_len0(virtualaddress, dwtmp);
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun if (ptcb_desc->empkt_num <= 3) {
293*4882a593Smuzhiyun dwtmp = ptcb_desc->empkt_len[2];
294*4882a593Smuzhiyun } else {
295*4882a593Smuzhiyun dwtmp = ptcb_desc->empkt_len[2];
296*4882a593Smuzhiyun dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
297*4882a593Smuzhiyun dwtmp += ptcb_desc->empkt_len[3];
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun set_earlymode_len1(virtualaddress, dwtmp);
300*4882a593Smuzhiyun if (ptcb_desc->empkt_num <= 5) {
301*4882a593Smuzhiyun dwtmp = ptcb_desc->empkt_len[4];
302*4882a593Smuzhiyun } else {
303*4882a593Smuzhiyun dwtmp = ptcb_desc->empkt_len[4];
304*4882a593Smuzhiyun dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
305*4882a593Smuzhiyun dwtmp += ptcb_desc->empkt_len[5];
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun set_earlymode_len2_1(virtualaddress, dwtmp & 0xF);
308*4882a593Smuzhiyun set_earlymode_len2_2(virtualaddress, dwtmp >> 4);
309*4882a593Smuzhiyun if (ptcb_desc->empkt_num <= 7) {
310*4882a593Smuzhiyun dwtmp = ptcb_desc->empkt_len[6];
311*4882a593Smuzhiyun } else {
312*4882a593Smuzhiyun dwtmp = ptcb_desc->empkt_len[6];
313*4882a593Smuzhiyun dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
314*4882a593Smuzhiyun dwtmp += ptcb_desc->empkt_len[7];
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun set_earlymode_len3(virtualaddress, dwtmp);
317*4882a593Smuzhiyun if (ptcb_desc->empkt_num <= 9) {
318*4882a593Smuzhiyun dwtmp = ptcb_desc->empkt_len[8];
319*4882a593Smuzhiyun } else {
320*4882a593Smuzhiyun dwtmp = ptcb_desc->empkt_len[8];
321*4882a593Smuzhiyun dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
322*4882a593Smuzhiyun dwtmp += ptcb_desc->empkt_len[9];
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun set_earlymode_len4(virtualaddress, dwtmp);
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun
rtl92ee_rx_query_desc(struct ieee80211_hw * hw,struct rtl_stats * status,struct ieee80211_rx_status * rx_status,u8 * pdesc8,struct sk_buff * skb)327*4882a593Smuzhiyun bool rtl92ee_rx_query_desc(struct ieee80211_hw *hw,
328*4882a593Smuzhiyun struct rtl_stats *status,
329*4882a593Smuzhiyun struct ieee80211_rx_status *rx_status,
330*4882a593Smuzhiyun u8 *pdesc8, struct sk_buff *skb)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
333*4882a593Smuzhiyun struct rx_fwinfo *p_drvinfo;
334*4882a593Smuzhiyun struct ieee80211_hdr *hdr;
335*4882a593Smuzhiyun __le32 *pdesc = (__le32 *)pdesc8;
336*4882a593Smuzhiyun u32 phystatus = get_rx_desc_physt(pdesc);
337*4882a593Smuzhiyun u8 wake_match;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun if (get_rx_status_desc_rpt_sel(pdesc) == 0)
340*4882a593Smuzhiyun status->packet_report_type = NORMAL_RX;
341*4882a593Smuzhiyun else
342*4882a593Smuzhiyun status->packet_report_type = C2H_PACKET;
343*4882a593Smuzhiyun status->length = (u16)get_rx_desc_pkt_len(pdesc);
344*4882a593Smuzhiyun status->rx_drvinfo_size = (u8)get_rx_desc_drv_info_size(pdesc) *
345*4882a593Smuzhiyun RX_DRV_INFO_SIZE_UNIT;
346*4882a593Smuzhiyun status->rx_bufshift = (u8)(get_rx_desc_shift(pdesc) & 0x03);
347*4882a593Smuzhiyun status->icv = (u16)get_rx_desc_icv(pdesc);
348*4882a593Smuzhiyun status->crc = (u16)get_rx_desc_crc32(pdesc);
349*4882a593Smuzhiyun status->hwerror = (status->crc | status->icv);
350*4882a593Smuzhiyun status->decrypted = !get_rx_desc_swdec(pdesc);
351*4882a593Smuzhiyun status->rate = (u8)get_rx_desc_rxmcs(pdesc);
352*4882a593Smuzhiyun status->isampdu = (bool)(get_rx_desc_paggr(pdesc) == 1);
353*4882a593Smuzhiyun status->timestamp_low = get_rx_desc_tsfl(pdesc);
354*4882a593Smuzhiyun status->is_cck = RTL92EE_RX_HAL_IS_CCK_RATE(status->rate);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun status->macid = get_rx_desc_macid(pdesc);
357*4882a593Smuzhiyun if (get_rx_status_desc_pattern_match(pdesc))
358*4882a593Smuzhiyun wake_match = BIT(2);
359*4882a593Smuzhiyun else if (get_rx_status_desc_magic_match(pdesc))
360*4882a593Smuzhiyun wake_match = BIT(1);
361*4882a593Smuzhiyun else if (get_rx_status_desc_unicast_match(pdesc))
362*4882a593Smuzhiyun wake_match = BIT(0);
363*4882a593Smuzhiyun else
364*4882a593Smuzhiyun wake_match = 0;
365*4882a593Smuzhiyun if (wake_match)
366*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_RXDESC, DBG_LOUD,
367*4882a593Smuzhiyun "GGGGGGGGGGGGGet Wakeup Packet!! WakeMatch=%d\n",
368*4882a593Smuzhiyun wake_match);
369*4882a593Smuzhiyun rx_status->freq = hw->conf.chandef.chan->center_freq;
370*4882a593Smuzhiyun rx_status->band = hw->conf.chandef.chan->band;
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun hdr = (struct ieee80211_hdr *)(skb->data + status->rx_drvinfo_size +
373*4882a593Smuzhiyun status->rx_bufshift + 24);
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun if (status->crc)
376*4882a593Smuzhiyun rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun if (status->rx_is40mhzpacket)
379*4882a593Smuzhiyun rx_status->bw = RATE_INFO_BW_40;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun if (status->is_ht)
382*4882a593Smuzhiyun rx_status->encoding = RX_ENC_HT;
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun rx_status->flag |= RX_FLAG_MACTIME_START;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun /* hw will set status->decrypted true, if it finds the
387*4882a593Smuzhiyun * frame is open data frame or mgmt frame.
388*4882a593Smuzhiyun * So hw will not decryption robust managment frame
389*4882a593Smuzhiyun * for IEEE80211w but still set status->decrypted
390*4882a593Smuzhiyun * true, so here we should set it back to undecrypted
391*4882a593Smuzhiyun * for IEEE80211w frame, and mac80211 sw will help
392*4882a593Smuzhiyun * to decrypt it
393*4882a593Smuzhiyun */
394*4882a593Smuzhiyun if (status->decrypted) {
395*4882a593Smuzhiyun if ((!_ieee80211_is_robust_mgmt_frame(hdr)) &&
396*4882a593Smuzhiyun (ieee80211_has_protected(hdr->frame_control)))
397*4882a593Smuzhiyun rx_status->flag |= RX_FLAG_DECRYPTED;
398*4882a593Smuzhiyun else
399*4882a593Smuzhiyun rx_status->flag &= ~RX_FLAG_DECRYPTED;
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun /* rate_idx: index of data rate into band's
403*4882a593Smuzhiyun * supported rates or MCS index if HT rates
404*4882a593Smuzhiyun * are use (RX_FLAG_HT)
405*4882a593Smuzhiyun * Notice: this is diff with windows define
406*4882a593Smuzhiyun */
407*4882a593Smuzhiyun rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht,
408*4882a593Smuzhiyun false, status->rate);
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun rx_status->mactime = status->timestamp_low;
411*4882a593Smuzhiyun if (phystatus) {
412*4882a593Smuzhiyun p_drvinfo = (struct rx_fwinfo *)(skb->data +
413*4882a593Smuzhiyun status->rx_bufshift + 24);
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun _rtl92ee_translate_rx_signal_stuff(hw, skb, status, pdesc8,
416*4882a593Smuzhiyun p_drvinfo);
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun rx_status->signal = status->recvsignalpower + 10;
419*4882a593Smuzhiyun if (status->packet_report_type == TX_REPORT2) {
420*4882a593Smuzhiyun status->macid_valid_entry[0] =
421*4882a593Smuzhiyun get_rx_rpt2_desc_macid_valid_1(pdesc);
422*4882a593Smuzhiyun status->macid_valid_entry[1] =
423*4882a593Smuzhiyun get_rx_rpt2_desc_macid_valid_2(pdesc);
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun return true;
426*4882a593Smuzhiyun }
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun /*in Windows, this == Rx_92EE_Interrupt*/
rtl92ee_rx_check_dma_ok(struct ieee80211_hw * hw,u8 * header_desc8,u8 queue_index)429*4882a593Smuzhiyun void rtl92ee_rx_check_dma_ok(struct ieee80211_hw *hw, u8 *header_desc8,
430*4882a593Smuzhiyun u8 queue_index)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun u8 first_seg = 0;
433*4882a593Smuzhiyun u8 last_seg = 0;
434*4882a593Smuzhiyun u16 total_len = 0;
435*4882a593Smuzhiyun u16 read_cnt = 0;
436*4882a593Smuzhiyun __le32 *header_desc = (__le32 *)header_desc8;
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun if (header_desc == NULL)
439*4882a593Smuzhiyun return;
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun total_len = (u16)get_rx_buffer_desc_total_length(header_desc);
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun first_seg = (u8)get_rx_buffer_desc_fs(header_desc);
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun last_seg = (u8)get_rx_buffer_desc_ls(header_desc);
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun while (total_len == 0 && first_seg == 0 && last_seg == 0) {
448*4882a593Smuzhiyun read_cnt++;
449*4882a593Smuzhiyun total_len = (u16)get_rx_buffer_desc_total_length(header_desc);
450*4882a593Smuzhiyun first_seg = (u8)get_rx_buffer_desc_fs(header_desc);
451*4882a593Smuzhiyun last_seg = (u8)get_rx_buffer_desc_ls(header_desc);
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun if (read_cnt > 20)
454*4882a593Smuzhiyun break;
455*4882a593Smuzhiyun }
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun
rtl92ee_rx_desc_buff_remained_cnt(struct ieee80211_hw * hw,u8 queue_index)458*4882a593Smuzhiyun u16 rtl92ee_rx_desc_buff_remained_cnt(struct ieee80211_hw *hw, u8 queue_index)
459*4882a593Smuzhiyun {
460*4882a593Smuzhiyun struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
461*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
462*4882a593Smuzhiyun u16 read_point, write_point, remind_cnt;
463*4882a593Smuzhiyun u32 tmp_4byte;
464*4882a593Smuzhiyun static bool start_rx;
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun tmp_4byte = rtl_read_dword(rtlpriv, REG_RXQ_TXBD_IDX);
467*4882a593Smuzhiyun read_point = (u16)((tmp_4byte>>16) & 0x7ff);
468*4882a593Smuzhiyun write_point = (u16)(tmp_4byte & 0x7ff);
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun if (write_point != rtlpci->rx_ring[queue_index].next_rx_rp) {
471*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_RXDESC, DBG_DMESG,
472*4882a593Smuzhiyun "!!!write point is 0x%x, reg 0x3B4 value is 0x%x\n",
473*4882a593Smuzhiyun write_point, tmp_4byte);
474*4882a593Smuzhiyun tmp_4byte = rtl_read_dword(rtlpriv, REG_RXQ_TXBD_IDX);
475*4882a593Smuzhiyun read_point = (u16)((tmp_4byte>>16) & 0x7ff);
476*4882a593Smuzhiyun write_point = (u16)(tmp_4byte & 0x7ff);
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun if (read_point > 0)
480*4882a593Smuzhiyun start_rx = true;
481*4882a593Smuzhiyun if (!start_rx)
482*4882a593Smuzhiyun return 0;
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun remind_cnt = calc_fifo_space(read_point, write_point,
485*4882a593Smuzhiyun RTL_PCI_MAX_RX_COUNT);
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun if (remind_cnt == 0)
488*4882a593Smuzhiyun return 0;
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun rtlpci->rx_ring[queue_index].next_rx_rp = write_point;
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun return remind_cnt;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
get_desc_addr_fr_q_idx(u16 queue_index)495*4882a593Smuzhiyun static u16 get_desc_addr_fr_q_idx(u16 queue_index)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun u16 desc_address;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun switch (queue_index) {
500*4882a593Smuzhiyun case BK_QUEUE:
501*4882a593Smuzhiyun desc_address = REG_BKQ_TXBD_IDX;
502*4882a593Smuzhiyun break;
503*4882a593Smuzhiyun case BE_QUEUE:
504*4882a593Smuzhiyun desc_address = REG_BEQ_TXBD_IDX;
505*4882a593Smuzhiyun break;
506*4882a593Smuzhiyun case VI_QUEUE:
507*4882a593Smuzhiyun desc_address = REG_VIQ_TXBD_IDX;
508*4882a593Smuzhiyun break;
509*4882a593Smuzhiyun case VO_QUEUE:
510*4882a593Smuzhiyun desc_address = REG_VOQ_TXBD_IDX;
511*4882a593Smuzhiyun break;
512*4882a593Smuzhiyun case BEACON_QUEUE:
513*4882a593Smuzhiyun desc_address = REG_BEQ_TXBD_IDX;
514*4882a593Smuzhiyun break;
515*4882a593Smuzhiyun case TXCMD_QUEUE:
516*4882a593Smuzhiyun desc_address = REG_BEQ_TXBD_IDX;
517*4882a593Smuzhiyun break;
518*4882a593Smuzhiyun case MGNT_QUEUE:
519*4882a593Smuzhiyun desc_address = REG_MGQ_TXBD_IDX;
520*4882a593Smuzhiyun break;
521*4882a593Smuzhiyun case HIGH_QUEUE:
522*4882a593Smuzhiyun desc_address = REG_HI0Q_TXBD_IDX;
523*4882a593Smuzhiyun break;
524*4882a593Smuzhiyun case HCCA_QUEUE:
525*4882a593Smuzhiyun desc_address = REG_BEQ_TXBD_IDX;
526*4882a593Smuzhiyun break;
527*4882a593Smuzhiyun default:
528*4882a593Smuzhiyun desc_address = REG_BEQ_TXBD_IDX;
529*4882a593Smuzhiyun break;
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun return desc_address;
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun
rtl92ee_get_available_desc(struct ieee80211_hw * hw,u8 q_idx)534*4882a593Smuzhiyun u16 rtl92ee_get_available_desc(struct ieee80211_hw *hw, u8 q_idx)
535*4882a593Smuzhiyun {
536*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
537*4882a593Smuzhiyun u16 point_diff = 0;
538*4882a593Smuzhiyun u16 current_tx_read_point, current_tx_write_point;
539*4882a593Smuzhiyun u32 tmp_4byte;
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun tmp_4byte = rtl_read_dword(rtlpriv,
542*4882a593Smuzhiyun get_desc_addr_fr_q_idx(q_idx));
543*4882a593Smuzhiyun current_tx_read_point = (u16)((tmp_4byte >> 16) & 0x0fff);
544*4882a593Smuzhiyun current_tx_write_point = (u16)((tmp_4byte) & 0x0fff);
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun point_diff = calc_fifo_space(current_tx_read_point,
547*4882a593Smuzhiyun current_tx_write_point,
548*4882a593Smuzhiyun TX_DESC_NUM_92E);
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun return point_diff;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun
rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw * hw,u8 * tx_bd_desc8,u8 * desc8,u8 queue_index,struct sk_buff * skb,dma_addr_t addr)553*4882a593Smuzhiyun void rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw *hw,
554*4882a593Smuzhiyun u8 *tx_bd_desc8, u8 *desc8, u8 queue_index,
555*4882a593Smuzhiyun struct sk_buff *skb, dma_addr_t addr)
556*4882a593Smuzhiyun {
557*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
558*4882a593Smuzhiyun struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
559*4882a593Smuzhiyun u32 pkt_len = skb->len;
560*4882a593Smuzhiyun u16 desc_size = 40; /*tx desc size*/
561*4882a593Smuzhiyun u32 psblen = 0;
562*4882a593Smuzhiyun u16 tx_page_size;
563*4882a593Smuzhiyun u32 total_packet_size;
564*4882a593Smuzhiyun u16 current_bd_desc;
565*4882a593Smuzhiyun u8 i;
566*4882a593Smuzhiyun u16 real_desc_size = 0x28;
567*4882a593Smuzhiyun u16 append_early_mode_size = 0;
568*4882a593Smuzhiyun u8 segmentnum = 1 << (RTL8192EE_SEG_NUM + 1);
569*4882a593Smuzhiyun dma_addr_t desc_dma_addr;
570*4882a593Smuzhiyun bool dma64 = rtlpriv->cfg->mod_params->dma64;
571*4882a593Smuzhiyun __le32 *desc = (__le32 *)desc8;
572*4882a593Smuzhiyun __le32 *tx_bd_desc = (__le32 *)tx_bd_desc8;
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun tx_page_size = 2;
575*4882a593Smuzhiyun current_bd_desc = rtlpci->tx_ring[queue_index].cur_tx_wp;
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun total_packet_size = desc_size+pkt_len;
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun if (rtlpriv->rtlhal.earlymode_enable) {
580*4882a593Smuzhiyun if (queue_index < BEACON_QUEUE) {
581*4882a593Smuzhiyun append_early_mode_size = 8;
582*4882a593Smuzhiyun total_packet_size += append_early_mode_size;
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun if (tx_page_size > 0) {
587*4882a593Smuzhiyun psblen = (pkt_len + real_desc_size + append_early_mode_size) /
588*4882a593Smuzhiyun (tx_page_size * 128);
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun if (psblen * (tx_page_size * 128) < total_packet_size)
591*4882a593Smuzhiyun psblen += 1;
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun /* tx desc addr */
595*4882a593Smuzhiyun desc_dma_addr = rtlpci->tx_ring[queue_index].dma +
596*4882a593Smuzhiyun (current_bd_desc * TX_DESC_SIZE);
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun /* Reset */
599*4882a593Smuzhiyun set_tx_buff_desc_len_0(tx_bd_desc, 0);
600*4882a593Smuzhiyun set_tx_buff_desc_psb(tx_bd_desc, 0);
601*4882a593Smuzhiyun set_tx_buff_desc_own(tx_bd_desc, 0);
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun for (i = 1; i < segmentnum; i++) {
604*4882a593Smuzhiyun set_txbuffer_desc_len_with_offset(tx_bd_desc, i, 0);
605*4882a593Smuzhiyun set_txbuffer_desc_amsdu_with_offset(tx_bd_desc, i, 0);
606*4882a593Smuzhiyun set_txbuffer_desc_add_low_with_offset(tx_bd_desc, i, 0);
607*4882a593Smuzhiyun set_txbuffer_desc_add_high_with_offset(tx_bd_desc, i, 0, dma64);
608*4882a593Smuzhiyun }
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun /* Clear all status */
611*4882a593Smuzhiyun clear_pci_tx_desc_content(desc, TX_DESC_SIZE);
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun if (rtlpriv->rtlhal.earlymode_enable) {
614*4882a593Smuzhiyun if (queue_index < BEACON_QUEUE) {
615*4882a593Smuzhiyun /* This if needs braces */
616*4882a593Smuzhiyun set_tx_buff_desc_len_0(tx_bd_desc, desc_size + 8);
617*4882a593Smuzhiyun } else {
618*4882a593Smuzhiyun set_tx_buff_desc_len_0(tx_bd_desc, desc_size);
619*4882a593Smuzhiyun }
620*4882a593Smuzhiyun } else {
621*4882a593Smuzhiyun set_tx_buff_desc_len_0(tx_bd_desc, desc_size);
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun set_tx_buff_desc_psb(tx_bd_desc, psblen);
624*4882a593Smuzhiyun set_tx_buff_desc_addr_low_0(tx_bd_desc, desc_dma_addr);
625*4882a593Smuzhiyun set_tx_buff_desc_addr_high_0(tx_bd_desc, ((u64)desc_dma_addr >> 32),
626*4882a593Smuzhiyun dma64);
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun set_txbuffer_desc_len_with_offset(tx_bd_desc, 1, pkt_len);
629*4882a593Smuzhiyun /* don't using extendsion mode. */
630*4882a593Smuzhiyun set_txbuffer_desc_amsdu_with_offset(tx_bd_desc, 1, 0);
631*4882a593Smuzhiyun set_txbuffer_desc_add_low_with_offset(tx_bd_desc, 1, addr);
632*4882a593Smuzhiyun set_txbuffer_desc_add_high_with_offset(tx_bd_desc, 1,
633*4882a593Smuzhiyun ((u64)addr >> 32), dma64);
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun set_tx_desc_pkt_size(desc, (u16)(pkt_len));
636*4882a593Smuzhiyun set_tx_desc_tx_buffer_size(desc, (u16)(pkt_len));
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun
rtl92ee_tx_fill_desc(struct ieee80211_hw * hw,struct ieee80211_hdr * hdr,u8 * pdesc8,u8 * pbd_desc_tx,struct ieee80211_tx_info * info,struct ieee80211_sta * sta,struct sk_buff * skb,u8 hw_queue,struct rtl_tcb_desc * ptcb_desc)639*4882a593Smuzhiyun void rtl92ee_tx_fill_desc(struct ieee80211_hw *hw,
640*4882a593Smuzhiyun struct ieee80211_hdr *hdr, u8 *pdesc8,
641*4882a593Smuzhiyun u8 *pbd_desc_tx,
642*4882a593Smuzhiyun struct ieee80211_tx_info *info,
643*4882a593Smuzhiyun struct ieee80211_sta *sta,
644*4882a593Smuzhiyun struct sk_buff *skb,
645*4882a593Smuzhiyun u8 hw_queue, struct rtl_tcb_desc *ptcb_desc)
646*4882a593Smuzhiyun {
647*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
648*4882a593Smuzhiyun struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
649*4882a593Smuzhiyun struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
650*4882a593Smuzhiyun struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
651*4882a593Smuzhiyun struct rtlwifi_tx_info *tx_info = rtl_tx_skb_cb_info(skb);
652*4882a593Smuzhiyun u16 seq_number;
653*4882a593Smuzhiyun __le16 fc = hdr->frame_control;
654*4882a593Smuzhiyun u8 fw_qsel = _rtl92ee_map_hwqueue_to_fwqueue(skb, hw_queue);
655*4882a593Smuzhiyun bool firstseg = ((hdr->seq_ctrl &
656*4882a593Smuzhiyun cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
657*4882a593Smuzhiyun bool lastseg = ((hdr->frame_control &
658*4882a593Smuzhiyun cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
659*4882a593Smuzhiyun dma_addr_t mapping;
660*4882a593Smuzhiyun u8 bw_40 = 0;
661*4882a593Smuzhiyun __le32 *pdesc = (__le32 *)pdesc8;
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun if (mac->opmode == NL80211_IFTYPE_STATION) {
664*4882a593Smuzhiyun bw_40 = mac->bw_40;
665*4882a593Smuzhiyun } else if (mac->opmode == NL80211_IFTYPE_AP ||
666*4882a593Smuzhiyun mac->opmode == NL80211_IFTYPE_ADHOC) {
667*4882a593Smuzhiyun if (sta)
668*4882a593Smuzhiyun bw_40 = sta->ht_cap.cap &
669*4882a593Smuzhiyun IEEE80211_HT_CAP_SUP_WIDTH_20_40;
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
672*4882a593Smuzhiyun rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc);
673*4882a593Smuzhiyun /* reserve 8 byte for AMPDU early mode */
674*4882a593Smuzhiyun if (rtlhal->earlymode_enable) {
675*4882a593Smuzhiyun skb_push(skb, EM_HDR_LEN);
676*4882a593Smuzhiyun memset(skb->data, 0, EM_HDR_LEN);
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun mapping = dma_map_single(&rtlpci->pdev->dev, skb->data, skb->len,
679*4882a593Smuzhiyun DMA_TO_DEVICE);
680*4882a593Smuzhiyun if (dma_mapping_error(&rtlpci->pdev->dev, mapping)) {
681*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE,
682*4882a593Smuzhiyun "DMA mapping error\n");
683*4882a593Smuzhiyun return;
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun if (pbd_desc_tx != NULL)
687*4882a593Smuzhiyun rtl92ee_pre_fill_tx_bd_desc(hw, pbd_desc_tx, pdesc8, hw_queue,
688*4882a593Smuzhiyun skb, mapping);
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) {
691*4882a593Smuzhiyun firstseg = true;
692*4882a593Smuzhiyun lastseg = true;
693*4882a593Smuzhiyun }
694*4882a593Smuzhiyun if (firstseg) {
695*4882a593Smuzhiyun if (rtlhal->earlymode_enable) {
696*4882a593Smuzhiyun set_tx_desc_pkt_offset(pdesc, 1);
697*4882a593Smuzhiyun set_tx_desc_offset(pdesc,
698*4882a593Smuzhiyun USB_HWDESC_HEADER_LEN + EM_HDR_LEN);
699*4882a593Smuzhiyun if (ptcb_desc->empkt_num) {
700*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE,
701*4882a593Smuzhiyun "Insert 8 byte.pTcb->EMPktNum:%d\n",
702*4882a593Smuzhiyun ptcb_desc->empkt_num);
703*4882a593Smuzhiyun _rtl92ee_insert_emcontent(ptcb_desc,
704*4882a593Smuzhiyun (u8 *)(skb->data));
705*4882a593Smuzhiyun }
706*4882a593Smuzhiyun } else {
707*4882a593Smuzhiyun set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN);
708*4882a593Smuzhiyun }
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun
711*4882a593Smuzhiyun set_tx_desc_tx_rate(pdesc, ptcb_desc->hw_rate);
712*4882a593Smuzhiyun
713*4882a593Smuzhiyun if (ieee80211_is_mgmt(fc)) {
714*4882a593Smuzhiyun ptcb_desc->use_driver_rate = true;
715*4882a593Smuzhiyun } else {
716*4882a593Smuzhiyun if (rtlpriv->ra.is_special_data) {
717*4882a593Smuzhiyun ptcb_desc->use_driver_rate = true;
718*4882a593Smuzhiyun set_tx_desc_tx_rate(pdesc, DESC_RATE11M);
719*4882a593Smuzhiyun } else {
720*4882a593Smuzhiyun ptcb_desc->use_driver_rate = false;
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun }
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun if (info->flags & IEEE80211_TX_CTL_AMPDU) {
725*4882a593Smuzhiyun set_tx_desc_agg_enable(pdesc, 1);
726*4882a593Smuzhiyun set_tx_desc_max_agg_num(pdesc, 0x14);
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun set_tx_desc_seq(pdesc, seq_number);
729*4882a593Smuzhiyun set_tx_desc_rts_enable(pdesc,
730*4882a593Smuzhiyun ((ptcb_desc->rts_enable &&
731*4882a593Smuzhiyun !ptcb_desc->cts_enable) ? 1 : 0));
732*4882a593Smuzhiyun set_tx_desc_hw_rts_enable(pdesc, 0);
733*4882a593Smuzhiyun set_tx_desc_cts2self(pdesc,
734*4882a593Smuzhiyun ((ptcb_desc->cts_enable) ? 1 : 0));
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun set_tx_desc_rts_rate(pdesc, ptcb_desc->rts_rate);
737*4882a593Smuzhiyun set_tx_desc_rts_sc(pdesc, ptcb_desc->rts_sc);
738*4882a593Smuzhiyun set_tx_desc_rts_short(pdesc,
739*4882a593Smuzhiyun ((ptcb_desc->rts_rate <= DESC_RATE54M) ?
740*4882a593Smuzhiyun (ptcb_desc->rts_use_shortpreamble ? 1 : 0) :
741*4882a593Smuzhiyun (ptcb_desc->rts_use_shortgi ? 1 : 0)));
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun if (ptcb_desc->tx_enable_sw_calc_duration)
744*4882a593Smuzhiyun set_tx_desc_nav_use_hdr(pdesc, 1);
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun if (bw_40) {
747*4882a593Smuzhiyun if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) {
748*4882a593Smuzhiyun set_tx_desc_data_bw(pdesc, 1);
749*4882a593Smuzhiyun set_tx_desc_tx_sub_carrier(pdesc, 3);
750*4882a593Smuzhiyun } else {
751*4882a593Smuzhiyun set_tx_desc_data_bw(pdesc, 0);
752*4882a593Smuzhiyun set_tx_desc_tx_sub_carrier(pdesc,
753*4882a593Smuzhiyun mac->cur_40_prime_sc);
754*4882a593Smuzhiyun }
755*4882a593Smuzhiyun } else {
756*4882a593Smuzhiyun set_tx_desc_data_bw(pdesc, 0);
757*4882a593Smuzhiyun set_tx_desc_tx_sub_carrier(pdesc, 0);
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun set_tx_desc_linip(pdesc, 0);
761*4882a593Smuzhiyun if (sta) {
762*4882a593Smuzhiyun u8 ampdu_density = sta->ht_cap.ampdu_density;
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun set_tx_desc_ampdu_density(pdesc, ampdu_density);
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun if (info->control.hw_key) {
767*4882a593Smuzhiyun struct ieee80211_key_conf *key = info->control.hw_key;
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun switch (key->cipher) {
770*4882a593Smuzhiyun case WLAN_CIPHER_SUITE_WEP40:
771*4882a593Smuzhiyun case WLAN_CIPHER_SUITE_WEP104:
772*4882a593Smuzhiyun case WLAN_CIPHER_SUITE_TKIP:
773*4882a593Smuzhiyun set_tx_desc_sec_type(pdesc, 0x1);
774*4882a593Smuzhiyun break;
775*4882a593Smuzhiyun case WLAN_CIPHER_SUITE_CCMP:
776*4882a593Smuzhiyun set_tx_desc_sec_type(pdesc, 0x3);
777*4882a593Smuzhiyun break;
778*4882a593Smuzhiyun default:
779*4882a593Smuzhiyun set_tx_desc_sec_type(pdesc, 0x0);
780*4882a593Smuzhiyun break;
781*4882a593Smuzhiyun }
782*4882a593Smuzhiyun }
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun set_tx_desc_queue_sel(pdesc, fw_qsel);
785*4882a593Smuzhiyun set_tx_desc_data_rate_fb_limit(pdesc, 0x1F);
786*4882a593Smuzhiyun set_tx_desc_rts_rate_fb_limit(pdesc, 0xF);
787*4882a593Smuzhiyun set_tx_desc_disable_fb(pdesc,
788*4882a593Smuzhiyun ptcb_desc->disable_ratefallback ? 1 : 0);
789*4882a593Smuzhiyun set_tx_desc_use_rate(pdesc, ptcb_desc->use_driver_rate ? 1 : 0);
790*4882a593Smuzhiyun
791*4882a593Smuzhiyun /*set_tx_desc_pwr_status(pdesc, pwr_status);*/
792*4882a593Smuzhiyun /* Set TxRate and RTSRate in TxDesc */
793*4882a593Smuzhiyun /* This prevent Tx initial rate of new-coming packets */
794*4882a593Smuzhiyun /* from being overwritten by retried packet rate.*/
795*4882a593Smuzhiyun if (!ptcb_desc->use_driver_rate) {
796*4882a593Smuzhiyun /*set_tx_desc_rts_rate(pdesc, 0x08); */
797*4882a593Smuzhiyun /* set_tx_desc_tx_rate(pdesc, 0x0b); */
798*4882a593Smuzhiyun }
799*4882a593Smuzhiyun if (ieee80211_is_data_qos(fc)) {
800*4882a593Smuzhiyun if (mac->rdg_en) {
801*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE,
802*4882a593Smuzhiyun "Enable RDG function.\n");
803*4882a593Smuzhiyun set_tx_desc_rdg_enable(pdesc, 1);
804*4882a593Smuzhiyun set_tx_desc_htc(pdesc, 1);
805*4882a593Smuzhiyun }
806*4882a593Smuzhiyun }
807*4882a593Smuzhiyun /* tx report */
808*4882a593Smuzhiyun rtl_set_tx_report(ptcb_desc, pdesc8, hw, tx_info);
809*4882a593Smuzhiyun }
810*4882a593Smuzhiyun
811*4882a593Smuzhiyun set_tx_desc_first_seg(pdesc, (firstseg ? 1 : 0));
812*4882a593Smuzhiyun set_tx_desc_last_seg(pdesc, (lastseg ? 1 : 0));
813*4882a593Smuzhiyun set_tx_desc_tx_buffer_address(pdesc, mapping);
814*4882a593Smuzhiyun if (rtlpriv->dm.useramask) {
815*4882a593Smuzhiyun set_tx_desc_rate_id(pdesc, ptcb_desc->ratr_index);
816*4882a593Smuzhiyun set_tx_desc_macid(pdesc, ptcb_desc->mac_id);
817*4882a593Smuzhiyun } else {
818*4882a593Smuzhiyun set_tx_desc_rate_id(pdesc, 0xC + ptcb_desc->ratr_index);
819*4882a593Smuzhiyun set_tx_desc_macid(pdesc, ptcb_desc->ratr_index);
820*4882a593Smuzhiyun }
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun set_tx_desc_more_frag(pdesc, (lastseg ? 0 : 1));
823*4882a593Smuzhiyun if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
824*4882a593Smuzhiyun is_broadcast_ether_addr(ieee80211_get_DA(hdr))) {
825*4882a593Smuzhiyun set_tx_desc_bmc(pdesc, 1);
826*4882a593Smuzhiyun }
827*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE, "\n");
828*4882a593Smuzhiyun }
829*4882a593Smuzhiyun
rtl92ee_tx_fill_cmddesc(struct ieee80211_hw * hw,u8 * pdesc8,bool firstseg,bool lastseg,struct sk_buff * skb)830*4882a593Smuzhiyun void rtl92ee_tx_fill_cmddesc(struct ieee80211_hw *hw,
831*4882a593Smuzhiyun u8 *pdesc8, bool firstseg,
832*4882a593Smuzhiyun bool lastseg, struct sk_buff *skb)
833*4882a593Smuzhiyun {
834*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
835*4882a593Smuzhiyun struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
836*4882a593Smuzhiyun u8 fw_queue = QSLT_BEACON;
837*4882a593Smuzhiyun dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data,
838*4882a593Smuzhiyun skb->len, DMA_TO_DEVICE);
839*4882a593Smuzhiyun u8 txdesc_len = 40;
840*4882a593Smuzhiyun __le32 *pdesc = (__le32 *)pdesc8;
841*4882a593Smuzhiyun
842*4882a593Smuzhiyun if (dma_mapping_error(&rtlpci->pdev->dev, mapping)) {
843*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE,
844*4882a593Smuzhiyun "DMA mapping error\n");
845*4882a593Smuzhiyun return;
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun clear_pci_tx_desc_content(pdesc, txdesc_len);
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun if (firstseg)
850*4882a593Smuzhiyun set_tx_desc_offset(pdesc, txdesc_len);
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun set_tx_desc_tx_rate(pdesc, DESC_RATE1M);
853*4882a593Smuzhiyun
854*4882a593Smuzhiyun set_tx_desc_seq(pdesc, 0);
855*4882a593Smuzhiyun
856*4882a593Smuzhiyun set_tx_desc_linip(pdesc, 0);
857*4882a593Smuzhiyun
858*4882a593Smuzhiyun set_tx_desc_queue_sel(pdesc, fw_queue);
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun set_tx_desc_first_seg(pdesc, 1);
861*4882a593Smuzhiyun set_tx_desc_last_seg(pdesc, 1);
862*4882a593Smuzhiyun
863*4882a593Smuzhiyun set_tx_desc_tx_buffer_size(pdesc, (u16)(skb->len));
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun set_tx_desc_tx_buffer_address(pdesc, mapping);
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun set_tx_desc_rate_id(pdesc, 7);
868*4882a593Smuzhiyun set_tx_desc_macid(pdesc, 0);
869*4882a593Smuzhiyun
870*4882a593Smuzhiyun set_tx_desc_own(pdesc, 1);
871*4882a593Smuzhiyun
872*4882a593Smuzhiyun set_tx_desc_pkt_size(pdesc, (u16)(skb->len));
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun set_tx_desc_first_seg(pdesc, 1);
875*4882a593Smuzhiyun set_tx_desc_last_seg(pdesc, 1);
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun set_tx_desc_offset(pdesc, 40);
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun set_tx_desc_use_rate(pdesc, 1);
880*4882a593Smuzhiyun
881*4882a593Smuzhiyun RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
882*4882a593Smuzhiyun "H2C Tx Cmd Content\n", pdesc, txdesc_len);
883*4882a593Smuzhiyun }
884*4882a593Smuzhiyun
rtl92ee_set_desc(struct ieee80211_hw * hw,u8 * pdesc8,bool istx,u8 desc_name,u8 * val)885*4882a593Smuzhiyun void rtl92ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc8, bool istx,
886*4882a593Smuzhiyun u8 desc_name, u8 *val)
887*4882a593Smuzhiyun {
888*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
889*4882a593Smuzhiyun u8 q_idx = *val;
890*4882a593Smuzhiyun bool dma64 = rtlpriv->cfg->mod_params->dma64;
891*4882a593Smuzhiyun __le32 *pdesc = (__le32 *)pdesc8;
892*4882a593Smuzhiyun
893*4882a593Smuzhiyun if (istx) {
894*4882a593Smuzhiyun switch (desc_name) {
895*4882a593Smuzhiyun case HW_DESC_TX_NEXTDESC_ADDR:
896*4882a593Smuzhiyun set_tx_desc_next_desc_address(pdesc, *(u32 *)val);
897*4882a593Smuzhiyun break;
898*4882a593Smuzhiyun case HW_DESC_OWN:{
899*4882a593Smuzhiyun struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
900*4882a593Smuzhiyun struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[q_idx];
901*4882a593Smuzhiyun u16 max_tx_desc = ring->entries;
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun if (q_idx == BEACON_QUEUE) {
904*4882a593Smuzhiyun ring->cur_tx_wp = 0;
905*4882a593Smuzhiyun ring->cur_tx_rp = 0;
906*4882a593Smuzhiyun set_tx_buff_desc_own(pdesc, 1);
907*4882a593Smuzhiyun return;
908*4882a593Smuzhiyun }
909*4882a593Smuzhiyun
910*4882a593Smuzhiyun /* make sure tx desc is available by caller */
911*4882a593Smuzhiyun ring->cur_tx_wp = ((ring->cur_tx_wp + 1) % max_tx_desc);
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun rtl_write_word(rtlpriv,
914*4882a593Smuzhiyun get_desc_addr_fr_q_idx(q_idx),
915*4882a593Smuzhiyun ring->cur_tx_wp);
916*4882a593Smuzhiyun }
917*4882a593Smuzhiyun break;
918*4882a593Smuzhiyun }
919*4882a593Smuzhiyun } else {
920*4882a593Smuzhiyun switch (desc_name) {
921*4882a593Smuzhiyun case HW_DESC_RX_PREPARE:
922*4882a593Smuzhiyun set_rx_buffer_desc_ls(pdesc, 0);
923*4882a593Smuzhiyun set_rx_buffer_desc_fs(pdesc, 0);
924*4882a593Smuzhiyun set_rx_buffer_desc_total_length(pdesc, 0);
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun set_rx_buffer_desc_data_length(pdesc,
927*4882a593Smuzhiyun MAX_RECEIVE_BUFFER_SIZE +
928*4882a593Smuzhiyun RX_DESC_SIZE);
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun set_rx_buffer_physical_low(pdesc, (*(dma_addr_t *)val) &
931*4882a593Smuzhiyun DMA_BIT_MASK(32));
932*4882a593Smuzhiyun set_rx_buffer_physical_high(pdesc,
933*4882a593Smuzhiyun ((u64)(*(dma_addr_t *)val)
934*4882a593Smuzhiyun >> 32),
935*4882a593Smuzhiyun dma64);
936*4882a593Smuzhiyun break;
937*4882a593Smuzhiyun case HW_DESC_RXERO:
938*4882a593Smuzhiyun set_rx_desc_eor(pdesc, 1);
939*4882a593Smuzhiyun break;
940*4882a593Smuzhiyun default:
941*4882a593Smuzhiyun WARN_ONCE(true,
942*4882a593Smuzhiyun "rtl8192ee: ERR rxdesc :%d not processed\n",
943*4882a593Smuzhiyun desc_name);
944*4882a593Smuzhiyun break;
945*4882a593Smuzhiyun }
946*4882a593Smuzhiyun }
947*4882a593Smuzhiyun }
948*4882a593Smuzhiyun
rtl92ee_get_desc(struct ieee80211_hw * hw,u8 * pdesc8,bool istx,u8 desc_name)949*4882a593Smuzhiyun u64 rtl92ee_get_desc(struct ieee80211_hw *hw,
950*4882a593Smuzhiyun u8 *pdesc8, bool istx, u8 desc_name)
951*4882a593Smuzhiyun {
952*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
953*4882a593Smuzhiyun u64 ret = 0;
954*4882a593Smuzhiyun bool dma64 = rtlpriv->cfg->mod_params->dma64;
955*4882a593Smuzhiyun __le32 *pdesc = (__le32 *)pdesc8;
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun if (istx) {
958*4882a593Smuzhiyun switch (desc_name) {
959*4882a593Smuzhiyun case HW_DESC_OWN:
960*4882a593Smuzhiyun ret = get_tx_desc_own(pdesc);
961*4882a593Smuzhiyun break;
962*4882a593Smuzhiyun case HW_DESC_TXBUFF_ADDR:
963*4882a593Smuzhiyun ret = get_txbuffer_desc_addr_low(pdesc, 1);
964*4882a593Smuzhiyun ret |= (u64)get_txbuffer_desc_addr_high(pdesc, 1,
965*4882a593Smuzhiyun dma64) << 32;
966*4882a593Smuzhiyun break;
967*4882a593Smuzhiyun default:
968*4882a593Smuzhiyun WARN_ONCE(true,
969*4882a593Smuzhiyun "rtl8192ee: ERR txdesc :%d not processed\n",
970*4882a593Smuzhiyun desc_name);
971*4882a593Smuzhiyun break;
972*4882a593Smuzhiyun }
973*4882a593Smuzhiyun } else {
974*4882a593Smuzhiyun switch (desc_name) {
975*4882a593Smuzhiyun case HW_DESC_OWN:
976*4882a593Smuzhiyun ret = get_rx_desc_own(pdesc);
977*4882a593Smuzhiyun break;
978*4882a593Smuzhiyun case HW_DESC_RXPKT_LEN:
979*4882a593Smuzhiyun ret = get_rx_desc_pkt_len(pdesc);
980*4882a593Smuzhiyun break;
981*4882a593Smuzhiyun case HW_DESC_RXBUFF_ADDR:
982*4882a593Smuzhiyun ret = get_rx_desc_buff_addr(pdesc);
983*4882a593Smuzhiyun break;
984*4882a593Smuzhiyun default:
985*4882a593Smuzhiyun WARN_ONCE(true,
986*4882a593Smuzhiyun "rtl8192ee: ERR rxdesc :%d not processed\n",
987*4882a593Smuzhiyun desc_name);
988*4882a593Smuzhiyun break;
989*4882a593Smuzhiyun }
990*4882a593Smuzhiyun }
991*4882a593Smuzhiyun return ret;
992*4882a593Smuzhiyun }
993*4882a593Smuzhiyun
rtl92ee_is_tx_desc_closed(struct ieee80211_hw * hw,u8 hw_queue,u16 index)994*4882a593Smuzhiyun bool rtl92ee_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index)
995*4882a593Smuzhiyun {
996*4882a593Smuzhiyun struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
997*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
998*4882a593Smuzhiyun u16 read_point, write_point;
999*4882a593Smuzhiyun bool ret = false;
1000*4882a593Smuzhiyun static u8 stop_report_cnt;
1001*4882a593Smuzhiyun struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun {
1004*4882a593Smuzhiyun u16 cur_tx_rp;
1005*4882a593Smuzhiyun u32 tmpu32;
1006*4882a593Smuzhiyun
1007*4882a593Smuzhiyun tmpu32 =
1008*4882a593Smuzhiyun rtl_read_dword(rtlpriv,
1009*4882a593Smuzhiyun get_desc_addr_fr_q_idx(hw_queue));
1010*4882a593Smuzhiyun cur_tx_rp = (u16)((tmpu32 >> 16) & 0x0fff);
1011*4882a593Smuzhiyun
1012*4882a593Smuzhiyun /* don't need to update ring->cur_tx_wp */
1013*4882a593Smuzhiyun ring->cur_tx_rp = cur_tx_rp;
1014*4882a593Smuzhiyun }
1015*4882a593Smuzhiyun
1016*4882a593Smuzhiyun read_point = ring->cur_tx_rp;
1017*4882a593Smuzhiyun write_point = ring->cur_tx_wp;
1018*4882a593Smuzhiyun
1019*4882a593Smuzhiyun if (write_point > read_point) {
1020*4882a593Smuzhiyun if (index < write_point && index >= read_point)
1021*4882a593Smuzhiyun ret = false;
1022*4882a593Smuzhiyun else
1023*4882a593Smuzhiyun ret = true;
1024*4882a593Smuzhiyun } else if (write_point < read_point) {
1025*4882a593Smuzhiyun if (index > write_point && index < read_point)
1026*4882a593Smuzhiyun ret = true;
1027*4882a593Smuzhiyun else
1028*4882a593Smuzhiyun ret = false;
1029*4882a593Smuzhiyun } else {
1030*4882a593Smuzhiyun if (index != read_point)
1031*4882a593Smuzhiyun ret = true;
1032*4882a593Smuzhiyun }
1033*4882a593Smuzhiyun
1034*4882a593Smuzhiyun if (hw_queue == BEACON_QUEUE)
1035*4882a593Smuzhiyun ret = true;
1036*4882a593Smuzhiyun
1037*4882a593Smuzhiyun if (rtlpriv->rtlhal.driver_is_goingto_unload ||
1038*4882a593Smuzhiyun rtlpriv->psc.rfoff_reason > RF_CHANGE_BY_PS)
1039*4882a593Smuzhiyun ret = true;
1040*4882a593Smuzhiyun
1041*4882a593Smuzhiyun if (hw_queue < BEACON_QUEUE) {
1042*4882a593Smuzhiyun if (!ret)
1043*4882a593Smuzhiyun stop_report_cnt++;
1044*4882a593Smuzhiyun else
1045*4882a593Smuzhiyun stop_report_cnt = 0;
1046*4882a593Smuzhiyun }
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun return ret;
1049*4882a593Smuzhiyun }
1050*4882a593Smuzhiyun
rtl92ee_tx_polling(struct ieee80211_hw * hw,u8 hw_queue)1051*4882a593Smuzhiyun void rtl92ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
1052*4882a593Smuzhiyun {
1053*4882a593Smuzhiyun }
1054