]> err.no Git - linux-2.6/blob - drivers/net/wireless/libertas/cmdresp.c
[PATCH] libertas: debug print spacing fixes in assoc.c
[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 wlan_private structure
24  *  @return        n/a
25  */
26 void libertas_mac_event_disconnected(wlan_private * priv)
27 {
28         wlan_adapter *adapter = priv->adapter;
29         union iwreq_data wrqu;
30
31         if (adapter->connect_status != libertas_connected)
32                 return;
33
34         lbs_deb_cmd("Handles disconnect event.\n");
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->rxpd_rate = 0;
64         lbs_deb_cmd("Current SSID=%s, ssid length=%u\n",
65                adapter->curbssparams.ssid.ssid,
66                adapter->curbssparams.ssid.ssidlength);
67         lbs_deb_cmd("Previous SSID=%s, ssid length=%u\n",
68                adapter->previousssid.ssid, adapter->previousssid.ssidlength);
69
70         adapter->connect_status = libertas_disconnected;
71
72         /* Save previous SSID and BSSID for possible reassociation */
73         memcpy(&adapter->previousssid,
74                &adapter->curbssparams.ssid, sizeof(struct WLAN_802_11_SSID));
75         memcpy(adapter->previousbssid,
76                adapter->curbssparams.bssid, ETH_ALEN);
77
78         /* Clear out associated SSID and BSSID since connection is
79          * no longer valid.
80          */
81         memset(&adapter->curbssparams.bssid, 0, ETH_ALEN);
82         memset(&adapter->curbssparams.ssid, 0, sizeof(struct WLAN_802_11_SSID));
83
84         if (adapter->psstate != PS_STATE_FULL_POWER) {
85                 /* make firmware to exit PS mode */
86                 lbs_deb_cmd("Disconnected, so exit PS mode.\n");
87                 libertas_ps_wakeup(priv, 0);
88         }
89 }
90
91 /**
92  *  @brief This function handles MIC failure event.
93  *
94  *  @param priv    A pointer to wlan_private structure
95  *  @para  event   the event id
96  *  @return        n/a
97  */
98 static void handle_mic_failureevent(wlan_private * priv, u32 event)
99 {
100         char buf[50];
101
102         memset(buf, 0, sizeof(buf));
103
104         sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
105
106         if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) {
107                 strcat(buf, "unicast ");
108         } else {
109                 strcat(buf, "multicast ");
110         }
111
112         libertas_send_iwevcustom_event(priv, buf);
113 }
114
115 static int wlan_ret_reg_access(wlan_private * priv,
116                                u16 type, struct cmd_ds_command *resp)
117 {
118         int ret = 0;
119         wlan_adapter *adapter = priv->adapter;
120
121         lbs_deb_enter(LBS_DEB_CMD);
122
123         switch (type) {
124         case cmd_ret_mac_reg_access:
125                 {
126                         struct cmd_ds_mac_reg_access *reg;
127
128                         reg =
129                             (struct cmd_ds_mac_reg_access *)&resp->params.
130                             macreg;
131
132                         adapter->offsetvalue.offset = reg->offset;
133                         adapter->offsetvalue.value = reg->value;
134                         break;
135                 }
136
137         case cmd_ret_bbp_reg_access:
138                 {
139                         struct cmd_ds_bbp_reg_access *reg;
140                         reg =
141                             (struct cmd_ds_bbp_reg_access *)&resp->params.
142                             bbpreg;
143
144                         adapter->offsetvalue.offset = reg->offset;
145                         adapter->offsetvalue.value = reg->value;
146                         break;
147                 }
148
149         case cmd_ret_rf_reg_access:
150                 {
151                         struct cmd_ds_rf_reg_access *reg;
152                         reg =
153                             (struct cmd_ds_rf_reg_access *)&resp->params.
154                             rfreg;
155
156                         adapter->offsetvalue.offset = reg->offset;
157                         adapter->offsetvalue.value = reg->value;
158                         break;
159                 }
160
161         default:
162                 ret = -1;
163         }
164
165         lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
166         return ret;
167 }
168
169 static int wlan_ret_get_hw_spec(wlan_private * priv,
170                                 struct cmd_ds_command *resp)
171 {
172         u32 i;
173         struct cmd_ds_get_hw_spec *hwspec = &resp->params.hwspec;
174         wlan_adapter *adapter = priv->adapter;
175         int ret = 0;
176
177         lbs_deb_enter(LBS_DEB_CMD);
178
179         adapter->fwcapinfo = le32_to_cpu(hwspec->fwcapinfo);
180
181         adapter->fwreleasenumber = hwspec->fwreleasenumber;
182
183         lbs_deb_cmd("GET_HW_SPEC: FWReleaseVersion- 0x%X\n",
184                adapter->fwreleasenumber);
185         lbs_deb_cmd("GET_HW_SPEC: Permanent addr- %2x:%2x:%2x:%2x:%2x:%2x\n",
186                hwspec->permanentaddr[0], hwspec->permanentaddr[1],
187                hwspec->permanentaddr[2], hwspec->permanentaddr[3],
188                hwspec->permanentaddr[4], hwspec->permanentaddr[5]);
189         lbs_deb_cmd("GET_HW_SPEC: hwifversion=0x%X  version=0x%X\n",
190                hwspec->hwifversion, hwspec->version);
191
192         adapter->regioncode = le16_to_cpu(hwspec->regioncode);
193
194         for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
195                 /* use the region code to search for the index */
196                 if (adapter->regioncode == libertas_region_code_to_index[i]) {
197                         adapter->regiontableindex = (u16) i;
198                         break;
199                 }
200         }
201
202         /* if it's unidentified region code, use the default (USA) */
203         if (i >= MRVDRV_MAX_REGION_CODE) {
204                 adapter->regioncode = 0x10;
205                 adapter->regiontableindex = 0;
206                 lbs_pr_info(
207                        "unidentified region code, use the default (USA)\n");
208         }
209
210         if (adapter->current_addr[0] == 0xff) {
211                 memmove(adapter->current_addr, hwspec->permanentaddr,
212                         ETH_ALEN);
213         }
214
215         memcpy(priv->dev->dev_addr, adapter->current_addr, ETH_ALEN);
216         if (priv->mesh_dev)
217                 memcpy(priv->mesh_dev->dev_addr, adapter->current_addr,
218                        ETH_ALEN);
219
220         if (libertas_set_regiontable(priv, adapter->regioncode, 0)) {
221                 ret = -1;
222                 goto done;
223         }
224
225         if (libertas_set_universaltable(priv, 0)) {
226                 ret = -1;
227                 goto done;
228         }
229
230 done:
231         lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
232         return ret;
233 }
234
235 static int wlan_ret_802_11_sleep_params(wlan_private * priv,
236                                         struct cmd_ds_command *resp)
237 {
238         struct cmd_ds_802_11_sleep_params *sp = &resp->params.sleep_params;
239         wlan_adapter *adapter = priv->adapter;
240
241         lbs_deb_enter(LBS_DEB_CMD);
242
243         lbs_deb_cmd("error=%x offset=%x stabletime=%x calcontrol=%x\n"
244                " extsleepclk=%x\n", sp->error, sp->offset,
245                sp->stabletime, sp->calcontrol, sp->externalsleepclk);
246         adapter->sp.sp_error = le16_to_cpu(sp->error);
247         adapter->sp.sp_offset = le16_to_cpu(sp->offset);
248         adapter->sp.sp_stabletime = le16_to_cpu(sp->stabletime);
249         adapter->sp.sp_calcontrol = le16_to_cpu(sp->calcontrol);
250         adapter->sp.sp_extsleepclk = le16_to_cpu(sp->externalsleepclk);
251         adapter->sp.sp_reserved = le16_to_cpu(sp->reserved);
252
253         lbs_deb_enter(LBS_DEB_CMD);
254         return 0;
255 }
256
257 static int wlan_ret_802_11_stat(wlan_private * priv,
258                                 struct cmd_ds_command *resp)
259 {
260 /*      currently adapter->wlan802_11Stat is unused
261
262         struct cmd_ds_802_11_get_stat *p11Stat = &resp->params.gstat;
263         wlan_adapter *adapter = priv->adapter;
264
265         // TODO Convert it to Big endian befor copy
266         memcpy(&adapter->wlan802_11Stat,
267                p11Stat, sizeof(struct cmd_ds_802_11_get_stat));
268 */
269         return 0;
270 }
271
272 static int wlan_ret_802_11_snmp_mib(wlan_private * priv,
273                                     struct cmd_ds_command *resp)
274 {
275         struct cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
276         u16 oid = le16_to_cpu(smib->oid);
277         u16 querytype = le16_to_cpu(smib->querytype);
278
279         lbs_deb_enter(LBS_DEB_CMD);
280
281         lbs_deb_cmd("SNMP_RESP: value of the oid = %x, querytype=%x\n", oid,
282                querytype);
283         lbs_deb_cmd("SNMP_RESP: Buf size  = %x\n",
284                le16_to_cpu(smib->bufsize));
285
286         if (querytype == cmd_act_get) {
287                 switch (oid) {
288                 case fragthresh_i:
289                         priv->adapter->fragthsd =
290                             le16_to_cpu(*
291                                              ((unsigned short *)(smib->value)));
292                         lbs_deb_cmd("SNMP_RESP: fragthsd =%u\n",
293                                priv->adapter->fragthsd);
294                         break;
295                 case rtsthresh_i:
296                         priv->adapter->rtsthsd =
297                             le16_to_cpu(*
298                                              ((unsigned short *)(smib->value)));
299                         lbs_deb_cmd("SNMP_RESP: rtsthsd =%u\n",
300                                priv->adapter->rtsthsd);
301                         break;
302                 case short_retrylim_i:
303                         priv->adapter->txretrycount =
304                             le16_to_cpu(*
305                                              ((unsigned short *)(smib->value)));
306                         lbs_deb_cmd("SNMP_RESP: txretrycount =%u\n",
307                                priv->adapter->rtsthsd);
308                         break;
309                 default:
310                         break;
311                 }
312         }
313
314         lbs_deb_enter(LBS_DEB_CMD);
315         return 0;
316 }
317
318 static int wlan_ret_802_11_key_material(wlan_private * priv,
319                                         struct cmd_ds_command *resp)
320 {
321         struct cmd_ds_802_11_key_material *pkeymaterial =
322             &resp->params.keymaterial;
323         wlan_adapter *adapter = priv->adapter;
324         u16 action = le16_to_cpu(pkeymaterial->action);
325
326         lbs_deb_enter(LBS_DEB_CMD);
327
328         /* Copy the returned key to driver private data */
329         if (action == cmd_act_get) {
330                 u8 * buf_ptr = (u8 *) &pkeymaterial->keyParamSet;
331                 u8 * resp_end = (u8 *) (resp + le16_to_cpu(resp->size));
332
333                 while (buf_ptr < resp_end) {
334                         struct MrvlIEtype_keyParamSet * pkeyparamset =
335                             (struct MrvlIEtype_keyParamSet *) buf_ptr;
336                         struct WLAN_802_11_KEY * pkey;
337                         u16 key_info = le16_to_cpu(pkeyparamset->keyinfo);
338                         u16 param_set_len = le16_to_cpu(pkeyparamset->length);
339                         u8 * end;
340                         u16 key_len = le16_to_cpu(pkeyparamset->keylen);
341
342                         end = (u8 *) pkeyparamset + sizeof (pkeyparamset->type)
343                                                   + sizeof (pkeyparamset->length)
344                                                   + param_set_len;
345                         /* Make sure we don't access past the end of the IEs */
346                         if (end > resp_end)
347                                 break;
348
349                         if (key_info & KEY_INFO_WPA_UNICAST)
350                                 pkey = &adapter->wpa_unicast_key;
351                         else if (key_info & KEY_INFO_WPA_MCAST)
352                                 pkey = &adapter->wpa_mcast_key;
353                         else
354                                 break;
355
356                         /* Copy returned key into driver */
357                         memset(pkey, 0, sizeof(struct WLAN_802_11_KEY));
358                         if (key_len > sizeof(pkey->key))
359                                 break;
360                         pkey->type = le16_to_cpu(pkeyparamset->keytypeid);
361                         pkey->flags = le16_to_cpu(pkeyparamset->keyinfo);
362                         pkey->len = le16_to_cpu(pkeyparamset->keylen);
363                         memcpy(pkey->key, pkeyparamset->key, pkey->len);
364
365                         buf_ptr = end + 1;
366                 }
367         }
368
369         lbs_deb_enter(LBS_DEB_CMD);
370         return 0;
371 }
372
373 static int wlan_ret_802_11_mac_address(wlan_private * priv,
374                                        struct cmd_ds_command *resp)
375 {
376         struct cmd_ds_802_11_mac_address *macadd = &resp->params.macadd;
377         wlan_adapter *adapter = priv->adapter;
378
379         lbs_deb_enter(LBS_DEB_CMD);
380
381         memcpy(adapter->current_addr, macadd->macadd, ETH_ALEN);
382
383         lbs_deb_enter(LBS_DEB_CMD);
384         return 0;
385 }
386
387 static int wlan_ret_802_11_rf_tx_power(wlan_private * priv,
388                                        struct cmd_ds_command *resp)
389 {
390         struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp;
391         wlan_adapter *adapter = priv->adapter;
392
393         lbs_deb_enter(LBS_DEB_CMD);
394
395         adapter->txpowerlevel = le16_to_cpu(rtp->currentlevel);
396
397         lbs_deb_cmd("Current TxPower Level = %d\n", adapter->txpowerlevel);
398
399         lbs_deb_enter(LBS_DEB_CMD);
400         return 0;
401 }
402
403 static int wlan_ret_802_11_rf_antenna(wlan_private * priv,
404                                       struct cmd_ds_command *resp)
405 {
406         struct cmd_ds_802_11_rf_antenna *pAntenna = &resp->params.rant;
407         wlan_adapter *adapter = priv->adapter;
408         u16 action = le16_to_cpu(pAntenna->action);
409
410         if (action == cmd_act_get_rx)
411                 adapter->rxantennamode =
412                     le16_to_cpu(pAntenna->antennamode);
413
414         if (action == cmd_act_get_tx)
415                 adapter->txantennamode =
416                     le16_to_cpu(pAntenna->antennamode);
417
418         lbs_deb_cmd("RF_ANT_RESP: action = 0x%x, mode = 0x%04x\n",
419                action, le16_to_cpu(pAntenna->antennamode));
420
421         return 0;
422 }
423
424 static int wlan_ret_802_11_rate_adapt_rateset(wlan_private * priv,
425                                               struct cmd_ds_command *resp)
426 {
427         struct cmd_ds_802_11_rate_adapt_rateset *rates =
428             &resp->params.rateset;
429         wlan_adapter *adapter = priv->adapter;
430
431         lbs_deb_enter(LBS_DEB_CMD);
432
433         if (rates->action == cmd_act_get) {
434                 adapter->enablehwauto = rates->enablehwauto;
435                 adapter->ratebitmap = rates->bitmap;
436         }
437
438         lbs_deb_enter(LBS_DEB_CMD);
439         return 0;
440 }
441
442 static int wlan_ret_802_11_data_rate(wlan_private * priv,
443                                      struct cmd_ds_command *resp)
444 {
445         struct cmd_ds_802_11_data_rate *pdatarate = &resp->params.drate;
446         wlan_adapter *adapter = priv->adapter;
447         u8 dot11datarate;
448
449         lbs_deb_enter(LBS_DEB_CMD);
450
451         lbs_dbg_hex("DATA_RATE_RESP: data_rate- ",
452                 (u8 *) pdatarate, sizeof(struct cmd_ds_802_11_data_rate));
453
454         dot11datarate = pdatarate->datarate[0];
455         if (pdatarate->action == cmd_act_get_tx_rate) {
456                 memcpy(adapter->libertas_supported_rates, pdatarate->datarate,
457                        sizeof(adapter->libertas_supported_rates));
458         }
459         adapter->datarate = libertas_index_to_data_rate(dot11datarate);
460
461         lbs_deb_enter(LBS_DEB_CMD);
462         return 0;
463 }
464
465 static int wlan_ret_802_11_rf_channel(wlan_private * priv,
466                                       struct cmd_ds_command *resp)
467 {
468         struct cmd_ds_802_11_rf_channel *rfchannel =
469             &resp->params.rfchannel;
470         wlan_adapter *adapter = priv->adapter;
471         u16 action = le16_to_cpu(rfchannel->action);
472         u16 newchannel = le16_to_cpu(rfchannel->currentchannel);
473
474         lbs_deb_enter(LBS_DEB_CMD);
475
476         if (action == cmd_opt_802_11_rf_channel_get
477             && adapter->curbssparams.channel != newchannel) {
478                 lbs_deb_cmd("channel Switch: %d to %d\n",
479                        adapter->curbssparams.channel, newchannel);
480
481                 /* Update the channel again */
482                 adapter->curbssparams.channel = newchannel;
483         }
484
485         lbs_deb_enter(LBS_DEB_CMD);
486         return 0;
487 }
488
489 static int wlan_ret_802_11_rssi(wlan_private * priv,
490                                 struct cmd_ds_command *resp)
491 {
492         struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
493         wlan_adapter *adapter = priv->adapter;
494
495         /* store the non average value */
496         adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR);
497         adapter->NF[TYPE_BEACON][TYPE_NOAVG] =
498             le16_to_cpu(rssirsp->noisefloor);
499
500         adapter->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR);
501         adapter->NF[TYPE_BEACON][TYPE_AVG] =
502             le16_to_cpu(rssirsp->avgnoisefloor);
503
504         adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] =
505             CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
506                      adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
507
508         adapter->RSSI[TYPE_BEACON][TYPE_AVG] =
509             CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
510                      adapter->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
511
512         lbs_deb_cmd("Beacon RSSI value = 0x%x\n",
513                adapter->RSSI[TYPE_BEACON][TYPE_AVG]);
514
515         return 0;
516 }
517
518 static int wlan_ret_802_11_eeprom_access(wlan_private * priv,
519                                   struct cmd_ds_command *resp)
520 {
521         wlan_adapter *adapter = priv->adapter;
522         struct wlan_ioctl_regrdwr *pbuf;
523         pbuf = (struct wlan_ioctl_regrdwr *) adapter->prdeeprom;
524
525         lbs_deb_cmd("eeprom read len=%x\n",
526                le16_to_cpu(resp->params.rdeeprom.bytecount));
527         if (pbuf->NOB < le16_to_cpu(resp->params.rdeeprom.bytecount)) {
528                 pbuf->NOB = 0;
529                 lbs_deb_cmd("eeprom read return length is too big\n");
530                 return -1;
531         }
532         pbuf->NOB = le16_to_cpu(resp->params.rdeeprom.bytecount);
533         if (pbuf->NOB > 0) {
534
535                 memcpy(&pbuf->value, (u8 *) & resp->params.rdeeprom.value,
536                        le16_to_cpu(resp->params.rdeeprom.bytecount));
537                 lbs_dbg_hex("adapter", (char *)&pbuf->value,
538                         le16_to_cpu(resp->params.rdeeprom.bytecount));
539         }
540         return 0;
541 }
542
543 static int wlan_ret_get_log(wlan_private * priv,
544                             struct cmd_ds_command *resp)
545 {
546         struct cmd_ds_802_11_get_log *logmessage =
547             (struct cmd_ds_802_11_get_log *)&resp->params.glog;
548         wlan_adapter *adapter = priv->adapter;
549
550         lbs_deb_enter(LBS_DEB_CMD);
551
552         /* TODO Convert it to Big Endian before copy */
553         memcpy(&adapter->logmsg, logmessage,
554                sizeof(struct cmd_ds_802_11_get_log));
555
556         lbs_deb_enter(LBS_DEB_CMD);
557         return 0;
558 }
559
560 static inline int handle_cmd_response(u16 respcmd,
561                                       struct cmd_ds_command *resp,
562                                       wlan_private *priv)
563 {
564         int ret = 0;
565         unsigned long flags;
566         wlan_adapter *adapter = priv->adapter;
567
568         switch (respcmd) {
569         case cmd_ret_mac_reg_access:
570         case cmd_ret_bbp_reg_access:
571         case cmd_ret_rf_reg_access:
572                 ret = wlan_ret_reg_access(priv, respcmd, resp);
573                 break;
574
575         case cmd_ret_hw_spec_info:
576                 ret = wlan_ret_get_hw_spec(priv, resp);
577                 break;
578
579         case cmd_ret_802_11_scan:
580                 ret = libertas_ret_80211_scan(priv, resp);
581                 break;
582
583         case cmd_ret_802_11_get_log:
584                 ret = wlan_ret_get_log(priv, resp);
585                 break;
586
587         case cmd_ret_802_11_associate:
588         case cmd_ret_802_11_reassociate:
589                 ret = libertas_ret_80211_associate(priv, resp);
590                 break;
591
592         case cmd_ret_802_11_disassociate:
593         case cmd_ret_802_11_deauthenticate:
594                 ret = libertas_ret_80211_disassociate(priv, resp);
595                 break;
596
597         case cmd_ret_802_11_ad_hoc_start:
598         case cmd_ret_802_11_ad_hoc_join:
599                 ret = libertas_ret_80211_ad_hoc_start(priv, resp);
600                 break;
601
602         case cmd_ret_802_11_stat:
603                 ret = wlan_ret_802_11_stat(priv, resp);
604                 break;
605
606         case cmd_ret_802_11_snmp_mib:
607                 ret = wlan_ret_802_11_snmp_mib(priv, resp);
608                 break;
609
610         case cmd_ret_802_11_rf_tx_power:
611                 ret = wlan_ret_802_11_rf_tx_power(priv, resp);
612                 break;
613
614         case cmd_ret_802_11_set_afc:
615         case cmd_ret_802_11_get_afc:
616                 spin_lock_irqsave(&adapter->driver_lock, flags);
617                 memmove(adapter->cur_cmd->pdata_buf,
618                         &resp->params.afc,
619                         sizeof(struct cmd_ds_802_11_afc));
620                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
621
622                 break;
623         case cmd_ret_802_11_rf_antenna:
624                 ret = wlan_ret_802_11_rf_antenna(priv, resp);
625                 break;
626
627         case cmd_ret_mac_multicast_adr:
628         case cmd_ret_mac_control:
629         case cmd_ret_802_11_set_wep:
630         case cmd_ret_802_11_reset:
631         case cmd_ret_802_11_authenticate:
632         case cmd_ret_802_11_radio_control:
633         case cmd_ret_802_11_beacon_stop:
634         case cmd_ret_802_11_enable_rsn:
635                 break;
636
637         case cmd_ret_802_11_data_rate:
638                 ret = wlan_ret_802_11_data_rate(priv, resp);
639                 break;
640         case cmd_ret_802_11_rate_adapt_rateset:
641                 ret = wlan_ret_802_11_rate_adapt_rateset(priv, resp);
642                 break;
643         case cmd_ret_802_11_rf_channel:
644                 ret = wlan_ret_802_11_rf_channel(priv, resp);
645                 break;
646
647         case cmd_ret_802_11_rssi:
648                 ret = wlan_ret_802_11_rssi(priv, resp);
649                 break;
650
651         case cmd_ret_802_11_mac_address:
652                 ret = wlan_ret_802_11_mac_address(priv, resp);
653                 break;
654
655         case cmd_ret_802_11_ad_hoc_stop:
656                 ret = libertas_ret_80211_ad_hoc_stop(priv, resp);
657                 break;
658
659         case cmd_ret_802_11_key_material:
660                 lbs_deb_cmd("CMD_RESP: KEY_MATERIAL command response\n");
661                 ret = wlan_ret_802_11_key_material(priv, resp);
662                 break;
663
664         case cmd_ret_802_11_eeprom_access:
665                 ret = wlan_ret_802_11_eeprom_access(priv, resp);
666                 break;
667
668         case cmd_ret_802_11d_domain_info:
669                 ret = libertas_ret_802_11d_domain_info(priv, resp);
670                 break;
671
672         case cmd_ret_802_11_sleep_params:
673                 ret = wlan_ret_802_11_sleep_params(priv, resp);
674                 break;
675         case cmd_ret_802_11_inactivity_timeout:
676                 spin_lock_irqsave(&adapter->driver_lock, flags);
677                 *((u16 *) adapter->cur_cmd->pdata_buf) =
678                     le16_to_cpu(resp->params.inactivity_timeout.timeout);
679                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
680                 break;
681
682         case cmd_ret_802_11_tpc_cfg:
683                 spin_lock_irqsave(&adapter->driver_lock, flags);
684                 memmove(adapter->cur_cmd->pdata_buf,
685                         &resp->params.tpccfg,
686                         sizeof(struct cmd_ds_802_11_tpc_cfg));
687                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
688                 break;
689         case cmd_ret_802_11_led_gpio_ctrl:
690                 spin_lock_irqsave(&adapter->driver_lock, flags);
691                 memmove(adapter->cur_cmd->pdata_buf,
692                         &resp->params.ledgpio,
693                         sizeof(struct cmd_ds_802_11_led_ctrl));
694                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
695                 break;
696         case cmd_ret_802_11_pwr_cfg:
697                 spin_lock_irqsave(&adapter->driver_lock, flags);
698                 memmove(adapter->cur_cmd->pdata_buf,
699                         &resp->params.pwrcfg,
700                         sizeof(struct cmd_ds_802_11_pwr_cfg));
701                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
702
703                 break;
704
705         case cmd_ret_get_tsf:
706                 spin_lock_irqsave(&adapter->driver_lock, flags);
707                 memcpy(priv->adapter->cur_cmd->pdata_buf,
708                        &resp->params.gettsf.tsfvalue, sizeof(u64));
709                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
710                 break;
711         case cmd_ret_bt_access:
712                 spin_lock_irqsave(&adapter->driver_lock, flags);
713                 if (adapter->cur_cmd->pdata_buf)
714                         memcpy(adapter->cur_cmd->pdata_buf,
715                                &resp->params.bt.addr1, 2 * ETH_ALEN);
716                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
717                 break;
718         case cmd_ret_fwt_access:
719                 spin_lock_irqsave(&adapter->driver_lock, flags);
720                 if (adapter->cur_cmd->pdata_buf)
721                         memcpy(adapter->cur_cmd->pdata_buf,
722                                &resp->params.fwt,
723                                 sizeof(resp->params.fwt));
724                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
725                 break;
726         case cmd_ret_mesh_access:
727                 if (adapter->cur_cmd->pdata_buf)
728                         memcpy(adapter->cur_cmd->pdata_buf,
729                                &resp->params.mesh,
730                                sizeof(resp->params.mesh));
731                 break;
732         case cmd_rte_802_11_tx_rate_query:
733                 priv->adapter->txrate = resp->params.txrate.txrate;
734                 break;
735         default:
736                 lbs_deb_cmd("CMD_RESP: Unknown command response %#x\n",
737                        resp->command);
738                 break;
739         }
740         return ret;
741 }
742
743 int libertas_process_rx_command(wlan_private * priv)
744 {
745         u16 respcmd;
746         struct cmd_ds_command *resp;
747         wlan_adapter *adapter = priv->adapter;
748         int ret = 0;
749         ulong flags;
750         u16 result;
751
752         lbs_deb_enter(LBS_DEB_CMD);
753
754         lbs_deb_cmd("CMD_RESP: @ %lu\n", jiffies);
755
756         /* Now we got response from FW, cancel the command timer */
757         del_timer(&adapter->command_timer);
758
759         mutex_lock(&adapter->lock);
760         spin_lock_irqsave(&adapter->driver_lock, flags);
761
762         if (!adapter->cur_cmd) {
763                 lbs_deb_cmd("CMD_RESP: NULL cur_cmd=%p\n", adapter->cur_cmd);
764                 ret = -1;
765                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
766                 goto done;
767         }
768         resp = (struct cmd_ds_command *)(adapter->cur_cmd->bufvirtualaddr);
769
770         lbs_dbg_hex("CMD_RESP:", adapter->cur_cmd->bufvirtualaddr,
771                 priv->upld_len);
772
773         respcmd = le16_to_cpu(resp->command);
774
775         result = le16_to_cpu(resp->result);
776
777         lbs_deb_cmd("CMD_RESP: %x result: %d length: %d\n", respcmd,
778                result, priv->upld_len);
779
780         if (!(respcmd & 0x8000)) {
781                 lbs_deb_cmd("Invalid response to command!");
782                 adapter->cur_cmd_retcode = -1;
783                 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
784                 adapter->nr_cmd_pending--;
785                 adapter->cur_cmd = NULL;
786                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
787                 ret = -1;
788                 goto done;
789         }
790
791         /* Store the response code to cur_cmd_retcode. */
792         adapter->cur_cmd_retcode = le16_to_cpu(resp->result);
793
794         if (respcmd == cmd_ret_802_11_ps_mode) {
795                 struct cmd_ds_802_11_ps_mode *psmode;
796
797                 psmode = &resp->params.psmode;
798                 lbs_deb_cmd(
799                        "CMD_RESP: PS_MODE cmd reply result=%#x action=0x%X\n",
800                        resp->result, psmode->action);
801                 psmode->action = cpu_to_le16(psmode->action);
802
803                 if (result) {
804                         lbs_deb_cmd("CMD_RESP: PS command failed- %#x \n",
805                                resp->result);
806                         if (adapter->mode == IW_MODE_ADHOC) {
807                                 /*
808                                  * We should not re-try enter-ps command in
809                                  * ad-hoc mode. It takes place in
810                                  * libertas_execute_next_command().
811                                  */
812                                 if (psmode->action == cmd_subcmd_enter_ps)
813                                         adapter->psmode =
814                                             wlan802_11powermodecam;
815                         }
816                 } else if (psmode->action == cmd_subcmd_enter_ps) {
817                         adapter->needtowakeup = 0;
818                         adapter->psstate = PS_STATE_AWAKE;
819
820                         lbs_deb_cmd("CMD_RESP: Enter_PS command response\n");
821                         if (adapter->connect_status != libertas_connected) {
822                                 /*
823                                  * When Deauth Event received before Enter_PS command
824                                  * response, We need to wake up the firmware.
825                                  */
826                                 lbs_deb_cmd(
827                                        "Disconnected, Going to invoke libertas_ps_wakeup\n");
828
829                                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
830                                 mutex_unlock(&adapter->lock);
831                                 libertas_ps_wakeup(priv, 0);
832                                 mutex_lock(&adapter->lock);
833                                 spin_lock_irqsave(&adapter->driver_lock, flags);
834                         }
835                 } else if (psmode->action == cmd_subcmd_exit_ps) {
836                         adapter->needtowakeup = 0;
837                         adapter->psstate = PS_STATE_FULL_POWER;
838                         lbs_deb_cmd("CMD_RESP: Exit_PS command response\n");
839                 } else {
840                         lbs_deb_cmd("CMD_RESP: PS- action=0x%X\n",
841                                psmode->action);
842                 }
843
844                 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
845                 adapter->nr_cmd_pending--;
846                 adapter->cur_cmd = NULL;
847                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
848
849                 ret = 0;
850                 goto done;
851         }
852
853         if (adapter->cur_cmd->cmdflags & CMD_F_HOSTCMD) {
854                 /* Copy the response back to response buffer */
855                 memcpy(adapter->cur_cmd->pdata_buf, resp, resp->size);
856
857                 adapter->cur_cmd->cmdflags &= ~CMD_F_HOSTCMD;
858         }
859
860         /* If the command is not successful, cleanup and return failure */
861         if ((result != 0 || !(respcmd & 0x8000))) {
862                 lbs_deb_cmd("CMD_RESP: command reply %#x result=%#x\n",
863                        resp->command, resp->result);
864                 /*
865                  * Handling errors here
866                  */
867                 switch (respcmd) {
868                 case cmd_ret_hw_spec_info:
869                 case cmd_ret_802_11_reset:
870                         lbs_deb_cmd("CMD_RESP: Reset command failed\n");
871                         break;
872
873                 }
874
875                 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
876                 adapter->nr_cmd_pending--;
877                 adapter->cur_cmd = NULL;
878                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
879
880                 ret = -1;
881                 goto done;
882         }
883
884         spin_unlock_irqrestore(&adapter->driver_lock, flags);
885
886         ret = handle_cmd_response(respcmd, resp, priv);
887
888         spin_lock_irqsave(&adapter->driver_lock, flags);
889         if (adapter->cur_cmd) {
890                 /* Clean up and Put current command back to cmdfreeq */
891                 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
892                 adapter->nr_cmd_pending--;
893                 WARN_ON(adapter->nr_cmd_pending > 128);
894                 adapter->cur_cmd = NULL;
895         }
896         spin_unlock_irqrestore(&adapter->driver_lock, flags);
897
898 done:
899         mutex_unlock(&adapter->lock);
900         lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
901         return ret;
902 }
903
904 int libertas_process_event(wlan_private * priv)
905 {
906         int ret = 0;
907         wlan_adapter *adapter = priv->adapter;
908         u32 eventcause;
909
910         spin_lock_irq(&adapter->driver_lock);
911         eventcause = adapter->eventcause;
912         spin_unlock_irq(&adapter->driver_lock);
913
914         lbs_deb_enter(LBS_DEB_CMD);
915
916         lbs_deb_cmd("EVENT Cause %x\n", eventcause);
917
918         switch (eventcause >> SBI_EVENT_CAUSE_SHIFT) {
919         case MACREG_INT_CODE_LINK_SENSED:
920                 lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n");
921                 break;
922
923         case MACREG_INT_CODE_DEAUTHENTICATED:
924                 lbs_deb_cmd("EVENT: Deauthenticated\n");
925                 libertas_mac_event_disconnected(priv);
926                 break;
927
928         case MACREG_INT_CODE_DISASSOCIATED:
929                 lbs_deb_cmd("EVENT: Disassociated\n");
930                 libertas_mac_event_disconnected(priv);
931                 break;
932
933         case MACREG_INT_CODE_LINK_LOSE_NO_SCAN:
934                 lbs_deb_cmd("EVENT: Link lost\n");
935                 libertas_mac_event_disconnected(priv);
936                 break;
937
938         case MACREG_INT_CODE_PS_SLEEP:
939                 lbs_deb_cmd("EVENT: SLEEP\n");
940                 lbs_deb_cmd("_");
941
942                 /* handle unexpected PS SLEEP event */
943                 if (adapter->psstate == PS_STATE_FULL_POWER) {
944                         lbs_deb_cmd(
945                                "EVENT: In FULL POWER mode - ignore PS SLEEP\n");
946                         break;
947                 }
948                 adapter->psstate = PS_STATE_PRE_SLEEP;
949
950                 libertas_ps_confirm_sleep(priv, (u16) adapter->psmode);
951
952                 break;
953
954         case MACREG_INT_CODE_PS_AWAKE:
955                 lbs_deb_cmd("EVENT: AWAKE \n");
956                 lbs_deb_cmd("|");
957
958                 /* handle unexpected PS AWAKE event */
959                 if (adapter->psstate == PS_STATE_FULL_POWER) {
960                         lbs_deb_cmd(
961                                "EVENT: In FULL POWER mode - ignore PS AWAKE\n");
962                         break;
963                 }
964
965                 adapter->psstate = PS_STATE_AWAKE;
966
967                 if (adapter->needtowakeup) {
968                         /*
969                          * wait for the command processing to finish
970                          * before resuming sending
971                          * adapter->needtowakeup will be set to FALSE
972                          * in libertas_ps_wakeup()
973                          */
974                         lbs_deb_cmd("Waking up...\n");
975                         libertas_ps_wakeup(priv, 0);
976                 }
977                 break;
978
979         case MACREG_INT_CODE_MIC_ERR_UNICAST:
980                 lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
981                 handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST);
982                 break;
983
984         case MACREG_INT_CODE_MIC_ERR_MULTICAST:
985                 lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
986                 handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
987                 break;
988         case MACREG_INT_CODE_MIB_CHANGED:
989         case MACREG_INT_CODE_INIT_DONE:
990                 break;
991
992         case MACREG_INT_CODE_ADHOC_BCN_LOST:
993                 lbs_deb_cmd("EVENT: HWAC - ADHOC BCN LOST\n");
994                 break;
995
996         case MACREG_INT_CODE_RSSI_LOW:
997                 lbs_pr_alert( "EVENT: RSSI_LOW\n");
998                 break;
999         case MACREG_INT_CODE_SNR_LOW:
1000                 lbs_pr_alert( "EVENT: SNR_LOW\n");
1001                 break;
1002         case MACREG_INT_CODE_MAX_FAIL:
1003                 lbs_pr_alert( "EVENT: MAX_FAIL\n");
1004                 break;
1005         case MACREG_INT_CODE_RSSI_HIGH:
1006                 lbs_pr_alert( "EVENT: RSSI_HIGH\n");
1007                 break;
1008         case MACREG_INT_CODE_SNR_HIGH:
1009                 lbs_pr_alert( "EVENT: SNR_HIGH\n");
1010                 break;
1011
1012         default:
1013                 lbs_pr_alert( "EVENT: unknown event id: %#x\n",
1014                        eventcause >> SBI_EVENT_CAUSE_SHIFT);
1015                 break;
1016         }
1017
1018         spin_lock_irq(&adapter->driver_lock);
1019         adapter->eventcause = 0;
1020         spin_unlock_irq(&adapter->driver_lock);
1021
1022         lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
1023         return ret;
1024 }