rtw_cmd.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2012 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 _RTW_CMD_C_
  21. #include <osdep_service.h>
  22. #include <drv_types.h>
  23. #include <recv_osdep.h>
  24. #include <mlme_osdep.h>
  25. #include <rtw_mlme_ext.h>
  26. /*
  27. Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
  28. No irqsave is necessary.
  29. */
  30. int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
  31. {
  32. sema_init(&(pcmdpriv->cmd_queue_sema), 0);
  33. sema_init(&(pcmdpriv->terminate_cmdthread_sema), 0);
  34. _rtw_init_queue(&(pcmdpriv->cmd_queue));
  35. return _SUCCESS;
  36. }
  37. /*
  38. Calling Context:
  39. rtw_enqueue_cmd can only be called between kernel thread,
  40. since only spin_lock is used.
  41. ISR/Call-Back functions can't call this sub-function.
  42. */
  43. static int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
  44. {
  45. unsigned long irqL;
  46. if (obj == NULL)
  47. goto exit;
  48. spin_lock_irqsave(&queue->lock, irqL);
  49. list_add_tail(&obj->list, &queue->queue);
  50. spin_unlock_irqrestore(&queue->lock, irqL);
  51. exit:
  52. return _SUCCESS;
  53. }
  54. struct cmd_obj *rtw_dequeue_cmd(struct __queue *queue)
  55. {
  56. unsigned long irqL;
  57. struct cmd_obj *obj;
  58. spin_lock_irqsave(&queue->lock, irqL);
  59. if (list_empty(&(queue->queue))) {
  60. obj = NULL;
  61. } else {
  62. obj = container_of((&queue->queue)->next, struct cmd_obj, list);
  63. list_del_init(&obj->list);
  64. }
  65. spin_unlock_irqrestore(&queue->lock, irqL);
  66. return obj;
  67. }
  68. static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
  69. {
  70. u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */
  71. /* To decide allow or not */
  72. if ((pcmdpriv->padapter->pwrctrlpriv.bHWPwrPindetect) &&
  73. (!pcmdpriv->padapter->registrypriv.usbss_enable)) {
  74. if (cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
  75. struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf;
  76. if (pdrvextra_cmd_parm->ec_id == POWER_SAVING_CTRL_WK_CID)
  77. bAllow = true;
  78. }
  79. }
  80. if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))
  81. bAllow = true;
  82. if ((!pcmdpriv->padapter->hw_init_completed && !bAllow) ||
  83. !pcmdpriv->cmdthd_running) /* com_thread not running */
  84. return _FAIL;
  85. return _SUCCESS;
  86. }
  87. u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
  88. {
  89. int res = _FAIL;
  90. struct adapter *padapter = pcmdpriv->padapter;
  91. if (cmd_obj == NULL)
  92. goto exit;
  93. cmd_obj->padapter = padapter;
  94. res = rtw_cmd_filter(pcmdpriv, cmd_obj);
  95. if (res == _FAIL) {
  96. rtw_free_cmd_obj(cmd_obj);
  97. goto exit;
  98. }
  99. res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj);
  100. if (res == _SUCCESS)
  101. up(&pcmdpriv->cmd_queue_sema);
  102. exit:
  103. return res;
  104. }
  105. void rtw_free_cmd_obj(struct cmd_obj *pcmd)
  106. {
  107. if ((pcmd->cmdcode != _JoinBss_CMD_) && (pcmd->cmdcode != _CreateBss_CMD_)) {
  108. /* free parmbuf in cmd_obj */
  109. kfree(pcmd->parmbuf);
  110. }
  111. if (pcmd->rsp != NULL) {
  112. if (pcmd->rspsz != 0) {
  113. /* free rsp in cmd_obj */
  114. kfree(pcmd->rsp);
  115. }
  116. }
  117. /* free cmd_obj */
  118. kfree(pcmd);
  119. }
  120. int rtw_cmd_thread(void *context)
  121. {
  122. u8 ret;
  123. struct cmd_obj *pcmd;
  124. u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf);
  125. void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd);
  126. struct adapter *padapter = context;
  127. struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
  128. allow_signal(SIGTERM);
  129. pcmdpriv->cmdthd_running = true;
  130. up(&pcmdpriv->terminate_cmdthread_sema);
  131. RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("start r871x rtw_cmd_thread !!!!\n"));
  132. while (1) {
  133. if (_rtw_down_sema(&pcmdpriv->cmd_queue_sema) == _FAIL)
  134. break;
  135. if (padapter->bDriverStopped ||
  136. padapter->bSurpriseRemoved) {
  137. DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
  138. __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
  139. break;
  140. }
  141. _next:
  142. if (padapter->bDriverStopped ||
  143. padapter->bSurpriseRemoved) {
  144. DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
  145. __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
  146. break;
  147. }
  148. pcmd = rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
  149. if (!pcmd)
  150. continue;
  151. if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) {
  152. pcmd->res = H2C_DROPPED;
  153. goto post_process;
  154. }
  155. if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) {
  156. cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
  157. if (cmd_hdl) {
  158. ret = cmd_hdl(pcmd->padapter, pcmd->parmbuf);
  159. pcmd->res = ret;
  160. }
  161. } else {
  162. pcmd->res = H2C_PARAMETERS_ERROR;
  163. }
  164. cmd_hdl = NULL;
  165. post_process:
  166. /* call callback function for post-processed */
  167. if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) {
  168. pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
  169. if (pcmd_callback == NULL) {
  170. RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("mlme_cmd_hdl(): pcmd_callback = 0x%p, cmdcode = 0x%x\n", pcmd_callback, pcmd->cmdcode));
  171. rtw_free_cmd_obj(pcmd);
  172. } else {
  173. /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */
  174. pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */
  175. }
  176. } else {
  177. RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("%s: cmdcode = 0x%x callback not defined!\n", __func__, pcmd->cmdcode));
  178. rtw_free_cmd_obj(pcmd);
  179. }
  180. if (signal_pending(current))
  181. flush_signals(current);
  182. goto _next;
  183. }
  184. pcmdpriv->cmdthd_running = false;
  185. /* free all cmd_obj resources */
  186. do {
  187. pcmd = rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
  188. if (pcmd == NULL)
  189. break;
  190. /* DBG_88E("%s: leaving... drop cmdcode:%u\n", __func__, pcmd->cmdcode); */
  191. rtw_free_cmd_obj(pcmd);
  192. } while (1);
  193. up(&pcmdpriv->terminate_cmdthread_sema);
  194. complete_and_exit(NULL, 0);
  195. }
  196. /*
  197. rtw_sitesurvey_cmd(~)
  198. ### NOTE:#### (!!!!)
  199. MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
  200. */
  201. u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, int ssid_num,
  202. struct rtw_ieee80211_channel *ch, int ch_num)
  203. {
  204. u8 res = _FAIL;
  205. struct cmd_obj *ph2c;
  206. struct sitesurvey_parm *psurveyPara;
  207. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  208. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  209. if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
  210. rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
  211. ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
  212. if (ph2c == NULL)
  213. return _FAIL;
  214. psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
  215. if (psurveyPara == NULL) {
  216. kfree(ph2c);
  217. return _FAIL;
  218. }
  219. rtw_free_network_queue(padapter, false);
  220. RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("%s: flush network queue\n", __func__));
  221. init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
  222. /* psurveyPara->bsslimit = 48; */
  223. psurveyPara->scan_mode = pmlmepriv->scan_mode;
  224. /* prepare ssid list */
  225. if (ssid) {
  226. int i;
  227. for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
  228. if (ssid[i].SsidLength) {
  229. memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid));
  230. psurveyPara->ssid_num++;
  231. }
  232. }
  233. }
  234. /* prepare channel list */
  235. if (ch) {
  236. int i;
  237. for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
  238. if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) {
  239. memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel));
  240. psurveyPara->ch_num++;
  241. }
  242. }
  243. }
  244. set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
  245. res = rtw_enqueue_cmd(pcmdpriv, ph2c);
  246. if (res == _SUCCESS) {
  247. pmlmepriv->scan_start_time = jiffies;
  248. mod_timer(&pmlmepriv->scan_to_timer,
  249. jiffies + msecs_to_jiffies(SCANNING_TIMEOUT));
  250. rtw_led_control(padapter, LED_CTL_SITE_SURVEY);
  251. pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
  252. } else {
  253. _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
  254. }
  255. return res;
  256. }
  257. void rtw_readtssi_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
  258. {
  259. kfree(pcmd->parmbuf);
  260. kfree(pcmd);
  261. }
  262. u8 rtw_createbss_cmd(struct adapter *padapter)
  263. {
  264. struct cmd_obj *pcmd;
  265. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  266. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  267. struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
  268. u8 res = _SUCCESS;
  269. rtw_led_control(padapter, LED_CTL_START_TO_LINK);
  270. if (pmlmepriv->assoc_ssid.SsidLength == 0)
  271. RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for Any SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
  272. else
  273. RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
  274. pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
  275. if (pcmd == NULL) {
  276. res = _FAIL;
  277. goto exit;
  278. }
  279. INIT_LIST_HEAD(&pcmd->list);
  280. pcmd->cmdcode = _CreateBss_CMD_;
  281. pcmd->parmbuf = (unsigned char *)pdev_network;
  282. pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
  283. pcmd->rsp = NULL;
  284. pcmd->rspsz = 0;
  285. pdev_network->Length = pcmd->cmdsz;
  286. res = rtw_enqueue_cmd(pcmdpriv, pcmd);
  287. exit:
  288. return res;
  289. }
  290. u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
  291. {
  292. u8 res = _SUCCESS;
  293. uint t_len = 0;
  294. struct wlan_bssid_ex *psecnetwork;
  295. struct cmd_obj *pcmd;
  296. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  297. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  298. struct qos_priv *pqospriv = &pmlmepriv->qospriv;
  299. struct security_priv *psecuritypriv = &padapter->securitypriv;
  300. struct registry_priv *pregistrypriv = &padapter->registrypriv;
  301. struct ht_priv *phtpriv = &pmlmepriv->htpriv;
  302. enum ndis_802_11_network_infra ndis_network_mode = pnetwork->network.InfrastructureMode;
  303. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  304. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  305. rtw_led_control(padapter, LED_CTL_START_TO_LINK);
  306. if (pmlmepriv->assoc_ssid.SsidLength == 0)
  307. RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+Join cmd: Any SSid\n"));
  308. else
  309. RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.Ssid));
  310. pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
  311. if (pcmd == NULL) {
  312. res = _FAIL;
  313. RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd: memory allocate for cmd_obj fail!!!\n"));
  314. goto exit;
  315. }
  316. /* for IEs is fix buf size */
  317. t_len = sizeof(struct wlan_bssid_ex);
  318. /* for hidden ap to set fw_state here */
  319. if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE)) {
  320. switch (ndis_network_mode) {
  321. case Ndis802_11IBSS:
  322. set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
  323. break;
  324. case Ndis802_11Infrastructure:
  325. set_fwstate(pmlmepriv, WIFI_STATION_STATE);
  326. break;
  327. case Ndis802_11APMode:
  328. case Ndis802_11AutoUnknown:
  329. case Ndis802_11InfrastructureMax:
  330. break;
  331. }
  332. }
  333. psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss;
  334. if (psecnetwork == NULL) {
  335. kfree(pcmd);
  336. res = _FAIL;
  337. RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd :psecnetwork == NULL!!!\n"));
  338. goto exit;
  339. }
  340. memset(psecnetwork, 0, t_len);
  341. memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network));
  342. psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength;
  343. if ((psecnetwork->IELength-12) < (256-1))
  344. memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength-12);
  345. else
  346. memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256-1));
  347. psecnetwork->IELength = 0;
  348. /* Added by Albert 2009/02/18 */
  349. /* If the driver wants to use the bssid to create the connection. */
  350. /* If not, we have to copy the connecting AP's MAC address to it so that */
  351. /* the driver just has the bssid information for PMKIDList searching. */
  352. if (!pmlmepriv->assoc_by_bssid)
  353. memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
  354. psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength);
  355. pqospriv->qos_option = 0;
  356. if (pregistrypriv->wmm_enable) {
  357. u32 tmp_len;
  358. tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);
  359. if (psecnetwork->IELength != tmp_len) {
  360. psecnetwork->IELength = tmp_len;
  361. pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
  362. } else {
  363. pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
  364. }
  365. }
  366. phtpriv->ht_option = false;
  367. if (pregistrypriv->ht_enable) {
  368. /*
  369. * Added by Albert 2010/06/23
  370. * For the WEP mode, we will use the bg mode to do
  371. * the connection to avoid some IOT issue.
  372. * Especially for Realtek 8192u SoftAP.
  373. */
  374. if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
  375. (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
  376. (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
  377. /* rtw_restructure_ht_ie */
  378. rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0],
  379. pnetwork->network.IELength, &psecnetwork->IELength);
  380. }
  381. }
  382. pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);
  383. if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA)
  384. padapter->pwrctrlpriv.smart_ps = 0;
  385. else
  386. padapter->pwrctrlpriv.smart_ps = padapter->registrypriv.smart_ps;
  387. DBG_88E("%s: smart_ps =%d\n", __func__, padapter->pwrctrlpriv.smart_ps);
  388. pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */
  389. INIT_LIST_HEAD(&pcmd->list);
  390. pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */
  391. pcmd->parmbuf = (unsigned char *)psecnetwork;
  392. pcmd->rsp = NULL;
  393. pcmd->rspsz = 0;
  394. res = rtw_enqueue_cmd(pcmdpriv, pcmd);
  395. exit:
  396. return res;
  397. }
  398. u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */
  399. {
  400. struct cmd_obj *cmdobj = NULL;
  401. struct disconnect_parm *param = NULL;
  402. struct cmd_priv *cmdpriv = &padapter->cmdpriv;
  403. u8 res = _SUCCESS;
  404. RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_disassoc_cmd\n"));
  405. /* prepare cmd parameter */
  406. param = kzalloc(sizeof(*param), GFP_KERNEL);
  407. if (param == NULL) {
  408. res = _FAIL;
  409. goto exit;
  410. }
  411. param->deauth_timeout_ms = deauth_timeout_ms;
  412. if (enqueue) {
  413. /* need enqueue, prepare cmd_obj and enqueue */
  414. cmdobj = kzalloc(sizeof(*cmdobj), GFP_KERNEL);
  415. if (cmdobj == NULL) {
  416. res = _FAIL;
  417. kfree(param);
  418. goto exit;
  419. }
  420. init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
  421. res = rtw_enqueue_cmd(cmdpriv, cmdobj);
  422. } else {
  423. /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
  424. if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS)
  425. res = _FAIL;
  426. kfree(param);
  427. }
  428. exit:
  429. return res;
  430. }
  431. u8 rtw_setopmode_cmd(struct adapter *padapter, enum ndis_802_11_network_infra networktype)
  432. {
  433. struct cmd_obj *ph2c;
  434. struct setopmode_parm *psetop;
  435. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  436. u8 res = _SUCCESS;
  437. ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
  438. if (ph2c == NULL) {
  439. res = false;
  440. goto exit;
  441. }
  442. psetop = kzalloc(sizeof(struct setopmode_parm), GFP_KERNEL);
  443. if (psetop == NULL) {
  444. kfree(ph2c);
  445. res = false;
  446. goto exit;
  447. }
  448. init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
  449. psetop->mode = (u8)networktype;
  450. res = rtw_enqueue_cmd(pcmdpriv, ph2c);
  451. exit:
  452. return res;
  453. }
  454. u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key)
  455. {
  456. struct cmd_obj *ph2c;
  457. struct set_stakey_parm *psetstakey_para;
  458. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  459. struct set_stakey_rsp *psetstakey_rsp = NULL;
  460. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  461. struct security_priv *psecuritypriv = &padapter->securitypriv;
  462. struct sta_info *sta = (struct sta_info *)psta;
  463. u8 res = _SUCCESS;
  464. ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
  465. if (ph2c == NULL) {
  466. res = _FAIL;
  467. goto exit;
  468. }
  469. psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
  470. if (psetstakey_para == NULL) {
  471. kfree(ph2c);
  472. res = _FAIL;
  473. goto exit;
  474. }
  475. psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_KERNEL);
  476. if (psetstakey_rsp == NULL) {
  477. kfree(ph2c);
  478. kfree(psetstakey_para);
  479. res = _FAIL;
  480. goto exit;
  481. }
  482. init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
  483. ph2c->rsp = (u8 *)psetstakey_rsp;
  484. ph2c->rspsz = sizeof(struct set_stakey_rsp);
  485. ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
  486. if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
  487. psetstakey_para->algorithm = (unsigned char)psecuritypriv->dot11PrivacyAlgrthm;
  488. else
  489. GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false);
  490. if (unicast_key)
  491. memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
  492. else
  493. memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
  494. /* jeff: set this because at least sw key is ready */
  495. padapter->securitypriv.busetkipkey = true;
  496. res = rtw_enqueue_cmd(pcmdpriv, ph2c);
  497. exit:
  498. return res;
  499. }
  500. u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue)
  501. {
  502. struct cmd_obj *ph2c;
  503. struct set_stakey_parm *psetstakey_para;
  504. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  505. struct set_stakey_rsp *psetstakey_rsp = NULL;
  506. struct sta_info *sta = (struct sta_info *)psta;
  507. u8 res = _SUCCESS;
  508. if (!enqueue) {
  509. clear_cam_entry(padapter, entry);
  510. } else {
  511. ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
  512. if (ph2c == NULL) {
  513. res = _FAIL;
  514. goto exit;
  515. }
  516. psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_ATOMIC);
  517. if (psetstakey_para == NULL) {
  518. kfree(ph2c);
  519. res = _FAIL;
  520. goto exit;
  521. }
  522. psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_ATOMIC);
  523. if (psetstakey_rsp == NULL) {
  524. kfree(ph2c);
  525. kfree(psetstakey_para);
  526. res = _FAIL;
  527. goto exit;
  528. }
  529. init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
  530. ph2c->rsp = (u8 *)psetstakey_rsp;
  531. ph2c->rspsz = sizeof(struct set_stakey_rsp);
  532. ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
  533. psetstakey_para->algorithm = _NO_PRIVACY_;
  534. psetstakey_para->id = entry;
  535. res = rtw_enqueue_cmd(pcmdpriv, ph2c);
  536. }
  537. exit:
  538. return res;
  539. }
  540. u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
  541. {
  542. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  543. struct cmd_obj *ph2c;
  544. struct addBaReq_parm *paddbareq_parm;
  545. u8 res = _SUCCESS;
  546. ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
  547. if (ph2c == NULL) {
  548. res = _FAIL;
  549. goto exit;
  550. }
  551. paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_ATOMIC);
  552. if (paddbareq_parm == NULL) {
  553. kfree(ph2c);
  554. res = _FAIL;
  555. goto exit;
  556. }
  557. paddbareq_parm->tid = tid;
  558. memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
  559. init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq));
  560. /* DBG_88E("rtw_addbareq_cmd, tid =%d\n", tid); */
  561. /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
  562. res = rtw_enqueue_cmd(pcmdpriv, ph2c);
  563. exit:
  564. return res;
  565. }
  566. u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
  567. {
  568. struct cmd_obj *ph2c;
  569. struct drvextra_cmd_parm *pdrvextra_cmd_parm;
  570. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  571. u8 res = _SUCCESS;
  572. ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
  573. if (ph2c == NULL) {
  574. res = _FAIL;
  575. goto exit;
  576. }
  577. pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
  578. if (pdrvextra_cmd_parm == NULL) {
  579. kfree(ph2c);
  580. res = _FAIL;
  581. goto exit;
  582. }
  583. pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
  584. pdrvextra_cmd_parm->type_size = 0;
  585. pdrvextra_cmd_parm->pbuf = (u8 *)padapter;
  586. init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
  587. /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
  588. res = rtw_enqueue_cmd(pcmdpriv, ph2c);
  589. exit:
  590. return res;
  591. }
  592. u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue)
  593. {
  594. struct cmd_obj *pcmdobj;
  595. struct SetChannelPlan_param *setChannelPlan_param;
  596. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  597. u8 res = _SUCCESS;
  598. RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_chplan_cmd\n"));
  599. /* check input parameter */
  600. if (!rtw_is_channel_plan_valid(chplan)) {
  601. res = _FAIL;
  602. goto exit;
  603. }
  604. /* prepare cmd parameter */
  605. setChannelPlan_param = kzalloc(sizeof(struct SetChannelPlan_param), GFP_KERNEL);
  606. if (setChannelPlan_param == NULL) {
  607. res = _FAIL;
  608. goto exit;
  609. }
  610. setChannelPlan_param->channel_plan = chplan;
  611. if (enqueue) {
  612. /* need enqueue, prepare cmd_obj and enqueue */
  613. pcmdobj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
  614. if (pcmdobj == NULL) {
  615. kfree(setChannelPlan_param);
  616. res = _FAIL;
  617. goto exit;
  618. }
  619. init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan));
  620. res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
  621. } else {
  622. /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
  623. if (set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param) != H2C_SUCCESS)
  624. res = _FAIL;
  625. kfree(setChannelPlan_param);
  626. }
  627. /* do something based on res... */
  628. if (res == _SUCCESS)
  629. padapter->mlmepriv.ChannelPlan = chplan;
  630. exit:
  631. return res;
  632. }
  633. static void traffic_status_watchdog(struct adapter *padapter)
  634. {
  635. u8 bEnterPS;
  636. u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
  637. u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false;
  638. struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  639. /* */
  640. /* Determine if our traffic is busy now */
  641. /* */
  642. if (check_fwstate(pmlmepriv, _FW_LINKED)) {
  643. if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 100 ||
  644. pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 100) {
  645. bBusyTraffic = true;
  646. if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
  647. bRxBusyTraffic = true;
  648. else
  649. bTxBusyTraffic = true;
  650. }
  651. /* Higher Tx/Rx data. */
  652. if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
  653. pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
  654. bHigherBusyTraffic = true;
  655. if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
  656. bHigherBusyRxTraffic = true;
  657. else
  658. bHigherBusyTxTraffic = true;
  659. }
  660. /* check traffic for powersaving. */
  661. if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
  662. (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2))
  663. bEnterPS = false;
  664. else
  665. bEnterPS = true;
  666. /* LeisurePS only work in infra mode. */
  667. if (bEnterPS)
  668. LPS_Enter(padapter);
  669. else
  670. LPS_Leave(padapter);
  671. } else {
  672. LPS_Leave(padapter);
  673. }
  674. pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
  675. pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
  676. pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
  677. pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
  678. pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
  679. pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
  680. pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
  681. pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
  682. pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
  683. }
  684. static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
  685. {
  686. struct mlme_priv *pmlmepriv;
  687. padapter = (struct adapter *)pbuf;
  688. pmlmepriv = &(padapter->mlmepriv);
  689. #ifdef CONFIG_88EU_AP_MODE
  690. if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
  691. expire_timeout_chk(padapter);
  692. #endif
  693. linked_status_chk(padapter);
  694. traffic_status_watchdog(padapter);
  695. rtw_hal_dm_watchdog(padapter);
  696. }
  697. static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type)
  698. {
  699. struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
  700. struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  701. u8 mstatus;
  702. if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
  703. (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
  704. return;
  705. switch (lps_ctrl_type) {
  706. case LPS_CTRL_SCAN:
  707. if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
  708. /* connect */
  709. LPS_Leave(padapter);
  710. }
  711. break;
  712. case LPS_CTRL_JOINBSS:
  713. LPS_Leave(padapter);
  714. break;
  715. case LPS_CTRL_CONNECT:
  716. mstatus = 1;/* connect */
  717. /* Reset LPS Setting */
  718. padapter->pwrctrlpriv.LpsIdleCount = 0;
  719. rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
  720. break;
  721. case LPS_CTRL_DISCONNECT:
  722. mstatus = 0;/* disconnect */
  723. LPS_Leave(padapter);
  724. rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
  725. break;
  726. case LPS_CTRL_SPECIAL_PACKET:
  727. /* DBG_88E("LPS_CTRL_SPECIAL_PACKET\n"); */
  728. pwrpriv->DelayLPSLastTimeStamp = jiffies;
  729. LPS_Leave(padapter);
  730. break;
  731. case LPS_CTRL_LEAVE:
  732. LPS_Leave(padapter);
  733. break;
  734. default:
  735. break;
  736. }
  737. }
  738. u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
  739. {
  740. struct cmd_obj *ph2c;
  741. struct drvextra_cmd_parm *pdrvextra_cmd_parm;
  742. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  743. /* struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; */
  744. u8 res = _SUCCESS;
  745. if (enqueue) {
  746. ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
  747. if (ph2c == NULL) {
  748. res = _FAIL;
  749. goto exit;
  750. }
  751. pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
  752. if (pdrvextra_cmd_parm == NULL) {
  753. kfree(ph2c);
  754. res = _FAIL;
  755. goto exit;
  756. }
  757. pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
  758. pdrvextra_cmd_parm->type_size = lps_ctrl_type;
  759. pdrvextra_cmd_parm->pbuf = NULL;
  760. init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
  761. res = rtw_enqueue_cmd(pcmdpriv, ph2c);
  762. } else {
  763. lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
  764. }
  765. exit:
  766. return res;
  767. }
  768. static void rpt_timer_setting_wk_hdl(struct adapter *padapter, u16 min_time)
  769. {
  770. rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&min_time));
  771. }
  772. u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time)
  773. {
  774. struct cmd_obj *ph2c;
  775. struct drvextra_cmd_parm *pdrvextra_cmd_parm;
  776. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  777. u8 res = _SUCCESS;
  778. ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
  779. if (ph2c == NULL) {
  780. res = _FAIL;
  781. goto exit;
  782. }
  783. pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
  784. if (pdrvextra_cmd_parm == NULL) {
  785. kfree(ph2c);
  786. res = _FAIL;
  787. goto exit;
  788. }
  789. pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;
  790. pdrvextra_cmd_parm->type_size = min_time;
  791. pdrvextra_cmd_parm->pbuf = NULL;
  792. init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
  793. res = rtw_enqueue_cmd(pcmdpriv, ph2c);
  794. exit:
  795. return res;
  796. }
  797. static void antenna_select_wk_hdl(struct adapter *padapter, u8 antenna)
  798. {
  799. rtw_hal_set_hwreg(padapter, HW_VAR_ANTENNA_DIVERSITY_SELECT, (u8 *)(&antenna));
  800. }
  801. u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue)
  802. {
  803. struct cmd_obj *ph2c;
  804. struct drvextra_cmd_parm *pdrvextra_cmd_parm;
  805. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  806. u8 support_ant_div;
  807. u8 res = _SUCCESS;
  808. rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &support_ant_div);
  809. if (!support_ant_div)
  810. return res;
  811. if (enqueue) {
  812. ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
  813. if (ph2c == NULL) {
  814. res = _FAIL;
  815. goto exit;
  816. }
  817. pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
  818. if (pdrvextra_cmd_parm == NULL) {
  819. kfree(ph2c);
  820. res = _FAIL;
  821. goto exit;
  822. }
  823. pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;
  824. pdrvextra_cmd_parm->type_size = antenna;
  825. pdrvextra_cmd_parm->pbuf = NULL;
  826. init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
  827. res = rtw_enqueue_cmd(pcmdpriv, ph2c);
  828. } else {
  829. antenna_select_wk_hdl(padapter, antenna);
  830. }
  831. exit:
  832. return res;
  833. }
  834. u8 rtw_ps_cmd(struct adapter *padapter)
  835. {
  836. struct cmd_obj *ppscmd;
  837. struct drvextra_cmd_parm *pdrvextra_cmd_parm;
  838. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  839. u8 res = _SUCCESS;
  840. ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
  841. if (ppscmd == NULL) {
  842. res = _FAIL;
  843. goto exit;
  844. }
  845. pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
  846. if (pdrvextra_cmd_parm == NULL) {
  847. kfree(ppscmd);
  848. res = _FAIL;
  849. goto exit;
  850. }
  851. pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
  852. pdrvextra_cmd_parm->pbuf = NULL;
  853. init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
  854. res = rtw_enqueue_cmd(pcmdpriv, ppscmd);
  855. exit:
  856. return res;
  857. }
  858. #ifdef CONFIG_88EU_AP_MODE
  859. static void rtw_chk_hi_queue_hdl(struct adapter *padapter)
  860. {
  861. int cnt = 0;
  862. struct sta_info *psta_bmc;
  863. struct sta_priv *pstapriv = &padapter->stapriv;
  864. psta_bmc = rtw_get_bcmc_stainfo(padapter);
  865. if (!psta_bmc)
  866. return;
  867. if (psta_bmc->sleepq_len == 0) {
  868. u8 val = 0;
  869. /* while ((rtw_read32(padapter, 0x414)&0x00ffff00)!= 0) */
  870. /* while ((rtw_read32(padapter, 0x414)&0x0000ff00)!= 0) */
  871. rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
  872. while (!val) {
  873. msleep(100);
  874. cnt++;
  875. if (cnt > 10)
  876. break;
  877. rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
  878. }
  879. if (cnt <= 10) {
  880. pstapriv->tim_bitmap &= ~BIT(0);
  881. pstapriv->sta_dz_bitmap &= ~BIT(0);
  882. update_beacon(padapter, _TIM_IE_, NULL, false);
  883. } else { /* re check again */
  884. rtw_chk_hi_queue_cmd(padapter);
  885. }
  886. }
  887. }
  888. u8 rtw_chk_hi_queue_cmd(struct adapter *padapter)
  889. {
  890. struct cmd_obj *ph2c;
  891. struct drvextra_cmd_parm *pdrvextra_cmd_parm;
  892. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  893. u8 res = _SUCCESS;
  894. ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
  895. if (ph2c == NULL) {
  896. res = _FAIL;
  897. goto exit;
  898. }
  899. pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
  900. if (pdrvextra_cmd_parm == NULL) {
  901. kfree(ph2c);
  902. res = _FAIL;
  903. goto exit;
  904. }
  905. pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
  906. pdrvextra_cmd_parm->type_size = 0;
  907. pdrvextra_cmd_parm->pbuf = NULL;
  908. init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
  909. res = rtw_enqueue_cmd(pcmdpriv, ph2c);
  910. exit:
  911. return res;
  912. }
  913. #endif
  914. u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf)
  915. {
  916. struct drvextra_cmd_parm *pdrvextra_cmd;
  917. if (!pbuf)
  918. return H2C_PARAMETERS_ERROR;
  919. pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
  920. switch (pdrvextra_cmd->ec_id) {
  921. case DYNAMIC_CHK_WK_CID:
  922. dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size);
  923. break;
  924. case POWER_SAVING_CTRL_WK_CID:
  925. rtw_ps_processor(padapter);
  926. break;
  927. case LPS_CTRL_WK_CID:
  928. lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
  929. break;
  930. case RTP_TIMER_CFG_WK_CID:
  931. rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type_size);
  932. break;
  933. case ANT_SELECT_WK_CID:
  934. antenna_select_wk_hdl(padapter, pdrvextra_cmd->type_size);
  935. break;
  936. #ifdef CONFIG_88EU_AP_MODE
  937. case CHECK_HIQ_WK_CID:
  938. rtw_chk_hi_queue_hdl(padapter);
  939. break;
  940. #endif /* CONFIG_88EU_AP_MODE */
  941. default:
  942. break;
  943. }
  944. if (pdrvextra_cmd->pbuf && pdrvextra_cmd->type_size > 0)
  945. kfree(pdrvextra_cmd->pbuf);
  946. return H2C_SUCCESS;
  947. }
  948. void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
  949. {
  950. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  951. if (pcmd->res == H2C_DROPPED) {
  952. /* TODO: cancel timer and do timeout handler directly... */
  953. /* need to make timeout handlerOS independent */
  954. mod_timer(&pmlmepriv->scan_to_timer,
  955. jiffies + msecs_to_jiffies(1));
  956. } else if (pcmd->res != H2C_SUCCESS) {
  957. mod_timer(&pmlmepriv->scan_to_timer,
  958. jiffies + msecs_to_jiffies(1));
  959. RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: MgntActrtw_set_802_11_bssid_LIST_SCAN Fail ************\n\n."));
  960. }
  961. /* free cmd */
  962. rtw_free_cmd_obj(pcmd);
  963. }
  964. void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
  965. {
  966. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  967. if (pcmd->res != H2C_SUCCESS) {
  968. spin_lock_bh(&pmlmepriv->lock);
  969. set_fwstate(pmlmepriv, _FW_LINKED);
  970. spin_unlock_bh(&pmlmepriv->lock);
  971. RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ***Error: disconnect_cmd_callback Fail ***\n."));
  972. return;
  973. }
  974. /* free cmd */
  975. rtw_free_cmd_obj(pcmd);
  976. }
  977. void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
  978. {
  979. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  980. if (pcmd->res == H2C_DROPPED) {
  981. /* TODO: cancel timer and do timeout handler directly... */
  982. /* need to make timeout handlerOS independent */
  983. mod_timer(&pmlmepriv->assoc_timer,
  984. jiffies + msecs_to_jiffies(1));
  985. } else if (pcmd->res != H2C_SUCCESS) {
  986. RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("********Error:rtw_select_and_join_from_scanned_queue Wait Sema Fail ************\n"));
  987. mod_timer(&pmlmepriv->assoc_timer,
  988. jiffies + msecs_to_jiffies(1));
  989. }
  990. rtw_free_cmd_obj(pcmd);
  991. }
  992. void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
  993. {
  994. struct sta_info *psta = NULL;
  995. struct wlan_network *pwlan = NULL;
  996. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  997. struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
  998. struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
  999. if (pcmd->res != H2C_SUCCESS) {
  1000. RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: rtw_createbss_cmd_callback Fail ************\n\n."));
  1001. mod_timer(&pmlmepriv->assoc_timer,
  1002. jiffies + msecs_to_jiffies(1));
  1003. }
  1004. del_timer_sync(&pmlmepriv->assoc_timer);
  1005. spin_lock_bh(&pmlmepriv->lock);
  1006. if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
  1007. psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
  1008. if (!psta) {
  1009. psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
  1010. if (psta == NULL) {
  1011. RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nCan't alloc sta_info when createbss_cmd_callback\n"));
  1012. goto createbss_cmd_fail;
  1013. }
  1014. }
  1015. rtw_indicate_connect(padapter);
  1016. } else {
  1017. pwlan = _rtw_alloc_network(pmlmepriv);
  1018. spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
  1019. if (pwlan == NULL) {
  1020. pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
  1021. if (pwlan == NULL) {
  1022. RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n Error: can't get pwlan in rtw_joinbss_event_callback\n"));
  1023. spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
  1024. goto createbss_cmd_fail;
  1025. }
  1026. pwlan->last_scanned = jiffies;
  1027. } else {
  1028. list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
  1029. }
  1030. pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
  1031. memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
  1032. memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork)));
  1033. _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
  1034. spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
  1035. /* we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */
  1036. }
  1037. createbss_cmd_fail:
  1038. spin_unlock_bh(&pmlmepriv->lock);
  1039. rtw_free_cmd_obj(pcmd);
  1040. }
  1041. void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
  1042. {
  1043. struct sta_priv *pstapriv = &padapter->stapriv;
  1044. struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
  1045. struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
  1046. if (psta == NULL) {
  1047. RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: rtw_setstaKey_cmdrsp_callback => can't get sta_info\n\n"));
  1048. goto exit;
  1049. }
  1050. exit:
  1051. rtw_free_cmd_obj(pcmd);
  1052. }
  1053. void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
  1054. {
  1055. struct sta_priv *pstapriv = &padapter->stapriv;
  1056. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  1057. struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
  1058. struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp);
  1059. struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
  1060. if (psta == NULL) {
  1061. RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: setassocsta_cmdrsp_callbac => can't get sta_info\n\n"));
  1062. goto exit;
  1063. }
  1064. psta->aid = passocsta_rsp->cam_id;
  1065. psta->mac_id = passocsta_rsp->cam_id;
  1066. spin_lock_bh(&pmlmepriv->lock);
  1067. if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true))
  1068. _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
  1069. set_fwstate(pmlmepriv, _FW_LINKED);
  1070. spin_unlock_bh(&pmlmepriv->lock);
  1071. exit:
  1072. rtw_free_cmd_obj(pcmd);
  1073. }