• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright(c) 2009-2014  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  * The full GNU General Public License is included in this distribution in the
15  * file called LICENSE.
16  *
17  * Contact Information:
18  * wlanfae <wlanfae@realtek.com>
19  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20  * Hsinchu 300, Taiwan.
21  *
22  * Larry Finger <Larry.Finger@lwfinger.net>
23  *
24  *****************************************************************************/
25 
26 #include "../wifi.h"
27 #include "../pci.h"
28 #include "../base.h"
29 #include "../core.h"
30 #include "reg.h"
31 #include "def.h"
32 #include "fw.h"
33 #include "dm.h"
34 
_rtl92ee_enable_fw_download(struct ieee80211_hw * hw,bool enable)35 static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable)
36 {
37 	struct rtl_priv *rtlpriv = rtl_priv(hw);
38 	u8 tmp;
39 
40 	if (enable) {
41 		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05);
42 
43 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
44 		rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
45 	} else {
46 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
47 		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
48 	}
49 }
50 
_rtl92ee_fw_block_write(struct ieee80211_hw * hw,const u8 * buffer,u32 size)51 static void _rtl92ee_fw_block_write(struct ieee80211_hw *hw,
52 				    const u8 *buffer, u32 size)
53 {
54 	struct rtl_priv *rtlpriv = rtl_priv(hw);
55 	u32 blocksize = sizeof(u32);
56 	u8 *bufferptr = (u8 *)buffer;
57 	u32 *pu4byteptr = (u32 *)buffer;
58 	u32 i, offset, blockcount, remainsize;
59 
60 	blockcount = size / blocksize;
61 	remainsize = size % blocksize;
62 
63 	for (i = 0; i < blockcount; i++) {
64 		offset = i * blocksize;
65 		rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
66 				*(pu4byteptr + i));
67 	}
68 
69 	if (remainsize) {
70 		offset = blockcount * blocksize;
71 		bufferptr += offset;
72 		for (i = 0; i < remainsize; i++) {
73 			rtl_write_byte(rtlpriv,
74 				       (FW_8192C_START_ADDRESS + offset + i),
75 				       *(bufferptr + i));
76 		}
77 	}
78 }
79 
_rtl92ee_fw_page_write(struct ieee80211_hw * hw,u32 page,const u8 * buffer,u32 size)80 static void _rtl92ee_fw_page_write(struct ieee80211_hw *hw, u32 page,
81 				   const u8 *buffer, u32 size)
82 {
83 	struct rtl_priv *rtlpriv = rtl_priv(hw);
84 	u8 value8;
85 	u8 u8page = (u8)(page & 0x07);
86 
87 	value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
88 	rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
89 
90 	_rtl92ee_fw_block_write(hw, buffer, size);
91 }
92 
_rtl92ee_fill_dummy(u8 * pfwbuf,u32 * pfwlen)93 static void _rtl92ee_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
94 {
95 	u32 fwlen = *pfwlen;
96 	u8 remain = (u8)(fwlen % 4);
97 
98 	remain = (remain == 0) ? 0 : (4 - remain);
99 
100 	while (remain > 0) {
101 		pfwbuf[fwlen] = 0;
102 		fwlen++;
103 		remain--;
104 	}
105 
106 	*pfwlen = fwlen;
107 }
108 
_rtl92ee_write_fw(struct ieee80211_hw * hw,enum version_8192e version,u8 * buffer,u32 size)109 static void _rtl92ee_write_fw(struct ieee80211_hw *hw,
110 			      enum version_8192e version,
111 			      u8 *buffer, u32 size)
112 {
113 	struct rtl_priv *rtlpriv = rtl_priv(hw);
114 	u8 *bufferptr = (u8 *)buffer;
115 	u32 pagenums, remainsize;
116 	u32 page, offset;
117 
118 	RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "FW size is %d bytes,\n", size);
119 
120 	_rtl92ee_fill_dummy(bufferptr, &size);
121 
122 	pagenums = size / FW_8192C_PAGE_SIZE;
123 	remainsize = size % FW_8192C_PAGE_SIZE;
124 
125 	if (pagenums > 8) {
126 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
127 			 "Page numbers should not greater then 8\n");
128 	}
129 
130 	for (page = 0; page < pagenums; page++) {
131 		offset = page * FW_8192C_PAGE_SIZE;
132 		_rtl92ee_fw_page_write(hw, page, (bufferptr + offset),
133 				       FW_8192C_PAGE_SIZE);
134 		udelay(2);
135 	}
136 
137 	if (remainsize) {
138 		offset = pagenums * FW_8192C_PAGE_SIZE;
139 		page = pagenums;
140 		_rtl92ee_fw_page_write(hw, page, (bufferptr + offset),
141 				       remainsize);
142 	}
143 }
144 
_rtl92ee_fw_free_to_go(struct ieee80211_hw * hw)145 static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw)
146 {
147 	struct rtl_priv *rtlpriv = rtl_priv(hw);
148 	int err = -EIO;
149 	u32 counter = 0;
150 	u32 value32;
151 
152 	do {
153 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
154 	} while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
155 		 (!(value32 & FWDL_CHKSUM_RPT)));
156 
157 	if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
158 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
159 			 "chksum report faill ! REG_MCUFWDL:0x%08x .\n",
160 			  value32);
161 		goto exit;
162 	}
163 
164 	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
165 		 "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32);
166 
167 	value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
168 	value32 |= MCUFWDL_RDY;
169 	value32 &= ~WINTINI_RDY;
170 	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
171 
172 	rtl92ee_firmware_selfreset(hw);
173 	counter = 0;
174 
175 	do {
176 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
177 		if (value32 & WINTINI_RDY) {
178 			RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD ,
179 				 "Polling FW ready success!! REG_MCUFWDL:0x%08x. count = %d\n",
180 				 value32, counter);
181 			err = 0;
182 			goto exit;
183 		}
184 
185 		udelay(FW_8192C_POLLING_DELAY*10);
186 
187 	} while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
188 
189 	RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
190 		 "Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
191 		 value32, counter);
192 
193 exit:
194 	return err;
195 }
196 
rtl92ee_download_fw(struct ieee80211_hw * hw,bool buse_wake_on_wlan_fw)197 int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
198 {
199 	struct rtl_priv *rtlpriv = rtl_priv(hw);
200 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
201 	struct rtlwifi_firmware_header *pfwheader;
202 	u8 *pfwdata;
203 	u32 fwsize;
204 	int err;
205 	enum version_8192e version = rtlhal->version;
206 
207 	if (!rtlhal->pfirmware)
208 		return 1;
209 
210 	pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
211 	rtlhal->fw_version = le16_to_cpu(pfwheader->version);
212 	rtlhal->fw_subversion = pfwheader->subversion;
213 	pfwdata = (u8 *)rtlhal->pfirmware;
214 	fwsize = rtlhal->fwsize;
215 	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
216 		 "normal Firmware SIZE %d\n" , fwsize);
217 
218 	if (IS_FW_HEADER_EXIST(pfwheader)) {
219 		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
220 			 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
221 			  pfwheader->version, pfwheader->signature,
222 			  (int)sizeof(struct rtlwifi_firmware_header));
223 
224 		pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
225 		fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
226 	} else {
227 		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
228 			 "Firmware no Header, Signature(%#x)\n",
229 			  pfwheader->signature);
230 	}
231 
232 	if (rtlhal->mac_func_enable) {
233 		if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
234 			rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
235 			rtl92ee_firmware_selfreset(hw);
236 		}
237 	}
238 	_rtl92ee_enable_fw_download(hw, true);
239 	_rtl92ee_write_fw(hw, version, pfwdata, fwsize);
240 	_rtl92ee_enable_fw_download(hw, false);
241 
242 	err = _rtl92ee_fw_free_to_go(hw);
243 	if (err) {
244 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
245 			 "Firmware is not ready to run!\n");
246 	} else {
247 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD ,
248 			 "Firmware is ready to run!\n");
249 	}
250 
251 	return 0;
252 }
253 
_rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw * hw,u8 boxnum)254 static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
255 {
256 	struct rtl_priv *rtlpriv = rtl_priv(hw);
257 	u8 val_hmetfr;
258 	bool result = false;
259 
260 	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
261 	if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
262 		result = true;
263 	return result;
264 }
265 
_rtl92ee_fill_h2c_command(struct ieee80211_hw * hw,u8 element_id,u32 cmd_len,u8 * cmdbuffer)266 static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
267 				      u32 cmd_len, u8 *cmdbuffer)
268 {
269 	struct rtl_priv *rtlpriv = rtl_priv(hw);
270 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
271 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
272 	u8 boxnum;
273 	u16 box_reg = 0, box_extreg = 0;
274 	u8 u1b_tmp;
275 	bool isfw_read = false;
276 	u8 buf_index = 0;
277 	bool bwrite_sucess = false;
278 	u8 wait_h2c_limmit = 100;
279 	u8 boxcontent[4], boxextcontent[4];
280 	u32 h2c_waitcounter = 0;
281 	unsigned long flag;
282 	u8 idx;
283 
284 	if (ppsc->dot11_psmode != EACTIVE ||
285 	    ppsc->inactive_pwrstate == ERFOFF) {
286 		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
287 			 "FillH2CCommand8192E(): Return because RF is off!!!\n");
288 		return;
289 	}
290 
291 	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "come in\n");
292 
293 	/* 1. Prevent race condition in setting H2C cmd.
294 	 * (copy from MgntActSet_RF_State().)
295 	 */
296 	while (true) {
297 		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
298 		if (rtlhal->h2c_setinprogress) {
299 			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
300 				 "H2C set in progress! Wait to set..element_id(%d).\n",
301 				  element_id);
302 
303 			while (rtlhal->h2c_setinprogress) {
304 				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
305 						       flag);
306 				h2c_waitcounter++;
307 				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
308 					 "Wait 100 us (%d times)...\n",
309 					  h2c_waitcounter);
310 				udelay(100);
311 
312 				if (h2c_waitcounter > 1000)
313 					return;
314 				spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
315 						  flag);
316 			}
317 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
318 		} else {
319 			rtlhal->h2c_setinprogress = true;
320 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
321 			break;
322 		}
323 	}
324 
325 	while (!bwrite_sucess) {
326 		/* 2. Find the last BOX number which has been writen. */
327 		boxnum = rtlhal->last_hmeboxnum;
328 		switch (boxnum) {
329 		case 0:
330 			box_reg = REG_HMEBOX_0;
331 			box_extreg = REG_HMEBOX_EXT_0;
332 			break;
333 		case 1:
334 			box_reg = REG_HMEBOX_1;
335 			box_extreg = REG_HMEBOX_EXT_1;
336 			break;
337 		case 2:
338 			box_reg = REG_HMEBOX_2;
339 			box_extreg = REG_HMEBOX_EXT_2;
340 			break;
341 		case 3:
342 			box_reg = REG_HMEBOX_3;
343 			box_extreg = REG_HMEBOX_EXT_3;
344 			break;
345 		default:
346 			RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
347 				 "switch case not process\n");
348 			break;
349 		}
350 
351 		/* 3. Check if the box content is empty. */
352 		isfw_read = false;
353 		u1b_tmp = rtl_read_byte(rtlpriv, REG_CR);
354 
355 		if (u1b_tmp != 0xea) {
356 			isfw_read = true;
357 		} else {
358 			if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea ||
359 			    rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea)
360 				rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff);
361 		}
362 
363 		if (isfw_read) {
364 			wait_h2c_limmit = 100;
365 			isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
366 			while (!isfw_read) {
367 				wait_h2c_limmit--;
368 				if (wait_h2c_limmit == 0) {
369 					RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
370 						 "Waiting too long for FW read clear HMEBox(%d)!!!\n",
371 						 boxnum);
372 					break;
373 				}
374 				udelay(10);
375 				isfw_read =
376 				  _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
377 				u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
378 				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
379 					 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
380 					 boxnum, u1b_tmp);
381 			}
382 		}
383 
384 		/* If Fw has not read the last
385 		 * H2C cmd, break and give up this H2C.
386 		 */
387 		if (!isfw_read) {
388 			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
389 				 "Write H2C reg BOX[%d] fail,Fw don't read.\n",
390 				 boxnum);
391 			break;
392 		}
393 		/* 4. Fill the H2C cmd into box */
394 		memset(boxcontent, 0, sizeof(boxcontent));
395 		memset(boxextcontent, 0, sizeof(boxextcontent));
396 		boxcontent[0] = element_id;
397 		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
398 			 "Write element_id box_reg(%4x) = %2x\n",
399 			  box_reg, element_id);
400 
401 		switch (cmd_len) {
402 		case 1:
403 		case 2:
404 		case 3:
405 			/*boxcontent[0] &= ~(BIT(7));*/
406 			memcpy((u8 *)(boxcontent) + 1,
407 			       cmdbuffer + buf_index, cmd_len);
408 
409 			for (idx = 0; idx < 4; idx++) {
410 				rtl_write_byte(rtlpriv, box_reg + idx,
411 					       boxcontent[idx]);
412 			}
413 			break;
414 		case 4:
415 		case 5:
416 		case 6:
417 		case 7:
418 			/*boxcontent[0] |= (BIT(7));*/
419 			memcpy((u8 *)(boxextcontent),
420 			       cmdbuffer + buf_index+3, cmd_len-3);
421 			memcpy((u8 *)(boxcontent) + 1,
422 			       cmdbuffer + buf_index, 3);
423 
424 			for (idx = 0; idx < 4; idx++) {
425 				rtl_write_byte(rtlpriv, box_extreg + idx,
426 					       boxextcontent[idx]);
427 			}
428 
429 			for (idx = 0; idx < 4; idx++) {
430 				rtl_write_byte(rtlpriv, box_reg + idx,
431 					       boxcontent[idx]);
432 			}
433 			break;
434 		default:
435 			RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
436 				 "switch case not process\n");
437 			break;
438 		}
439 
440 		bwrite_sucess = true;
441 
442 		rtlhal->last_hmeboxnum = boxnum + 1;
443 		if (rtlhal->last_hmeboxnum == 4)
444 			rtlhal->last_hmeboxnum = 0;
445 
446 		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
447 			 "pHalData->last_hmeboxnum  = %d\n",
448 			  rtlhal->last_hmeboxnum);
449 	}
450 
451 	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
452 	rtlhal->h2c_setinprogress = false;
453 	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
454 
455 	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "go out\n");
456 }
457 
rtl92ee_fill_h2c_cmd(struct ieee80211_hw * hw,u8 element_id,u32 cmd_len,u8 * cmdbuffer)458 void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw,
459 			  u8 element_id, u32 cmd_len, u8 *cmdbuffer)
460 {
461 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
462 	u32 tmp_cmdbuf[2];
463 
464 	if (!rtlhal->fw_ready) {
465 		RT_ASSERT(false,
466 			  "return H2C cmd because of Fw download fail!!!\n");
467 		return;
468 	}
469 
470 	memset(tmp_cmdbuf, 0, 8);
471 	memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
472 	_rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
473 }
474 
rtl92ee_firmware_selfreset(struct ieee80211_hw * hw)475 void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw)
476 {
477 	u8 u1b_tmp;
478 	struct rtl_priv *rtlpriv = rtl_priv(hw);
479 
480 	u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
481 	rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
482 
483 	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
484 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
485 
486 	udelay(50);
487 
488 	u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
489 	rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));
490 
491 	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
492 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
493 
494 	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD ,
495 		 "  _8051Reset92E(): 8051 reset success .\n");
496 }
497 
rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw * hw,u8 mode)498 void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
499 {
500 	struct rtl_priv *rtlpriv = rtl_priv(hw);
501 	u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
502 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
503 	u8 rlbm , power_state = 0;
504 
505 	RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , "FW LPS mode = %d\n", mode);
506 
507 	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
508 	rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
509 	SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
510 	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
511 					 (rtlpriv->mac80211.p2p) ?
512 					 ppsc->smart_ps : 1);
513 	SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
514 					       ppsc->reg_max_lps_awakeintvl);
515 	SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
516 	if (mode == FW_PS_ACTIVE_MODE)
517 		power_state |= FW_PWR_STATE_ACTIVE;
518 	else
519 		power_state |= FW_PWR_STATE_RF_OFF;
520 	SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
521 
522 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
523 		      "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
524 		      u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
525 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
526 			     u1_h2c_set_pwrmode);
527 }
528 
rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw * hw,u8 mstatus)529 void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
530 {
531 	u8 parm[3] = { 0 , 0 , 0 };
532 	/* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
533 	 *          bit1=0-->update Media Status to MACID
534 	 *          bit1=1-->update Media Status from MACID to MACID_End
535 	 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
536 	 * parm[2]: MACID_End
537 	 */
538 
539 	SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
540 	SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
541 
542 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
543 }
544 
545 #define BEACON_PG		0 /* ->1 */
546 #define PSPOLL_PG		2
547 #define NULL_PG			3
548 #define PROBERSP_PG		4 /* ->5 */
549 
550 #define TOTAL_RESERVED_PKT_LEN	768
551 
552 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
553 	/* page 0 beacon */
554 	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
555 	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
556 	0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
557 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 	0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
559 	0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
560 	0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
561 	0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
562 	0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
563 	0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
564 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 	0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
567 	0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
568 	0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
569 	0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
570 
571 	/* page 1 beacon */
572 	0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
573 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 	0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
584 	0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
585 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588 
589 	/* page 2  ps-poll */
590 	0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
591 	0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
592 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 	0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
602 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
603 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606 
607 	/* page 3  null */
608 	0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
609 	0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
610 	0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
611 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 	0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
620 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
621 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 	0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 
625 	/* page 4  probe_resp */
626 	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
627 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
628 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
629 	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
630 	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
631 	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
632 	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
633 	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
634 	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
635 	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
636 	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
640 	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642 
643 	/* page 5  probe_resp */
644 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660 };
661 
rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw * hw,bool b_dl_finished)662 void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
663 {
664 	struct rtl_priv *rtlpriv = rtl_priv(hw);
665 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
666 	struct sk_buff *skb = NULL;
667 	bool rtstatus;
668 	u32 totalpacketlen;
669 	u8 u1rsvdpageloc[5] = { 0 };
670 	bool b_dlok = false;
671 
672 	u8 *beacon;
673 	u8 *p_pspoll;
674 	u8 *nullfunc;
675 	u8 *p_probersp;
676 	/*---------------------------------------------------------
677 	 *			(1) beacon
678 	 *---------------------------------------------------------
679 	 */
680 	beacon = &reserved_page_packet[BEACON_PG * 128];
681 	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
682 	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
683 
684 	/*-------------------------------------------------------
685 	 *			(2) ps-poll
686 	 *--------------------------------------------------------
687 	 */
688 	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
689 	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
690 	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
691 	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
692 
693 	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
694 
695 	/*--------------------------------------------------------
696 	 *			(3) null data
697 	 *---------------------------------------------------------
698 	 */
699 	nullfunc = &reserved_page_packet[NULL_PG * 128];
700 	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
701 	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
702 	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
703 
704 	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
705 
706 	/*---------------------------------------------------------
707 	 *			(4) probe response
708 	 *----------------------------------------------------------
709 	 */
710 	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
711 	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
712 	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
713 	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
714 
715 	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
716 
717 	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
718 
719 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
720 		      "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
721 		      &reserved_page_packet[0], totalpacketlen);
722 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
723 		      "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
724 		      u1rsvdpageloc, 3);
725 
726 	skb = dev_alloc_skb(totalpacketlen);
727 	memcpy((u8 *)skb_put(skb, totalpacketlen),
728 	       &reserved_page_packet, totalpacketlen);
729 
730 	rtstatus = rtl_cmd_send_packet(hw, skb);
731 	if (rtstatus)
732 		b_dlok = true;
733 
734 	if (b_dlok) {
735 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD ,
736 			 "Set RSVD page location to Fw.\n");
737 		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
738 			      "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
739 		rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
740 				     sizeof(u1rsvdpageloc), u1rsvdpageloc);
741 	} else {
742 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
743 			 "Set RSVD page location to Fw FAIL!!!!!!.\n");
744 	}
745 }
746 
747 /*Shoud check FW support p2p or not.*/
rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw * hw,u8 ctwindow)748 static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
749 {
750 	u8 u1_ctwindow_period[1] = {ctwindow};
751 
752 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
753 }
754 
rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw * hw,u8 p2p_ps_state)755 void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
756 {
757 	struct rtl_priv *rtlpriv = rtl_priv(hw);
758 	struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
759 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
760 	struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
761 	struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
762 	u8 i;
763 	u16 ctwindow;
764 	u32 start_time, tsf_low;
765 
766 	switch (p2p_ps_state) {
767 	case P2P_PS_DISABLE:
768 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_DISABLE\n");
769 		memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
770 		break;
771 	case P2P_PS_ENABLE:
772 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_ENABLE\n");
773 		/* update CTWindow value. */
774 		if (p2pinfo->ctwindow > 0) {
775 			p2p_ps_offload->ctwindow_en = 1;
776 			ctwindow = p2pinfo->ctwindow;
777 			rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
778 		}
779 		/* hw only support 2 set of NoA */
780 		for (i = 0 ; i < p2pinfo->noa_num ; i++) {
781 			/* To control the register setting for which NOA*/
782 			rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
783 			if (i == 0)
784 				p2p_ps_offload->noa0_en = 1;
785 			else
786 				p2p_ps_offload->noa1_en = 1;
787 			/* config P2P NoA Descriptor Register */
788 			rtl_write_dword(rtlpriv, 0x5E0,
789 					p2pinfo->noa_duration[i]);
790 			rtl_write_dword(rtlpriv, 0x5E4,
791 					p2pinfo->noa_interval[i]);
792 
793 			/*Get Current TSF value */
794 			tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
795 
796 			start_time = p2pinfo->noa_start_time[i];
797 			if (p2pinfo->noa_count_type[i] != 1) {
798 				while (start_time <= (tsf_low + (50 * 1024))) {
799 					start_time += p2pinfo->noa_interval[i];
800 					if (p2pinfo->noa_count_type[i] != 255)
801 						p2pinfo->noa_count_type[i]--;
802 				}
803 			}
804 			rtl_write_dword(rtlpriv, 0x5E8, start_time);
805 			rtl_write_dword(rtlpriv, 0x5EC,
806 					p2pinfo->noa_count_type[i]);
807 		}
808 		if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
809 			/* rst p2p circuit */
810 			rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
811 			p2p_ps_offload->offload_en = 1;
812 
813 			if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
814 				p2p_ps_offload->role = 1;
815 				p2p_ps_offload->allstasleep = 0;
816 			} else {
817 				p2p_ps_offload->role = 0;
818 			}
819 			p2p_ps_offload->discovery = 0;
820 		}
821 		break;
822 	case P2P_PS_SCAN:
823 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN\n");
824 		p2p_ps_offload->discovery = 1;
825 		break;
826 	case P2P_PS_SCAN_DONE:
827 		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN_DONE\n");
828 		p2p_ps_offload->discovery = 0;
829 		p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
830 		break;
831 	default:
832 		break;
833 	}
834 	rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
835 			     (u8 *)p2p_ps_offload);
836 }
837 
_rtl92ee_c2h_ra_report_handler(struct ieee80211_hw * hw,u8 * cmd_buf,u8 cmd_len)838 static void _rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
839 					   u8 *cmd_buf, u8 cmd_len)
840 {
841 	u8 rate = cmd_buf[0] & 0x3F;
842 	bool collision_state = cmd_buf[3] & BIT(0);
843 
844 	rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
845 }
846 
_rtl92ee_c2h_content_parsing(struct ieee80211_hw * hw,u8 c2h_cmd_id,u8 c2h_cmd_len,u8 * tmp_buf)847 static void _rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
848 					 u8 c2h_cmd_len, u8 *tmp_buf)
849 {
850 	struct rtl_priv *rtlpriv = rtl_priv(hw);
851 
852 	switch (c2h_cmd_id) {
853 	case C2H_8192E_DBG:
854 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
855 			 "[C2H], C2H_8723BE_DBG!!\n");
856 		break;
857 	case C2H_8192E_TXBF:
858 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
859 			 "[C2H], C2H_8192E_TXBF!!\n");
860 		break;
861 	case C2H_8192E_TX_REPORT:
862 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE ,
863 			 "[C2H], C2H_8723BE_TX_REPORT!\n");
864 		break;
865 	case C2H_8192E_BT_INFO:
866 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
867 			 "[C2H], C2H_8723BE_BT_INFO!!\n");
868 		rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
869 							      c2h_cmd_len);
870 		break;
871 	case C2H_8192E_BT_MP:
872 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
873 			 "[C2H], C2H_8723BE_BT_MP!!\n");
874 		break;
875 	case C2H_8192E_RA_RPT:
876 		_rtl92ee_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len);
877 		break;
878 	default:
879 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
880 			 "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
881 		break;
882 	}
883 }
884 
rtl92ee_c2h_packet_handler(struct ieee80211_hw * hw,u8 * buffer,u8 len)885 void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
886 {
887 	struct rtl_priv *rtlpriv = rtl_priv(hw);
888 	u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
889 	u8 *tmp_buf = NULL;
890 
891 	c2h_cmd_id = buffer[0];
892 	c2h_cmd_seq = buffer[1];
893 	c2h_cmd_len = len - 2;
894 	tmp_buf = buffer + 2;
895 
896 	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
897 		 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
898 		 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
899 
900 	RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
901 		      "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
902 
903 	_rtl92ee_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
904 }
905