rtl8821c_cmd.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2016 Realtek Corporation. All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of version 2 of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along with
  15. * this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17. *
  18. *
  19. ******************************************************************************/
  20. #define _RTL8821C_CMD_C_
  21. #include <hal_data.h> /* HAL_DATA_TYPE */
  22. #include "../hal_halmac.h" /* HRTW_HALMAC_H2C_MAX_SIZE, CMD_ID_RSVD_PAGE and etc. */
  23. #include "rtl8821c.h"
  24. /*
  25. * Below functions are for C2H
  26. */
  27. /*****************************************
  28. * H2C Msg format :
  29. *| 31 - 8 |7-5 | 4 - 0 |
  30. *| h2c_msg |Class |CMD_ID |
  31. *| 31-0 |
  32. *| Ext msg |
  33. *
  34. ******************************************/
  35. s32 rtl8821c_fillh2ccmd(PADAPTER adapter, u8 id, u32 buf_len, u8 *pbuf)
  36. {
  37. u8 h2c[RTW_HALMAC_H2C_MAX_SIZE] = {0};
  38. #ifdef DBG_H2C_CONTENT
  39. u8 msg[(RTW_HALMAC_H2C_MAX_SIZE - 1) * 5 + 1] = {0};
  40. u8 *msg_p;
  41. u32 msg_size, i, n;
  42. #endif /* CONFIG_RTW_DEBUG */
  43. int err;
  44. s32 ret = _FAIL;
  45. if (!pbuf)
  46. goto exit;
  47. if (buf_len > (RTW_HALMAC_H2C_MAX_SIZE - 1))
  48. goto exit;
  49. if (rtw_is_surprise_removed(adapter))
  50. goto exit;
  51. #ifdef DBG_H2C_CONTENT
  52. msg_p = msg;
  53. msg_size = (RTW_HALMAC_H2C_MAX_SIZE - 1) * 5 + 1;
  54. for (i = 0; i < buf_len; i++) {
  55. n = rtw_sprintf(msg_p, msg_size, " 0x%02x", pbuf[i]);
  56. msg_p += n;
  57. msg_size -= n;
  58. if (msg_size == 0)
  59. break;
  60. }
  61. RTW_INFO(FUNC_ADPT_FMT ": id=0x%02x buf=%s\n",
  62. FUNC_ADPT_ARG(adapter), id, msg);
  63. #endif /* CONFIG_RTW_DEBUG */
  64. h2c[0] = id;
  65. _rtw_memcpy(h2c + 1, pbuf, buf_len);
  66. err = rtw_halmac_send_h2c(adapter_to_dvobj(adapter), h2c);
  67. if (_SUCCESS == err)
  68. ret = _SUCCESS;
  69. exit:
  70. return ret;
  71. }
  72. static void rtl8821c_set_FwRsvdPage_cmd(PADAPTER adapter, PRSVDPAGE_LOC rsvdpageloc)
  73. {
  74. u8 h2c[RTW_HALMAC_H2C_MAX_SIZE] = {0};
  75. RTW_INFO(FUNC_ADPT_FMT ": ProbeRsp=%d PsPoll=%d Null=%d QoSNull=%d BTNull=%d\n",
  76. FUNC_ADPT_ARG(adapter),
  77. rsvdpageloc->LocProbeRsp, rsvdpageloc->LocPsPoll,
  78. rsvdpageloc->LocNullData, rsvdpageloc->LocQosNull,
  79. rsvdpageloc->LocBTQosNull);
  80. RSVD_PAGE_SET_CMD_ID(h2c, CMD_ID_RSVD_PAGE);
  81. RSVD_PAGE_SET_CLASS(h2c, CLASS_RSVD_PAGE);
  82. RSVD_PAGE_SET_LOC_PROBE_RSP(h2c, rsvdpageloc->LocProbeRsp);
  83. RSVD_PAGE_SET_LOC_PS_POLL(h2c, rsvdpageloc->LocPsPoll);
  84. RSVD_PAGE_SET_LOC_NULL_DATA(h2c, rsvdpageloc->LocNullData);
  85. RSVD_PAGE_SET_LOC_QOS_NULL(h2c, rsvdpageloc->LocQosNull);
  86. RSVD_PAGE_SET_LOC_BT_QOS_NULL(h2c, rsvdpageloc->LocBTQosNull);
  87. RTW_DBG_DUMP("H2C-RsvdPage Parm:", h2c, RTW_HALMAC_H2C_MAX_SIZE);
  88. rtw_halmac_send_h2c(adapter_to_dvobj(adapter), h2c);
  89. }
  90. static void rtl8821c_set_FwAoacRsvdPage_cmd(PADAPTER adapter, PRSVDPAGE_LOC rsvdpageloc)
  91. {
  92. #ifdef CONFIG_WOWLAN
  93. struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
  94. struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
  95. u8 res = 0, count = 0;
  96. u8 h2c[RTW_HALMAC_H2C_MAX_SIZE] = {0};
  97. RTW_INFO(FUNC_ADPT_FMT ": RWC=%d ArpRsp=%d NbrAdv=%d GtkRsp=%d GtkInfo=%d ProbeReq=%d NetworkList=%d\n",
  98. FUNC_ADPT_ARG(adapter),
  99. rsvdpageloc->LocRemoteCtrlInfo, rsvdpageloc->LocArpRsp,
  100. rsvdpageloc->LocNbrAdv, rsvdpageloc->LocGTKRsp,
  101. rsvdpageloc->LocGTKInfo, rsvdpageloc->LocProbeReq,
  102. rsvdpageloc->LocNetList);
  103. if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
  104. AOAC_RSVD_PAGE_SET_CMD_ID(h2c, CMD_ID_AOAC_RSVD_PAGE);
  105. AOAC_RSVD_PAGE_SET_CLASS(h2c, CLASS_AOAC_RSVD_PAGE);
  106. AOAC_RSVD_PAGE_SET_LOC_REMOTE_CTRL_INFO(h2c, rsvdpageloc->LocRemoteCtrlInfo);
  107. AOAC_RSVD_PAGE_SET_LOC_ARP_RESPONSE(h2c, rsvdpageloc->LocArpRsp);
  108. AOAC_RSVD_PAGE_SET_LOC_GTK_RSP(h2c, rsvdpageloc->LocGTKRsp);
  109. AOAC_RSVD_PAGE_SET_LOC_GTK_INFO(h2c, rsvdpageloc->LocGTKInfo);
  110. #ifdef CONFIG_GTK_OL
  111. AOAC_RSVD_PAGE_SET_LOC_GTK_EXT_MEM(h2c, rsvdpageloc->LocGTKEXTMEM);
  112. #endif /* CONFIG_GTK_OL */
  113. RTW_DBG_DUMP("H2C-AoacRsvdPage Parm:", h2c, RTW_HALMAC_H2C_MAX_SIZE);
  114. rtw_halmac_send_h2c(adapter_to_dvobj(adapter), h2c);
  115. } else {
  116. #ifdef CONFIG_PNO_SUPPORT
  117. if (!pwrpriv->wowlan_in_resume) {
  118. RTW_INFO("%s: NLO_INFO=%d\n", __FUNCTION__, rsvdpageloc->LocPNOInfo);
  119. AOAC_RSVD_PAGE3_SET_CMD_ID(h2c, CMD_ID_AOAC_RSVD_PAGE3);
  120. AOAC_RSVD_PAGE3_SET_CLASS(h2c, CLASS_AOAC_RSVD_PAGE3);
  121. AOAC_RSVD_PAGE3_SET_LOC_NLO_INFO(h2c, rsvdpageloc->LocPNOInfo);
  122. RTW_DBG_DUMP("H2C-AoacRsvdPage3 Parm:", h2c, RTW_HALMAC_H2C_MAX_SIZE);
  123. rtw_halmac_send_h2c(adapter_to_dvobj(adapter), h2c);
  124. rtw_msleep_os(10);
  125. }
  126. #endif /* CONFIG_PNO_SUPPORT */
  127. }
  128. #endif /* CONFIG_WOWLAN */
  129. }
  130. static void rtl8821c_set_FwKeepAlive_cmd(PADAPTER adapter, u8 benable, u8 pkt_type)
  131. {
  132. u8 h2c[RTW_HALMAC_H2C_MAX_SIZE] = {0};
  133. u8 adopt = 1;
  134. #ifdef CONFIG_PLATFORM_INTEL_BYT
  135. u8 check_period = 10;
  136. #else
  137. u8 check_period = 5;
  138. #endif
  139. RTW_INFO(FUNC_ADPT_FMT ": benable=%d\n", FUNC_ADPT_ARG(adapter), benable);
  140. KEEP_ALIVE_SET_CMD_ID(h2c, CMD_ID_KEEP_ALIVE);
  141. KEEP_ALIVE_SET_CLASS(h2c, CLASS_KEEP_ALIVE);
  142. KEEP_ALIVE_SET_ENABLE(h2c, benable);
  143. KEEP_ALIVE_SET_ADOPT_USER_SETTING(h2c, adopt);
  144. KEEP_ALIVE_SET_PKT_TYPE(h2c, pkt_type);
  145. KEEP_ALIVE_SET_KEEP_ALIVE_CHECK_PERIOD(h2c, check_period);
  146. RTW_DBG_DUMP("H2C-KeepAlive Parm:", h2c, RTW_HALMAC_H2C_MAX_SIZE);
  147. rtw_halmac_send_h2c(adapter_to_dvobj(adapter), h2c);
  148. }
  149. static void rtl8821c_set_FwDisconDecision_cmd(PADAPTER adapter, u8 benable)
  150. {
  151. u8 h2c[RTW_HALMAC_H2C_MAX_SIZE] = {0};
  152. u8 adopt = 1, check_period = 10, trypkt_num = 0;
  153. RTW_INFO(FUNC_ADPT_FMT ": benable=%d\n",
  154. FUNC_ADPT_ARG(adapter), benable);
  155. DISCONNECT_DECISION_SET_CMD_ID(h2c, CMD_ID_DISCONNECT_DECISION);
  156. DISCONNECT_DECISION_SET_CLASS(h2c, CLASS_DISCONNECT_DECISION);
  157. DISCONNECT_DECISION_SET_ENABLE(h2c, benable);
  158. DISCONNECT_DECISION_SET_ADOPT_USER_SETTING(h2c, adopt);
  159. DISCONNECT_DECISION_SET_DISCON_DECISION_CHECK_PERIOD(h2c, check_period);
  160. DISCONNECT_DECISION_SET_TRY_PKT_NUM(h2c, trypkt_num);
  161. RTW_DBG_DUMP("H2C-DisconDecision Parm:", h2c, RTW_HALMAC_H2C_MAX_SIZE);
  162. rtw_halmac_send_h2c(adapter_to_dvobj(adapter), h2c);
  163. }
  164. static u8 get_ra_vht_en(u32 wirelessMode, u32 bitmap)
  165. {
  166. u8 ret = 0;
  167. if (wirelessMode == WIRELESS_11_24AC) {
  168. if (bitmap & 0xfff00000) /* 2SS */
  169. ret = 3;
  170. else /* 1SS */
  171. ret = 2;
  172. } else if (wirelessMode == WIRELESS_11_5AC)
  173. ret = 1;
  174. return ret;
  175. }
  176. static u8 get_ra_ldpc(struct sta_info *psta)
  177. {
  178. u8 en_ldpc = 0;
  179. if (psta != NULL) {
  180. if (psta->mac_id == 1)
  181. en_ldpc = 0;
  182. else {
  183. #ifdef CONFIG_80211AC_VHT
  184. if (is_supported_vht(psta->wireless_mode)) {
  185. if (TEST_FLAG(psta->vhtpriv.ldpc_cap, LDPC_VHT_CAP_TX))
  186. en_ldpc = 1;
  187. else
  188. en_ldpc = 0;
  189. } else if (is_supported_ht(psta->wireless_mode)) {
  190. if (TEST_FLAG(psta->htpriv.ldpc_cap, LDPC_HT_CAP_TX))
  191. en_ldpc = 1;
  192. else
  193. en_ldpc = 0;
  194. } else
  195. #endif
  196. en_ldpc = 0;
  197. }
  198. }
  199. return en_ldpc;
  200. }
  201. /*
  202. * arg[0] = macid
  203. * arg[1] = raid
  204. * arg[2] = shortGIrate
  205. * arg[3] = init_rate
  206. */
  207. void rtl8821c_set_FwMacIdConfig_cmd(PADAPTER adapter, u64 mask, u8 *arg, u8 bw)
  208. {
  209. HAL_DATA_TYPE *hal = GET_HAL_DATA(adapter);
  210. struct macid_ctl_t *macid_ctl = &adapter->dvobj->macid_ctl;
  211. struct sta_info *psta = NULL;
  212. u8 mac_id, init_rate, raid, sgi = _FALSE;
  213. u8 h2c[RTW_HALMAC_H2C_MAX_SIZE] = {0};
  214. u8 ignore_bw = _FALSE;
  215. if (hal->fw_ractrl == _FALSE) {
  216. RTW_INFO(FUNC_ADPT_FMT" fw ractrl = _FALSE\n",
  217. FUNC_ADPT_ARG(adapter));
  218. return;
  219. }
  220. mac_id = arg[0];
  221. raid = arg[1];
  222. sgi = arg[2] & 0x0F;
  223. ignore_bw = arg[2] >> 4;
  224. init_rate = arg[3];
  225. if (mac_id < macid_ctl->num)
  226. psta = macid_ctl->sta[mac_id];
  227. if (!psta) {
  228. RTW_INFO(FUNC_ADPT_FMT" macid:%u, sta is NULL\n",
  229. FUNC_ADPT_ARG(adapter), mac_id);
  230. return;
  231. }
  232. RTW_INFO(FUNC_ADPT_FMT ": mac_id=%d raid=0x%x bw=%d mask=0x%016llx\n",
  233. FUNC_ADPT_ARG(adapter), mac_id, raid, bw, mask);
  234. MACID_CFG_SET_CMD_ID(h2c, CMD_ID_MACID_CFG);
  235. MACID_CFG_SET_CLASS(h2c, CLASS_MACID_CFG);
  236. /* common for h2c cmd 0x40 */
  237. MACID_CFG_SET_MAC_ID(h2c, mac_id);
  238. MACID_CFG_SET_RATE_ID(h2c, raid);
  239. #ifdef CONFIG_LPS_PG
  240. MACID_CFG_SET_INIT_RATE_LV(h2c, psta->lps_pg_rssi_lv);
  241. #endif
  242. MACID_CFG_SET_SGI(h2c, (sgi) ? 1 : 0);
  243. MACID_CFG_SET_NO_UPDATE(h2c, (ignore_bw) ? 1 : 0);
  244. MACID_CFG_SET_BW(h2c, bw);
  245. MACID_CFG_SET_LDPC_CAP(h2c, get_ra_ldpc(psta));
  246. MACID_CFG_SET_WHT_EN(h2c, get_ra_vht_en(psta->wireless_mode, mask));
  247. /* DisableTXPowerTraining */
  248. if (hal->bDisableTXPowerTraining) {
  249. MACID_CFG_SET_DISPT(h2c, 1);
  250. RTW_INFO("%s: Disable PWT by driver\n", __FUNCTION__);
  251. } else {
  252. struct PHY_DM_STRUCT *pDM_OutSrc = &hal->odmpriv;
  253. if (pDM_OutSrc->is_disable_power_training) {
  254. MACID_CFG_SET_DISPT(h2c, 1);
  255. RTW_INFO("%s: Disable PWT by DM\n", __FUNCTION__);
  256. }
  257. }
  258. MACID_CFG_SET_RATE_MASK7_0(h2c, (u8)(mask & 0x000000ff));
  259. MACID_CFG_SET_RATE_MASK15_8(h2c, (u8)((mask & 0x0000ff00) >> 8));
  260. MACID_CFG_SET_RATE_MASK23_16(h2c, (u8)((mask & 0x00ff0000) >> 16));
  261. MACID_CFG_SET_RATE_MASK31_24(h2c, (u8)((mask & 0xff000000) >> 24));
  262. RTW_INFO("%s, mask=0x%016llx, mac_id=0x%x, raid=0x%x, shortGIrate=%x, power training=%02x\n"
  263. , __FUNCTION__, mask, mac_id, raid, sgi, h2c[2] & BIT(6));
  264. #ifdef CONFIG_LPS_PG
  265. RTW_INFO("lps_pg_rssi_lv:%d\n", psta->lps_pg_rssi_lv);
  266. #endif
  267. RTW_DBG_DUMP("H2C-MACIDConfig Parm:", h2c, RTW_HALMAC_H2C_MAX_SIZE);
  268. rtw_halmac_send_h2c(adapter_to_dvobj(adapter), h2c);
  269. /* update initial rate */
  270. if (sgi)
  271. init_rate |= BIT(7);
  272. hal->INIDATA_RATE[mac_id] = init_rate;
  273. }
  274. void rtl8821c_set_FwRssiSetting_cmd(PADAPTER adapter, u8 *param)
  275. {
  276. u8 h2c[RTW_HALMAC_H2C_MAX_SIZE] = {0};
  277. u8 mac_id = *param;
  278. u8 rssi = *(param + 2);
  279. u8 ra_info = 0;
  280. RTW_INFO(FUNC_ADPT_FMT ": mac_id=%d rssi=%d param=%.2x-%.2x-%.2x\n",
  281. FUNC_ADPT_ARG(adapter),
  282. mac_id, rssi, *param, *(param + 1), *(param + 2));
  283. RSSI_SETTING_SET_CMD_ID(h2c, CMD_ID_RSSI_SETTING);
  284. RSSI_SETTING_SET_CLASS(h2c, CLASS_RSSI_SETTING);
  285. RSSI_SETTING_SET_MAC_ID(h2c, mac_id);
  286. RSSI_SETTING_SET_RSSI(h2c, rssi);
  287. RSSI_SETTING_SET_RA_INFO(h2c, ra_info);
  288. RTW_DBG_DUMP("H2C-RssiSetting Parm:", h2c, RTW_HALMAC_H2C_MAX_SIZE);
  289. rtw_halmac_send_h2c(adapter_to_dvobj(adapter), h2c);
  290. }
  291. void rtl8821c_set_FwAPReqRPT_cmd(PADAPTER adapter, u32 need_ack)
  292. {
  293. u8 h2c[RTW_HALMAC_H2C_MAX_SIZE] = {0};
  294. u8 macid1 = 1, macid2 = 0;
  295. RTW_INFO(FUNC_ADPT_FMT ": need_ack = %d\n",
  296. FUNC_ADPT_ARG(adapter), need_ack);
  297. AP_REQ_TXRPT_SET_CMD_ID(h2c, CMD_ID_AP_REQ_TXRPT);
  298. AP_REQ_TXRPT_SET_CLASS(h2c, CLASS_AP_REQ_TXRPT);
  299. AP_REQ_TXRPT_SET_STA1_MACID(h2c, macid1);
  300. AP_REQ_TXRPT_SET_STA2_MACID(h2c, macid2);
  301. RTW_DBG_DUMP("H2C-ApReqRpt Parm:", h2c, RTW_HALMAC_H2C_MAX_SIZE);
  302. rtw_halmac_send_h2c(adapter_to_dvobj(adapter), h2c);
  303. }
  304. void rtl8821c_set_FwPwrMode_cmd(PADAPTER adapter, u8 psmode)
  305. {
  306. int i;
  307. u8 mode = 0, smart_ps = 0;
  308. struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
  309. struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
  310. u8 h2c[RTW_HALMAC_H2C_MAX_SIZE] = {0};
  311. u8 PowerState = 0, awake_intvl = 1, rlbm = 0;
  312. u8 pwrmode_data5 = 0;
  313. #ifdef CONFIG_P2P
  314. struct wifidirect_info *wdinfo = &adapter->wdinfo;
  315. #endif /* CONFIG_P2P */
  316. if (pwrpriv->dtim > 0)
  317. RTW_INFO(FUNC_ADPT_FMT ": FW LPS mode = %d, SmartPS=%d, dtim=%d, HW port id=%d\n",
  318. FUNC_ADPT_ARG(adapter), psmode, pwrpriv->smart_ps, pwrpriv->dtim,
  319. psmode == PS_MODE_ACTIVE ? pwrpriv->current_lps_hw_port_id:get_hw_port(adapter));
  320. else
  321. RTW_INFO(FUNC_ADPT_FMT ": FW LPS mode = %d, SmartPS=%d, HW port id=%d\n",
  322. FUNC_ADPT_ARG(adapter), psmode, pwrpriv->smart_ps,
  323. psmode == PS_MODE_ACTIVE ? pwrpriv->current_lps_hw_port_id:get_hw_port(adapter));
  324. smart_ps = pwrpriv->smart_ps;
  325. switch (psmode) {
  326. case PS_MODE_MIN:
  327. mode = 1;
  328. rlbm = 0;
  329. awake_intvl = 2;
  330. break;
  331. case PS_MODE_MAX:
  332. mode = 1;
  333. rlbm = 1;
  334. awake_intvl = 2;
  335. break;
  336. case PS_MODE_DTIM:
  337. {
  338. mode = 1;
  339. rlbm = 2;
  340. /* For WOWLAN LPS, DTIM = (awake_intvl - 1) */
  341. if (pwrpriv->dtim > 0 && pwrpriv->dtim < 16) /* DTIM = (awake_intvl - 1) */
  342. awake_intvl = pwrpriv->dtim + 1;
  343. else /* DTIM = 3 */
  344. awake_intvl = 4;
  345. }
  346. break;
  347. case PS_MODE_UAPSD_WMM:
  348. mode = 2;
  349. rlbm = 0; /*1*/
  350. /*(WMM)smart_ps: 0:PS_Poll, 1:NullData*/
  351. smart_ps = (pwrpriv->smart_ps) ? 1 : 0;
  352. break;
  353. case PS_MODE_ACTIVE:
  354. default:
  355. mode = 0;
  356. break;
  357. }
  358. #ifdef CONFIG_P2P
  359. if (!rtw_p2p_chk_state(wdinfo, P2P_STATE_NONE)) {
  360. awake_intvl = 2;
  361. rlbm = 1;
  362. }
  363. #endif /* CONFIG_P2P */
  364. if (adapter->registrypriv.wifi_spec == 1) {
  365. awake_intvl = 2;
  366. rlbm = 1;
  367. }
  368. if (psmode > 0) {
  369. #ifdef CONFIG_BT_COEXIST
  370. if (rtw_btcoex_IsBtControlLps(adapter) == _TRUE) {
  371. PowerState = rtw_btcoex_RpwmVal(adapter);
  372. pwrmode_data5 = rtw_btcoex_LpsVal(adapter);
  373. if ((rlbm == 2) && (pwrmode_data5 & BIT(4))) {
  374. /*
  375. * Keep awake interval to 1 to prevent from
  376. * decreasing coex performance
  377. */
  378. awake_intvl = 2;
  379. rlbm = 2;
  380. }
  381. } else
  382. #endif /* CONFIG_BT_COEXIST */
  383. {
  384. PowerState = 0x00; /* AllON(0x0C), RFON(0x04), RFOFF(0x00) */
  385. pwrmode_data5 = 0x40;
  386. }
  387. } else {
  388. PowerState = 0x0C; /* AllON(0x0C), RFON(0x04), RFOFF(0x00) */
  389. pwrmode_data5 = 0x40;
  390. }
  391. SET_PWR_MODE_SET_CMD_ID(h2c, CMD_ID_SET_PWR_MODE);
  392. SET_PWR_MODE_SET_CLASS(h2c, CLASS_SET_PWR_MODE);
  393. SET_PWR_MODE_SET_MODE(h2c, mode);
  394. SET_PWR_MODE_SET_SMART_PS(h2c, smart_ps);
  395. SET_PWR_MODE_SET_RLBM(h2c, rlbm);
  396. SET_PWR_MODE_SET_AWAKE_INTERVAL(h2c, awake_intvl);
  397. SET_PWR_MODE_SET_B_ALL_QUEUE_UAPSD(h2c, adapter->registrypriv.uapsd_enable);
  398. SET_PWR_MODE_SET_PWR_STATE(h2c, PowerState);
  399. if (psmode == PS_MODE_ACTIVE) {
  400. /* Leave LPS, set the same HW port ID */
  401. SET_PWR_MODE_SET_PORT_ID(h2c, pwrpriv->current_lps_hw_port_id);
  402. } else {
  403. /* Enter LPS, record HW port ID */
  404. SET_PWR_MODE_SET_PORT_ID(h2c, get_hw_port(adapter));
  405. pwrpriv->current_lps_hw_port_id = get_hw_port(adapter);
  406. }
  407. if (pwrmode_data5)
  408. h2c[6] = pwrmode_data5;
  409. else {
  410. /* pwrmode_data5 section*/
  411. SET_PWR_MODE_SET_LOW_POWER_RX_BCN(h2c, 0);/*bit-16*/
  412. SET_PWR_MODE_SET_ANT_AUTO_SWITCH(h2c, 0);/*bit-17*/
  413. SET_PWR_MODE_SET_PS_ALLOW_BT_HIGH_PRIORITY(h2c, 0);/*bit-18*/
  414. SET_PWR_MODE_SET_PROTECT_BCN(h2c, 0);/*bit-19*/
  415. SET_PWR_MODE_SET_SILENCE_PERIOD(h2c, 0);/*bit-20*/
  416. SET_PWR_MODE_SET_FAST_BT_CONNECT(h2c, 0);/*bit-21*/
  417. SET_PWR_MODE_SET_TWO_ANTENNA_EN(h2c, 0);/*bit-22*/
  418. }
  419. /* pwrmode_data6 section*/
  420. SET_PWR_MODE_SET_ADOPT_USER_SETTING(h2c, 0);/*bit-24*/
  421. SET_PWR_MODE_SET_DRV_BCN_EARLY_SHIFT(h2c, 0);/*bit-25:3*/
  422. SET_PWR_MODE_SET_DRV_BCN_EARLY_SHIFT2(h2c, 0);/*bit-28:4*/
  423. RTW_INFO("%s=> psmode:%02x, smart_ps:%02x, PowerState:%02x\n", __func__, psmode, smart_ps, PowerState);
  424. #ifdef CONFIG_LPS_LCLK
  425. if (psmode != PS_MODE_ACTIVE) {
  426. if ((pmlmeext->adaptive_tsf_done == _FALSE)
  427. && (pmlmeext->bcn_cnt > 0)) {
  428. u8 ratio_20_delay, ratio_80_delay;
  429. /*
  430. * byte 6 for adaptive_early_32k
  431. * [0:3] = DrvBcnEarly (ms), [4:7] = DrvBcnTimeOut (ms)
  432. * 20% for DrvBcnEarly, 80% for DrvBcnTimeOut
  433. */
  434. ratio_20_delay = 0;
  435. ratio_80_delay = 0;
  436. pmlmeext->DrvBcnEarly = 0xff;
  437. pmlmeext->DrvBcnTimeOut = 0xff;
  438. for (i = 0; i < 9; i++) {
  439. pmlmeext->bcn_delay_ratio[i] = (pmlmeext->bcn_delay_cnt[i] * 100) / pmlmeext->bcn_cnt;
  440. ratio_20_delay += pmlmeext->bcn_delay_ratio[i];
  441. ratio_80_delay += pmlmeext->bcn_delay_ratio[i];
  442. if (ratio_20_delay > 20 && pmlmeext->DrvBcnEarly == 0xff)
  443. pmlmeext->DrvBcnEarly = i;
  444. if (ratio_80_delay > 80 && pmlmeext->DrvBcnTimeOut == 0xff)
  445. pmlmeext->DrvBcnTimeOut = i;
  446. /* reset adaptive_early_32k cnt */
  447. pmlmeext->bcn_delay_cnt[i] = 0;
  448. pmlmeext->bcn_delay_ratio[i] = 0;
  449. }
  450. pmlmeext->bcn_cnt = 0;
  451. pmlmeext->adaptive_tsf_done = _TRUE;
  452. }
  453. }
  454. #endif /* CONFIG_LPS_LCLK */
  455. #ifdef CONFIG_BT_COEXIST
  456. rtw_btcoex_RecordPwrMode(adapter, h2c + 1, RTW_HALMAC_H2C_MAX_SIZE - 1);
  457. #endif /* CONFIG_BT_COEXIST */
  458. RTW_DBG_DUMP("H2C-PwrMode Parm:", h2c, RTW_HALMAC_H2C_MAX_SIZE);
  459. rtw_halmac_send_h2c(adapter_to_dvobj(adapter), h2c);
  460. }
  461. void rtl8821c_set_FwPwrModeInIPS_cmd(PADAPTER adapter, u8 cmd_param)
  462. {
  463. u8 h2c[RTW_HALMAC_H2C_MAX_SIZE] = {0};
  464. INACTIVE_PS_SET_CMD_ID(h2c, CMD_ID_INACTIVE_PS);
  465. INACTIVE_PS_SET_CLASS(h2c, CLASS_INACTIVE_PS);
  466. if (cmd_param & BIT0)
  467. INACTIVE_PS_SET_ENABLE(h2c, 1);
  468. if (cmd_param & BIT1)
  469. INACTIVE_PS_SET_IGNORE_PS_CONDITION(h2c, 1);
  470. RTW_DBG_DUMP("FW_IPS Parm:", h2c, RTW_HALMAC_H2C_MAX_SIZE);
  471. rtw_halmac_send_h2c(adapter_to_dvobj(adapter), h2c);
  472. }
  473. #ifdef CONFIG_BT_COEXIST
  474. static void ConstructBeacon(PADAPTER adapter, u8 *pframe, u32 *pLength)
  475. {
  476. struct rtw_ieee80211_hdr *pwlanhdr;
  477. u16 *fctrl;
  478. u32 rate_len, pktlen;
  479. struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
  480. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  481. WLAN_BSSID_EX *cur_network = &pmlmeinfo->network;
  482. u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  483. pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
  484. fctrl = &(pwlanhdr->frame_ctl);
  485. *(fctrl) = 0;
  486. _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
  487. _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
  488. _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
  489. SetSeqNum(pwlanhdr, 0);
  490. set_frame_sub_type(pframe, WIFI_BEACON);
  491. pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
  492. pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
  493. /* timestamp will be inserted by hardware */
  494. pframe += 8;
  495. pktlen += 8;
  496. /* beacon interval: 2 bytes */
  497. _rtw_memcpy(pframe, (u8 *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
  498. pframe += 2;
  499. pktlen += 2;
  500. /* capability info: 2 bytes */
  501. _rtw_memcpy(pframe, (u8 *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
  502. pframe += 2;
  503. pktlen += 2;
  504. if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
  505. pktlen += cur_network->IELength - sizeof(NDIS_802_11_FIXED_IEs);
  506. _rtw_memcpy(pframe, cur_network->IEs + sizeof(NDIS_802_11_FIXED_IEs), pktlen);
  507. goto _ConstructBeacon;
  508. }
  509. /* below for ad-hoc mode */
  510. /* SSID */
  511. pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen);
  512. /* supported rates... */
  513. rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
  514. pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pktlen);
  515. /* DS parameter set */
  516. pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen);
  517. if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
  518. u32 ATIMWindow;
  519. /* IBSS Parameter Set... */
  520. ATIMWindow = 0;
  521. pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
  522. }
  523. /* todo: ERP IE */
  524. /* EXTERNDED SUPPORTED RATE */
  525. if (rate_len > 8)
  526. pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
  527. /* todo:HT for adhoc */
  528. _ConstructBeacon:
  529. if ((pktlen + TXDESC_SIZE) > 512) {
  530. RTW_INFO("beacon frame too large\n");
  531. return;
  532. }
  533. *pLength = pktlen;
  534. }
  535. static void ConstructPSPoll(PADAPTER adapter, u8 *pframe, u32 *pLength)
  536. {
  537. struct rtw_ieee80211_hdr *pwlanhdr;
  538. u16 *fctrl;
  539. u32 pktlen;
  540. struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
  541. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  542. pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
  543. /* Frame control. */
  544. fctrl = &(pwlanhdr->frame_ctl);
  545. *(fctrl) = 0;
  546. SetPwrMgt(fctrl);
  547. set_frame_sub_type(pframe, WIFI_PSPOLL);
  548. /* AID. */
  549. set_duration(pframe, (pmlmeinfo->aid | 0xc000));
  550. /* BSSID. */
  551. _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
  552. /* TA. */
  553. _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
  554. *pLength = 16;
  555. }
  556. static void ConstructNullFunctionData(
  557. PADAPTER adapter,
  558. u8 *pframe,
  559. u32 *pLength,
  560. u8 *StaAddr,
  561. u8 bQoS,
  562. u8 AC,
  563. u8 bEosp,
  564. u8 bForcePowerSave)
  565. {
  566. struct rtw_ieee80211_hdr *pwlanhdr;
  567. u16 *fctrl;
  568. u32 pktlen;
  569. struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
  570. struct wlan_network *cur_network = &pmlmepriv->cur_network;
  571. struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
  572. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  573. pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
  574. fctrl = &pwlanhdr->frame_ctl;
  575. *(fctrl) = 0;
  576. if (bForcePowerSave)
  577. SetPwrMgt(fctrl);
  578. switch (cur_network->network.InfrastructureMode) {
  579. case Ndis802_11Infrastructure:
  580. SetToDs(fctrl);
  581. _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
  582. _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
  583. _rtw_memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
  584. break;
  585. case Ndis802_11APMode:
  586. SetFrDs(fctrl);
  587. _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
  588. _rtw_memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
  589. _rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(adapter), ETH_ALEN);
  590. break;
  591. case Ndis802_11IBSS:
  592. default:
  593. _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
  594. _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
  595. _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
  596. break;
  597. }
  598. SetSeqNum(pwlanhdr, 0);
  599. if (bQoS == _TRUE) {
  600. struct rtw_ieee80211_hdr_3addr_qos *pwlanqoshdr;
  601. set_frame_sub_type(pframe, WIFI_QOS_DATA_NULL);
  602. pwlanqoshdr = (struct rtw_ieee80211_hdr_3addr_qos *)pframe;
  603. SetPriority(&pwlanqoshdr->qc, AC);
  604. SetEOSP(&pwlanqoshdr->qc, bEosp);
  605. pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
  606. } else {
  607. set_frame_sub_type(pframe, WIFI_DATA_NULL);
  608. pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
  609. }
  610. *pLength = pktlen;
  611. }
  612. static void ConstructProbeRsp(PADAPTER adapter, u8 *pframe, u32 *pLength, u8 *StaAddr, BOOLEAN bHideSSID)
  613. {
  614. struct rtw_ieee80211_hdr *pwlanhdr;
  615. u16 *fctrl;
  616. u8 *mac, *bssid;
  617. u32 pktlen;
  618. struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
  619. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  620. WLAN_BSSID_EX *cur_network = &pmlmeinfo->network;
  621. #if defined(CONFIG_AP_MODE) && defined(CONFIG_NATIVEAP_MLME)
  622. u8 *pwps_ie;
  623. uint wps_ielen;
  624. struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
  625. #endif /* CONFIG_AP_MODE && CONFIG_NATIVEAP_MLME */
  626. #ifdef CONFIG_P2P
  627. struct wifidirect_info *pwdinfo = &adapter->wdinfo;
  628. #ifdef CONFIG_WFD
  629. u32 wfdielen = 0;
  630. #endif /* CONFIG_WFD */
  631. #endif /* CONFIG_P2P */
  632. pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
  633. mac = adapter_mac_addr(adapter);
  634. bssid = cur_network->MacAddress;
  635. fctrl = &(pwlanhdr->frame_ctl);
  636. *(fctrl) = 0;
  637. _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
  638. _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
  639. _rtw_memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
  640. RTW_INFO("%s FW Mac Addr:" MAC_FMT "\n", __FUNCTION__, MAC_ARG(mac));
  641. RTW_INFO("%s FW IP Addr" IP_FMT "\n", __FUNCTION__, IP_ARG(StaAddr));
  642. SetSeqNum(pwlanhdr, 0);
  643. set_frame_sub_type(fctrl, WIFI_PROBERSP);
  644. pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
  645. pframe += pktlen;
  646. if (cur_network->IELength > MAX_IE_SZ)
  647. return;
  648. pwps_ie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_,
  649. cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wps_ielen);
  650. /* inerset & update wps_probe_resp_ie */
  651. if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie && (wps_ielen > 0)) {
  652. uint wps_offset, remainder_ielen;
  653. u8 *premainder_ie;
  654. wps_offset = (uint)(pwps_ie - cur_network->IEs);
  655. premainder_ie = pwps_ie + wps_ielen;
  656. remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
  657. _rtw_memcpy(pframe, cur_network->IEs, wps_offset);
  658. pframe += wps_offset;
  659. pktlen += wps_offset;
  660. wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
  661. if ((wps_offset + wps_ielen + 2) <= MAX_IE_SZ) {
  662. _rtw_memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen + 2);
  663. pframe += wps_ielen + 2;
  664. pktlen += wps_ielen + 2;
  665. }
  666. if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) {
  667. _rtw_memcpy(pframe, premainder_ie, remainder_ielen);
  668. pframe += remainder_ielen;
  669. pktlen += remainder_ielen;
  670. }
  671. } else {
  672. _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
  673. pframe += cur_network->IELength;
  674. pktlen += cur_network->IELength;
  675. }
  676. /* retrieve SSID IE from cur_network->Ssid */
  677. {
  678. u8 *ssid_ie;
  679. sint ssid_ielen = 0;
  680. sint ssid_ielen_diff;
  681. u8 buf[MAX_IE_SZ];
  682. u8 *ies = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
  683. ssid_ie = rtw_get_ie(ies + _FIXED_IE_LENGTH_, _SSID_IE_, &ssid_ielen,
  684. (pframe - ies) - _FIXED_IE_LENGTH_);
  685. ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen;
  686. if (ssid_ie && cur_network->Ssid.SsidLength) {
  687. uint remainder_ielen;
  688. u8 *remainder_ie;
  689. remainder_ie = ssid_ie + 2;
  690. remainder_ielen = (pframe - remainder_ie);
  691. if (remainder_ielen > MAX_IE_SZ) {
  692. RTW_WARN(FUNC_ADPT_FMT" remainder_ielen > MAX_IE_SZ\n", FUNC_ADPT_ARG(adapter));
  693. remainder_ielen = MAX_IE_SZ;
  694. }
  695. _rtw_memcpy(buf, remainder_ie, remainder_ielen);
  696. _rtw_memcpy(remainder_ie + ssid_ielen_diff, buf, remainder_ielen);
  697. *(ssid_ie + 1) = cur_network->Ssid.SsidLength;
  698. _rtw_memcpy(ssid_ie + 2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength);
  699. pframe += ssid_ielen_diff;
  700. pktlen += ssid_ielen_diff;
  701. }
  702. }
  703. #ifdef CONFIG_P2P
  704. if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
  705. u32 len;
  706. #ifdef CONFIG_IOCTL_CFG80211
  707. if (adapter_wdev_data(adapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) {
  708. /* if pwdinfo->role == P2P_ROLE_DEVICE will call issue_probersp_p2p() */
  709. len = pmlmepriv->p2p_go_probe_resp_ie_len;
  710. if (pmlmepriv->p2p_go_probe_resp_ie && len > 0)
  711. _rtw_memcpy(pframe, pmlmepriv->p2p_go_probe_resp_ie, len);
  712. } else
  713. #endif /* CONFIG_IOCTL_CFG80211 */
  714. {
  715. len = build_probe_resp_p2p_ie(pwdinfo, pframe);
  716. }
  717. pframe += len;
  718. pktlen += len;
  719. #ifdef CONFIG_WFD
  720. #ifdef CONFIG_IOCTL_CFG80211
  721. if (_TRUE == pwdinfo->wfd_info->wfd_enable)
  722. #endif /* CONFIG_IOCTL_CFG80211 */
  723. {
  724. len = build_probe_resp_wfd_ie(pwdinfo, pframe, 0);
  725. }
  726. #ifdef CONFIG_IOCTL_CFG80211
  727. else {
  728. len = 0;
  729. if (pmlmepriv->wfd_probe_resp_ie && pmlmepriv->wfd_probe_resp_ie_len > 0) {
  730. len = pmlmepriv->wfd_probe_resp_ie_len;
  731. _rtw_memcpy(pframe, pmlmepriv->wfd_probe_resp_ie, len);
  732. }
  733. }
  734. #endif /* CONFIG_IOCTL_CFG80211 */
  735. pframe += len;
  736. pktlen += len;
  737. #endif /* CONFIG_WFD */
  738. }
  739. #endif /* CONFIG_P2P */
  740. *pLength = pktlen;
  741. }
  742. static void ConstructBtNullFunctionData(
  743. PADAPTER adapter,
  744. u8 *pframe,
  745. u32 *pLength,
  746. u8 *StaAddr,
  747. u8 bQoS,
  748. u8 AC,
  749. u8 bEosp,
  750. u8 bForcePowerSave)
  751. {
  752. struct rtw_ieee80211_hdr *pwlanhdr;
  753. u16 *fctrl;
  754. u32 pktlen;
  755. struct mlme_ext_priv *pmlmeext;
  756. struct mlme_ext_info *pmlmeinfo;
  757. u8 bssid[ETH_ALEN];
  758. RTW_INFO("+" FUNC_ADPT_FMT ": qos=%d eosp=%d ps=%d\n",
  759. FUNC_ADPT_ARG(adapter), bQoS, bEosp, bForcePowerSave);
  760. pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
  761. pmlmeext = &adapter->mlmeextpriv;
  762. pmlmeinfo = &pmlmeext->mlmext_info;
  763. if (NULL == StaAddr) {
  764. _rtw_memcpy(bssid, adapter_mac_addr(adapter), ETH_ALEN);
  765. StaAddr = bssid;
  766. }
  767. fctrl = &pwlanhdr->frame_ctl;
  768. *fctrl = 0;
  769. if (bForcePowerSave)
  770. SetPwrMgt(fctrl);
  771. SetFrDs(fctrl);
  772. _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
  773. _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
  774. _rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(adapter), ETH_ALEN);
  775. set_duration(pwlanhdr, 0);
  776. SetSeqNum(pwlanhdr, 0);
  777. if (bQoS == _TRUE) {
  778. struct rtw_ieee80211_hdr_3addr_qos *pwlanqoshdr;
  779. set_frame_sub_type(pframe, WIFI_QOS_DATA_NULL);
  780. pwlanqoshdr = (struct rtw_ieee80211_hdr_3addr_qos *)pframe;
  781. SetPriority(&pwlanqoshdr->qc, AC);
  782. SetEOSP(&pwlanqoshdr->qc, bEosp);
  783. pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
  784. } else {
  785. set_frame_sub_type(pframe, WIFI_DATA_NULL);
  786. pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
  787. }
  788. *pLength = pktlen;
  789. }
  790. static void SetFwRsvdPagePkt_BTCoex(PADAPTER adapter)
  791. {
  792. PHAL_DATA_TYPE hal;
  793. struct xmit_frame *pcmdframe;
  794. struct pkt_attrib *pattrib;
  795. struct xmit_priv *pxmitpriv;
  796. struct mlme_ext_priv *pmlmeext;
  797. struct mlme_ext_info *pmlmeinfo;
  798. u32 BeaconLength = 0;
  799. u32 BTQosNullLength = 0;
  800. u8 *ReservedPagePacket;
  801. u8 TxDescLen, TxDescOffset;
  802. u8 TotalPageNum = 0, CurtPktPageNum = 0, RsvdPageNum = 0;
  803. u16 BufIndex, PageSize;
  804. u32 TotalPacketLen, MaxRsvdPageBufSize = 0;
  805. RSVDPAGE_LOC RsvdPageLoc;
  806. hal = GET_HAL_DATA(adapter);
  807. pxmitpriv = &adapter->xmitpriv;
  808. pmlmeext = &adapter->mlmeextpriv;
  809. pmlmeinfo = &pmlmeext->mlmext_info;
  810. TxDescLen = TXDESC_SIZE;
  811. TxDescOffset = TXDESC_OFFSET;
  812. PageSize = HALMAC_TX_PAGE_SIZE_8821C;
  813. RsvdPageNum = rtw_hal_get_txbuff_rsvd_page_num(adapter, _FALSE);
  814. MaxRsvdPageBufSize = RsvdPageNum * PageSize;
  815. pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv);
  816. if (pcmdframe == NULL) {
  817. RTW_INFO("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
  818. return;
  819. }
  820. ReservedPagePacket = pcmdframe->buf_addr;
  821. _rtw_memset(&RsvdPageLoc, 0, sizeof(RSVDPAGE_LOC));
  822. /* beacon */
  823. BufIndex = TxDescOffset;
  824. ConstructBeacon(adapter, &ReservedPagePacket[BufIndex], &BeaconLength);
  825. /*
  826. * When we count the first page size, we need to reserve description size for the RSVD
  827. * packet, it will be filled in front of the packet in TXPKTBUF.
  828. */
  829. CurtPktPageNum = (u8)PageNum_128(TxDescLen + BeaconLength);
  830. /*
  831. * If we don't add 1 more page, the WOWLAN function has a problem.
  832. * Maybe it's a bug of firmware?
  833. */
  834. if (CurtPktPageNum == 1)
  835. CurtPktPageNum += 1;
  836. TotalPageNum += CurtPktPageNum;
  837. BufIndex += (CurtPktPageNum * PageSize);
  838. /* Jump to lastest page */
  839. if (BufIndex < (MaxRsvdPageBufSize - PageSize)) {
  840. BufIndex = TxDescOffset + (MaxRsvdPageBufSize - PageSize);
  841. TotalPageNum = RsvdPageNum - 1;
  842. }
  843. /* BT Qos null data */
  844. RsvdPageLoc.LocBTQosNull = TotalPageNum;
  845. ConstructBtNullFunctionData(
  846. adapter,
  847. &ReservedPagePacket[BufIndex],
  848. &BTQosNullLength,
  849. NULL,
  850. _TRUE, 0, 0, _FALSE);
  851. rtw_hal_fill_fake_txdesc(adapter, &ReservedPagePacket[BufIndex - TxDescLen], BTQosNullLength, _FALSE, _TRUE, _FALSE);
  852. CurtPktPageNum = (u8)PageNum_128(TxDescLen + BTQosNullLength);
  853. TotalPageNum += CurtPktPageNum;
  854. TotalPacketLen = BufIndex + BTQosNullLength;
  855. if (TotalPacketLen > MaxRsvdPageBufSize) {
  856. RTW_INFO(FUNC_ADPT_FMT ": ERROR: The rsvd page size is not enough!!TotalPacketLen %d, MaxRsvdPageBufSize %d\n",
  857. FUNC_ADPT_ARG(adapter), TotalPacketLen, MaxRsvdPageBufSize);
  858. goto error;
  859. }
  860. /* update attribute */
  861. pattrib = &pcmdframe->attrib;
  862. update_mgntframe_attrib(adapter, pattrib);
  863. pattrib->qsel = QSLT_BEACON;
  864. pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TxDescOffset;
  865. #ifdef CONFIG_PCI_HCI
  866. dump_mgntframe(adapter, pcmdframe);
  867. #else /* !CONFIG_PCI_HCI */
  868. dump_mgntframe_and_wait(adapter, pcmdframe, 100);
  869. #endif /* !CONFIG_PCI_HCI */
  870. rtl8821c_set_FwRsvdPage_cmd(adapter, &RsvdPageLoc);
  871. rtl8821c_set_FwAoacRsvdPage_cmd(adapter, &RsvdPageLoc);
  872. return;
  873. error:
  874. rtw_free_xmitframe(pxmitpriv, pcmdframe);
  875. }
  876. void rtl8821c_download_BTCoex_AP_mode_rsvd_page(PADAPTER adapter)
  877. {
  878. PHAL_DATA_TYPE hal;
  879. struct mlme_ext_priv *pmlmeext;
  880. struct mlme_ext_info *pmlmeinfo;
  881. u8 bRecover = _FALSE;
  882. u8 bcn_valid = _FALSE;
  883. u8 DLBcnCount = 0;
  884. u32 poll = 0;
  885. u8 val8;
  886. RTW_INFO("+" FUNC_ADPT_FMT ": hw_port=%d fw_state=0x%08X\n",
  887. FUNC_ADPT_ARG(adapter), get_hw_port(adapter), get_fwstate(&adapter->mlmepriv));
  888. #ifdef CONFIG_RTW_DEBUG
  889. if (check_fwstate(&adapter->mlmepriv, WIFI_AP_STATE) == _FALSE) {
  890. RTW_INFO(FUNC_ADPT_FMT ": [WARNING] not in AP mode!!\n",
  891. FUNC_ADPT_ARG(adapter));
  892. }
  893. #endif /* CONFIG_RTW_DEBUG */
  894. hal = GET_HAL_DATA(adapter);
  895. pmlmeext = &adapter->mlmeextpriv;
  896. pmlmeinfo = &pmlmeext->mlmext_info;
  897. /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
  898. rtw_write16(adapter, REG_BCN_PSR_RPT, (0xC000 | pmlmeinfo->aid));
  899. /* set REG_CR bit 8 */
  900. val8 = rtw_read8(adapter, REG_CR + 1);
  901. val8 |= BIT(0); /* ENSWBCN */
  902. rtw_write8(adapter, REG_CR + 1, val8);
  903. /*
  904. * Disable Hw protection for a time which revserd for Hw sending beacon.
  905. * Fix download reserved page packet fail that access collision with the protection time.
  906. */
  907. val8 = rtw_read8(adapter, REG_BCN_CTRL);
  908. val8 &= ~EN_BCN_FUNCTION;
  909. val8 |= DIS_TSF_UDT;
  910. rtw_write8(adapter, REG_BCN_CTRL, val8);
  911. /* Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame. */
  912. if (hal->RegFwHwTxQCtrl & BIT(6))
  913. bRecover = _TRUE;
  914. /* To tell Hw the packet is not a real beacon frame. */
  915. hal->RegFwHwTxQCtrl &= ~BIT(6);
  916. rtw_write8(adapter, REG_FWHW_TXQ_CTRL + 2, hal->RegFwHwTxQCtrl);
  917. /* Clear beacon valid check bit. */
  918. rtw_hal_set_hwreg(adapter, HW_VAR_BCN_VALID, NULL);
  919. rtw_hal_set_hwreg(adapter, HW_VAR_DL_BCN_SEL, NULL);
  920. DLBcnCount = 0;
  921. poll = 0;
  922. do {
  923. SetFwRsvdPagePkt_BTCoex(adapter);
  924. DLBcnCount++;
  925. do {
  926. rtw_yield_os();
  927. /* check rsvd page download OK. */
  928. rtw_hal_get_hwreg(adapter, HW_VAR_BCN_VALID, &bcn_valid);
  929. poll++;
  930. } while (!bcn_valid && (poll % 10) != 0 && !RTW_CANNOT_RUN(adapter));
  931. } while (!bcn_valid && (DLBcnCount <= 100) && !RTW_CANNOT_RUN(adapter));
  932. if (_TRUE == bcn_valid) {
  933. struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
  934. pwrctl->fw_psmode_iface_id = adapter->iface_id;
  935. RTW_INFO(ADPT_FMT": DL RSVD page success! DLBcnCount:%d, poll:%d\n",
  936. ADPT_ARG(adapter), DLBcnCount, poll);
  937. } else {
  938. RTW_INFO(ADPT_FMT": DL RSVD page fail! DLBcnCount:%d, poll:%d\n",
  939. ADPT_ARG(adapter), DLBcnCount, poll);
  940. RTW_INFO(ADPT_FMT": DL RSVD page fail! bSurpriseRemoved=%s\n",
  941. ADPT_ARG(adapter), rtw_is_surprise_removed(adapter) ? "True" : "False");
  942. RTW_INFO(ADPT_FMT": DL RSVD page fail! bDriverStopped=%s\n",
  943. ADPT_ARG(adapter), rtw_is_drv_stopped(adapter) ? "True" : "False");
  944. }
  945. val8 = rtw_read8(adapter, REG_BCN_CTRL);
  946. val8 |= EN_BCN_FUNCTION;
  947. val8 &= ~DIS_TSF_UDT;
  948. rtw_write8(adapter, REG_BCN_CTRL, val8);
  949. /*
  950. * To make sure that if there exists an adapter which would like to send beacon.
  951. * If exists, the origianl value of 0x422[6] will be 1, we should check this to
  952. * prevent from setting 0x422[6] to 0 after download reserved page, or it will cause
  953. * the beacon cannot be sent by HW.
  954. */
  955. if (bRecover) {
  956. hal->RegFwHwTxQCtrl |= BIT(6);
  957. rtw_write8(adapter, REG_FWHW_TXQ_CTRL + 2, hal->RegFwHwTxQCtrl);
  958. }
  959. /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
  960. #ifndef CONFIG_PCI_HCI
  961. val8 = rtw_read8(adapter, REG_CR + 1);
  962. val8 &= ~BIT(0); /* ~ENSWBCN*/
  963. rtw_write8(adapter, REG_CR + 1, val8);
  964. #endif /* !CONFIG_PCI_HCI */
  965. }
  966. #endif /* CONFIG_BT_COEXIST */
  967. #ifdef CONFIG_TSF_RESET_OFFLOAD
  968. /*
  969. * ask FW to Reset sync register at Beacon early interrupt
  970. */
  971. u8 rtl8821c_reset_tsf(_adapter *adapter, u8 reset_port)
  972. {
  973. u8 buf[2];
  974. u8 res = _SUCCESS;
  975. if (HW_PORT0 == reset_port) {
  976. buf[0] = 0x1;
  977. buf[1] = 0;
  978. } else {
  979. buf[0] = 0x0;
  980. buf[1] = 0x1;
  981. }
  982. rtl8821c_fillh2ccmd(adapter, H2C_RESET_TSF, 2, buf);
  983. return res;
  984. }
  985. #endif /* CONFIG_TSF_RESET_OFFLOAD */
  986. void rtl8821c_fw_update_beacon_cmd(PADAPTER adapter)
  987. {
  988. }
  989. /*
  990. * Below functions are for C2H
  991. */
  992. static void c2h_ccx_rpt(PADAPTER adapter, u8 *pdata)
  993. {
  994. #ifdef CONFIG_XMIT_ACK
  995. #define C2H_CCX_RPT_GET_TX_STATE(__pC2H) LE_BITS_TO_4BYTE(__pC2H + 0X04, 30, 2)
  996. u8 tx_state = _FALSE;
  997. tx_state = C2H_CCX_RPT_GET_TX_STATE(pdata);
  998. /* 0 means success, 1 means retry drop */
  999. if (tx_state == 0)
  1000. rtw_ack_tx_done(&adapter->xmitpriv, RTW_SCTX_DONE_SUCCESS);
  1001. else
  1002. rtw_ack_tx_done(&adapter->xmitpriv, RTW_SCTX_DONE_CCX_PKT_FAIL);
  1003. #endif /* CONFIG_XMIT_ACK */
  1004. }
  1005. /**
  1006. * pbuf = RXDESC + c2h packet
  1007. * length = RXDESC_SIZE + c2h packet size
  1008. * c2h format => ID(1B) | SN(1B) | Payload
  1009. */
  1010. void c2h_handler_rtl8821c(PADAPTER adapter, u8 *pbuf, u16 length)
  1011. {
  1012. u8 c2h_id, c2h_sn;
  1013. int c2h_len;
  1014. u8 *pc2h_hdr;
  1015. u8 *pc2h_data;
  1016. u8 c2h_sub_cmd_id = 0;
  1017. #ifdef CONFIG_WOWLAN
  1018. struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
  1019. if (pwrpriv->wowlan_mode == _TRUE) {
  1020. RTW_INFO("%s: return because wowolan_mode==TRUE! CMDID=%d\n",
  1021. __FUNCTION__, C2H_GET_CMD_ID(pbuf + RXDESC_SIZE));
  1022. return;
  1023. }
  1024. #endif /* CONFIG_WOWLAN*/
  1025. if (pbuf == NULL)
  1026. return;
  1027. if (length < HALMAC_RX_DESC_SIZE_8821C) {
  1028. RTW_INFO("%s: [ERROR] c2h length(%d) is smaller than RXDESC_SIZE(%d)!!\n",
  1029. __func__, length, HALMAC_RX_DESC_SIZE_8821C);
  1030. return;
  1031. }
  1032. pc2h_hdr = pbuf + HALMAC_RX_DESC_SIZE_8821C;
  1033. pc2h_data = pbuf + HALMAC_RX_DESC_SIZE_8821C + 2; /* cmd ID not 0xFF original C2H have 2 bytes C2H header */
  1034. c2h_id = C2H_GET_CMD_ID(pc2h_hdr);
  1035. c2h_sn = C2H_GET_SEQ(pc2h_hdr);
  1036. c2h_len = length - HALMAC_RX_DESC_SIZE_8821C - 2;
  1037. if ((c2h_len < 0) || (c2h_len > C2H_DBG_CONTENT_MAX_LENGTH)) {
  1038. RTW_ERR("%s: [ERROR] C2H_ID(%02x) C2H_SN(%d) warn c2h_len :%d (length:%d)\n", __func__, c2h_id, c2h_sn, c2h_len, length);
  1039. rtw_warn_on(1);
  1040. }
  1041. #ifdef DBG_C2H_CONTENT
  1042. RTW_INFO("%s "ADPT_FMT" C2H, ID=%d seq=%d len=%d\n", __func__, ADPT_ARG(adapter), c2h_id, c2h_sn, length);
  1043. #endif
  1044. switch (c2h_id) {
  1045. case CMD_ID_C2H_SND_TXBF:
  1046. /*C2HTxBeamformingHandler_8821C(adapter, pc2h_data, c2h_len);*/
  1047. break;
  1048. /* FW offload C2H is 0xFF cmd according to halmac function - halmac_parse_c2h_packet */
  1049. case 0xFF:
  1050. /* Get C2H sub cmd ID */
  1051. c2h_sub_cmd_id = (u8)C2H_HDR_GET_C2H_SUB_CMD_ID(pc2h_hdr);
  1052. if (c2h_sub_cmd_id == C2H_SUB_CMD_ID_CCX_RPT)
  1053. c2h_ccx_rpt(adapter, pbuf + HALMAC_RX_DESC_SIZE_8821C + 4); /* cmd ID 0xFF new C2H have 4 bytes C2H header */
  1054. else
  1055. /* indicate rx desc + c2h pkt to halmac */
  1056. if (rtw_halmac_c2h_handle(adapter_to_dvobj(adapter), pbuf, length == (-1)))
  1057. RTW_ERR("%s "ADPT_FMT" C2H, ID=%d, SubID=%d seq=%d len=%d ,HALMAC not to handle\n",
  1058. __func__, ADPT_ARG(adapter), c2h_id, c2h_sub_cmd_id, c2h_sn, length);
  1059. break;
  1060. /* others for c2h common code */
  1061. default:
  1062. /* shift 2 byte to remove cmd id & seq */
  1063. c2h_handler(adapter, c2h_id, c2h_sn, c2h_len, pc2h_data);
  1064. break;
  1065. }
  1066. }
  1067. static inline u8 is_c2h_id_handle_directly(u8 c2h_id, u8 c2h_sub_cmd_id)
  1068. {
  1069. switch (c2h_id) {
  1070. case CMD_ID_C2H_CCX_RPT:
  1071. case C2H_IQK_FINISH:
  1072. #if defined(CONFIG_TDLS) && defined(CONFIG_TDLS_CH_SW)
  1073. case C2H_BCN_EARLY_RPT:
  1074. case C2H_FW_CHNL_SWITCH_COMPLETE:
  1075. #endif
  1076. #ifdef CONFIG_BT_COEXIST
  1077. case C2H_BT_MP_INFO:
  1078. #endif
  1079. #ifdef CONFIG_MCC_MODE
  1080. case C2H_MCC:
  1081. #endif
  1082. return _TRUE;
  1083. case 0xFF:
  1084. switch (c2h_sub_cmd_id) {
  1085. case C2H_SUB_CMD_ID_CCX_RPT:
  1086. return _TRUE;
  1087. default:
  1088. return _FALSE;
  1089. }
  1090. default:
  1091. return _FALSE;
  1092. }
  1093. }
  1094. /*
  1095. * pbuf = RXDESC + c2h packet
  1096. * length = RXDESC_SIZE + c2h packet size
  1097. */
  1098. void c2h_pre_handler_rtl8821c(_adapter *adapter, u8 *pbuf, s32 length)
  1099. {
  1100. u8 c2h_id;
  1101. u8 c2h_sub_cmd_id = 0;
  1102. if ((length <= 0) || (!pbuf))
  1103. return;
  1104. c2h_id = C2H_GET_CMD_ID(pbuf + HALMAC_RX_DESC_SIZE_8821C);
  1105. /* Get C2H sub cmd ID */
  1106. if (c2h_id == 0xFF)
  1107. c2h_sub_cmd_id = (u8)C2H_HDR_GET_C2H_SUB_CMD_ID(pbuf + HALMAC_RX_DESC_SIZE_8821C);
  1108. if (is_c2h_id_handle_directly(c2h_id, c2h_sub_cmd_id))
  1109. c2h_handler_rtl8821c(adapter, pbuf, length);
  1110. else
  1111. rtw_c2h_packet_wk_cmd(adapter, pbuf, length);
  1112. }