fw.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2009-2012 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. #include "../wifi.h"
  26. #include "../pci.h"
  27. #include "../base.h"
  28. #include "../efuse.h"
  29. #include "reg.h"
  30. #include "def.h"
  31. #include "fw.h"
  32. #include "sw.h"
  33. static bool _rtl92d_is_fw_downloaded(struct rtl_priv *rtlpriv)
  34. {
  35. return (rtl_read_dword(rtlpriv, REG_MCUFWDL) & MCUFWDL_RDY) ?
  36. true : false;
  37. }
  38. static void _rtl92d_enable_fw_download(struct ieee80211_hw *hw, bool enable)
  39. {
  40. struct rtl_priv *rtlpriv = rtl_priv(hw);
  41. u8 tmp;
  42. if (enable) {
  43. tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
  44. rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
  45. tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
  46. rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
  47. tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
  48. rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
  49. } else {
  50. tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
  51. rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
  52. /* Reserved for fw extension.
  53. * 0x81[7] is used for mac0 status ,
  54. * so don't write this reg here
  55. * rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);*/
  56. }
  57. }
  58. static void _rtl92d_write_fw(struct ieee80211_hw *hw,
  59. enum version_8192d version, u8 *buffer, u32 size)
  60. {
  61. struct rtl_priv *rtlpriv = rtl_priv(hw);
  62. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  63. u8 *bufferptr = buffer;
  64. u32 pagenums, remainsize;
  65. u32 page, offset;
  66. RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);
  67. if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE)
  68. rtl_fill_dummy(bufferptr, &size);
  69. pagenums = size / FW_8192D_PAGE_SIZE;
  70. remainsize = size % FW_8192D_PAGE_SIZE;
  71. if (pagenums > 8)
  72. pr_err("Page numbers should not greater then 8\n");
  73. for (page = 0; page < pagenums; page++) {
  74. offset = page * FW_8192D_PAGE_SIZE;
  75. rtl_fw_page_write(hw, page, (bufferptr + offset),
  76. FW_8192D_PAGE_SIZE);
  77. }
  78. if (remainsize) {
  79. offset = pagenums * FW_8192D_PAGE_SIZE;
  80. page = pagenums;
  81. rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
  82. }
  83. }
  84. static int _rtl92d_fw_free_to_go(struct ieee80211_hw *hw)
  85. {
  86. struct rtl_priv *rtlpriv = rtl_priv(hw);
  87. u32 counter = 0;
  88. u32 value32;
  89. do {
  90. value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  91. } while ((counter++ < FW_8192D_POLLING_TIMEOUT_COUNT) &&
  92. (!(value32 & FWDL_ChkSum_rpt)));
  93. if (counter >= FW_8192D_POLLING_TIMEOUT_COUNT) {
  94. pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
  95. value32);
  96. return -EIO;
  97. }
  98. value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  99. value32 |= MCUFWDL_RDY;
  100. rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
  101. return 0;
  102. }
  103. void rtl92d_firmware_selfreset(struct ieee80211_hw *hw)
  104. {
  105. struct rtl_priv *rtlpriv = rtl_priv(hw);
  106. u8 u1b_tmp;
  107. u8 delay = 100;
  108. /* Set (REG_HMETFR + 3) to 0x20 is reset 8051 */
  109. rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
  110. u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
  111. while (u1b_tmp & BIT(2)) {
  112. delay--;
  113. if (delay == 0)
  114. break;
  115. udelay(50);
  116. u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
  117. }
  118. WARN_ONCE((delay <= 0), "rtl8192de: 8051 reset failed!\n");
  119. RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
  120. "=====> 8051 reset success (%d)\n", delay);
  121. }
  122. static int _rtl92d_fw_init(struct ieee80211_hw *hw)
  123. {
  124. struct rtl_priv *rtlpriv = rtl_priv(hw);
  125. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  126. u32 counter;
  127. RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, "FW already have download\n");
  128. /* polling for FW ready */
  129. counter = 0;
  130. do {
  131. if (rtlhal->interfaceindex == 0) {
  132. if (rtl_read_byte(rtlpriv, FW_MAC0_READY) &
  133. MAC0_READY) {
  134. RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
  135. "Polling FW ready success!! REG_MCUFWDL: 0x%x\n",
  136. rtl_read_byte(rtlpriv,
  137. FW_MAC0_READY));
  138. return 0;
  139. }
  140. udelay(5);
  141. } else {
  142. if (rtl_read_byte(rtlpriv, FW_MAC1_READY) &
  143. MAC1_READY) {
  144. RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
  145. "Polling FW ready success!! REG_MCUFWDL: 0x%x\n",
  146. rtl_read_byte(rtlpriv,
  147. FW_MAC1_READY));
  148. return 0;
  149. }
  150. udelay(5);
  151. }
  152. } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
  153. if (rtlhal->interfaceindex == 0) {
  154. RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
  155. "Polling FW ready fail!! MAC0 FW init not ready: 0x%x\n",
  156. rtl_read_byte(rtlpriv, FW_MAC0_READY));
  157. } else {
  158. RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
  159. "Polling FW ready fail!! MAC1 FW init not ready: 0x%x\n",
  160. rtl_read_byte(rtlpriv, FW_MAC1_READY));
  161. }
  162. RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
  163. "Polling FW ready fail!! REG_MCUFWDL:0x%08x\n",
  164. rtl_read_dword(rtlpriv, REG_MCUFWDL));
  165. return -1;
  166. }
  167. int rtl92d_download_fw(struct ieee80211_hw *hw)
  168. {
  169. struct rtl_priv *rtlpriv = rtl_priv(hw);
  170. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  171. u8 *pfwheader;
  172. u8 *pfwdata;
  173. u32 fwsize;
  174. int err;
  175. enum version_8192d version = rtlhal->version;
  176. u8 value;
  177. u32 count;
  178. bool fw_downloaded = false, fwdl_in_process = false;
  179. unsigned long flags;
  180. if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
  181. return 1;
  182. fwsize = rtlhal->fwsize;
  183. pfwheader = rtlhal->pfirmware;
  184. pfwdata = rtlhal->pfirmware;
  185. rtlhal->fw_version = (u16) GET_FIRMWARE_HDR_VERSION(pfwheader);
  186. rtlhal->fw_subversion = (u16) GET_FIRMWARE_HDR_SUB_VER(pfwheader);
  187. RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
  188. "FirmwareVersion(%d), FirmwareSubVersion(%d), Signature(%#x)\n",
  189. rtlhal->fw_version, rtlhal->fw_subversion,
  190. GET_FIRMWARE_HDR_SIGNATURE(pfwheader));
  191. if (IS_FW_HEADER_EXIST(pfwheader)) {
  192. RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
  193. "Shift 32 bytes for FW header!!\n");
  194. pfwdata = pfwdata + 32;
  195. fwsize = fwsize - 32;
  196. }
  197. spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
  198. fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
  199. if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
  200. fwdl_in_process = true;
  201. else
  202. fwdl_in_process = false;
  203. if (fw_downloaded) {
  204. spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
  205. goto exit;
  206. } else if (fwdl_in_process) {
  207. spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
  208. for (count = 0; count < 5000; count++) {
  209. udelay(500);
  210. spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
  211. fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
  212. if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
  213. fwdl_in_process = true;
  214. else
  215. fwdl_in_process = false;
  216. spin_unlock_irqrestore(&globalmutex_for_fwdownload,
  217. flags);
  218. if (fw_downloaded)
  219. goto exit;
  220. else if (!fwdl_in_process)
  221. break;
  222. else
  223. RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
  224. "Wait for another mac download fw\n");
  225. }
  226. spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
  227. value = rtl_read_byte(rtlpriv, 0x1f);
  228. value |= BIT(5);
  229. rtl_write_byte(rtlpriv, 0x1f, value);
  230. spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
  231. } else {
  232. value = rtl_read_byte(rtlpriv, 0x1f);
  233. value |= BIT(5);
  234. rtl_write_byte(rtlpriv, 0x1f, value);
  235. spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
  236. }
  237. /* If 8051 is running in RAM code, driver should
  238. * inform Fw to reset by itself, or it will cause
  239. * download Fw fail.*/
  240. /* 8051 RAM code */
  241. if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
  242. rtl92d_firmware_selfreset(hw);
  243. rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
  244. }
  245. _rtl92d_enable_fw_download(hw, true);
  246. _rtl92d_write_fw(hw, version, pfwdata, fwsize);
  247. _rtl92d_enable_fw_download(hw, false);
  248. spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
  249. err = _rtl92d_fw_free_to_go(hw);
  250. /* download fw over,clear 0x1f[5] */
  251. value = rtl_read_byte(rtlpriv, 0x1f);
  252. value &= (~BIT(5));
  253. rtl_write_byte(rtlpriv, 0x1f, value);
  254. spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
  255. if (err)
  256. pr_err("fw is not ready to run!\n");
  257. exit:
  258. err = _rtl92d_fw_init(hw);
  259. return err;
  260. }
  261. static bool _rtl92d_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
  262. {
  263. struct rtl_priv *rtlpriv = rtl_priv(hw);
  264. u8 val_hmetfr;
  265. bool result = false;
  266. val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
  267. if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
  268. result = true;
  269. return result;
  270. }
  271. static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw,
  272. u8 element_id, u32 cmd_len, u8 *cmdbuffer)
  273. {
  274. struct rtl_priv *rtlpriv = rtl_priv(hw);
  275. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  276. struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
  277. u8 boxnum;
  278. u16 box_reg = 0, box_extreg = 0;
  279. u8 u1b_tmp;
  280. bool isfw_read = false;
  281. u8 buf_index = 0;
  282. bool bwrite_success = false;
  283. u8 wait_h2c_limmit = 100;
  284. u8 wait_writeh2c_limmit = 100;
  285. u8 boxcontent[4], boxextcontent[2];
  286. u32 h2c_waitcounter = 0;
  287. unsigned long flag;
  288. u8 idx;
  289. if (ppsc->rfpwr_state == ERFOFF || ppsc->inactive_pwrstate == ERFOFF) {
  290. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
  291. "Return as RF is off!!!\n");
  292. return;
  293. }
  294. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
  295. while (true) {
  296. spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
  297. if (rtlhal->h2c_setinprogress) {
  298. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
  299. "H2C set in progress! Wait to set..element_id(%d)\n",
  300. element_id);
  301. while (rtlhal->h2c_setinprogress) {
  302. spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
  303. flag);
  304. h2c_waitcounter++;
  305. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
  306. "Wait 100 us (%d times)...\n",
  307. h2c_waitcounter);
  308. udelay(100);
  309. if (h2c_waitcounter > 1000)
  310. return;
  311. spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
  312. flag);
  313. }
  314. spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
  315. } else {
  316. rtlhal->h2c_setinprogress = true;
  317. spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
  318. break;
  319. }
  320. }
  321. while (!bwrite_success) {
  322. wait_writeh2c_limmit--;
  323. if (wait_writeh2c_limmit == 0) {
  324. pr_err("Write H2C fail because no trigger for FW INT!\n");
  325. break;
  326. }
  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. pr_err("switch case %#x not processed\n",
  347. boxnum);
  348. break;
  349. }
  350. isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
  351. while (!isfw_read) {
  352. wait_h2c_limmit--;
  353. if (wait_h2c_limmit == 0) {
  354. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
  355. "Waiting too long for FW read clear HMEBox(%d)!\n",
  356. boxnum);
  357. break;
  358. }
  359. udelay(10);
  360. isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
  361. u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
  362. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
  363. "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
  364. boxnum, u1b_tmp);
  365. }
  366. if (!isfw_read) {
  367. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
  368. "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
  369. boxnum);
  370. break;
  371. }
  372. memset(boxcontent, 0, sizeof(boxcontent));
  373. memset(boxextcontent, 0, sizeof(boxextcontent));
  374. boxcontent[0] = element_id;
  375. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
  376. "Write element_id box_reg(%4x) = %2x\n",
  377. box_reg, element_id);
  378. switch (cmd_len) {
  379. case 1:
  380. boxcontent[0] &= ~(BIT(7));
  381. memcpy(boxcontent + 1, cmdbuffer + buf_index, 1);
  382. for (idx = 0; idx < 4; idx++)
  383. rtl_write_byte(rtlpriv, box_reg + idx,
  384. boxcontent[idx]);
  385. break;
  386. case 2:
  387. boxcontent[0] &= ~(BIT(7));
  388. memcpy(boxcontent + 1, cmdbuffer + buf_index, 2);
  389. for (idx = 0; idx < 4; idx++)
  390. rtl_write_byte(rtlpriv, box_reg + idx,
  391. boxcontent[idx]);
  392. break;
  393. case 3:
  394. boxcontent[0] &= ~(BIT(7));
  395. memcpy(boxcontent + 1, cmdbuffer + buf_index, 3);
  396. for (idx = 0; idx < 4; idx++)
  397. rtl_write_byte(rtlpriv, box_reg + idx,
  398. boxcontent[idx]);
  399. break;
  400. case 4:
  401. boxcontent[0] |= (BIT(7));
  402. memcpy(boxextcontent, cmdbuffer + buf_index, 2);
  403. memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 2);
  404. for (idx = 0; idx < 2; idx++)
  405. rtl_write_byte(rtlpriv, box_extreg + idx,
  406. boxextcontent[idx]);
  407. for (idx = 0; idx < 4; idx++)
  408. rtl_write_byte(rtlpriv, box_reg + idx,
  409. boxcontent[idx]);
  410. break;
  411. case 5:
  412. boxcontent[0] |= (BIT(7));
  413. memcpy(boxextcontent, cmdbuffer + buf_index, 2);
  414. memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 3);
  415. for (idx = 0; idx < 2; idx++)
  416. rtl_write_byte(rtlpriv, box_extreg + idx,
  417. boxextcontent[idx]);
  418. for (idx = 0; idx < 4; idx++)
  419. rtl_write_byte(rtlpriv, box_reg + idx,
  420. boxcontent[idx]);
  421. break;
  422. default:
  423. pr_err("switch case %#x not processed\n",
  424. cmd_len);
  425. break;
  426. }
  427. bwrite_success = true;
  428. rtlhal->last_hmeboxnum = boxnum + 1;
  429. if (rtlhal->last_hmeboxnum == 4)
  430. rtlhal->last_hmeboxnum = 0;
  431. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
  432. "pHalData->last_hmeboxnum = %d\n",
  433. rtlhal->last_hmeboxnum);
  434. }
  435. spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
  436. rtlhal->h2c_setinprogress = false;
  437. spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
  438. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
  439. }
  440. void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw,
  441. u8 element_id, u32 cmd_len, u8 *cmdbuffer)
  442. {
  443. u32 tmp_cmdbuf[2];
  444. memset(tmp_cmdbuf, 0, 8);
  445. memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
  446. _rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
  447. return;
  448. }
  449. static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw,
  450. struct sk_buff *skb)
  451. {
  452. struct rtl_priv *rtlpriv = rtl_priv(hw);
  453. struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
  454. struct rtl8192_tx_ring *ring;
  455. struct rtl_tx_desc *pdesc;
  456. u8 idx = 0;
  457. unsigned long flags;
  458. struct sk_buff *pskb;
  459. ring = &rtlpci->tx_ring[BEACON_QUEUE];
  460. pskb = __skb_dequeue(&ring->queue);
  461. kfree_skb(pskb);
  462. spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
  463. pdesc = &ring->desc[idx];
  464. /* discard output from call below */
  465. rtlpriv->cfg->ops->get_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN);
  466. rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
  467. __skb_queue_tail(&ring->queue, skb);
  468. spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
  469. rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
  470. return true;
  471. }
  472. #define BEACON_PG 0 /*->1 */
  473. #define PSPOLL_PG 2
  474. #define NULL_PG 3
  475. #define PROBERSP_PG 4 /*->5 */
  476. #define TOTAL_RESERVED_PKT_LEN 768
  477. static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
  478. /* page 0 beacon */
  479. 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
  480. 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
  481. 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
  482. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  483. 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
  484. 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
  485. 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
  486. 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
  487. 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
  488. 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
  489. 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  490. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  491. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  492. 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
  493. 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  494. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  495. /* page 1 beacon */
  496. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  497. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  498. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  499. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  500. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  501. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  502. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  503. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  504. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  505. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  506. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  507. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  508. 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
  509. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  510. 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  511. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  512. /* page 2 ps-poll */
  513. 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
  514. 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
  515. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  516. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  517. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  518. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  519. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  520. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  521. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  522. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  523. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  524. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  525. 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
  526. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
  527. 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  528. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  529. /* page 3 null */
  530. 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
  531. 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
  532. 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
  533. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  534. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  535. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  536. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  537. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  538. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  539. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  540. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  541. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  542. 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
  543. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
  544. 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  545. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  546. /* page 4 probe_resp */
  547. 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
  548. 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
  549. 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
  550. 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
  551. 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
  552. 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
  553. 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
  554. 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
  555. 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
  556. 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
  557. 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  558. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  559. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  560. 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
  561. 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  562. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  563. /* page 5 probe_resp */
  564. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  565. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  566. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  567. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  568. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  569. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  570. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  571. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  572. 0x00, 0x00, 0x00, 0x00, 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. };
  581. void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
  582. {
  583. struct rtl_priv *rtlpriv = rtl_priv(hw);
  584. struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
  585. struct sk_buff *skb = NULL;
  586. u32 totalpacketlen;
  587. bool rtstatus;
  588. u8 u1RsvdPageLoc[3] = { 0 };
  589. bool dlok = false;
  590. u8 *beacon;
  591. u8 *p_pspoll;
  592. u8 *nullfunc;
  593. u8 *p_probersp;
  594. /*---------------------------------------------------------
  595. (1) beacon
  596. ---------------------------------------------------------*/
  597. beacon = &reserved_page_packet[BEACON_PG * 128];
  598. SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
  599. SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
  600. /*-------------------------------------------------------
  601. (2) ps-poll
  602. --------------------------------------------------------*/
  603. p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
  604. SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
  605. SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
  606. SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
  607. SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
  608. /*--------------------------------------------------------
  609. (3) null data
  610. ---------------------------------------------------------*/
  611. nullfunc = &reserved_page_packet[NULL_PG * 128];
  612. SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
  613. SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
  614. SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
  615. SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
  616. /*---------------------------------------------------------
  617. (4) probe response
  618. ----------------------------------------------------------*/
  619. p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
  620. SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
  621. SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
  622. SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
  623. SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
  624. totalpacketlen = TOTAL_RESERVED_PKT_LEN;
  625. RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
  626. "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
  627. &reserved_page_packet[0], totalpacketlen);
  628. RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
  629. "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
  630. u1RsvdPageLoc, 3);
  631. skb = dev_alloc_skb(totalpacketlen);
  632. if (!skb) {
  633. dlok = false;
  634. } else {
  635. skb_put_data(skb, &reserved_page_packet, totalpacketlen);
  636. rtstatus = _rtl92d_cmd_send_packet(hw, skb);
  637. if (rtstatus)
  638. dlok = true;
  639. }
  640. if (dlok) {
  641. RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
  642. "Set RSVD page location to Fw\n");
  643. RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
  644. "H2C_RSVDPAGE", u1RsvdPageLoc, 3);
  645. rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE,
  646. sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
  647. } else
  648. RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
  649. "Set RSVD page location to Fw FAIL!!!!!!\n");
  650. }
  651. void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
  652. {
  653. u8 u1_joinbssrpt_parm[1] = {0};
  654. SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
  655. rtl92d_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
  656. }