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