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