]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/net/wireless/libertas/cmdresp.c
[PATCH] libertas: fix two debug statements in cmdresp.c
[linux-2.6-omap-h63xx.git] / 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_enter(LBS_DEB_CMD);
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         lbs_deb_cmd("current SSID '%s', length %u\n",
64                     escape_essid(adapter->curbssparams.ssid,
65                                  adapter->curbssparams.ssid_len),
66                     adapter->curbssparams.ssid_len);
67
68         adapter->connect_status = LIBERTAS_DISCONNECTED;
69
70         /* Clear out associated SSID and BSSID since connection is
71          * no longer valid.
72          */
73         memset(&adapter->curbssparams.bssid, 0, ETH_ALEN);
74         memset(&adapter->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE);
75         adapter->curbssparams.ssid_len = 0;
76
77         if (adapter->psstate != PS_STATE_FULL_POWER) {
78                 /* make firmware to exit PS mode */
79                 lbs_deb_cmd("disconnected, so exit PS mode\n");
80                 libertas_ps_wakeup(priv, 0);
81         }
82         lbs_deb_leave(LBS_DEB_CMD);
83 }
84
85 /**
86  *  @brief This function handles MIC failure event.
87  *
88  *  @param priv    A pointer to wlan_private structure
89  *  @para  event   the event id
90  *  @return        n/a
91  */
92 static void handle_mic_failureevent(wlan_private * priv, u32 event)
93 {
94         char buf[50];
95
96         lbs_deb_enter(LBS_DEB_CMD);
97         memset(buf, 0, sizeof(buf));
98
99         sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
100
101         if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) {
102                 strcat(buf, "unicast ");
103         } else {
104                 strcat(buf, "multicast ");
105         }
106
107         libertas_send_iwevcustom_event(priv, buf);
108         lbs_deb_leave(LBS_DEB_CMD);
109 }
110
111 static int wlan_ret_reg_access(wlan_private * priv,
112                                u16 type, struct cmd_ds_command *resp)
113 {
114         int ret = 0;
115         wlan_adapter *adapter = priv->adapter;
116
117         lbs_deb_enter(LBS_DEB_CMD);
118
119         switch (type) {
120         case CMD_RET(CMD_MAC_REG_ACCESS):
121                 {
122                         struct cmd_ds_mac_reg_access *reg = &resp->params.macreg;
123
124                         adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
125                         adapter->offsetvalue.value = le32_to_cpu(reg->value);
126                         break;
127                 }
128
129         case CMD_RET(CMD_BBP_REG_ACCESS):
130                 {
131                         struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg;
132
133                         adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
134                         adapter->offsetvalue.value = reg->value;
135                         break;
136                 }
137
138         case CMD_RET(CMD_RF_REG_ACCESS):
139                 {
140                         struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg;
141
142                         adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
143                         adapter->offsetvalue.value = reg->value;
144                         break;
145                 }
146
147         default:
148                 ret = -1;
149         }
150
151         lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
152         return ret;
153 }
154
155 static int wlan_ret_get_hw_spec(wlan_private * priv,
156                                 struct cmd_ds_command *resp)
157 {
158         u32 i;
159         struct cmd_ds_get_hw_spec *hwspec = &resp->params.hwspec;
160         wlan_adapter *adapter = priv->adapter;
161         int ret = 0;
162
163         lbs_deb_enter(LBS_DEB_CMD);
164
165         adapter->fwcapinfo = le32_to_cpu(hwspec->fwcapinfo);
166
167         memcpy(adapter->fwreleasenumber, hwspec->fwreleasenumber, 4);
168
169         lbs_deb_cmd("GET_HW_SPEC: firmware release %u.%u.%up%u\n",
170                     adapter->fwreleasenumber[2], adapter->fwreleasenumber[1],
171                     adapter->fwreleasenumber[0], adapter->fwreleasenumber[3]);
172         lbs_deb_cmd("GET_HW_SPEC: MAC addr " MAC_FMT "\n",
173                MAC_ARG(hwspec->permanentaddr));
174         lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
175                hwspec->hwifversion, hwspec->version);
176
177         adapter->regioncode = le16_to_cpu(hwspec->regioncode);
178
179         for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
180                 /* use the region code to search for the index */
181                 if (adapter->regioncode == libertas_region_code_to_index[i]) {
182                         break;
183                 }
184         }
185
186         /* if it's unidentified region code, use the default (USA) */
187         if (i >= MRVDRV_MAX_REGION_CODE) {
188                 adapter->regioncode = 0x10;
189                 lbs_pr_info("unidentified region code; using the default (USA)\n");
190         }
191
192         if (adapter->current_addr[0] == 0xff)
193                 memmove(adapter->current_addr, hwspec->permanentaddr, ETH_ALEN);
194
195         memcpy(priv->dev->dev_addr, adapter->current_addr, ETH_ALEN);
196         if (priv->mesh_dev)
197                 memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);
198
199         if (libertas_set_regiontable(priv, adapter->regioncode, 0)) {
200                 ret = -1;
201                 goto done;
202         }
203
204         if (libertas_set_universaltable(priv, 0)) {
205                 ret = -1;
206                 goto done;
207         }
208
209 done:
210         lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
211         return ret;
212 }
213
214 static int wlan_ret_802_11_sleep_params(wlan_private * priv,
215                                         struct cmd_ds_command *resp)
216 {
217         struct cmd_ds_802_11_sleep_params *sp = &resp->params.sleep_params;
218         wlan_adapter *adapter = priv->adapter;
219
220         lbs_deb_enter(LBS_DEB_CMD);
221
222         lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, calcontrol 0x%x "
223                     "extsleepclk 0x%x\n", le16_to_cpu(sp->error),
224                     le16_to_cpu(sp->offset), le16_to_cpu(sp->stabletime),
225                     sp->calcontrol, sp->externalsleepclk);
226
227         adapter->sp.sp_error = le16_to_cpu(sp->error);
228         adapter->sp.sp_offset = le16_to_cpu(sp->offset);
229         adapter->sp.sp_stabletime = le16_to_cpu(sp->stabletime);
230         adapter->sp.sp_calcontrol = sp->calcontrol;
231         adapter->sp.sp_extsleepclk = sp->externalsleepclk;
232         adapter->sp.sp_reserved = le16_to_cpu(sp->reserved);
233
234         lbs_deb_enter(LBS_DEB_CMD);
235         return 0;
236 }
237
238 static int wlan_ret_802_11_stat(wlan_private * priv,
239                                 struct cmd_ds_command *resp)
240 {
241         lbs_deb_enter(LBS_DEB_CMD);
242 /*      currently adapter->wlan802_11Stat is unused
243
244         struct cmd_ds_802_11_get_stat *p11Stat = &resp->params.gstat;
245         wlan_adapter *adapter = priv->adapter;
246
247         // TODO Convert it to Big endian befor copy
248         memcpy(&adapter->wlan802_11Stat,
249                p11Stat, sizeof(struct cmd_ds_802_11_get_stat));
250 */
251         lbs_deb_leave(LBS_DEB_CMD);
252         return 0;
253 }
254
255 static int wlan_ret_802_11_snmp_mib(wlan_private * priv,
256                                     struct cmd_ds_command *resp)
257 {
258         struct cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
259         u16 oid = le16_to_cpu(smib->oid);
260         u16 querytype = le16_to_cpu(smib->querytype);
261
262         lbs_deb_enter(LBS_DEB_CMD);
263
264         lbs_deb_cmd("SNMP_RESP: oid 0x%x, querytype 0x%x\n", oid,
265                querytype);
266         lbs_deb_cmd("SNMP_RESP: Buf size %d\n", le16_to_cpu(smib->bufsize));
267
268         if (querytype == CMD_ACT_GET) {
269                 switch (oid) {
270                 case FRAGTHRESH_I:
271                         priv->adapter->fragthsd =
272                                 le16_to_cpu(*((__le16 *)(smib->value)));
273                         lbs_deb_cmd("SNMP_RESP: frag threshold %u\n",
274                                     priv->adapter->fragthsd);
275                         break;
276                 case RTSTHRESH_I:
277                         priv->adapter->rtsthsd =
278                                 le16_to_cpu(*((__le16 *)(smib->value)));
279                         lbs_deb_cmd("SNMP_RESP: rts threshold %u\n",
280                                     priv->adapter->rtsthsd);
281                         break;
282                 case SHORT_RETRYLIM_I:
283                         priv->adapter->txretrycount =
284                                 le16_to_cpu(*((__le16 *)(smib->value)));
285                         lbs_deb_cmd("SNMP_RESP: tx retry count %u\n",
286                                     priv->adapter->rtsthsd);
287                         break;
288                 default:
289                         break;
290                 }
291         }
292
293         lbs_deb_enter(LBS_DEB_CMD);
294         return 0;
295 }
296
297 static int wlan_ret_802_11_key_material(wlan_private * priv,
298                                         struct cmd_ds_command *resp)
299 {
300         struct cmd_ds_802_11_key_material *pkeymaterial =
301             &resp->params.keymaterial;
302         wlan_adapter *adapter = priv->adapter;
303         u16 action = le16_to_cpu(pkeymaterial->action);
304
305         lbs_deb_enter(LBS_DEB_CMD);
306
307         /* Copy the returned key to driver private data */
308         if (action == CMD_ACT_GET) {
309                 u8 * buf_ptr = (u8 *) &pkeymaterial->keyParamSet;
310                 u8 * resp_end = (u8 *) (resp + le16_to_cpu(resp->size));
311
312                 while (buf_ptr < resp_end) {
313                         struct MrvlIEtype_keyParamSet * pkeyparamset =
314                             (struct MrvlIEtype_keyParamSet *) buf_ptr;
315                         struct enc_key * pkey;
316                         u16 param_set_len = le16_to_cpu(pkeyparamset->length);
317                         u16 key_len = le16_to_cpu(pkeyparamset->keylen);
318                         u16 key_flags = le16_to_cpu(pkeyparamset->keyinfo);
319                         u16 key_type = le16_to_cpu(pkeyparamset->keytypeid);
320                         u8 * end;
321
322                         end = (u8 *) pkeyparamset + sizeof (pkeyparamset->type)
323                                                   + sizeof (pkeyparamset->length)
324                                                   + param_set_len;
325                         /* Make sure we don't access past the end of the IEs */
326                         if (end > resp_end)
327                                 break;
328
329                         if (key_flags & KEY_INFO_WPA_UNICAST)
330                                 pkey = &adapter->wpa_unicast_key;
331                         else if (key_flags & KEY_INFO_WPA_MCAST)
332                                 pkey = &adapter->wpa_mcast_key;
333                         else
334                                 break;
335
336                         /* Copy returned key into driver */
337                         memset(pkey, 0, sizeof(struct enc_key));
338                         if (key_len > sizeof(pkey->key))
339                                 break;
340                         pkey->type = key_type;
341                         pkey->flags = key_flags;
342                         pkey->len = key_len;
343                         memcpy(pkey->key, pkeyparamset->key, pkey->len);
344
345                         buf_ptr = end + 1;
346                 }
347         }
348
349         lbs_deb_enter(LBS_DEB_CMD);
350         return 0;
351 }
352
353 static int wlan_ret_802_11_mac_address(wlan_private * priv,
354                                        struct cmd_ds_command *resp)
355 {
356         struct cmd_ds_802_11_mac_address *macadd = &resp->params.macadd;
357         wlan_adapter *adapter = priv->adapter;
358
359         lbs_deb_enter(LBS_DEB_CMD);
360
361         memcpy(adapter->current_addr, macadd->macadd, ETH_ALEN);
362
363         lbs_deb_enter(LBS_DEB_CMD);
364         return 0;
365 }
366
367 static int wlan_ret_802_11_rf_tx_power(wlan_private * priv,
368                                        struct cmd_ds_command *resp)
369 {
370         struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp;
371         wlan_adapter *adapter = priv->adapter;
372
373         lbs_deb_enter(LBS_DEB_CMD);
374
375         adapter->txpowerlevel = le16_to_cpu(rtp->currentlevel);
376
377         lbs_deb_cmd("TX power currently %d\n", adapter->txpowerlevel);
378
379         lbs_deb_leave(LBS_DEB_CMD);
380         return 0;
381 }
382
383 static int wlan_ret_802_11_rate_adapt_rateset(wlan_private * priv,
384                                               struct cmd_ds_command *resp)
385 {
386         struct cmd_ds_802_11_rate_adapt_rateset *rates = &resp->params.rateset;
387         wlan_adapter *adapter = priv->adapter;
388
389         lbs_deb_enter(LBS_DEB_CMD);
390
391         if (rates->action == CMD_ACT_GET) {
392                 adapter->enablehwauto = le16_to_cpu(rates->enablehwauto);
393                 adapter->ratebitmap = le16_to_cpu(rates->bitmap);
394         }
395
396         lbs_deb_leave(LBS_DEB_CMD);
397         return 0;
398 }
399
400 static int wlan_ret_802_11_data_rate(wlan_private * priv,
401                                      struct cmd_ds_command *resp)
402 {
403         struct cmd_ds_802_11_data_rate *pdatarate = &resp->params.drate;
404         wlan_adapter *adapter = priv->adapter;
405
406         lbs_deb_enter(LBS_DEB_CMD);
407
408         lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) pdatarate,
409                 sizeof(struct cmd_ds_802_11_data_rate));
410
411         /* FIXME: get actual rates FW can do if this command actually returns
412          * all data rates supported.
413          */
414         adapter->cur_rate = libertas_fw_index_to_data_rate(pdatarate->rates[0]);
415         lbs_deb_cmd("DATA_RATE: current rate 0x%02x\n", adapter->cur_rate);
416
417         lbs_deb_leave(LBS_DEB_CMD);
418         return 0;
419 }
420
421 static int wlan_ret_802_11_rf_channel(wlan_private * priv,
422                                       struct cmd_ds_command *resp)
423 {
424         struct cmd_ds_802_11_rf_channel *rfchannel = &resp->params.rfchannel;
425         wlan_adapter *adapter = priv->adapter;
426         u16 action = le16_to_cpu(rfchannel->action);
427         u16 newchannel = le16_to_cpu(rfchannel->currentchannel);
428
429         lbs_deb_enter(LBS_DEB_CMD);
430
431         if (action == CMD_OPT_802_11_RF_CHANNEL_GET
432             && adapter->curbssparams.channel != newchannel) {
433                 lbs_deb_cmd("channel switch from %d to %d\n",
434                        adapter->curbssparams.channel, newchannel);
435
436                 /* Update the channel again */
437                 adapter->curbssparams.channel = newchannel;
438         }
439
440         lbs_deb_enter(LBS_DEB_CMD);
441         return 0;
442 }
443
444 static int wlan_ret_802_11_rssi(wlan_private * priv,
445                                 struct cmd_ds_command *resp)
446 {
447         struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
448         wlan_adapter *adapter = priv->adapter;
449
450         lbs_deb_enter(LBS_DEB_CMD);
451
452         /* store the non average value */
453         adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR);
454         adapter->NF[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->noisefloor);
455
456         adapter->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR);
457         adapter->NF[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgnoisefloor);
458
459         adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] =
460             CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
461                      adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
462
463         adapter->RSSI[TYPE_BEACON][TYPE_AVG] =
464             CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
465                      adapter->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
466
467         lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
468                adapter->RSSI[TYPE_BEACON][TYPE_NOAVG],
469                adapter->RSSI[TYPE_BEACON][TYPE_AVG]);
470
471         lbs_deb_leave(LBS_DEB_CMD);
472         return 0;
473 }
474
475 static int wlan_ret_802_11_eeprom_access(wlan_private * priv,
476                                   struct cmd_ds_command *resp)
477 {
478         wlan_adapter *adapter = priv->adapter;
479         struct wlan_ioctl_regrdwr *pbuf;
480         pbuf = (struct wlan_ioctl_regrdwr *) adapter->prdeeprom;
481
482         lbs_deb_enter_args(LBS_DEB_CMD, "len %d",
483                le16_to_cpu(resp->params.rdeeprom.bytecount));
484         if (pbuf->NOB < le16_to_cpu(resp->params.rdeeprom.bytecount)) {
485                 pbuf->NOB = 0;
486                 lbs_deb_cmd("EEPROM read length too big\n");
487                 return -1;
488         }
489         pbuf->NOB = le16_to_cpu(resp->params.rdeeprom.bytecount);
490         if (pbuf->NOB > 0) {
491
492                 memcpy(&pbuf->value, (u8 *) & resp->params.rdeeprom.value,
493                        le16_to_cpu(resp->params.rdeeprom.bytecount));
494                 lbs_deb_hex(LBS_DEB_CMD, "EEPROM", (char *)&pbuf->value,
495                         le16_to_cpu(resp->params.rdeeprom.bytecount));
496         }
497         lbs_deb_leave(LBS_DEB_CMD);
498         return 0;
499 }
500
501 static int wlan_ret_get_log(wlan_private * priv,
502                             struct cmd_ds_command *resp)
503 {
504         struct cmd_ds_802_11_get_log *logmessage = &resp->params.glog;
505         wlan_adapter *adapter = priv->adapter;
506
507         lbs_deb_enter(LBS_DEB_CMD);
508
509         /* Stored little-endian */
510         memcpy(&adapter->logmsg, logmessage, sizeof(struct cmd_ds_802_11_get_log));
511
512         lbs_deb_leave(LBS_DEB_CMD);
513         return 0;
514 }
515
516 static int libertas_ret_802_11_enable_rsn(wlan_private * priv,
517                                           struct cmd_ds_command *resp)
518 {
519         struct cmd_ds_802_11_enable_rsn *enable_rsn = &resp->params.enbrsn;
520         wlan_adapter *adapter = priv->adapter;
521         u32 * pdata_buf = adapter->cur_cmd->pdata_buf;
522
523         lbs_deb_enter(LBS_DEB_CMD);
524
525         if (enable_rsn->action == cpu_to_le16(CMD_ACT_GET)) {
526                 if (pdata_buf)
527                         *pdata_buf = (u32) le16_to_cpu(enable_rsn->enable);
528         }
529
530         lbs_deb_leave(LBS_DEB_CMD);
531         return 0;
532 }
533
534 static inline int handle_cmd_response(u16 respcmd,
535                                       struct cmd_ds_command *resp,
536                                       wlan_private *priv)
537 {
538         int ret = 0;
539         unsigned long flags;
540         wlan_adapter *adapter = priv->adapter;
541
542         lbs_deb_enter(LBS_DEB_HOST);
543
544         switch (respcmd) {
545         case CMD_RET(CMD_MAC_REG_ACCESS):
546         case CMD_RET(CMD_BBP_REG_ACCESS):
547         case CMD_RET(CMD_RF_REG_ACCESS):
548                 ret = wlan_ret_reg_access(priv, respcmd, resp);
549                 break;
550
551         case CMD_RET(CMD_GET_HW_SPEC):
552                 ret = wlan_ret_get_hw_spec(priv, resp);
553                 break;
554
555         case CMD_RET(CMD_802_11_SCAN):
556                 ret = libertas_ret_80211_scan(priv, resp);
557                 break;
558
559         case CMD_RET(CMD_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(CMD_802_11_ASSOCIATE):
565         case CMD_RET(CMD_802_11_REASSOCIATE):
566                 ret = libertas_ret_80211_associate(priv, resp);
567                 break;
568
569         case CMD_RET(CMD_802_11_DISASSOCIATE):
570         case CMD_RET(CMD_802_11_DEAUTHENTICATE):
571                 ret = libertas_ret_80211_disassociate(priv, resp);
572                 break;
573
574         case CMD_RET(CMD_802_11_AD_HOC_START):
575         case CMD_RET(CMD_802_11_AD_HOC_JOIN):
576                 ret = libertas_ret_80211_ad_hoc_start(priv, resp);
577                 break;
578
579         case CMD_RET(CMD_802_11_GET_STAT):
580                 ret = wlan_ret_802_11_stat(priv, resp);
581                 break;
582
583         case CMD_RET(CMD_802_11_SNMP_MIB):
584                 ret = wlan_ret_802_11_snmp_mib(priv, resp);
585                 break;
586
587         case CMD_RET(CMD_802_11_RF_TX_POWER):
588                 ret = wlan_ret_802_11_rf_tx_power(priv, resp);
589                 break;
590
591         case CMD_RET(CMD_802_11_SET_AFC):
592         case CMD_RET(CMD_802_11_GET_AFC):
593                 spin_lock_irqsave(&adapter->driver_lock, flags);
594                 memmove(adapter->cur_cmd->pdata_buf, &resp->params.afc,
595                         sizeof(struct cmd_ds_802_11_afc));
596                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
597
598                 break;
599
600         case CMD_RET(CMD_MAC_MULTICAST_ADR):
601         case CMD_RET(CMD_MAC_CONTROL):
602         case CMD_RET(CMD_802_11_SET_WEP):
603         case CMD_RET(CMD_802_11_RESET):
604         case CMD_RET(CMD_802_11_AUTHENTICATE):
605         case CMD_RET(CMD_802_11_RADIO_CONTROL):
606         case CMD_RET(CMD_802_11_BEACON_STOP):
607                 break;
608
609         case CMD_RET(CMD_802_11_ENABLE_RSN):
610                 ret = libertas_ret_802_11_enable_rsn(priv, resp);
611                 break;
612
613         case CMD_RET(CMD_802_11_DATA_RATE):
614                 ret = wlan_ret_802_11_data_rate(priv, resp);
615                 break;
616         case CMD_RET(CMD_802_11_RATE_ADAPT_RATESET):
617                 ret = wlan_ret_802_11_rate_adapt_rateset(priv, resp);
618                 break;
619         case CMD_RET(CMD_802_11_RF_CHANNEL):
620                 ret = wlan_ret_802_11_rf_channel(priv, resp);
621                 break;
622
623         case CMD_RET(CMD_802_11_RSSI):
624                 ret = wlan_ret_802_11_rssi(priv, resp);
625                 break;
626
627         case CMD_RET(CMD_802_11_MAC_ADDRESS):
628                 ret = wlan_ret_802_11_mac_address(priv, resp);
629                 break;
630
631         case CMD_RET(CMD_802_11_AD_HOC_STOP):
632                 ret = libertas_ret_80211_ad_hoc_stop(priv, resp);
633                 break;
634
635         case CMD_RET(CMD_802_11_KEY_MATERIAL):
636                 ret = wlan_ret_802_11_key_material(priv, resp);
637                 break;
638
639         case CMD_RET(CMD_802_11_EEPROM_ACCESS):
640                 ret = wlan_ret_802_11_eeprom_access(priv, resp);
641                 break;
642
643         case CMD_RET(CMD_802_11D_DOMAIN_INFO):
644                 ret = libertas_ret_802_11d_domain_info(priv, resp);
645                 break;
646
647         case CMD_RET(CMD_802_11_SLEEP_PARAMS):
648                 ret = wlan_ret_802_11_sleep_params(priv, resp);
649                 break;
650         case CMD_RET(CMD_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(CMD_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(CMD_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(CMD_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(CMD_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(CMD_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(CMD_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(CMD_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         default:
703                 lbs_deb_host("CMD_RESP: unknown cmd response 0x%04x\n",
704                             resp->command);
705                 break;
706         }
707         lbs_deb_leave(LBS_DEB_HOST);
708         return ret;
709 }
710
711 int libertas_process_rx_command(wlan_private * priv)
712 {
713         u16 respcmd;
714         struct cmd_ds_command *resp;
715         wlan_adapter *adapter = priv->adapter;
716         int ret = 0;
717         ulong flags;
718         u16 result;
719
720         lbs_deb_enter(LBS_DEB_HOST);
721
722         /* Now we got response from FW, cancel the command timer */
723         del_timer(&adapter->command_timer);
724
725         mutex_lock(&adapter->lock);
726         spin_lock_irqsave(&adapter->driver_lock, flags);
727
728         if (!adapter->cur_cmd) {
729                 lbs_deb_host("CMD_RESP: cur_cmd is NULL\n");
730                 ret = -1;
731                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
732                 goto done;
733         }
734         resp = (struct cmd_ds_command *)(adapter->cur_cmd->bufvirtualaddr);
735
736         respcmd = le16_to_cpu(resp->command);
737         result = le16_to_cpu(resp->result);
738
739         lbs_deb_host("CMD_RESP: response 0x%04x, size %d, jiffies %lu\n",
740                 respcmd, priv->upld_len, jiffies);
741         lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", adapter->cur_cmd->bufvirtualaddr,
742                     priv->upld_len);
743
744         if (!(respcmd & 0x8000)) {
745                 lbs_deb_host("invalid response!\n");
746                 adapter->cur_cmd_retcode = -1;
747                 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
748                 adapter->nr_cmd_pending--;
749                 adapter->cur_cmd = NULL;
750                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
751                 ret = -1;
752                 goto done;
753         }
754
755         /* Store the response code to cur_cmd_retcode. */
756         adapter->cur_cmd_retcode = result;;
757
758         if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
759                 struct cmd_ds_802_11_ps_mode *psmode = &resp->params.psmode;
760                 u16 action = le16_to_cpu(psmode->action);
761
762                 lbs_deb_host(
763                        "CMD_RESP: PS_MODE cmd reply result 0x%x, action 0x%x\n",
764                        result, action);
765
766                 if (result) {
767                         lbs_deb_host("CMD_RESP: PS command failed with 0x%x\n",
768                                     result);
769                         /*
770                          * We should not re-try enter-ps command in
771                          * ad-hoc mode. It takes place in
772                          * libertas_execute_next_command().
773                          */
774                         if (adapter->mode == IW_MODE_ADHOC &&
775                             action == CMD_SUBCMD_ENTER_PS)
776                                 adapter->psmode = WLAN802_11POWERMODECAM;
777                 } else if (action == CMD_SUBCMD_ENTER_PS) {
778                         adapter->needtowakeup = 0;
779                         adapter->psstate = PS_STATE_AWAKE;
780
781                         lbs_deb_host("CMD_RESP: ENTER_PS command response\n");
782                         if (adapter->connect_status != LIBERTAS_CONNECTED) {
783                                 /*
784                                  * When Deauth Event received before Enter_PS command
785                                  * response, We need to wake up the firmware.
786                                  */
787                                 lbs_deb_host(
788                                        "disconnected, invoking libertas_ps_wakeup\n");
789
790                                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
791                                 mutex_unlock(&adapter->lock);
792                                 libertas_ps_wakeup(priv, 0);
793                                 mutex_lock(&adapter->lock);
794                                 spin_lock_irqsave(&adapter->driver_lock, flags);
795                         }
796                 } else if (action == CMD_SUBCMD_EXIT_PS) {
797                         adapter->needtowakeup = 0;
798                         adapter->psstate = PS_STATE_FULL_POWER;
799                         lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
800                 } else {
801                         lbs_deb_host("CMD_RESP: PS action 0x%X\n", action);
802                 }
803
804                 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
805                 adapter->nr_cmd_pending--;
806                 adapter->cur_cmd = NULL;
807                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
808
809                 ret = 0;
810                 goto done;
811         }
812
813         if (adapter->cur_cmd->cmdflags & CMD_F_HOSTCMD) {
814                 /* Copy the response back to response buffer */
815                 memcpy(adapter->cur_cmd->pdata_buf, resp, resp->size);
816
817                 adapter->cur_cmd->cmdflags &= ~CMD_F_HOSTCMD;
818         }
819
820         /* If the command is not successful, cleanup and return failure */
821         if ((result != 0 || !(respcmd & 0x8000))) {
822                 lbs_deb_host("CMD_RESP: error 0x%04x in command reply 0x%04x\n",
823                        result, respcmd);
824                 /*
825                  * Handling errors here
826                  */
827                 switch (respcmd) {
828                 case CMD_RET(CMD_GET_HW_SPEC):
829                 case CMD_RET(CMD_802_11_RESET):
830                         lbs_deb_host("CMD_RESP: reset failed\n");
831                         break;
832
833                 }
834
835                 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
836                 adapter->nr_cmd_pending--;
837                 adapter->cur_cmd = NULL;
838                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
839
840                 ret = -1;
841                 goto done;
842         }
843
844         spin_unlock_irqrestore(&adapter->driver_lock, flags);
845
846         ret = handle_cmd_response(respcmd, resp, priv);
847
848         spin_lock_irqsave(&adapter->driver_lock, flags);
849         if (adapter->cur_cmd) {
850                 /* Clean up and Put current command back to cmdfreeq */
851                 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
852                 adapter->nr_cmd_pending--;
853                 WARN_ON(adapter->nr_cmd_pending > 128);
854                 adapter->cur_cmd = NULL;
855         }
856         spin_unlock_irqrestore(&adapter->driver_lock, flags);
857
858 done:
859         mutex_unlock(&adapter->lock);
860         lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
861         return ret;
862 }
863
864 int libertas_process_event(wlan_private * priv)
865 {
866         int ret = 0;
867         wlan_adapter *adapter = priv->adapter;
868         u32 eventcause;
869
870         lbs_deb_enter(LBS_DEB_CMD);
871
872         spin_lock_irq(&adapter->driver_lock);
873         eventcause = adapter->eventcause;
874         spin_unlock_irq(&adapter->driver_lock);
875
876         lbs_deb_cmd("event cause 0x%x\n", eventcause);
877
878         switch (eventcause >> SBI_EVENT_CAUSE_SHIFT) {
879         case MACREG_INT_CODE_LINK_SENSED:
880                 lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n");
881                 break;
882
883         case MACREG_INT_CODE_DEAUTHENTICATED:
884                 lbs_deb_cmd("EVENT: deauthenticated\n");
885                 libertas_mac_event_disconnected(priv);
886                 break;
887
888         case MACREG_INT_CODE_DISASSOCIATED:
889                 lbs_deb_cmd("EVENT: disassociated\n");
890                 libertas_mac_event_disconnected(priv);
891                 break;
892
893         case MACREG_INT_CODE_LINK_LOSE_NO_SCAN:
894                 lbs_deb_cmd("EVENT: link lost\n");
895                 libertas_mac_event_disconnected(priv);
896                 break;
897
898         case MACREG_INT_CODE_PS_SLEEP:
899                 lbs_deb_cmd("EVENT: sleep\n");
900
901                 /* handle unexpected PS SLEEP event */
902                 if (adapter->psstate == PS_STATE_FULL_POWER) {
903                         lbs_deb_cmd(
904                                "EVENT: in FULL POWER mode, ignoreing PS_SLEEP\n");
905                         break;
906                 }
907                 adapter->psstate = PS_STATE_PRE_SLEEP;
908
909                 libertas_ps_confirm_sleep(priv, (u16) adapter->psmode);
910
911                 break;
912
913         case MACREG_INT_CODE_PS_AWAKE:
914                 lbs_deb_cmd("EVENT: awake\n");
915
916                 /* handle unexpected PS AWAKE event */
917                 if (adapter->psstate == PS_STATE_FULL_POWER) {
918                         lbs_deb_cmd(
919                                "EVENT: In FULL POWER mode - ignore PS AWAKE\n");
920                         break;
921                 }
922
923                 adapter->psstate = PS_STATE_AWAKE;
924
925                 if (adapter->needtowakeup) {
926                         /*
927                          * wait for the command processing to finish
928                          * before resuming sending
929                          * adapter->needtowakeup will be set to FALSE
930                          * in libertas_ps_wakeup()
931                          */
932                         lbs_deb_cmd("waking up ...\n");
933                         libertas_ps_wakeup(priv, 0);
934                 }
935                 break;
936
937         case MACREG_INT_CODE_MIC_ERR_UNICAST:
938                 lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
939                 handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST);
940                 break;
941
942         case MACREG_INT_CODE_MIC_ERR_MULTICAST:
943                 lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
944                 handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
945                 break;
946         case MACREG_INT_CODE_MIB_CHANGED:
947         case MACREG_INT_CODE_INIT_DONE:
948                 break;
949
950         case MACREG_INT_CODE_ADHOC_BCN_LOST:
951                 lbs_deb_cmd("EVENT: ADHOC beacon lost\n");
952                 break;
953
954         case MACREG_INT_CODE_RSSI_LOW:
955                 lbs_pr_alert("EVENT: rssi low\n");
956                 break;
957         case MACREG_INT_CODE_SNR_LOW:
958                 lbs_pr_alert("EVENT: snr low\n");
959                 break;
960         case MACREG_INT_CODE_MAX_FAIL:
961                 lbs_pr_alert("EVENT: max fail\n");
962                 break;
963         case MACREG_INT_CODE_RSSI_HIGH:
964                 lbs_pr_alert("EVENT: rssi high\n");
965                 break;
966         case MACREG_INT_CODE_SNR_HIGH:
967                 lbs_pr_alert("EVENT: snr high\n");
968                 break;
969
970         case MACREG_INT_CODE_MESH_AUTO_STARTED:
971                 lbs_pr_info("EVENT: MESH_AUTO_STARTED\n");
972                 adapter->connect_status = LIBERTAS_CONNECTED;
973                 if (priv->mesh_open == 1) {
974                         netif_wake_queue(priv->mesh_dev);
975                         netif_carrier_on(priv->mesh_dev);
976                 }
977                 adapter->mode = IW_MODE_ADHOC;
978                 schedule_work(&priv->sync_channel);
979                 break;
980
981         default:
982                 lbs_pr_alert("EVENT: unknown event id 0x%04x\n",
983                        eventcause >> SBI_EVENT_CAUSE_SHIFT);
984                 break;
985         }
986
987         spin_lock_irq(&adapter->driver_lock);
988         adapter->eventcause = 0;
989         spin_unlock_irq(&adapter->driver_lock);
990
991         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
992         return ret;
993 }