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