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