cmdresp.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  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 <asm/unaligned.h>
  9. #include <net/iw_handler.h>
  10. #include "host.h"
  11. #include "decl.h"
  12. #include "defs.h"
  13. #include "dev.h"
  14. #include "assoc.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 struct lbs_private structure
  22. * @return n/a
  23. */
  24. void lbs_mac_event_disconnected(struct lbs_private *priv)
  25. {
  26. union iwreq_data wrqu;
  27. if (priv->connect_status != LBS_CONNECTED)
  28. return;
  29. lbs_deb_enter(LBS_DEB_ASSOC);
  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. /* report disconnect to upper layer */
  39. netif_stop_queue(priv->dev);
  40. netif_carrier_off(priv->dev);
  41. /* Free Tx and Rx packets */
  42. kfree_skb(priv->currenttxskb);
  43. priv->currenttxskb = NULL;
  44. priv->tx_pending_len = 0;
  45. /* reset SNR/NF/RSSI values */
  46. memset(priv->SNR, 0x00, sizeof(priv->SNR));
  47. memset(priv->NF, 0x00, sizeof(priv->NF));
  48. memset(priv->RSSI, 0x00, sizeof(priv->RSSI));
  49. memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
  50. memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
  51. priv->nextSNRNF = 0;
  52. priv->numSNRNF = 0;
  53. priv->connect_status = LBS_DISCONNECTED;
  54. /* Clear out associated SSID and BSSID since connection is
  55. * no longer valid.
  56. */
  57. memset(&priv->curbssparams.bssid, 0, ETH_ALEN);
  58. memset(&priv->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE);
  59. priv->curbssparams.ssid_len = 0;
  60. if (priv->psstate != PS_STATE_FULL_POWER) {
  61. /* make firmware to exit PS mode */
  62. lbs_deb_cmd("disconnected, so exit PS mode\n");
  63. lbs_ps_wakeup(priv, 0);
  64. }
  65. lbs_deb_leave(LBS_DEB_ASSOC);
  66. }
  67. /**
  68. * @brief This function handles MIC failure event.
  69. *
  70. * @param priv A pointer to struct lbs_private structure
  71. * @para event the event id
  72. * @return n/a
  73. */
  74. static void handle_mic_failureevent(struct lbs_private *priv, u32 event)
  75. {
  76. char buf[50];
  77. lbs_deb_enter(LBS_DEB_CMD);
  78. memset(buf, 0, sizeof(buf));
  79. sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
  80. if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) {
  81. strcat(buf, "unicast ");
  82. } else {
  83. strcat(buf, "multicast ");
  84. }
  85. lbs_send_iwevcustom_event(priv, buf);
  86. lbs_deb_leave(LBS_DEB_CMD);
  87. }
  88. static int lbs_ret_reg_access(struct lbs_private *priv,
  89. u16 type, struct cmd_ds_command *resp)
  90. {
  91. int ret = 0;
  92. lbs_deb_enter(LBS_DEB_CMD);
  93. switch (type) {
  94. case CMD_RET(CMD_MAC_REG_ACCESS):
  95. {
  96. struct cmd_ds_mac_reg_access *reg = &resp->params.macreg;
  97. priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
  98. priv->offsetvalue.value = le32_to_cpu(reg->value);
  99. break;
  100. }
  101. case CMD_RET(CMD_BBP_REG_ACCESS):
  102. {
  103. struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg;
  104. priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
  105. priv->offsetvalue.value = reg->value;
  106. break;
  107. }
  108. case CMD_RET(CMD_RF_REG_ACCESS):
  109. {
  110. struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg;
  111. priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
  112. priv->offsetvalue.value = reg->value;
  113. break;
  114. }
  115. default:
  116. ret = -1;
  117. }
  118. lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
  119. return ret;
  120. }
  121. static int lbs_ret_802_11_rssi(struct lbs_private *priv,
  122. struct cmd_ds_command *resp)
  123. {
  124. struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
  125. lbs_deb_enter(LBS_DEB_CMD);
  126. /* store the non average value */
  127. priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR);
  128. priv->NF[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->noisefloor);
  129. priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR);
  130. priv->NF[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgnoisefloor);
  131. priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
  132. CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
  133. priv->NF[TYPE_BEACON][TYPE_NOAVG]);
  134. priv->RSSI[TYPE_BEACON][TYPE_AVG] =
  135. CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
  136. priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
  137. lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
  138. priv->RSSI[TYPE_BEACON][TYPE_NOAVG],
  139. priv->RSSI[TYPE_BEACON][TYPE_AVG]);
  140. lbs_deb_leave(LBS_DEB_CMD);
  141. return 0;
  142. }
  143. static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
  144. struct cmd_ds_command *resp)
  145. {
  146. struct cmd_ds_802_11_beacon_control *bcn_ctrl =
  147. &resp->params.bcn_ctrl;
  148. lbs_deb_enter(LBS_DEB_CMD);
  149. if (bcn_ctrl->action == CMD_ACT_GET) {
  150. priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable);
  151. priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period);
  152. }
  153. lbs_deb_enter(LBS_DEB_CMD);
  154. return 0;
  155. }
  156. static inline int handle_cmd_response(struct lbs_private *priv,
  157. struct cmd_header *cmd_response)
  158. {
  159. struct cmd_ds_command *resp = (struct cmd_ds_command *) cmd_response;
  160. int ret = 0;
  161. unsigned long flags;
  162. uint16_t respcmd = le16_to_cpu(resp->command);
  163. lbs_deb_enter(LBS_DEB_HOST);
  164. switch (respcmd) {
  165. case CMD_RET(CMD_MAC_REG_ACCESS):
  166. case CMD_RET(CMD_BBP_REG_ACCESS):
  167. case CMD_RET(CMD_RF_REG_ACCESS):
  168. ret = lbs_ret_reg_access(priv, respcmd, resp);
  169. break;
  170. case CMD_RET(CMD_802_11_SET_AFC):
  171. case CMD_RET(CMD_802_11_GET_AFC):
  172. spin_lock_irqsave(&priv->driver_lock, flags);
  173. memmove((void *)priv->cur_cmd->callback_arg, &resp->params.afc,
  174. sizeof(struct cmd_ds_802_11_afc));
  175. spin_unlock_irqrestore(&priv->driver_lock, flags);
  176. break;
  177. case CMD_RET(CMD_802_11_BEACON_STOP):
  178. break;
  179. case CMD_RET(CMD_802_11_RSSI):
  180. ret = lbs_ret_802_11_rssi(priv, resp);
  181. break;
  182. case CMD_RET(CMD_802_11D_DOMAIN_INFO):
  183. ret = lbs_ret_802_11d_domain_info(resp);
  184. break;
  185. case CMD_RET(CMD_802_11_TPC_CFG):
  186. spin_lock_irqsave(&priv->driver_lock, flags);
  187. memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg,
  188. sizeof(struct cmd_ds_802_11_tpc_cfg));
  189. spin_unlock_irqrestore(&priv->driver_lock, flags);
  190. break;
  191. case CMD_RET(CMD_802_11_LED_GPIO_CTRL):
  192. spin_lock_irqsave(&priv->driver_lock, flags);
  193. memmove((void *)priv->cur_cmd->callback_arg, &resp->params.ledgpio,
  194. sizeof(struct cmd_ds_802_11_led_ctrl));
  195. spin_unlock_irqrestore(&priv->driver_lock, flags);
  196. break;
  197. case CMD_RET(CMD_GET_TSF):
  198. spin_lock_irqsave(&priv->driver_lock, flags);
  199. memcpy((void *)priv->cur_cmd->callback_arg,
  200. &resp->params.gettsf.tsfvalue, sizeof(u64));
  201. spin_unlock_irqrestore(&priv->driver_lock, flags);
  202. break;
  203. case CMD_RET(CMD_BT_ACCESS):
  204. spin_lock_irqsave(&priv->driver_lock, flags);
  205. if (priv->cur_cmd->callback_arg)
  206. memcpy((void *)priv->cur_cmd->callback_arg,
  207. &resp->params.bt.addr1, 2 * ETH_ALEN);
  208. spin_unlock_irqrestore(&priv->driver_lock, flags);
  209. break;
  210. case CMD_RET(CMD_FWT_ACCESS):
  211. spin_lock_irqsave(&priv->driver_lock, flags);
  212. if (priv->cur_cmd->callback_arg)
  213. memcpy((void *)priv->cur_cmd->callback_arg, &resp->params.fwt,
  214. sizeof(resp->params.fwt));
  215. spin_unlock_irqrestore(&priv->driver_lock, flags);
  216. break;
  217. case CMD_RET(CMD_802_11_BEACON_CTRL):
  218. ret = lbs_ret_802_11_bcn_ctrl(priv, resp);
  219. break;
  220. default:
  221. lbs_pr_err("CMD_RESP: unknown cmd response 0x%04x\n",
  222. le16_to_cpu(resp->command));
  223. break;
  224. }
  225. lbs_deb_leave(LBS_DEB_HOST);
  226. return ret;
  227. }
  228. int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
  229. {
  230. uint16_t respcmd, curcmd;
  231. struct cmd_header *resp;
  232. int ret = 0;
  233. unsigned long flags;
  234. uint16_t result;
  235. lbs_deb_enter(LBS_DEB_HOST);
  236. mutex_lock(&priv->lock);
  237. spin_lock_irqsave(&priv->driver_lock, flags);
  238. if (!priv->cur_cmd) {
  239. lbs_deb_host("CMD_RESP: cur_cmd is NULL\n");
  240. ret = -1;
  241. spin_unlock_irqrestore(&priv->driver_lock, flags);
  242. goto done;
  243. }
  244. resp = (void *)data;
  245. curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command);
  246. respcmd = le16_to_cpu(resp->command);
  247. result = le16_to_cpu(resp->result);
  248. lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n",
  249. respcmd, le16_to_cpu(resp->seqnum), len);
  250. lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len);
  251. if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
  252. lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n",
  253. le16_to_cpu(resp->seqnum), le16_to_cpu(priv->cur_cmd->cmdbuf->seqnum));
  254. spin_unlock_irqrestore(&priv->driver_lock, flags);
  255. ret = -1;
  256. goto done;
  257. }
  258. if (respcmd != CMD_RET(curcmd) &&
  259. respcmd != CMD_RET_802_11_ASSOCIATE && curcmd != CMD_802_11_ASSOCIATE) {
  260. lbs_pr_info("Invalid CMD_RESP %x to command %x!\n", respcmd, curcmd);
  261. spin_unlock_irqrestore(&priv->driver_lock, flags);
  262. ret = -1;
  263. goto done;
  264. }
  265. if (resp->result == cpu_to_le16(0x0004)) {
  266. /* 0x0004 means -EAGAIN. Drop the response, let it time out
  267. and be resubmitted */
  268. lbs_pr_info("Firmware returns DEFER to command %x. Will let it time out...\n",
  269. le16_to_cpu(resp->command));
  270. spin_unlock_irqrestore(&priv->driver_lock, flags);
  271. ret = -1;
  272. goto done;
  273. }
  274. /* Now we got response from FW, cancel the command timer */
  275. del_timer(&priv->command_timer);
  276. priv->cmd_timed_out = 0;
  277. if (priv->nr_retries) {
  278. lbs_pr_info("Received result %x to command %x after %d retries\n",
  279. result, curcmd, priv->nr_retries);
  280. priv->nr_retries = 0;
  281. }
  282. /* Store the response code to cur_cmd_retcode. */
  283. priv->cur_cmd_retcode = result;
  284. if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
  285. struct cmd_ds_802_11_ps_mode *psmode = (void *) &resp[1];
  286. u16 action = le16_to_cpu(psmode->action);
  287. lbs_deb_host(
  288. "CMD_RESP: PS_MODE cmd reply result 0x%x, action 0x%x\n",
  289. result, action);
  290. if (result) {
  291. lbs_deb_host("CMD_RESP: PS command failed with 0x%x\n",
  292. result);
  293. /*
  294. * We should not re-try enter-ps command in
  295. * ad-hoc mode. It takes place in
  296. * lbs_execute_next_command().
  297. */
  298. if (priv->mode == IW_MODE_ADHOC &&
  299. action == CMD_SUBCMD_ENTER_PS)
  300. priv->psmode = LBS802_11POWERMODECAM;
  301. } else if (action == CMD_SUBCMD_ENTER_PS) {
  302. priv->needtowakeup = 0;
  303. priv->psstate = PS_STATE_AWAKE;
  304. lbs_deb_host("CMD_RESP: ENTER_PS command response\n");
  305. if (priv->connect_status != LBS_CONNECTED) {
  306. /*
  307. * When Deauth Event received before Enter_PS command
  308. * response, We need to wake up the firmware.
  309. */
  310. lbs_deb_host(
  311. "disconnected, invoking lbs_ps_wakeup\n");
  312. spin_unlock_irqrestore(&priv->driver_lock, flags);
  313. mutex_unlock(&priv->lock);
  314. lbs_ps_wakeup(priv, 0);
  315. mutex_lock(&priv->lock);
  316. spin_lock_irqsave(&priv->driver_lock, flags);
  317. }
  318. } else if (action == CMD_SUBCMD_EXIT_PS) {
  319. priv->needtowakeup = 0;
  320. priv->psstate = PS_STATE_FULL_POWER;
  321. lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
  322. } else {
  323. lbs_deb_host("CMD_RESP: PS action 0x%X\n", action);
  324. }
  325. lbs_complete_command(priv, priv->cur_cmd, result);
  326. spin_unlock_irqrestore(&priv->driver_lock, flags);
  327. ret = 0;
  328. goto done;
  329. }
  330. /* If the command is not successful, cleanup and return failure */
  331. if ((result != 0 || !(respcmd & 0x8000))) {
  332. lbs_deb_host("CMD_RESP: error 0x%04x in command reply 0x%04x\n",
  333. result, respcmd);
  334. /*
  335. * Handling errors here
  336. */
  337. switch (respcmd) {
  338. case CMD_RET(CMD_GET_HW_SPEC):
  339. case CMD_RET(CMD_802_11_RESET):
  340. lbs_deb_host("CMD_RESP: reset failed\n");
  341. break;
  342. }
  343. lbs_complete_command(priv, priv->cur_cmd, result);
  344. spin_unlock_irqrestore(&priv->driver_lock, flags);
  345. ret = -1;
  346. goto done;
  347. }
  348. spin_unlock_irqrestore(&priv->driver_lock, flags);
  349. if (priv->cur_cmd && priv->cur_cmd->callback) {
  350. ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
  351. resp);
  352. } else
  353. ret = handle_cmd_response(priv, resp);
  354. spin_lock_irqsave(&priv->driver_lock, flags);
  355. if (priv->cur_cmd) {
  356. /* Clean up and Put current command back to cmdfreeq */
  357. lbs_complete_command(priv, priv->cur_cmd, result);
  358. }
  359. spin_unlock_irqrestore(&priv->driver_lock, flags);
  360. done:
  361. mutex_unlock(&priv->lock);
  362. lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
  363. return ret;
  364. }
  365. static int lbs_send_confirmwake(struct lbs_private *priv)
  366. {
  367. struct cmd_header cmd;
  368. int ret = 0;
  369. lbs_deb_enter(LBS_DEB_HOST);
  370. cmd.command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM);
  371. cmd.size = cpu_to_le16(sizeof(cmd));
  372. cmd.seqnum = cpu_to_le16(++priv->seqnum);
  373. cmd.result = 0;
  374. lbs_deb_hex(LBS_DEB_HOST, "wake confirm", (u8 *) &cmd,
  375. sizeof(cmd));
  376. ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &cmd, sizeof(cmd));
  377. if (ret)
  378. lbs_pr_alert("SEND_WAKEC_CMD: Host to Card failed for Confirm Wake\n");
  379. lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
  380. return ret;
  381. }
  382. int lbs_process_event(struct lbs_private *priv, u32 event)
  383. {
  384. int ret = 0;
  385. lbs_deb_enter(LBS_DEB_CMD);
  386. switch (event) {
  387. case MACREG_INT_CODE_LINK_SENSED:
  388. lbs_deb_cmd("EVENT: link sensed\n");
  389. break;
  390. case MACREG_INT_CODE_DEAUTHENTICATED:
  391. lbs_deb_cmd("EVENT: deauthenticated\n");
  392. lbs_mac_event_disconnected(priv);
  393. break;
  394. case MACREG_INT_CODE_DISASSOCIATED:
  395. lbs_deb_cmd("EVENT: disassociated\n");
  396. lbs_mac_event_disconnected(priv);
  397. break;
  398. case MACREG_INT_CODE_LINK_LOST_NO_SCAN:
  399. lbs_deb_cmd("EVENT: link lost\n");
  400. lbs_mac_event_disconnected(priv);
  401. break;
  402. case MACREG_INT_CODE_PS_SLEEP:
  403. lbs_deb_cmd("EVENT: ps sleep\n");
  404. /* handle unexpected PS SLEEP event */
  405. if (priv->psstate == PS_STATE_FULL_POWER) {
  406. lbs_deb_cmd(
  407. "EVENT: in FULL POWER mode, ignoreing PS_SLEEP\n");
  408. break;
  409. }
  410. priv->psstate = PS_STATE_PRE_SLEEP;
  411. lbs_ps_confirm_sleep(priv);
  412. break;
  413. case MACREG_INT_CODE_HOST_AWAKE:
  414. lbs_deb_cmd("EVENT: host awake\n");
  415. lbs_send_confirmwake(priv);
  416. break;
  417. case MACREG_INT_CODE_PS_AWAKE:
  418. lbs_deb_cmd("EVENT: ps awake\n");
  419. /* handle unexpected PS AWAKE event */
  420. if (priv->psstate == PS_STATE_FULL_POWER) {
  421. lbs_deb_cmd(
  422. "EVENT: In FULL POWER mode - ignore PS AWAKE\n");
  423. break;
  424. }
  425. priv->psstate = PS_STATE_AWAKE;
  426. if (priv->needtowakeup) {
  427. /*
  428. * wait for the command processing to finish
  429. * before resuming sending
  430. * priv->needtowakeup will be set to FALSE
  431. * in lbs_ps_wakeup()
  432. */
  433. lbs_deb_cmd("waking up ...\n");
  434. lbs_ps_wakeup(priv, 0);
  435. }
  436. break;
  437. case MACREG_INT_CODE_MIC_ERR_UNICAST:
  438. lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
  439. handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST);
  440. break;
  441. case MACREG_INT_CODE_MIC_ERR_MULTICAST:
  442. lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
  443. handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
  444. break;
  445. case MACREG_INT_CODE_MIB_CHANGED:
  446. lbs_deb_cmd("EVENT: MIB CHANGED\n");
  447. break;
  448. case MACREG_INT_CODE_INIT_DONE:
  449. lbs_deb_cmd("EVENT: INIT DONE\n");
  450. break;
  451. case MACREG_INT_CODE_ADHOC_BCN_LOST:
  452. lbs_deb_cmd("EVENT: ADHOC beacon lost\n");
  453. break;
  454. case MACREG_INT_CODE_RSSI_LOW:
  455. lbs_pr_alert("EVENT: rssi low\n");
  456. break;
  457. case MACREG_INT_CODE_SNR_LOW:
  458. lbs_pr_alert("EVENT: snr low\n");
  459. break;
  460. case MACREG_INT_CODE_MAX_FAIL:
  461. lbs_pr_alert("EVENT: max fail\n");
  462. break;
  463. case MACREG_INT_CODE_RSSI_HIGH:
  464. lbs_pr_alert("EVENT: rssi high\n");
  465. break;
  466. case MACREG_INT_CODE_SNR_HIGH:
  467. lbs_pr_alert("EVENT: snr high\n");
  468. break;
  469. case MACREG_INT_CODE_MESH_AUTO_STARTED:
  470. /* Ignore spurious autostart events if autostart is disabled */
  471. if (!priv->mesh_autostart_enabled) {
  472. lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n");
  473. break;
  474. }
  475. lbs_pr_info("EVENT: MESH_AUTO_STARTED\n");
  476. priv->mesh_connect_status = LBS_CONNECTED;
  477. if (priv->mesh_open) {
  478. netif_carrier_on(priv->mesh_dev);
  479. if (!priv->tx_pending_len)
  480. netif_wake_queue(priv->mesh_dev);
  481. }
  482. priv->mode = IW_MODE_ADHOC;
  483. schedule_work(&priv->sync_channel);
  484. break;
  485. default:
  486. lbs_pr_alert("EVENT: unknown event id %d\n", event);
  487. break;
  488. }
  489. lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
  490. return ret;
  491. }