cmdresp.c 27 KB

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