cmdresp.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  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 struct lbs_private structure
  21. * @return n/a
  22. */
  23. void lbs_mac_event_disconnected(struct lbs_private *priv)
  24. {
  25. union iwreq_data wrqu;
  26. if (priv->connect_status != LBS_CONNECTED)
  27. return;
  28. lbs_deb_enter(LBS_DEB_ASSOC);
  29. memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
  30. wrqu.ap_addr.sa_family = ARPHRD_ETHER;
  31. /*
  32. * Cisco AP sends EAP failure and de-auth in less than 0.5 ms.
  33. * It causes problem in the Supplicant
  34. */
  35. msleep_interruptible(1000);
  36. wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
  37. /* Free Tx and Rx packets */
  38. kfree_skb(priv->currenttxskb);
  39. priv->currenttxskb = NULL;
  40. /* report disconnect to upper layer */
  41. netif_stop_queue(priv->dev);
  42. netif_carrier_off(priv->dev);
  43. /* reset SNR/NF/RSSI values */
  44. memset(priv->SNR, 0x00, sizeof(priv->SNR));
  45. memset(priv->NF, 0x00, sizeof(priv->NF));
  46. memset(priv->RSSI, 0x00, sizeof(priv->RSSI));
  47. memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
  48. memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
  49. priv->nextSNRNF = 0;
  50. priv->numSNRNF = 0;
  51. priv->connect_status = LBS_DISCONNECTED;
  52. /* Clear out associated SSID and BSSID since connection is
  53. * no longer valid.
  54. */
  55. memset(&priv->curbssparams.bssid, 0, ETH_ALEN);
  56. memset(&priv->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE);
  57. priv->curbssparams.ssid_len = 0;
  58. if (priv->psstate != PS_STATE_FULL_POWER) {
  59. /* make firmware to exit PS mode */
  60. lbs_deb_cmd("disconnected, so exit PS mode\n");
  61. lbs_ps_wakeup(priv, 0);
  62. }
  63. lbs_deb_leave(LBS_DEB_CMD);
  64. }
  65. /**
  66. * @brief This function handles MIC failure event.
  67. *
  68. * @param priv A pointer to struct lbs_private structure
  69. * @para event the event id
  70. * @return n/a
  71. */
  72. static void handle_mic_failureevent(struct lbs_private *priv, u32 event)
  73. {
  74. char buf[50];
  75. lbs_deb_enter(LBS_DEB_CMD);
  76. memset(buf, 0, sizeof(buf));
  77. sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
  78. if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) {
  79. strcat(buf, "unicast ");
  80. } else {
  81. strcat(buf, "multicast ");
  82. }
  83. lbs_send_iwevcustom_event(priv, buf);
  84. lbs_deb_leave(LBS_DEB_CMD);
  85. }
  86. static int lbs_ret_reg_access(struct lbs_private *priv,
  87. u16 type, struct cmd_ds_command *resp)
  88. {
  89. int ret = 0;
  90. lbs_deb_enter(LBS_DEB_CMD);
  91. switch (type) {
  92. case CMD_RET(CMD_MAC_REG_ACCESS):
  93. {
  94. struct cmd_ds_mac_reg_access *reg = &resp->params.macreg;
  95. priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
  96. priv->offsetvalue.value = le32_to_cpu(reg->value);
  97. break;
  98. }
  99. case CMD_RET(CMD_BBP_REG_ACCESS):
  100. {
  101. struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg;
  102. priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
  103. priv->offsetvalue.value = reg->value;
  104. break;
  105. }
  106. case CMD_RET(CMD_RF_REG_ACCESS):
  107. {
  108. struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg;
  109. priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
  110. priv->offsetvalue.value = reg->value;
  111. break;
  112. }
  113. default:
  114. ret = -1;
  115. }
  116. lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
  117. return ret;
  118. }
  119. static int lbs_ret_get_hw_spec(struct lbs_private *priv,
  120. struct cmd_ds_command *resp)
  121. {
  122. u32 i;
  123. struct cmd_ds_get_hw_spec *hwspec = &resp->params.hwspec;
  124. int ret = 0;
  125. DECLARE_MAC_BUF(mac);
  126. lbs_deb_enter(LBS_DEB_CMD);
  127. priv->fwcapinfo = le32_to_cpu(hwspec->fwcapinfo);
  128. memcpy(priv->fwreleasenumber, hwspec->fwreleasenumber, 4);
  129. lbs_deb_cmd("GET_HW_SPEC: firmware release %u.%u.%up%u\n",
  130. priv->fwreleasenumber[2], priv->fwreleasenumber[1],
  131. priv->fwreleasenumber[0], priv->fwreleasenumber[3]);
  132. lbs_deb_cmd("GET_HW_SPEC: MAC addr %s\n",
  133. print_mac(mac, hwspec->permanentaddr));
  134. lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
  135. hwspec->hwifversion, hwspec->version);
  136. /* Clamp region code to 8-bit since FW spec indicates that it should
  137. * only ever be 8-bit, even though the field size is 16-bit. Some firmware
  138. * returns non-zero high 8 bits here.
  139. */
  140. priv->regioncode = le16_to_cpu(hwspec->regioncode) & 0xFF;
  141. for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
  142. /* use the region code to search for the index */
  143. if (priv->regioncode == lbs_region_code_to_index[i]) {
  144. break;
  145. }
  146. }
  147. /* if it's unidentified region code, use the default (USA) */
  148. if (i >= MRVDRV_MAX_REGION_CODE) {
  149. priv->regioncode = 0x10;
  150. lbs_pr_info("unidentified region code; using the default (USA)\n");
  151. }
  152. if (priv->current_addr[0] == 0xff)
  153. memmove(priv->current_addr, hwspec->permanentaddr, ETH_ALEN);
  154. memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN);
  155. if (priv->mesh_dev)
  156. memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
  157. if (lbs_set_regiontable(priv, priv->regioncode, 0)) {
  158. ret = -1;
  159. goto done;
  160. }
  161. if (lbs_set_universaltable(priv, 0)) {
  162. ret = -1;
  163. goto done;
  164. }
  165. done:
  166. lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
  167. return ret;
  168. }
  169. static int lbs_ret_802_11_sleep_params(struct lbs_private *priv,
  170. struct cmd_ds_command *resp)
  171. {
  172. struct cmd_ds_802_11_sleep_params *sp = &resp->params.sleep_params;
  173. lbs_deb_enter(LBS_DEB_CMD);
  174. lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, calcontrol 0x%x "
  175. "extsleepclk 0x%x\n", le16_to_cpu(sp->error),
  176. le16_to_cpu(sp->offset), le16_to_cpu(sp->stabletime),
  177. sp->calcontrol, sp->externalsleepclk);
  178. priv->sp.sp_error = le16_to_cpu(sp->error);
  179. priv->sp.sp_offset = le16_to_cpu(sp->offset);
  180. priv->sp.sp_stabletime = le16_to_cpu(sp->stabletime);
  181. priv->sp.sp_calcontrol = sp->calcontrol;
  182. priv->sp.sp_extsleepclk = sp->externalsleepclk;
  183. priv->sp.sp_reserved = le16_to_cpu(sp->reserved);
  184. lbs_deb_enter(LBS_DEB_CMD);
  185. return 0;
  186. }
  187. static int lbs_ret_802_11_stat(struct lbs_private *priv,
  188. struct cmd_ds_command *resp)
  189. {
  190. lbs_deb_enter(LBS_DEB_CMD);
  191. /* currently priv->wlan802_11Stat is unused
  192. struct cmd_ds_802_11_get_stat *p11Stat = &resp->params.gstat;
  193. // TODO Convert it to Big endian befor copy
  194. memcpy(&priv->wlan802_11Stat,
  195. p11Stat, sizeof(struct cmd_ds_802_11_get_stat));
  196. */
  197. lbs_deb_leave(LBS_DEB_CMD);
  198. return 0;
  199. }
  200. static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv,
  201. struct cmd_ds_command *resp)
  202. {
  203. struct cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
  204. u16 oid = le16_to_cpu(smib->oid);
  205. u16 querytype = le16_to_cpu(smib->querytype);
  206. lbs_deb_enter(LBS_DEB_CMD);
  207. lbs_deb_cmd("SNMP_RESP: oid 0x%x, querytype 0x%x\n", oid,
  208. querytype);
  209. lbs_deb_cmd("SNMP_RESP: Buf size %d\n", le16_to_cpu(smib->bufsize));
  210. if (querytype == CMD_ACT_GET) {
  211. switch (oid) {
  212. case FRAGTHRESH_I:
  213. priv->fragthsd =
  214. le16_to_cpu(*((__le16 *)(smib->value)));
  215. lbs_deb_cmd("SNMP_RESP: frag threshold %u\n",
  216. priv->fragthsd);
  217. break;
  218. case RTSTHRESH_I:
  219. priv->rtsthsd =
  220. le16_to_cpu(*((__le16 *)(smib->value)));
  221. lbs_deb_cmd("SNMP_RESP: rts threshold %u\n",
  222. priv->rtsthsd);
  223. break;
  224. case SHORT_RETRYLIM_I:
  225. priv->txretrycount =
  226. le16_to_cpu(*((__le16 *)(smib->value)));
  227. lbs_deb_cmd("SNMP_RESP: tx retry count %u\n",
  228. priv->rtsthsd);
  229. break;
  230. default:
  231. break;
  232. }
  233. }
  234. lbs_deb_enter(LBS_DEB_CMD);
  235. return 0;
  236. }
  237. static int lbs_ret_802_11_key_material(struct lbs_private *priv,
  238. struct cmd_ds_command *resp)
  239. {
  240. struct cmd_ds_802_11_key_material *pkeymaterial =
  241. &resp->params.keymaterial;
  242. u16 action = le16_to_cpu(pkeymaterial->action);
  243. lbs_deb_enter(LBS_DEB_CMD);
  244. /* Copy the returned key to driver private data */
  245. if (action == CMD_ACT_GET) {
  246. u8 * buf_ptr = (u8 *) &pkeymaterial->keyParamSet;
  247. u8 * resp_end = (u8 *) (resp + le16_to_cpu(resp->size));
  248. while (buf_ptr < resp_end) {
  249. struct MrvlIEtype_keyParamSet * pkeyparamset =
  250. (struct MrvlIEtype_keyParamSet *) buf_ptr;
  251. struct enc_key * pkey;
  252. u16 param_set_len = le16_to_cpu(pkeyparamset->length);
  253. u16 key_len = le16_to_cpu(pkeyparamset->keylen);
  254. u16 key_flags = le16_to_cpu(pkeyparamset->keyinfo);
  255. u16 key_type = le16_to_cpu(pkeyparamset->keytypeid);
  256. u8 * end;
  257. end = (u8 *) pkeyparamset + sizeof (pkeyparamset->type)
  258. + sizeof (pkeyparamset->length)
  259. + param_set_len;
  260. /* Make sure we don't access past the end of the IEs */
  261. if (end > resp_end)
  262. break;
  263. if (key_flags & KEY_INFO_WPA_UNICAST)
  264. pkey = &priv->wpa_unicast_key;
  265. else if (key_flags & KEY_INFO_WPA_MCAST)
  266. pkey = &priv->wpa_mcast_key;
  267. else
  268. break;
  269. /* Copy returned key into driver */
  270. memset(pkey, 0, sizeof(struct enc_key));
  271. if (key_len > sizeof(pkey->key))
  272. break;
  273. pkey->type = key_type;
  274. pkey->flags = key_flags;
  275. pkey->len = key_len;
  276. memcpy(pkey->key, pkeyparamset->key, pkey->len);
  277. buf_ptr = end + 1;
  278. }
  279. }
  280. lbs_deb_enter(LBS_DEB_CMD);
  281. return 0;
  282. }
  283. static int lbs_ret_802_11_mac_address(struct lbs_private *priv,
  284. struct cmd_ds_command *resp)
  285. {
  286. struct cmd_ds_802_11_mac_address *macadd = &resp->params.macadd;
  287. lbs_deb_enter(LBS_DEB_CMD);
  288. memcpy(priv->current_addr, macadd->macadd, ETH_ALEN);
  289. lbs_deb_enter(LBS_DEB_CMD);
  290. return 0;
  291. }
  292. static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv,
  293. struct cmd_ds_command *resp)
  294. {
  295. struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp;
  296. lbs_deb_enter(LBS_DEB_CMD);
  297. priv->txpowerlevel = le16_to_cpu(rtp->currentlevel);
  298. lbs_deb_cmd("TX power currently %d\n", priv->txpowerlevel);
  299. lbs_deb_leave(LBS_DEB_CMD);
  300. return 0;
  301. }
  302. static int lbs_ret_802_11_rate_adapt_rateset(struct lbs_private *priv,
  303. struct cmd_ds_command *resp)
  304. {
  305. struct cmd_ds_802_11_rate_adapt_rateset *rates = &resp->params.rateset;
  306. lbs_deb_enter(LBS_DEB_CMD);
  307. if (rates->action == CMD_ACT_GET) {
  308. priv->enablehwauto = le16_to_cpu(rates->enablehwauto);
  309. priv->ratebitmap = le16_to_cpu(rates->bitmap);
  310. }
  311. lbs_deb_leave(LBS_DEB_CMD);
  312. return 0;
  313. }
  314. static int lbs_ret_802_11_data_rate(struct lbs_private *priv,
  315. struct cmd_ds_command *resp)
  316. {
  317. struct cmd_ds_802_11_data_rate *pdatarate = &resp->params.drate;
  318. lbs_deb_enter(LBS_DEB_CMD);
  319. lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) pdatarate,
  320. sizeof(struct cmd_ds_802_11_data_rate));
  321. /* FIXME: get actual rates FW can do if this command actually returns
  322. * all data rates supported.
  323. */
  324. priv->cur_rate = lbs_fw_index_to_data_rate(pdatarate->rates[0]);
  325. lbs_deb_cmd("DATA_RATE: current rate 0x%02x\n", priv->cur_rate);
  326. lbs_deb_leave(LBS_DEB_CMD);
  327. return 0;
  328. }
  329. static int lbs_ret_802_11_rf_channel(struct lbs_private *priv,
  330. struct cmd_ds_command *resp)
  331. {
  332. struct cmd_ds_802_11_rf_channel *rfchannel = &resp->params.rfchannel;
  333. u16 action = le16_to_cpu(rfchannel->action);
  334. u16 newchannel = le16_to_cpu(rfchannel->currentchannel);
  335. lbs_deb_enter(LBS_DEB_CMD);
  336. if (action == CMD_OPT_802_11_RF_CHANNEL_GET
  337. && priv->curbssparams.channel != newchannel) {
  338. lbs_deb_cmd("channel switch from %d to %d\n",
  339. priv->curbssparams.channel, newchannel);
  340. /* Update the channel again */
  341. priv->curbssparams.channel = newchannel;
  342. }
  343. lbs_deb_enter(LBS_DEB_CMD);
  344. return 0;
  345. }
  346. static int lbs_ret_802_11_rssi(struct lbs_private *priv,
  347. struct cmd_ds_command *resp)
  348. {
  349. struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
  350. lbs_deb_enter(LBS_DEB_CMD);
  351. /* store the non average value */
  352. priv->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR);
  353. priv->NF[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->noisefloor);
  354. priv->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR);
  355. priv->NF[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgnoisefloor);
  356. priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
  357. CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
  358. priv->NF[TYPE_BEACON][TYPE_NOAVG]);
  359. priv->RSSI[TYPE_BEACON][TYPE_AVG] =
  360. CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
  361. priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
  362. lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
  363. priv->RSSI[TYPE_BEACON][TYPE_NOAVG],
  364. priv->RSSI[TYPE_BEACON][TYPE_AVG]);
  365. lbs_deb_leave(LBS_DEB_CMD);
  366. return 0;
  367. }
  368. static int lbs_ret_802_11_eeprom_access(struct lbs_private *priv,
  369. struct cmd_ds_command *resp)
  370. {
  371. struct lbs_ioctl_regrdwr *pbuf;
  372. pbuf = (struct lbs_ioctl_regrdwr *) priv->prdeeprom;
  373. lbs_deb_enter_args(LBS_DEB_CMD, "len %d",
  374. le16_to_cpu(resp->params.rdeeprom.bytecount));
  375. if (pbuf->NOB < le16_to_cpu(resp->params.rdeeprom.bytecount)) {
  376. pbuf->NOB = 0;
  377. lbs_deb_cmd("EEPROM read length too big\n");
  378. return -1;
  379. }
  380. pbuf->NOB = le16_to_cpu(resp->params.rdeeprom.bytecount);
  381. if (pbuf->NOB > 0) {
  382. memcpy(&pbuf->value, (u8 *) & resp->params.rdeeprom.value,
  383. le16_to_cpu(resp->params.rdeeprom.bytecount));
  384. lbs_deb_hex(LBS_DEB_CMD, "EEPROM", (char *)&pbuf->value,
  385. le16_to_cpu(resp->params.rdeeprom.bytecount));
  386. }
  387. lbs_deb_leave(LBS_DEB_CMD);
  388. return 0;
  389. }
  390. static int lbs_ret_get_log(struct lbs_private *priv,
  391. struct cmd_ds_command *resp)
  392. {
  393. struct cmd_ds_802_11_get_log *logmessage = &resp->params.glog;
  394. lbs_deb_enter(LBS_DEB_CMD);
  395. /* Stored little-endian */
  396. memcpy(&priv->logmsg, logmessage, sizeof(struct cmd_ds_802_11_get_log));
  397. lbs_deb_leave(LBS_DEB_CMD);
  398. return 0;
  399. }
  400. static int lbs_ret_802_11_enable_rsn(struct lbs_private *priv,
  401. struct cmd_ds_command *resp)
  402. {
  403. struct cmd_ds_802_11_enable_rsn *enable_rsn = &resp->params.enbrsn;
  404. u32 * pdata_buf = priv->cur_cmd->pdata_buf;
  405. lbs_deb_enter(LBS_DEB_CMD);
  406. if (enable_rsn->action == cpu_to_le16(CMD_ACT_GET)) {
  407. if (pdata_buf)
  408. *pdata_buf = (u32) le16_to_cpu(enable_rsn->enable);
  409. }
  410. lbs_deb_leave(LBS_DEB_CMD);
  411. return 0;
  412. }
  413. static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
  414. struct cmd_ds_command *resp)
  415. {
  416. struct cmd_ds_802_11_beacon_control *bcn_ctrl =
  417. &resp->params.bcn_ctrl;
  418. lbs_deb_enter(LBS_DEB_CMD);
  419. if (bcn_ctrl->action == CMD_ACT_GET) {
  420. priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable);
  421. priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period);
  422. }
  423. lbs_deb_enter(LBS_DEB_CMD);
  424. return 0;
  425. }
  426. static int lbs_ret_802_11_subscribe_event(struct lbs_private *priv,
  427. struct cmd_ds_command *resp)
  428. {
  429. struct cmd_ds_802_11_subscribe_event *cmd_event =
  430. &resp->params.subscribe_event;
  431. struct cmd_ds_802_11_subscribe_event *dst_event =
  432. priv->cur_cmd->pdata_buf;
  433. lbs_deb_enter(LBS_DEB_CMD);
  434. if (dst_event->action == cpu_to_le16(CMD_ACT_GET)) {
  435. dst_event->events = cmd_event->events;
  436. memcpy(dst_event->tlv, cmd_event->tlv, sizeof(dst_event->tlv));
  437. }
  438. lbs_deb_leave(LBS_DEB_CMD);
  439. return 0;
  440. }
  441. static inline int handle_cmd_response(u16 respcmd,
  442. struct cmd_ds_command *resp,
  443. struct lbs_private *priv)
  444. {
  445. int ret = 0;
  446. unsigned long flags;
  447. lbs_deb_enter(LBS_DEB_HOST);
  448. switch (respcmd) {
  449. case CMD_RET(CMD_MAC_REG_ACCESS):
  450. case CMD_RET(CMD_BBP_REG_ACCESS):
  451. case CMD_RET(CMD_RF_REG_ACCESS):
  452. ret = lbs_ret_reg_access(priv, respcmd, resp);
  453. break;
  454. case CMD_RET(CMD_GET_HW_SPEC):
  455. ret = lbs_ret_get_hw_spec(priv, resp);
  456. break;
  457. case CMD_RET(CMD_802_11_SCAN):
  458. ret = lbs_ret_80211_scan(priv, resp);
  459. break;
  460. case CMD_RET(CMD_802_11_GET_LOG):
  461. ret = lbs_ret_get_log(priv, resp);
  462. break;
  463. case CMD_RET_802_11_ASSOCIATE:
  464. case CMD_RET(CMD_802_11_ASSOCIATE):
  465. case CMD_RET(CMD_802_11_REASSOCIATE):
  466. ret = lbs_ret_80211_associate(priv, resp);
  467. break;
  468. case CMD_RET(CMD_802_11_DISASSOCIATE):
  469. case CMD_RET(CMD_802_11_DEAUTHENTICATE):
  470. ret = lbs_ret_80211_disassociate(priv, resp);
  471. break;
  472. case CMD_RET(CMD_802_11_AD_HOC_START):
  473. case CMD_RET(CMD_802_11_AD_HOC_JOIN):
  474. ret = lbs_ret_80211_ad_hoc_start(priv, resp);
  475. break;
  476. case CMD_RET(CMD_802_11_GET_STAT):
  477. ret = lbs_ret_802_11_stat(priv, resp);
  478. break;
  479. case CMD_RET(CMD_802_11_SNMP_MIB):
  480. ret = lbs_ret_802_11_snmp_mib(priv, resp);
  481. break;
  482. case CMD_RET(CMD_802_11_RF_TX_POWER):
  483. ret = lbs_ret_802_11_rf_tx_power(priv, resp);
  484. break;
  485. case CMD_RET(CMD_802_11_SET_AFC):
  486. case CMD_RET(CMD_802_11_GET_AFC):
  487. spin_lock_irqsave(&priv->driver_lock, flags);
  488. memmove(priv->cur_cmd->pdata_buf, &resp->params.afc,
  489. sizeof(struct cmd_ds_802_11_afc));
  490. spin_unlock_irqrestore(&priv->driver_lock, flags);
  491. break;
  492. case CMD_RET(CMD_MAC_MULTICAST_ADR):
  493. case CMD_RET(CMD_MAC_CONTROL):
  494. case CMD_RET(CMD_802_11_SET_WEP):
  495. case CMD_RET(CMD_802_11_RESET):
  496. case CMD_RET(CMD_802_11_AUTHENTICATE):
  497. case CMD_RET(CMD_802_11_RADIO_CONTROL):
  498. case CMD_RET(CMD_802_11_BEACON_STOP):
  499. break;
  500. case CMD_RET(CMD_802_11_ENABLE_RSN):
  501. ret = lbs_ret_802_11_enable_rsn(priv, resp);
  502. break;
  503. case CMD_RET(CMD_802_11_DATA_RATE):
  504. ret = lbs_ret_802_11_data_rate(priv, resp);
  505. break;
  506. case CMD_RET(CMD_802_11_RATE_ADAPT_RATESET):
  507. ret = lbs_ret_802_11_rate_adapt_rateset(priv, resp);
  508. break;
  509. case CMD_RET(CMD_802_11_RF_CHANNEL):
  510. ret = lbs_ret_802_11_rf_channel(priv, resp);
  511. break;
  512. case CMD_RET(CMD_802_11_RSSI):
  513. ret = lbs_ret_802_11_rssi(priv, resp);
  514. break;
  515. case CMD_RET(CMD_802_11_MAC_ADDRESS):
  516. ret = lbs_ret_802_11_mac_address(priv, resp);
  517. break;
  518. case CMD_RET(CMD_802_11_AD_HOC_STOP):
  519. ret = lbs_ret_80211_ad_hoc_stop(priv, resp);
  520. break;
  521. case CMD_RET(CMD_802_11_KEY_MATERIAL):
  522. ret = lbs_ret_802_11_key_material(priv, resp);
  523. break;
  524. case CMD_RET(CMD_802_11_EEPROM_ACCESS):
  525. ret = lbs_ret_802_11_eeprom_access(priv, resp);
  526. break;
  527. case CMD_RET(CMD_802_11D_DOMAIN_INFO):
  528. ret = lbs_ret_802_11d_domain_info(priv, resp);
  529. break;
  530. case CMD_RET(CMD_802_11_SLEEP_PARAMS):
  531. ret = lbs_ret_802_11_sleep_params(priv, resp);
  532. break;
  533. case CMD_RET(CMD_802_11_INACTIVITY_TIMEOUT):
  534. spin_lock_irqsave(&priv->driver_lock, flags);
  535. *((u16 *) priv->cur_cmd->pdata_buf) =
  536. le16_to_cpu(resp->params.inactivity_timeout.timeout);
  537. spin_unlock_irqrestore(&priv->driver_lock, flags);
  538. break;
  539. case CMD_RET(CMD_802_11_TPC_CFG):
  540. spin_lock_irqsave(&priv->driver_lock, flags);
  541. memmove(priv->cur_cmd->pdata_buf, &resp->params.tpccfg,
  542. sizeof(struct cmd_ds_802_11_tpc_cfg));
  543. spin_unlock_irqrestore(&priv->driver_lock, flags);
  544. break;
  545. case CMD_RET(CMD_802_11_LED_GPIO_CTRL):
  546. spin_lock_irqsave(&priv->driver_lock, flags);
  547. memmove(priv->cur_cmd->pdata_buf, &resp->params.ledgpio,
  548. sizeof(struct cmd_ds_802_11_led_ctrl));
  549. spin_unlock_irqrestore(&priv->driver_lock, flags);
  550. break;
  551. case CMD_RET(CMD_802_11_SUBSCRIBE_EVENT):
  552. ret = lbs_ret_802_11_subscribe_event(priv, resp);
  553. break;
  554. case CMD_RET(CMD_802_11_PWR_CFG):
  555. spin_lock_irqsave(&priv->driver_lock, flags);
  556. memmove(priv->cur_cmd->pdata_buf, &resp->params.pwrcfg,
  557. sizeof(struct cmd_ds_802_11_pwr_cfg));
  558. spin_unlock_irqrestore(&priv->driver_lock, flags);
  559. break;
  560. case CMD_RET(CMD_GET_TSF):
  561. spin_lock_irqsave(&priv->driver_lock, flags);
  562. memcpy(priv->cur_cmd->pdata_buf,
  563. &resp->params.gettsf.tsfvalue, sizeof(u64));
  564. spin_unlock_irqrestore(&priv->driver_lock, flags);
  565. break;
  566. case CMD_RET(CMD_BT_ACCESS):
  567. spin_lock_irqsave(&priv->driver_lock, flags);
  568. if (priv->cur_cmd->pdata_buf)
  569. memcpy(priv->cur_cmd->pdata_buf,
  570. &resp->params.bt.addr1, 2 * ETH_ALEN);
  571. spin_unlock_irqrestore(&priv->driver_lock, flags);
  572. break;
  573. case CMD_RET(CMD_FWT_ACCESS):
  574. spin_lock_irqsave(&priv->driver_lock, flags);
  575. if (priv->cur_cmd->pdata_buf)
  576. memcpy(priv->cur_cmd->pdata_buf, &resp->params.fwt,
  577. sizeof(resp->params.fwt));
  578. spin_unlock_irqrestore(&priv->driver_lock, flags);
  579. break;
  580. case CMD_RET(CMD_MESH_ACCESS):
  581. if (priv->cur_cmd->pdata_buf)
  582. memcpy(priv->cur_cmd->pdata_buf, &resp->params.mesh,
  583. sizeof(resp->params.mesh));
  584. break;
  585. case CMD_RET(CMD_802_11_BEACON_CTRL):
  586. ret = lbs_ret_802_11_bcn_ctrl(priv, resp);
  587. break;
  588. default:
  589. lbs_deb_host("CMD_RESP: unknown cmd response 0x%04x\n",
  590. resp->command);
  591. break;
  592. }
  593. lbs_deb_leave(LBS_DEB_HOST);
  594. return ret;
  595. }
  596. int lbs_process_rx_command(struct lbs_private *priv)
  597. {
  598. u16 respcmd;
  599. struct cmd_ds_command *resp;
  600. int ret = 0;
  601. ulong flags;
  602. u16 result;
  603. lbs_deb_enter(LBS_DEB_HOST);
  604. /* Now we got response from FW, cancel the command timer */
  605. del_timer(&priv->command_timer);
  606. mutex_lock(&priv->lock);
  607. spin_lock_irqsave(&priv->driver_lock, flags);
  608. if (!priv->cur_cmd) {
  609. lbs_deb_host("CMD_RESP: cur_cmd is NULL\n");
  610. ret = -1;
  611. spin_unlock_irqrestore(&priv->driver_lock, flags);
  612. goto done;
  613. }
  614. resp = (struct cmd_ds_command *)(priv->cur_cmd->bufvirtualaddr);
  615. respcmd = le16_to_cpu(resp->command);
  616. result = le16_to_cpu(resp->result);
  617. lbs_deb_host("CMD_RESP: response 0x%04x, size %d, jiffies %lu\n",
  618. respcmd, priv->upld_len, jiffies);
  619. lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", priv->cur_cmd->bufvirtualaddr,
  620. priv->upld_len);
  621. if (!(respcmd & 0x8000)) {
  622. lbs_deb_host("invalid response!\n");
  623. priv->cur_cmd_retcode = -1;
  624. __lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
  625. priv->cur_cmd = NULL;
  626. spin_unlock_irqrestore(&priv->driver_lock, flags);
  627. ret = -1;
  628. goto done;
  629. }
  630. /* Store the response code to cur_cmd_retcode. */
  631. priv->cur_cmd_retcode = result;
  632. if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
  633. struct cmd_ds_802_11_ps_mode *psmode = &resp->params.psmode;
  634. u16 action = le16_to_cpu(psmode->action);
  635. lbs_deb_host(
  636. "CMD_RESP: PS_MODE cmd reply result 0x%x, action 0x%x\n",
  637. result, action);
  638. if (result) {
  639. lbs_deb_host("CMD_RESP: PS command failed with 0x%x\n",
  640. result);
  641. /*
  642. * We should not re-try enter-ps command in
  643. * ad-hoc mode. It takes place in
  644. * lbs_execute_next_command().
  645. */
  646. if (priv->mode == IW_MODE_ADHOC &&
  647. action == CMD_SUBCMD_ENTER_PS)
  648. priv->psmode = LBS802_11POWERMODECAM;
  649. } else if (action == CMD_SUBCMD_ENTER_PS) {
  650. priv->needtowakeup = 0;
  651. priv->psstate = PS_STATE_AWAKE;
  652. lbs_deb_host("CMD_RESP: ENTER_PS command response\n");
  653. if (priv->connect_status != LBS_CONNECTED) {
  654. /*
  655. * When Deauth Event received before Enter_PS command
  656. * response, We need to wake up the firmware.
  657. */
  658. lbs_deb_host(
  659. "disconnected, invoking lbs_ps_wakeup\n");
  660. spin_unlock_irqrestore(&priv->driver_lock, flags);
  661. mutex_unlock(&priv->lock);
  662. lbs_ps_wakeup(priv, 0);
  663. mutex_lock(&priv->lock);
  664. spin_lock_irqsave(&priv->driver_lock, flags);
  665. }
  666. } else if (action == CMD_SUBCMD_EXIT_PS) {
  667. priv->needtowakeup = 0;
  668. priv->psstate = PS_STATE_FULL_POWER;
  669. lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
  670. } else {
  671. lbs_deb_host("CMD_RESP: PS action 0x%X\n", action);
  672. }
  673. __lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
  674. priv->cur_cmd = NULL;
  675. spin_unlock_irqrestore(&priv->driver_lock, flags);
  676. ret = 0;
  677. goto done;
  678. }
  679. /* If the command is not successful, cleanup and return failure */
  680. if ((result != 0 || !(respcmd & 0x8000))) {
  681. lbs_deb_host("CMD_RESP: error 0x%04x in command reply 0x%04x\n",
  682. result, respcmd);
  683. /*
  684. * Handling errors here
  685. */
  686. switch (respcmd) {
  687. case CMD_RET(CMD_GET_HW_SPEC):
  688. case CMD_RET(CMD_802_11_RESET):
  689. lbs_deb_host("CMD_RESP: reset failed\n");
  690. break;
  691. }
  692. __lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
  693. priv->cur_cmd = NULL;
  694. spin_unlock_irqrestore(&priv->driver_lock, flags);
  695. ret = -1;
  696. goto done;
  697. }
  698. spin_unlock_irqrestore(&priv->driver_lock, flags);
  699. if (priv->cur_cmd && priv->cur_cmd->callback)
  700. ret = priv->cur_cmd->callback(respcmd, resp, priv);
  701. else
  702. ret = handle_cmd_response(respcmd, resp, priv);
  703. spin_lock_irqsave(&priv->driver_lock, flags);
  704. if (priv->cur_cmd) {
  705. /* Clean up and Put current command back to cmdfreeq */
  706. __lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
  707. priv->cur_cmd = NULL;
  708. }
  709. spin_unlock_irqrestore(&priv->driver_lock, flags);
  710. done:
  711. mutex_unlock(&priv->lock);
  712. lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
  713. return ret;
  714. }
  715. int lbs_process_event(struct lbs_private *priv)
  716. {
  717. int ret = 0;
  718. u32 eventcause;
  719. lbs_deb_enter(LBS_DEB_CMD);
  720. spin_lock_irq(&priv->driver_lock);
  721. eventcause = priv->eventcause >> SBI_EVENT_CAUSE_SHIFT;
  722. spin_unlock_irq(&priv->driver_lock);
  723. lbs_deb_cmd("event cause %d\n", eventcause);
  724. switch (eventcause) {
  725. case MACREG_INT_CODE_LINK_SENSED:
  726. lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n");
  727. break;
  728. case MACREG_INT_CODE_DEAUTHENTICATED:
  729. lbs_deb_cmd("EVENT: deauthenticated\n");
  730. lbs_mac_event_disconnected(priv);
  731. break;
  732. case MACREG_INT_CODE_DISASSOCIATED:
  733. lbs_deb_cmd("EVENT: disassociated\n");
  734. lbs_mac_event_disconnected(priv);
  735. break;
  736. case MACREG_INT_CODE_LINK_LOST_NO_SCAN:
  737. lbs_deb_cmd("EVENT: link lost\n");
  738. lbs_mac_event_disconnected(priv);
  739. break;
  740. case MACREG_INT_CODE_PS_SLEEP:
  741. lbs_deb_cmd("EVENT: sleep\n");
  742. /* handle unexpected PS SLEEP event */
  743. if (priv->psstate == PS_STATE_FULL_POWER) {
  744. lbs_deb_cmd(
  745. "EVENT: in FULL POWER mode, ignoreing PS_SLEEP\n");
  746. break;
  747. }
  748. priv->psstate = PS_STATE_PRE_SLEEP;
  749. lbs_ps_confirm_sleep(priv, (u16) priv->psmode);
  750. break;
  751. case MACREG_INT_CODE_PS_AWAKE:
  752. lbs_deb_cmd("EVENT: awake\n");
  753. /* handle unexpected PS AWAKE event */
  754. if (priv->psstate == PS_STATE_FULL_POWER) {
  755. lbs_deb_cmd(
  756. "EVENT: In FULL POWER mode - ignore PS AWAKE\n");
  757. break;
  758. }
  759. priv->psstate = PS_STATE_AWAKE;
  760. if (priv->needtowakeup) {
  761. /*
  762. * wait for the command processing to finish
  763. * before resuming sending
  764. * priv->needtowakeup will be set to FALSE
  765. * in lbs_ps_wakeup()
  766. */
  767. lbs_deb_cmd("waking up ...\n");
  768. lbs_ps_wakeup(priv, 0);
  769. }
  770. break;
  771. case MACREG_INT_CODE_MIC_ERR_UNICAST:
  772. lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
  773. handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST);
  774. break;
  775. case MACREG_INT_CODE_MIC_ERR_MULTICAST:
  776. lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
  777. handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
  778. break;
  779. case MACREG_INT_CODE_MIB_CHANGED:
  780. case MACREG_INT_CODE_INIT_DONE:
  781. break;
  782. case MACREG_INT_CODE_ADHOC_BCN_LOST:
  783. lbs_deb_cmd("EVENT: ADHOC beacon lost\n");
  784. break;
  785. case MACREG_INT_CODE_RSSI_LOW:
  786. lbs_pr_alert("EVENT: rssi low\n");
  787. break;
  788. case MACREG_INT_CODE_SNR_LOW:
  789. lbs_pr_alert("EVENT: snr low\n");
  790. break;
  791. case MACREG_INT_CODE_MAX_FAIL:
  792. lbs_pr_alert("EVENT: max fail\n");
  793. break;
  794. case MACREG_INT_CODE_RSSI_HIGH:
  795. lbs_pr_alert("EVENT: rssi high\n");
  796. break;
  797. case MACREG_INT_CODE_SNR_HIGH:
  798. lbs_pr_alert("EVENT: snr high\n");
  799. break;
  800. case MACREG_INT_CODE_MESH_AUTO_STARTED:
  801. /* Ignore spurious autostart events if autostart is disabled */
  802. if (!priv->mesh_autostart_enabled) {
  803. lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n");
  804. break;
  805. }
  806. lbs_pr_info("EVENT: MESH_AUTO_STARTED\n");
  807. priv->mesh_connect_status = LBS_CONNECTED;
  808. if (priv->mesh_open == 1) {
  809. netif_wake_queue(priv->mesh_dev);
  810. netif_carrier_on(priv->mesh_dev);
  811. }
  812. priv->mode = IW_MODE_ADHOC;
  813. schedule_work(&priv->sync_channel);
  814. break;
  815. default:
  816. lbs_pr_alert("EVENT: unknown event id %d\n", eventcause);
  817. break;
  818. }
  819. spin_lock_irq(&priv->driver_lock);
  820. priv->eventcause = 0;
  821. spin_unlock_irq(&priv->driver_lock);
  822. lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
  823. return ret;
  824. }