cmdresp.c 27 KB

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