cmdresp.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029
  1. /**
  2. * This file contains the handling of command
  3. * responses as well as events generated by firmware.
  4. */
  5. #include <linux/delay.h>
  6. #include <linux/if_arp.h>
  7. #include <linux/netdevice.h>
  8. #include <net/iw_handler.h>
  9. #include "host.h"
  10. #include "sbi.h"
  11. #include "decl.h"
  12. #include "defs.h"
  13. #include "dev.h"
  14. #include "join.h"
  15. #include "wext.h"
  16. /**
  17. * @brief This function handles disconnect event. it
  18. * reports disconnect to upper layer, clean tx/rx packets,
  19. * reset link state etc.
  20. *
  21. * @param priv A pointer to wlan_private structure
  22. * @return n/a
  23. */
  24. void libertas_mac_event_disconnected(wlan_private * priv)
  25. {
  26. wlan_adapter *adapter = priv->adapter;
  27. union iwreq_data wrqu;
  28. if (adapter->connect_status != libertas_connected)
  29. return;
  30. lbs_pr_debug(1, "Handles disconnect event.\n");
  31. memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
  32. wrqu.ap_addr.sa_family = ARPHRD_ETHER;
  33. /*
  34. * Cisco AP sends EAP failure and de-auth in less than 0.5 ms.
  35. * It causes problem in the Supplicant
  36. */
  37. msleep_interruptible(1000);
  38. wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
  39. /* Free Tx and Rx packets */
  40. kfree_skb(priv->adapter->currenttxskb);
  41. priv->adapter->currenttxskb = NULL;
  42. /* report disconnect to upper layer */
  43. netif_stop_queue(priv->wlan_dev.netdev);
  44. netif_carrier_off(priv->wlan_dev.netdev);
  45. /* reset SNR/NF/RSSI values */
  46. memset(adapter->SNR, 0x00, sizeof(adapter->SNR));
  47. memset(adapter->NF, 0x00, sizeof(adapter->NF));
  48. memset(adapter->RSSI, 0x00, sizeof(adapter->RSSI));
  49. memset(adapter->rawSNR, 0x00, sizeof(adapter->rawSNR));
  50. memset(adapter->rawNF, 0x00, sizeof(adapter->rawNF));
  51. adapter->nextSNRNF = 0;
  52. adapter->numSNRNF = 0;
  53. adapter->rxpd_rate = 0;
  54. lbs_pr_debug(1, "Current SSID=%s, ssid length=%u\n",
  55. adapter->curbssparams.ssid.ssid,
  56. adapter->curbssparams.ssid.ssidlength);
  57. lbs_pr_debug(1, "Previous SSID=%s, ssid length=%u\n",
  58. adapter->previousssid.ssid, adapter->previousssid.ssidlength);
  59. /* reset internal flags */
  60. adapter->secinfo.WPAenabled = 0;
  61. adapter->secinfo.WPA2enabled = 0;
  62. adapter->wpa_ie_len = 0;
  63. adapter->connect_status = libertas_disconnected;
  64. /*
  65. * memorize the previous SSID and BSSID
  66. * it could be used for re-assoc
  67. */
  68. memcpy(&adapter->previousssid,
  69. &adapter->curbssparams.ssid, sizeof(struct WLAN_802_11_SSID));
  70. memcpy(adapter->previousbssid,
  71. adapter->curbssparams.bssid, ETH_ALEN);
  72. /* need to erase the current SSID and BSSID info */
  73. adapter->pattemptedbssdesc = NULL;
  74. memset(&adapter->curbssparams, 0, sizeof(adapter->curbssparams));
  75. if (adapter->psstate != PS_STATE_FULL_POWER) {
  76. /* make firmware to exit PS mode */
  77. lbs_pr_debug(1, "Disconnected, so exit PS mode.\n");
  78. libertas_ps_wakeup(priv, 0);
  79. }
  80. }
  81. /**
  82. * @brief This function handles MIC failure event.
  83. *
  84. * @param priv A pointer to wlan_private structure
  85. * @para event the event id
  86. * @return n/a
  87. */
  88. static void handle_mic_failureevent(wlan_private * priv, u32 event)
  89. {
  90. char buf[50];
  91. memset(buf, 0, sizeof(buf));
  92. sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
  93. if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) {
  94. strcat(buf, "unicast ");
  95. } else {
  96. strcat(buf, "multicast ");
  97. }
  98. libertas_send_iwevcustom_event(priv, buf);
  99. }
  100. static int wlan_ret_reg_access(wlan_private * priv,
  101. u16 type, struct cmd_ds_command *resp)
  102. {
  103. wlan_adapter *adapter = priv->adapter;
  104. ENTER();
  105. switch (type) {
  106. case cmd_ret_mac_reg_access:
  107. {
  108. struct cmd_ds_mac_reg_access *reg;
  109. reg =
  110. (struct cmd_ds_mac_reg_access *)&resp->params.
  111. macreg;
  112. adapter->offsetvalue.offset = reg->offset;
  113. adapter->offsetvalue.value = reg->value;
  114. break;
  115. }
  116. case cmd_ret_bbp_reg_access:
  117. {
  118. struct cmd_ds_bbp_reg_access *reg;
  119. reg =
  120. (struct cmd_ds_bbp_reg_access *)&resp->params.
  121. bbpreg;
  122. adapter->offsetvalue.offset = reg->offset;
  123. adapter->offsetvalue.value = reg->value;
  124. break;
  125. }
  126. case cmd_ret_rf_reg_access:
  127. {
  128. struct cmd_ds_rf_reg_access *reg;
  129. reg =
  130. (struct cmd_ds_rf_reg_access *)&resp->params.
  131. rfreg;
  132. adapter->offsetvalue.offset = reg->offset;
  133. adapter->offsetvalue.value = reg->value;
  134. break;
  135. }
  136. default:
  137. LEAVE();
  138. return -1;
  139. }
  140. LEAVE();
  141. return 0;
  142. }
  143. static int wlan_ret_get_hw_spec(wlan_private * priv,
  144. struct cmd_ds_command *resp)
  145. {
  146. u32 i;
  147. struct cmd_ds_get_hw_spec *hwspec = &resp->params.hwspec;
  148. wlan_adapter *adapter = priv->adapter;
  149. int ret = 0;
  150. ENTER();
  151. adapter->fwcapinfo = le32_to_cpu(hwspec->fwcapinfo);
  152. adapter->fwreleasenumber = hwspec->fwreleasenumber;
  153. lbs_pr_debug(1, "GET_HW_SPEC: FWReleaseVersion- 0x%X\n",
  154. adapter->fwreleasenumber);
  155. lbs_pr_debug(1, "GET_HW_SPEC: Permanent addr- %2x:%2x:%2x:%2x:%2x:%2x\n",
  156. hwspec->permanentaddr[0], hwspec->permanentaddr[1],
  157. hwspec->permanentaddr[2], hwspec->permanentaddr[3],
  158. hwspec->permanentaddr[4], hwspec->permanentaddr[5]);
  159. lbs_pr_debug(1, "GET_HW_SPEC: hwifversion=0x%X version=0x%X\n",
  160. hwspec->hwifversion, hwspec->version);
  161. adapter->regioncode = le16_to_cpu(hwspec->regioncode);
  162. for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
  163. /* use the region code to search for the index */
  164. if (adapter->regioncode == libertas_region_code_to_index[i]) {
  165. adapter->regiontableindex = (u16) i;
  166. break;
  167. }
  168. }
  169. /* if it's unidentified region code, use the default (USA) */
  170. if (i >= MRVDRV_MAX_REGION_CODE) {
  171. adapter->regioncode = 0x10;
  172. adapter->regiontableindex = 0;
  173. lbs_pr_info(
  174. "unidentified region code, use the default (USA)\n");
  175. }
  176. if (adapter->current_addr[0] == 0xff) {
  177. memmove(adapter->current_addr, hwspec->permanentaddr,
  178. ETH_ALEN);
  179. }
  180. memcpy(priv->wlan_dev.netdev->dev_addr, adapter->current_addr, ETH_ALEN);
  181. memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);
  182. if (libertas_set_regiontable(priv, adapter->regioncode, 0)) {
  183. ret = -1;
  184. goto done;
  185. }
  186. if (libertas_set_universaltable(priv, 0)) {
  187. ret = -1;
  188. goto done;
  189. }
  190. done:
  191. LEAVE();
  192. return ret;
  193. }
  194. static int wlan_ret_802_11_sleep_params(wlan_private * priv,
  195. struct cmd_ds_command *resp)
  196. {
  197. struct cmd_ds_802_11_sleep_params *sp = &resp->params.sleep_params;
  198. wlan_adapter *adapter = priv->adapter;
  199. ENTER();
  200. lbs_pr_debug(1, "error=%x offset=%x stabletime=%x calcontrol=%x\n"
  201. " extsleepclk=%x\n", sp->error, sp->offset,
  202. sp->stabletime, sp->calcontrol, sp->externalsleepclk);
  203. adapter->sp.sp_error = le16_to_cpu(sp->error);
  204. adapter->sp.sp_offset = le16_to_cpu(sp->offset);
  205. adapter->sp.sp_stabletime = le16_to_cpu(sp->stabletime);
  206. adapter->sp.sp_calcontrol = le16_to_cpu(sp->calcontrol);
  207. adapter->sp.sp_extsleepclk = le16_to_cpu(sp->externalsleepclk);
  208. adapter->sp.sp_reserved = le16_to_cpu(sp->reserved);
  209. LEAVE();
  210. return 0;
  211. }
  212. static int wlan_ret_802_11_stat(wlan_private * priv,
  213. struct cmd_ds_command *resp)
  214. {
  215. /* currently adapter->wlan802_11Stat is unused
  216. struct cmd_ds_802_11_get_stat *p11Stat = &resp->params.gstat;
  217. wlan_adapter *adapter = priv->adapter;
  218. // TODO Convert it to Big endian befor copy
  219. memcpy(&adapter->wlan802_11Stat,
  220. p11Stat, sizeof(struct cmd_ds_802_11_get_stat));
  221. */
  222. return 0;
  223. }
  224. static int wlan_ret_802_11_snmp_mib(wlan_private * priv,
  225. struct cmd_ds_command *resp)
  226. {
  227. struct cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
  228. u16 oid = le16_to_cpu(smib->oid);
  229. u16 querytype = le16_to_cpu(smib->querytype);
  230. ENTER();
  231. lbs_pr_debug(1, "SNMP_RESP: value of the oid = %x, querytype=%x\n", oid,
  232. querytype);
  233. lbs_pr_debug(1, "SNMP_RESP: Buf size = %x\n",
  234. le16_to_cpu(smib->bufsize));
  235. if (querytype == cmd_act_get) {
  236. switch (oid) {
  237. case fragthresh_i:
  238. priv->adapter->fragthsd =
  239. le16_to_cpu(*
  240. ((unsigned short *)(smib->value)));
  241. lbs_pr_debug(1, "SNMP_RESP: fragthsd =%u\n",
  242. priv->adapter->fragthsd);
  243. break;
  244. case rtsthresh_i:
  245. priv->adapter->rtsthsd =
  246. le16_to_cpu(*
  247. ((unsigned short *)(smib->value)));
  248. lbs_pr_debug(1, "SNMP_RESP: rtsthsd =%u\n",
  249. priv->adapter->rtsthsd);
  250. break;
  251. case short_retrylim_i:
  252. priv->adapter->txretrycount =
  253. le16_to_cpu(*
  254. ((unsigned short *)(smib->value)));
  255. lbs_pr_debug(1, "SNMP_RESP: txretrycount =%u\n",
  256. priv->adapter->rtsthsd);
  257. break;
  258. default:
  259. break;
  260. }
  261. }
  262. LEAVE();
  263. return 0;
  264. }
  265. static int wlan_ret_802_11_key_material(wlan_private * priv,
  266. struct cmd_ds_command *resp)
  267. {
  268. struct cmd_ds_802_11_key_material *pkeymaterial =
  269. &resp->params.keymaterial;
  270. wlan_adapter *adapter = priv->adapter;
  271. u16 action = le16_to_cpu(pkeymaterial->action);
  272. ENTER();
  273. /* Copy the returned key to driver private data */
  274. if (action == cmd_act_get) {
  275. u8 * buf_ptr = (u8 *) &pkeymaterial->keyParamSet;
  276. u8 * resp_end = (u8 *) (resp + le16_to_cpu(resp->size));
  277. while (buf_ptr < resp_end) {
  278. struct MrvlIEtype_keyParamSet * pkeyparamset =
  279. (struct MrvlIEtype_keyParamSet *) buf_ptr;
  280. struct WLAN_802_11_KEY * pkey;
  281. u16 key_info = le16_to_cpu(pkeyparamset->keyinfo);
  282. u16 param_set_len = le16_to_cpu(pkeyparamset->length);
  283. u8 * end;
  284. u16 key_len = le16_to_cpu(pkeyparamset->keylen);
  285. end = (u8 *) pkeyparamset + sizeof (pkeyparamset->type)
  286. + sizeof (pkeyparamset->length)
  287. + param_set_len;
  288. /* Make sure we don't access past the end of the IEs */
  289. if (end > resp_end)
  290. break;
  291. if (key_info & KEY_INFO_WPA_UNICAST)
  292. pkey = &adapter->wpa_unicast_key;
  293. else if (key_info & KEY_INFO_WPA_MCAST)
  294. pkey = &adapter->wpa_mcast_key;
  295. else
  296. break;
  297. /* Copy returned key into driver */
  298. memset(pkey, 0, sizeof(struct WLAN_802_11_KEY));
  299. if (key_len > sizeof(pkey->key))
  300. break;
  301. pkey->type = le16_to_cpu(pkeyparamset->keytypeid);
  302. pkey->flags = le16_to_cpu(pkeyparamset->keyinfo);
  303. pkey->len = le16_to_cpu(pkeyparamset->keylen);
  304. memcpy(pkey->key, pkeyparamset->key, pkey->len);
  305. buf_ptr = end + 1;
  306. }
  307. }
  308. LEAVE();
  309. return 0;
  310. }
  311. static int wlan_ret_802_11_mac_address(wlan_private * priv,
  312. struct cmd_ds_command *resp)
  313. {
  314. struct cmd_ds_802_11_mac_address *macadd = &resp->params.macadd;
  315. wlan_adapter *adapter = priv->adapter;
  316. ENTER();
  317. memcpy(adapter->current_addr, macadd->macadd, ETH_ALEN);
  318. LEAVE();
  319. return 0;
  320. }
  321. static int wlan_ret_802_11_rf_tx_power(wlan_private * priv,
  322. struct cmd_ds_command *resp)
  323. {
  324. struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp;
  325. wlan_adapter *adapter = priv->adapter;
  326. ENTER();
  327. adapter->txpowerlevel = le16_to_cpu(rtp->currentlevel);
  328. lbs_pr_debug(1, "Current TxPower Level = %d\n", adapter->txpowerlevel);
  329. LEAVE();
  330. return 0;
  331. }
  332. static int wlan_ret_802_11_rf_antenna(wlan_private * priv,
  333. struct cmd_ds_command *resp)
  334. {
  335. struct cmd_ds_802_11_rf_antenna *pAntenna = &resp->params.rant;
  336. wlan_adapter *adapter = priv->adapter;
  337. u16 action = le16_to_cpu(pAntenna->action);
  338. if (action == cmd_act_get_rx)
  339. adapter->rxantennamode =
  340. le16_to_cpu(pAntenna->antennamode);
  341. if (action == cmd_act_get_tx)
  342. adapter->txantennamode =
  343. le16_to_cpu(pAntenna->antennamode);
  344. lbs_pr_debug(1, "RF_ANT_RESP: action = 0x%x, mode = 0x%04x\n",
  345. action, le16_to_cpu(pAntenna->antennamode));
  346. return 0;
  347. }
  348. static int wlan_ret_802_11_rate_adapt_rateset(wlan_private * priv,
  349. struct cmd_ds_command *resp)
  350. {
  351. struct cmd_ds_802_11_rate_adapt_rateset *rates =
  352. &resp->params.rateset;
  353. wlan_adapter *adapter = priv->adapter;
  354. ENTER();
  355. if (rates->action == cmd_act_get) {
  356. adapter->enablehwauto = rates->enablehwauto;
  357. adapter->ratebitmap = rates->bitmap;
  358. }
  359. LEAVE();
  360. return 0;
  361. }
  362. static int wlan_ret_802_11_data_rate(wlan_private * priv,
  363. struct cmd_ds_command *resp)
  364. {
  365. struct cmd_ds_802_11_data_rate *pdatarate = &resp->params.drate;
  366. wlan_adapter *adapter = priv->adapter;
  367. u8 dot11datarate;
  368. ENTER();
  369. lbs_dbg_hex("DATA_RATE_RESP: data_rate- ",
  370. (u8 *) pdatarate, sizeof(struct cmd_ds_802_11_data_rate));
  371. dot11datarate = pdatarate->datarate[0];
  372. if (pdatarate->action == cmd_act_get_tx_rate) {
  373. memcpy(adapter->libertas_supported_rates, pdatarate->datarate,
  374. sizeof(adapter->libertas_supported_rates));
  375. }
  376. adapter->datarate = libertas_index_to_data_rate(dot11datarate);
  377. LEAVE();
  378. return 0;
  379. }
  380. static int wlan_ret_802_11_rf_channel(wlan_private * priv,
  381. struct cmd_ds_command *resp)
  382. {
  383. struct cmd_ds_802_11_rf_channel *rfchannel =
  384. &resp->params.rfchannel;
  385. wlan_adapter *adapter = priv->adapter;
  386. u16 action = le16_to_cpu(rfchannel->action);
  387. u16 newchannel = le16_to_cpu(rfchannel->currentchannel);
  388. ENTER();
  389. if (action == cmd_opt_802_11_rf_channel_get
  390. && adapter->curbssparams.channel != newchannel) {
  391. lbs_pr_debug(1, "channel Switch: %d to %d\n",
  392. adapter->curbssparams.channel, newchannel);
  393. /* Update the channel again */
  394. adapter->curbssparams.channel = newchannel;
  395. }
  396. LEAVE();
  397. return 0;
  398. }
  399. static int wlan_ret_802_11_rssi(wlan_private * priv,
  400. struct cmd_ds_command *resp)
  401. {
  402. struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
  403. wlan_adapter *adapter = priv->adapter;
  404. /* store the non average value */
  405. adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR);
  406. adapter->NF[TYPE_BEACON][TYPE_NOAVG] =
  407. le16_to_cpu(rssirsp->noisefloor);
  408. adapter->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR);
  409. adapter->NF[TYPE_BEACON][TYPE_AVG] =
  410. le16_to_cpu(rssirsp->avgnoisefloor);
  411. adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] =
  412. CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
  413. adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
  414. adapter->RSSI[TYPE_BEACON][TYPE_AVG] =
  415. CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
  416. adapter->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
  417. lbs_pr_debug(1, "Beacon RSSI value = 0x%x\n",
  418. adapter->RSSI[TYPE_BEACON][TYPE_AVG]);
  419. return 0;
  420. }
  421. static int wlan_ret_802_11_eeprom_access(wlan_private * priv,
  422. struct cmd_ds_command *resp)
  423. {
  424. wlan_adapter *adapter = priv->adapter;
  425. struct wlan_ioctl_regrdwr *pbuf;
  426. pbuf = (struct wlan_ioctl_regrdwr *) adapter->prdeeprom;
  427. lbs_pr_debug(1, "eeprom read len=%x\n",
  428. le16_to_cpu(resp->params.rdeeprom.bytecount));
  429. if (pbuf->NOB < le16_to_cpu(resp->params.rdeeprom.bytecount)) {
  430. pbuf->NOB = 0;
  431. lbs_pr_debug(1, "eeprom read return length is too big\n");
  432. return -1;
  433. }
  434. pbuf->NOB = le16_to_cpu(resp->params.rdeeprom.bytecount);
  435. if (pbuf->NOB > 0) {
  436. memcpy(&pbuf->value, (u8 *) & resp->params.rdeeprom.value,
  437. le16_to_cpu(resp->params.rdeeprom.bytecount));
  438. lbs_dbg_hex("adapter", (char *)&pbuf->value,
  439. le16_to_cpu(resp->params.rdeeprom.bytecount));
  440. }
  441. return 0;
  442. }
  443. static int wlan_ret_get_log(wlan_private * priv,
  444. struct cmd_ds_command *resp)
  445. {
  446. struct cmd_ds_802_11_get_log *logmessage =
  447. (struct cmd_ds_802_11_get_log *)&resp->params.glog;
  448. wlan_adapter *adapter = priv->adapter;
  449. ENTER();
  450. /* TODO Convert it to Big Endian before copy */
  451. memcpy(&adapter->logmsg, logmessage,
  452. sizeof(struct cmd_ds_802_11_get_log));
  453. LEAVE();
  454. return 0;
  455. }
  456. static inline int handle_cmd_response(u16 respcmd,
  457. struct cmd_ds_command *resp,
  458. wlan_private *priv)
  459. {
  460. int ret = 0;
  461. unsigned long flags;
  462. wlan_adapter *adapter = priv->adapter;
  463. switch (respcmd) {
  464. case cmd_ret_mac_reg_access:
  465. case cmd_ret_bbp_reg_access:
  466. case cmd_ret_rf_reg_access:
  467. ret = wlan_ret_reg_access(priv, respcmd, resp);
  468. break;
  469. case cmd_ret_hw_spec_info:
  470. ret = wlan_ret_get_hw_spec(priv, resp);
  471. break;
  472. case cmd_ret_802_11_scan:
  473. ret = libertas_ret_80211_scan(priv, resp);
  474. break;
  475. case cmd_ret_802_11_get_log:
  476. ret = wlan_ret_get_log(priv, resp);
  477. break;
  478. case cmd_ret_802_11_associate:
  479. case cmd_ret_802_11_reassociate:
  480. ret = libertas_ret_80211_associate(priv, resp);
  481. break;
  482. case cmd_ret_802_11_disassociate:
  483. case cmd_ret_802_11_deauthenticate:
  484. ret = libertas_ret_80211_disassociate(priv, resp);
  485. break;
  486. case cmd_ret_802_11_ad_hoc_start:
  487. case cmd_ret_802_11_ad_hoc_join:
  488. ret = libertas_ret_80211_ad_hoc_start(priv, resp);
  489. break;
  490. case cmd_ret_802_11_stat:
  491. ret = wlan_ret_802_11_stat(priv, resp);
  492. break;
  493. case cmd_ret_802_11_snmp_mib:
  494. ret = wlan_ret_802_11_snmp_mib(priv, resp);
  495. break;
  496. case cmd_ret_802_11_rf_tx_power:
  497. ret = wlan_ret_802_11_rf_tx_power(priv, resp);
  498. break;
  499. case cmd_ret_802_11_set_afc:
  500. case cmd_ret_802_11_get_afc:
  501. spin_lock_irqsave(&adapter->driver_lock, flags);
  502. memmove(adapter->cur_cmd->pdata_buf,
  503. &resp->params.afc,
  504. sizeof(struct cmd_ds_802_11_afc));
  505. spin_unlock_irqrestore(&adapter->driver_lock, flags);
  506. break;
  507. case cmd_ret_802_11_rf_antenna:
  508. ret = wlan_ret_802_11_rf_antenna(priv, resp);
  509. break;
  510. case cmd_ret_mac_multicast_adr:
  511. case cmd_ret_mac_control:
  512. case cmd_ret_802_11_set_wep:
  513. case cmd_ret_802_11_reset:
  514. case cmd_ret_802_11_authenticate:
  515. case cmd_ret_802_11_radio_control:
  516. case cmd_ret_802_11_beacon_stop:
  517. case cmd_ret_802_11_enable_rsn:
  518. break;
  519. case cmd_ret_802_11_data_rate:
  520. ret = wlan_ret_802_11_data_rate(priv, resp);
  521. break;
  522. case cmd_ret_802_11_rate_adapt_rateset:
  523. ret = wlan_ret_802_11_rate_adapt_rateset(priv, resp);
  524. break;
  525. case cmd_ret_802_11_rf_channel:
  526. ret = wlan_ret_802_11_rf_channel(priv, resp);
  527. break;
  528. case cmd_ret_802_11_rssi:
  529. ret = wlan_ret_802_11_rssi(priv, resp);
  530. break;
  531. case cmd_ret_802_11_mac_address:
  532. ret = wlan_ret_802_11_mac_address(priv, resp);
  533. break;
  534. case cmd_ret_802_11_ad_hoc_stop:
  535. ret = libertas_ret_80211_ad_hoc_stop(priv, resp);
  536. break;
  537. case cmd_ret_802_11_key_material:
  538. lbs_pr_debug(1, "CMD_RESP: KEY_MATERIAL command response\n");
  539. ret = wlan_ret_802_11_key_material(priv, resp);
  540. break;
  541. case cmd_ret_802_11_eeprom_access:
  542. ret = wlan_ret_802_11_eeprom_access(priv, resp);
  543. break;
  544. case cmd_ret_802_11d_domain_info:
  545. ret = libertas_ret_802_11d_domain_info(priv, resp);
  546. break;
  547. case cmd_ret_802_11_sleep_params:
  548. ret = wlan_ret_802_11_sleep_params(priv, resp);
  549. break;
  550. case cmd_ret_802_11_inactivity_timeout:
  551. spin_lock_irqsave(&adapter->driver_lock, flags);
  552. *((u16 *) adapter->cur_cmd->pdata_buf) =
  553. le16_to_cpu(resp->params.inactivity_timeout.timeout);
  554. spin_unlock_irqrestore(&adapter->driver_lock, flags);
  555. break;
  556. case cmd_ret_802_11_tpc_cfg:
  557. spin_lock_irqsave(&adapter->driver_lock, flags);
  558. memmove(adapter->cur_cmd->pdata_buf,
  559. &resp->params.tpccfg,
  560. sizeof(struct cmd_ds_802_11_tpc_cfg));
  561. spin_unlock_irqrestore(&adapter->driver_lock, flags);
  562. break;
  563. case cmd_ret_802_11_led_gpio_ctrl:
  564. spin_lock_irqsave(&adapter->driver_lock, flags);
  565. memmove(adapter->cur_cmd->pdata_buf,
  566. &resp->params.ledgpio,
  567. sizeof(struct cmd_ds_802_11_led_ctrl));
  568. spin_unlock_irqrestore(&adapter->driver_lock, flags);
  569. break;
  570. case cmd_ret_802_11_pwr_cfg:
  571. spin_lock_irqsave(&adapter->driver_lock, flags);
  572. memmove(adapter->cur_cmd->pdata_buf,
  573. &resp->params.pwrcfg,
  574. sizeof(struct cmd_ds_802_11_pwr_cfg));
  575. spin_unlock_irqrestore(&adapter->driver_lock, flags);
  576. break;
  577. case cmd_ret_get_tsf:
  578. spin_lock_irqsave(&adapter->driver_lock, flags);
  579. memcpy(priv->adapter->cur_cmd->pdata_buf,
  580. &resp->params.gettsf.tsfvalue, sizeof(u64));
  581. spin_unlock_irqrestore(&adapter->driver_lock, flags);
  582. break;
  583. case cmd_ret_bt_access:
  584. spin_lock_irqsave(&adapter->driver_lock, flags);
  585. if (adapter->cur_cmd->pdata_buf)
  586. memcpy(adapter->cur_cmd->pdata_buf,
  587. &resp->params.bt.addr1, 2 * ETH_ALEN);
  588. spin_unlock_irqrestore(&adapter->driver_lock, flags);
  589. break;
  590. case cmd_ret_fwt_access:
  591. spin_lock_irqsave(&adapter->driver_lock, flags);
  592. if (adapter->cur_cmd->pdata_buf)
  593. memcpy(adapter->cur_cmd->pdata_buf,
  594. &resp->params.fwt,
  595. sizeof(resp->params.fwt));
  596. spin_unlock_irqrestore(&adapter->driver_lock, flags);
  597. break;
  598. case cmd_ret_mesh_access:
  599. if (adapter->cur_cmd->pdata_buf)
  600. memcpy(adapter->cur_cmd->pdata_buf,
  601. &resp->params.mesh,
  602. sizeof(resp->params.mesh));
  603. break;
  604. case cmd_rte_802_11_tx_rate_query:
  605. priv->adapter->txrate = resp->params.txrate.txrate;
  606. break;
  607. default:
  608. lbs_pr_debug(1, "CMD_RESP: Unknown command response %#x\n",
  609. resp->command);
  610. break;
  611. }
  612. return ret;
  613. }
  614. int libertas_process_rx_command(wlan_private * priv)
  615. {
  616. u16 respcmd;
  617. struct cmd_ds_command *resp;
  618. wlan_adapter *adapter = priv->adapter;
  619. int ret = 0;
  620. ulong flags;
  621. u16 result;
  622. ENTER();
  623. lbs_pr_debug(1, "CMD_RESP: @ %lu\n", jiffies);
  624. /* Now we got response from FW, cancel the command timer */
  625. del_timer(&adapter->command_timer);
  626. mutex_lock(&adapter->lock);
  627. spin_lock_irqsave(&adapter->driver_lock, flags);
  628. if (!adapter->cur_cmd) {
  629. lbs_pr_debug(1, "CMD_RESP: NULL cur_cmd=%p\n", adapter->cur_cmd);
  630. ret = -1;
  631. spin_unlock_irqrestore(&adapter->driver_lock, flags);
  632. goto done;
  633. }
  634. resp = (struct cmd_ds_command *)(adapter->cur_cmd->bufvirtualaddr);
  635. lbs_dbg_hex("CMD_RESP:", adapter->cur_cmd->bufvirtualaddr,
  636. priv->wlan_dev.upld_len);
  637. respcmd = le16_to_cpu(resp->command);
  638. result = le16_to_cpu(resp->result);
  639. lbs_pr_debug(1, "CMD_RESP: %x result: %d length: %d\n", respcmd,
  640. result, priv->wlan_dev.upld_len);
  641. if (!(respcmd & 0x8000)) {
  642. lbs_pr_debug(1, "Invalid response to command!");
  643. adapter->cur_cmd_retcode = -1;
  644. __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
  645. adapter->nr_cmd_pending--;
  646. adapter->cur_cmd = NULL;
  647. spin_unlock_irqrestore(&adapter->driver_lock, flags);
  648. ret = -1;
  649. goto done;
  650. }
  651. /* Store the response code to cur_cmd_retcode. */
  652. adapter->cur_cmd_retcode = le16_to_cpu(resp->result);
  653. if (respcmd == cmd_ret_802_11_ps_mode) {
  654. struct cmd_ds_802_11_ps_mode *psmode;
  655. psmode = &resp->params.psmode;
  656. lbs_pr_debug(1,
  657. "CMD_RESP: PS_MODE cmd reply result=%#x action=0x%X\n",
  658. resp->result, psmode->action);
  659. psmode->action = cpu_to_le16(psmode->action);
  660. if (result) {
  661. lbs_pr_debug(1, "CMD_RESP: PS command failed- %#x \n",
  662. resp->result);
  663. if (adapter->mode == IW_MODE_ADHOC) {
  664. /*
  665. * We should not re-try enter-ps command in
  666. * ad-hoc mode. It takes place in
  667. * libertas_execute_next_command().
  668. */
  669. if (psmode->action == cmd_subcmd_enter_ps)
  670. adapter->psmode =
  671. wlan802_11powermodecam;
  672. }
  673. } else if (psmode->action == cmd_subcmd_enter_ps) {
  674. adapter->needtowakeup = 0;
  675. adapter->psstate = PS_STATE_AWAKE;
  676. lbs_pr_debug(1, "CMD_RESP: Enter_PS command response\n");
  677. if (adapter->connect_status != libertas_connected) {
  678. /*
  679. * When Deauth Event received before Enter_PS command
  680. * response, We need to wake up the firmware.
  681. */
  682. lbs_pr_debug(1,
  683. "Disconnected, Going to invoke libertas_ps_wakeup\n");
  684. mutex_unlock(&adapter->lock);
  685. spin_unlock_irqrestore(&adapter->driver_lock, flags);
  686. libertas_ps_wakeup(priv, 0);
  687. mutex_lock(&adapter->lock);
  688. spin_lock_irqsave(&adapter->driver_lock, flags);
  689. }
  690. } else if (psmode->action == cmd_subcmd_exit_ps) {
  691. adapter->needtowakeup = 0;
  692. adapter->psstate = PS_STATE_FULL_POWER;
  693. lbs_pr_debug(1, "CMD_RESP: Exit_PS command response\n");
  694. } else {
  695. lbs_pr_debug(1, "CMD_RESP: PS- action=0x%X\n",
  696. psmode->action);
  697. }
  698. __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
  699. adapter->nr_cmd_pending--;
  700. adapter->cur_cmd = NULL;
  701. spin_unlock_irqrestore(&adapter->driver_lock, flags);
  702. ret = 0;
  703. goto done;
  704. }
  705. if (adapter->cur_cmd->cmdflags & CMD_F_HOSTCMD) {
  706. /* Copy the response back to response buffer */
  707. memcpy(adapter->cur_cmd->pdata_buf, resp, resp->size);
  708. adapter->cur_cmd->cmdflags &= ~CMD_F_HOSTCMD;
  709. }
  710. /* If the command is not successful, cleanup and return failure */
  711. if ((result != 0 || !(respcmd & 0x8000))) {
  712. lbs_pr_debug(1, "CMD_RESP: command reply %#x result=%#x\n",
  713. resp->command, resp->result);
  714. /*
  715. * Handling errors here
  716. */
  717. switch (respcmd) {
  718. case cmd_ret_hw_spec_info:
  719. case cmd_ret_802_11_reset:
  720. lbs_pr_debug(1, "CMD_RESP: Reset command failed\n");
  721. break;
  722. }
  723. __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
  724. adapter->nr_cmd_pending--;
  725. adapter->cur_cmd = NULL;
  726. spin_unlock_irqrestore(&adapter->driver_lock, flags);
  727. ret = -1;
  728. goto done;
  729. }
  730. spin_unlock_irqrestore(&adapter->driver_lock, flags);
  731. ret = handle_cmd_response(respcmd, resp, priv);
  732. spin_lock_irqsave(&adapter->driver_lock, flags);
  733. if (adapter->cur_cmd) {
  734. /* Clean up and Put current command back to cmdfreeq */
  735. __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
  736. adapter->nr_cmd_pending--;
  737. WARN_ON(adapter->nr_cmd_pending > 128);
  738. adapter->cur_cmd = NULL;
  739. }
  740. spin_unlock_irqrestore(&adapter->driver_lock, flags);
  741. done:
  742. mutex_unlock(&adapter->lock);
  743. LEAVE();
  744. return ret;
  745. }
  746. int libertas_process_event(wlan_private * priv)
  747. {
  748. int ret = 0;
  749. wlan_adapter *adapter = priv->adapter;
  750. u32 eventcause;
  751. spin_lock_irq(&adapter->driver_lock);
  752. eventcause = adapter->eventcause;
  753. spin_unlock_irq(&adapter->driver_lock);
  754. ENTER();
  755. lbs_pr_debug(1, "EVENT Cause %x\n", eventcause);
  756. switch (eventcause >> SBI_EVENT_CAUSE_SHIFT) {
  757. case MACREG_INT_CODE_LINK_SENSED:
  758. lbs_pr_debug(1, "EVENT: MACREG_INT_CODE_LINK_SENSED\n");
  759. break;
  760. case MACREG_INT_CODE_DEAUTHENTICATED:
  761. lbs_pr_debug(1, "EVENT: Deauthenticated\n");
  762. libertas_mac_event_disconnected(priv);
  763. break;
  764. case MACREG_INT_CODE_DISASSOCIATED:
  765. lbs_pr_debug(1, "EVENT: Disassociated\n");
  766. libertas_mac_event_disconnected(priv);
  767. break;
  768. case MACREG_INT_CODE_LINK_LOSE_NO_SCAN:
  769. lbs_pr_debug(1, "EVENT: Link lost\n");
  770. libertas_mac_event_disconnected(priv);
  771. break;
  772. case MACREG_INT_CODE_PS_SLEEP:
  773. lbs_pr_debug(1, "EVENT: SLEEP\n");
  774. lbs_pr_debug(1, "_");
  775. /* handle unexpected PS SLEEP event */
  776. if (adapter->psstate == PS_STATE_FULL_POWER) {
  777. lbs_pr_debug(1,
  778. "EVENT: In FULL POWER mode - ignore PS SLEEP\n");
  779. break;
  780. }
  781. adapter->psstate = PS_STATE_PRE_SLEEP;
  782. libertas_ps_confirm_sleep(priv, (u16) adapter->psmode);
  783. break;
  784. case MACREG_INT_CODE_PS_AWAKE:
  785. lbs_pr_debug(1, "EVENT: AWAKE \n");
  786. lbs_pr_debug(1, "|");
  787. /* handle unexpected PS AWAKE event */
  788. if (adapter->psstate == PS_STATE_FULL_POWER) {
  789. lbs_pr_debug(1,
  790. "EVENT: In FULL POWER mode - ignore PS AWAKE\n");
  791. break;
  792. }
  793. adapter->psstate = PS_STATE_AWAKE;
  794. if (adapter->needtowakeup) {
  795. /*
  796. * wait for the command processing to finish
  797. * before resuming sending
  798. * adapter->needtowakeup will be set to FALSE
  799. * in libertas_ps_wakeup()
  800. */
  801. lbs_pr_debug(1, "Waking up...\n");
  802. libertas_ps_wakeup(priv, 0);
  803. }
  804. break;
  805. case MACREG_INT_CODE_MIC_ERR_UNICAST:
  806. lbs_pr_debug(1, "EVENT: UNICAST MIC ERROR\n");
  807. handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST);
  808. break;
  809. case MACREG_INT_CODE_MIC_ERR_MULTICAST:
  810. lbs_pr_debug(1, "EVENT: MULTICAST MIC ERROR\n");
  811. handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
  812. break;
  813. case MACREG_INT_CODE_MIB_CHANGED:
  814. case MACREG_INT_CODE_INIT_DONE:
  815. break;
  816. case MACREG_INT_CODE_ADHOC_BCN_LOST:
  817. lbs_pr_debug(1, "EVENT: HWAC - ADHOC BCN LOST\n");
  818. break;
  819. case MACREG_INT_CODE_RSSI_LOW:
  820. lbs_pr_alert( "EVENT: RSSI_LOW\n");
  821. break;
  822. case MACREG_INT_CODE_SNR_LOW:
  823. lbs_pr_alert( "EVENT: SNR_LOW\n");
  824. break;
  825. case MACREG_INT_CODE_MAX_FAIL:
  826. lbs_pr_alert( "EVENT: MAX_FAIL\n");
  827. break;
  828. case MACREG_INT_CODE_RSSI_HIGH:
  829. lbs_pr_alert( "EVENT: RSSI_HIGH\n");
  830. break;
  831. case MACREG_INT_CODE_SNR_HIGH:
  832. lbs_pr_alert( "EVENT: SNR_HIGH\n");
  833. break;
  834. default:
  835. lbs_pr_alert( "EVENT: unknown event id: %#x\n",
  836. eventcause >> SBI_EVENT_CAUSE_SHIFT);
  837. break;
  838. }
  839. spin_lock_irq(&adapter->driver_lock);
  840. adapter->eventcause = 0;
  841. spin_unlock_irq(&adapter->driver_lock);
  842. LEAVE();
  843. return ret;
  844. }