]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/net/wireless/libertas/cmdresp.c
[PATCH] libertas: region code values specified as 8bit
[karo-tx-linux.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         /* Clamp region code to 8-bit since FW spec indicates that it should
178          * only ever be 8-bit, even though the field size is 16-bit.  Some firmware
179          * returns non-zero high 8 bits here.
180          */
181         adapter->regioncode = le16_to_cpu(hwspec->regioncode) & 0xFF;
182
183         for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
184                 /* use the region code to search for the index */
185                 if (adapter->regioncode == libertas_region_code_to_index[i]) {
186                         break;
187                 }
188         }
189
190         /* if it's unidentified region code, use the default (USA) */
191         if (i >= MRVDRV_MAX_REGION_CODE) {
192                 adapter->regioncode = 0x10;
193                 lbs_pr_info("unidentified region code; using the default (USA)\n");
194         }
195
196         if (adapter->current_addr[0] == 0xff)
197                 memmove(adapter->current_addr, hwspec->permanentaddr, ETH_ALEN);
198
199         memcpy(priv->dev->dev_addr, adapter->current_addr, ETH_ALEN);
200         if (priv->mesh_dev)
201                 memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);
202
203         if (libertas_set_regiontable(priv, adapter->regioncode, 0)) {
204                 ret = -1;
205                 goto done;
206         }
207
208         if (libertas_set_universaltable(priv, 0)) {
209                 ret = -1;
210                 goto done;
211         }
212
213 done:
214         lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
215         return ret;
216 }
217
218 static int wlan_ret_802_11_sleep_params(wlan_private * priv,
219                                         struct cmd_ds_command *resp)
220 {
221         struct cmd_ds_802_11_sleep_params *sp = &resp->params.sleep_params;
222         wlan_adapter *adapter = priv->adapter;
223
224         lbs_deb_enter(LBS_DEB_CMD);
225
226         lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, calcontrol 0x%x "
227                     "extsleepclk 0x%x\n", le16_to_cpu(sp->error),
228                     le16_to_cpu(sp->offset), le16_to_cpu(sp->stabletime),
229                     sp->calcontrol, sp->externalsleepclk);
230
231         adapter->sp.sp_error = le16_to_cpu(sp->error);
232         adapter->sp.sp_offset = le16_to_cpu(sp->offset);
233         adapter->sp.sp_stabletime = le16_to_cpu(sp->stabletime);
234         adapter->sp.sp_calcontrol = sp->calcontrol;
235         adapter->sp.sp_extsleepclk = sp->externalsleepclk;
236         adapter->sp.sp_reserved = le16_to_cpu(sp->reserved);
237
238         lbs_deb_enter(LBS_DEB_CMD);
239         return 0;
240 }
241
242 static int wlan_ret_802_11_stat(wlan_private * priv,
243                                 struct cmd_ds_command *resp)
244 {
245         lbs_deb_enter(LBS_DEB_CMD);
246 /*      currently adapter->wlan802_11Stat is unused
247
248         struct cmd_ds_802_11_get_stat *p11Stat = &resp->params.gstat;
249         wlan_adapter *adapter = priv->adapter;
250
251         // TODO Convert it to Big endian befor copy
252         memcpy(&adapter->wlan802_11Stat,
253                p11Stat, sizeof(struct cmd_ds_802_11_get_stat));
254 */
255         lbs_deb_leave(LBS_DEB_CMD);
256         return 0;
257 }
258
259 static int wlan_ret_802_11_snmp_mib(wlan_private * priv,
260                                     struct cmd_ds_command *resp)
261 {
262         struct cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
263         u16 oid = le16_to_cpu(smib->oid);
264         u16 querytype = le16_to_cpu(smib->querytype);
265
266         lbs_deb_enter(LBS_DEB_CMD);
267
268         lbs_deb_cmd("SNMP_RESP: oid 0x%x, querytype 0x%x\n", oid,
269                querytype);
270         lbs_deb_cmd("SNMP_RESP: Buf size %d\n", le16_to_cpu(smib->bufsize));
271
272         if (querytype == CMD_ACT_GET) {
273                 switch (oid) {
274                 case FRAGTHRESH_I:
275                         priv->adapter->fragthsd =
276                                 le16_to_cpu(*((__le16 *)(smib->value)));
277                         lbs_deb_cmd("SNMP_RESP: frag threshold %u\n",
278                                     priv->adapter->fragthsd);
279                         break;
280                 case RTSTHRESH_I:
281                         priv->adapter->rtsthsd =
282                                 le16_to_cpu(*((__le16 *)(smib->value)));
283                         lbs_deb_cmd("SNMP_RESP: rts threshold %u\n",
284                                     priv->adapter->rtsthsd);
285                         break;
286                 case SHORT_RETRYLIM_I:
287                         priv->adapter->txretrycount =
288                                 le16_to_cpu(*((__le16 *)(smib->value)));
289                         lbs_deb_cmd("SNMP_RESP: tx retry count %u\n",
290                                     priv->adapter->rtsthsd);
291                         break;
292                 default:
293                         break;
294                 }
295         }
296
297         lbs_deb_enter(LBS_DEB_CMD);
298         return 0;
299 }
300
301 static int wlan_ret_802_11_key_material(wlan_private * priv,
302                                         struct cmd_ds_command *resp)
303 {
304         struct cmd_ds_802_11_key_material *pkeymaterial =
305             &resp->params.keymaterial;
306         wlan_adapter *adapter = priv->adapter;
307         u16 action = le16_to_cpu(pkeymaterial->action);
308
309         lbs_deb_enter(LBS_DEB_CMD);
310
311         /* Copy the returned key to driver private data */
312         if (action == CMD_ACT_GET) {
313                 u8 * buf_ptr = (u8 *) &pkeymaterial->keyParamSet;
314                 u8 * resp_end = (u8 *) (resp + le16_to_cpu(resp->size));
315
316                 while (buf_ptr < resp_end) {
317                         struct MrvlIEtype_keyParamSet * pkeyparamset =
318                             (struct MrvlIEtype_keyParamSet *) buf_ptr;
319                         struct enc_key * pkey;
320                         u16 param_set_len = le16_to_cpu(pkeyparamset->length);
321                         u16 key_len = le16_to_cpu(pkeyparamset->keylen);
322                         u16 key_flags = le16_to_cpu(pkeyparamset->keyinfo);
323                         u16 key_type = le16_to_cpu(pkeyparamset->keytypeid);
324                         u8 * end;
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_flags & KEY_INFO_WPA_UNICAST)
334                                 pkey = &adapter->wpa_unicast_key;
335                         else if (key_flags & 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 enc_key));
342                         if (key_len > sizeof(pkey->key))
343                                 break;
344                         pkey->type = key_type;
345                         pkey->flags = key_flags;
346                         pkey->len = key_len;
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("TX power currently %d\n", adapter->txpowerlevel);
382
383         lbs_deb_leave(LBS_DEB_CMD);
384         return 0;
385 }
386
387 static int wlan_ret_802_11_rate_adapt_rateset(wlan_private * priv,
388                                               struct cmd_ds_command *resp)
389 {
390         struct cmd_ds_802_11_rate_adapt_rateset *rates = &resp->params.rateset;
391         wlan_adapter *adapter = priv->adapter;
392
393         lbs_deb_enter(LBS_DEB_CMD);
394
395         if (rates->action == CMD_ACT_GET) {
396                 adapter->enablehwauto = le16_to_cpu(rates->enablehwauto);
397                 adapter->ratebitmap = le16_to_cpu(rates->bitmap);
398         }
399
400         lbs_deb_leave(LBS_DEB_CMD);
401         return 0;
402 }
403
404 static int wlan_ret_802_11_data_rate(wlan_private * priv,
405                                      struct cmd_ds_command *resp)
406 {
407         struct cmd_ds_802_11_data_rate *pdatarate = &resp->params.drate;
408         wlan_adapter *adapter = priv->adapter;
409
410         lbs_deb_enter(LBS_DEB_CMD);
411
412         lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) pdatarate,
413                 sizeof(struct cmd_ds_802_11_data_rate));
414
415         /* FIXME: get actual rates FW can do if this command actually returns
416          * all data rates supported.
417          */
418         adapter->cur_rate = libertas_fw_index_to_data_rate(pdatarate->rates[0]);
419         lbs_deb_cmd("DATA_RATE: current rate 0x%02x\n", adapter->cur_rate);
420
421         lbs_deb_leave(LBS_DEB_CMD);
422         return 0;
423 }
424
425 static int wlan_ret_802_11_rf_channel(wlan_private * priv,
426                                       struct cmd_ds_command *resp)
427 {
428         struct cmd_ds_802_11_rf_channel *rfchannel = &resp->params.rfchannel;
429         wlan_adapter *adapter = priv->adapter;
430         u16 action = le16_to_cpu(rfchannel->action);
431         u16 newchannel = le16_to_cpu(rfchannel->currentchannel);
432
433         lbs_deb_enter(LBS_DEB_CMD);
434
435         if (action == CMD_OPT_802_11_RF_CHANNEL_GET
436             && adapter->curbssparams.channel != newchannel) {
437                 lbs_deb_cmd("channel switch from %d to %d\n",
438                        adapter->curbssparams.channel, newchannel);
439
440                 /* Update the channel again */
441                 adapter->curbssparams.channel = newchannel;
442         }
443
444         lbs_deb_enter(LBS_DEB_CMD);
445         return 0;
446 }
447
448 static int wlan_ret_802_11_rssi(wlan_private * priv,
449                                 struct cmd_ds_command *resp)
450 {
451         struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
452         wlan_adapter *adapter = priv->adapter;
453
454         lbs_deb_enter(LBS_DEB_CMD);
455
456         /* store the non average value */
457         adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR);
458         adapter->NF[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->noisefloor);
459
460         adapter->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR);
461         adapter->NF[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgnoisefloor);
462
463         adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] =
464             CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
465                      adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
466
467         adapter->RSSI[TYPE_BEACON][TYPE_AVG] =
468             CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
469                      adapter->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
470
471         lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
472                adapter->RSSI[TYPE_BEACON][TYPE_NOAVG],
473                adapter->RSSI[TYPE_BEACON][TYPE_AVG]);
474
475         lbs_deb_leave(LBS_DEB_CMD);
476         return 0;
477 }
478
479 static int wlan_ret_802_11_eeprom_access(wlan_private * priv,
480                                   struct cmd_ds_command *resp)
481 {
482         wlan_adapter *adapter = priv->adapter;
483         struct wlan_ioctl_regrdwr *pbuf;
484         pbuf = (struct wlan_ioctl_regrdwr *) adapter->prdeeprom;
485
486         lbs_deb_enter_args(LBS_DEB_CMD, "len %d",
487                le16_to_cpu(resp->params.rdeeprom.bytecount));
488         if (pbuf->NOB < le16_to_cpu(resp->params.rdeeprom.bytecount)) {
489                 pbuf->NOB = 0;
490                 lbs_deb_cmd("EEPROM read length too big\n");
491                 return -1;
492         }
493         pbuf->NOB = le16_to_cpu(resp->params.rdeeprom.bytecount);
494         if (pbuf->NOB > 0) {
495
496                 memcpy(&pbuf->value, (u8 *) & resp->params.rdeeprom.value,
497                        le16_to_cpu(resp->params.rdeeprom.bytecount));
498                 lbs_deb_hex(LBS_DEB_CMD, "EEPROM", (char *)&pbuf->value,
499                         le16_to_cpu(resp->params.rdeeprom.bytecount));
500         }
501         lbs_deb_leave(LBS_DEB_CMD);
502         return 0;
503 }
504
505 static int wlan_ret_get_log(wlan_private * priv,
506                             struct cmd_ds_command *resp)
507 {
508         struct cmd_ds_802_11_get_log *logmessage = &resp->params.glog;
509         wlan_adapter *adapter = priv->adapter;
510
511         lbs_deb_enter(LBS_DEB_CMD);
512
513         /* Stored little-endian */
514         memcpy(&adapter->logmsg, logmessage, sizeof(struct cmd_ds_802_11_get_log));
515
516         lbs_deb_leave(LBS_DEB_CMD);
517         return 0;
518 }
519
520 static int libertas_ret_802_11_enable_rsn(wlan_private * priv,
521                                           struct cmd_ds_command *resp)
522 {
523         struct cmd_ds_802_11_enable_rsn *enable_rsn = &resp->params.enbrsn;
524         wlan_adapter *adapter = priv->adapter;
525         u32 * pdata_buf = adapter->cur_cmd->pdata_buf;
526
527         lbs_deb_enter(LBS_DEB_CMD);
528
529         if (enable_rsn->action == cpu_to_le16(CMD_ACT_GET)) {
530                 if (pdata_buf)
531                         *pdata_buf = (u32) le16_to_cpu(enable_rsn->enable);
532         }
533
534         lbs_deb_leave(LBS_DEB_CMD);
535         return 0;
536 }
537
538 static inline int handle_cmd_response(u16 respcmd,
539                                       struct cmd_ds_command *resp,
540                                       wlan_private *priv)
541 {
542         int ret = 0;
543         unsigned long flags;
544         wlan_adapter *adapter = priv->adapter;
545
546         lbs_deb_enter(LBS_DEB_HOST);
547
548         switch (respcmd) {
549         case CMD_RET(CMD_MAC_REG_ACCESS):
550         case CMD_RET(CMD_BBP_REG_ACCESS):
551         case CMD_RET(CMD_RF_REG_ACCESS):
552                 ret = wlan_ret_reg_access(priv, respcmd, resp);
553                 break;
554
555         case CMD_RET(CMD_GET_HW_SPEC):
556                 ret = wlan_ret_get_hw_spec(priv, resp);
557                 break;
558
559         case CMD_RET(CMD_802_11_SCAN):
560                 ret = libertas_ret_80211_scan(priv, resp);
561                 break;
562
563         case CMD_RET(CMD_802_11_GET_LOG):
564                 ret = wlan_ret_get_log(priv, resp);
565                 break;
566
567         case CMD_RET_802_11_ASSOCIATE:
568         case CMD_RET(CMD_802_11_ASSOCIATE):
569         case CMD_RET(CMD_802_11_REASSOCIATE):
570                 ret = libertas_ret_80211_associate(priv, resp);
571                 break;
572
573         case CMD_RET(CMD_802_11_DISASSOCIATE):
574         case CMD_RET(CMD_802_11_DEAUTHENTICATE):
575                 ret = libertas_ret_80211_disassociate(priv, resp);
576                 break;
577
578         case CMD_RET(CMD_802_11_AD_HOC_START):
579         case CMD_RET(CMD_802_11_AD_HOC_JOIN):
580                 ret = libertas_ret_80211_ad_hoc_start(priv, resp);
581                 break;
582
583         case CMD_RET(CMD_802_11_GET_STAT):
584                 ret = wlan_ret_802_11_stat(priv, resp);
585                 break;
586
587         case CMD_RET(CMD_802_11_SNMP_MIB):
588                 ret = wlan_ret_802_11_snmp_mib(priv, resp);
589                 break;
590
591         case CMD_RET(CMD_802_11_RF_TX_POWER):
592                 ret = wlan_ret_802_11_rf_tx_power(priv, resp);
593                 break;
594
595         case CMD_RET(CMD_802_11_SET_AFC):
596         case CMD_RET(CMD_802_11_GET_AFC):
597                 spin_lock_irqsave(&adapter->driver_lock, flags);
598                 memmove(adapter->cur_cmd->pdata_buf, &resp->params.afc,
599                         sizeof(struct cmd_ds_802_11_afc));
600                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
601
602                 break;
603
604         case CMD_RET(CMD_MAC_MULTICAST_ADR):
605         case CMD_RET(CMD_MAC_CONTROL):
606         case CMD_RET(CMD_802_11_SET_WEP):
607         case CMD_RET(CMD_802_11_RESET):
608         case CMD_RET(CMD_802_11_AUTHENTICATE):
609         case CMD_RET(CMD_802_11_RADIO_CONTROL):
610         case CMD_RET(CMD_802_11_BEACON_STOP):
611                 break;
612
613         case CMD_RET(CMD_802_11_ENABLE_RSN):
614                 ret = libertas_ret_802_11_enable_rsn(priv, resp);
615                 break;
616
617         case CMD_RET(CMD_802_11_DATA_RATE):
618                 ret = wlan_ret_802_11_data_rate(priv, resp);
619                 break;
620         case CMD_RET(CMD_802_11_RATE_ADAPT_RATESET):
621                 ret = wlan_ret_802_11_rate_adapt_rateset(priv, resp);
622                 break;
623         case CMD_RET(CMD_802_11_RF_CHANNEL):
624                 ret = wlan_ret_802_11_rf_channel(priv, resp);
625                 break;
626
627         case CMD_RET(CMD_802_11_RSSI):
628                 ret = wlan_ret_802_11_rssi(priv, resp);
629                 break;
630
631         case CMD_RET(CMD_802_11_MAC_ADDRESS):
632                 ret = wlan_ret_802_11_mac_address(priv, resp);
633                 break;
634
635         case CMD_RET(CMD_802_11_AD_HOC_STOP):
636                 ret = libertas_ret_80211_ad_hoc_stop(priv, resp);
637                 break;
638
639         case CMD_RET(CMD_802_11_KEY_MATERIAL):
640                 ret = wlan_ret_802_11_key_material(priv, resp);
641                 break;
642
643         case CMD_RET(CMD_802_11_EEPROM_ACCESS):
644                 ret = wlan_ret_802_11_eeprom_access(priv, resp);
645                 break;
646
647         case CMD_RET(CMD_802_11D_DOMAIN_INFO):
648                 ret = libertas_ret_802_11d_domain_info(priv, resp);
649                 break;
650
651         case CMD_RET(CMD_802_11_SLEEP_PARAMS):
652                 ret = wlan_ret_802_11_sleep_params(priv, resp);
653                 break;
654         case CMD_RET(CMD_802_11_INACTIVITY_TIMEOUT):
655                 spin_lock_irqsave(&adapter->driver_lock, flags);
656                 *((u16 *) adapter->cur_cmd->pdata_buf) =
657                     le16_to_cpu(resp->params.inactivity_timeout.timeout);
658                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
659                 break;
660
661         case CMD_RET(CMD_802_11_TPC_CFG):
662                 spin_lock_irqsave(&adapter->driver_lock, flags);
663                 memmove(adapter->cur_cmd->pdata_buf, &resp->params.tpccfg,
664                         sizeof(struct cmd_ds_802_11_tpc_cfg));
665                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
666                 break;
667         case CMD_RET(CMD_802_11_LED_GPIO_CTRL):
668                 spin_lock_irqsave(&adapter->driver_lock, flags);
669                 memmove(adapter->cur_cmd->pdata_buf, &resp->params.ledgpio,
670                         sizeof(struct cmd_ds_802_11_led_ctrl));
671                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
672                 break;
673         case CMD_RET(CMD_802_11_PWR_CFG):
674                 spin_lock_irqsave(&adapter->driver_lock, flags);
675                 memmove(adapter->cur_cmd->pdata_buf, &resp->params.pwrcfg,
676                         sizeof(struct cmd_ds_802_11_pwr_cfg));
677                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
678
679                 break;
680
681         case CMD_RET(CMD_GET_TSF):
682                 spin_lock_irqsave(&adapter->driver_lock, flags);
683                 memcpy(priv->adapter->cur_cmd->pdata_buf,
684                        &resp->params.gettsf.tsfvalue, sizeof(u64));
685                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
686                 break;
687         case CMD_RET(CMD_BT_ACCESS):
688                 spin_lock_irqsave(&adapter->driver_lock, flags);
689                 if (adapter->cur_cmd->pdata_buf)
690                         memcpy(adapter->cur_cmd->pdata_buf,
691                                &resp->params.bt.addr1, 2 * ETH_ALEN);
692                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
693                 break;
694         case CMD_RET(CMD_FWT_ACCESS):
695                 spin_lock_irqsave(&adapter->driver_lock, flags);
696                 if (adapter->cur_cmd->pdata_buf)
697                         memcpy(adapter->cur_cmd->pdata_buf, &resp->params.fwt,
698                                sizeof(resp->params.fwt));
699                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
700                 break;
701         case CMD_RET(CMD_MESH_ACCESS):
702                 if (adapter->cur_cmd->pdata_buf)
703                         memcpy(adapter->cur_cmd->pdata_buf, &resp->params.mesh,
704                                sizeof(resp->params.mesh));
705                 break;
706         default:
707                 lbs_deb_host("CMD_RESP: unknown cmd response 0x%04x\n",
708                             resp->command);
709                 break;
710         }
711         lbs_deb_leave(LBS_DEB_HOST);
712         return ret;
713 }
714
715 int libertas_process_rx_command(wlan_private * priv)
716 {
717         u16 respcmd;
718         struct cmd_ds_command *resp;
719         wlan_adapter *adapter = priv->adapter;
720         int ret = 0;
721         ulong flags;
722         u16 result;
723
724         lbs_deb_enter(LBS_DEB_HOST);
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_host("CMD_RESP: cur_cmd is NULL\n");
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         respcmd = le16_to_cpu(resp->command);
741         result = le16_to_cpu(resp->result);
742
743         lbs_deb_host("CMD_RESP: response 0x%04x, size %d, jiffies %lu\n",
744                 respcmd, priv->upld_len, jiffies);
745         lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", adapter->cur_cmd->bufvirtualaddr,
746                     priv->upld_len);
747
748         if (!(respcmd & 0x8000)) {
749                 lbs_deb_host("invalid response!\n");
750                 adapter->cur_cmd_retcode = -1;
751                 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
752                 adapter->nr_cmd_pending--;
753                 adapter->cur_cmd = NULL;
754                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
755                 ret = -1;
756                 goto done;
757         }
758
759         /* Store the response code to cur_cmd_retcode. */
760         adapter->cur_cmd_retcode = result;;
761
762         if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
763                 struct cmd_ds_802_11_ps_mode *psmode = &resp->params.psmode;
764                 u16 action = le16_to_cpu(psmode->action);
765
766                 lbs_deb_host(
767                        "CMD_RESP: PS_MODE cmd reply result 0x%x, action 0x%x\n",
768                        result, action);
769
770                 if (result) {
771                         lbs_deb_host("CMD_RESP: PS command failed with 0x%x\n",
772                                     result);
773                         /*
774                          * We should not re-try enter-ps command in
775                          * ad-hoc mode. It takes place in
776                          * libertas_execute_next_command().
777                          */
778                         if (adapter->mode == IW_MODE_ADHOC &&
779                             action == CMD_SUBCMD_ENTER_PS)
780                                 adapter->psmode = WLAN802_11POWERMODECAM;
781                 } else if (action == CMD_SUBCMD_ENTER_PS) {
782                         adapter->needtowakeup = 0;
783                         adapter->psstate = PS_STATE_AWAKE;
784
785                         lbs_deb_host("CMD_RESP: ENTER_PS command response\n");
786                         if (adapter->connect_status != LIBERTAS_CONNECTED) {
787                                 /*
788                                  * When Deauth Event received before Enter_PS command
789                                  * response, We need to wake up the firmware.
790                                  */
791                                 lbs_deb_host(
792                                        "disconnected, invoking libertas_ps_wakeup\n");
793
794                                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
795                                 mutex_unlock(&adapter->lock);
796                                 libertas_ps_wakeup(priv, 0);
797                                 mutex_lock(&adapter->lock);
798                                 spin_lock_irqsave(&adapter->driver_lock, flags);
799                         }
800                 } else if (action == CMD_SUBCMD_EXIT_PS) {
801                         adapter->needtowakeup = 0;
802                         adapter->psstate = PS_STATE_FULL_POWER;
803                         lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
804                 } else {
805                         lbs_deb_host("CMD_RESP: PS action 0x%X\n", action);
806                 }
807
808                 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
809                 adapter->nr_cmd_pending--;
810                 adapter->cur_cmd = NULL;
811                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
812
813                 ret = 0;
814                 goto done;
815         }
816
817         if (adapter->cur_cmd->cmdflags & CMD_F_HOSTCMD) {
818                 /* Copy the response back to response buffer */
819                 memcpy(adapter->cur_cmd->pdata_buf, resp,
820                        le16_to_cpu(resp->size));
821                 adapter->cur_cmd->cmdflags &= ~CMD_F_HOSTCMD;
822         }
823
824         /* If the command is not successful, cleanup and return failure */
825         if ((result != 0 || !(respcmd & 0x8000))) {
826                 lbs_deb_host("CMD_RESP: error 0x%04x in command reply 0x%04x\n",
827                        result, respcmd);
828                 /*
829                  * Handling errors here
830                  */
831                 switch (respcmd) {
832                 case CMD_RET(CMD_GET_HW_SPEC):
833                 case CMD_RET(CMD_802_11_RESET):
834                         lbs_deb_host("CMD_RESP: reset failed\n");
835                         break;
836
837                 }
838
839                 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
840                 adapter->nr_cmd_pending--;
841                 adapter->cur_cmd = NULL;
842                 spin_unlock_irqrestore(&adapter->driver_lock, flags);
843
844                 ret = -1;
845                 goto done;
846         }
847
848         spin_unlock_irqrestore(&adapter->driver_lock, flags);
849
850         ret = handle_cmd_response(respcmd, resp, priv);
851
852         spin_lock_irqsave(&adapter->driver_lock, flags);
853         if (adapter->cur_cmd) {
854                 /* Clean up and Put current command back to cmdfreeq */
855                 __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
856                 adapter->nr_cmd_pending--;
857                 WARN_ON(adapter->nr_cmd_pending > 128);
858                 adapter->cur_cmd = NULL;
859         }
860         spin_unlock_irqrestore(&adapter->driver_lock, flags);
861
862 done:
863         mutex_unlock(&adapter->lock);
864         lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
865         return ret;
866 }
867
868 int libertas_process_event(wlan_private * priv)
869 {
870         int ret = 0;
871         wlan_adapter *adapter = priv->adapter;
872         u32 eventcause;
873
874         lbs_deb_enter(LBS_DEB_CMD);
875
876         spin_lock_irq(&adapter->driver_lock);
877         eventcause = adapter->eventcause;
878         spin_unlock_irq(&adapter->driver_lock);
879
880         lbs_deb_cmd("event cause 0x%x\n", eventcause);
881
882         switch (eventcause >> SBI_EVENT_CAUSE_SHIFT) {
883         case MACREG_INT_CODE_LINK_SENSED:
884                 lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n");
885                 break;
886
887         case MACREG_INT_CODE_DEAUTHENTICATED:
888                 lbs_deb_cmd("EVENT: deauthenticated\n");
889                 libertas_mac_event_disconnected(priv);
890                 break;
891
892         case MACREG_INT_CODE_DISASSOCIATED:
893                 lbs_deb_cmd("EVENT: disassociated\n");
894                 libertas_mac_event_disconnected(priv);
895                 break;
896
897         case MACREG_INT_CODE_LINK_LOSE_NO_SCAN:
898                 lbs_deb_cmd("EVENT: link lost\n");
899                 libertas_mac_event_disconnected(priv);
900                 break;
901
902         case MACREG_INT_CODE_PS_SLEEP:
903                 lbs_deb_cmd("EVENT: sleep\n");
904
905                 /* handle unexpected PS SLEEP event */
906                 if (adapter->psstate == PS_STATE_FULL_POWER) {
907                         lbs_deb_cmd(
908                                "EVENT: in FULL POWER mode, ignoreing PS_SLEEP\n");
909                         break;
910                 }
911                 adapter->psstate = PS_STATE_PRE_SLEEP;
912
913                 libertas_ps_confirm_sleep(priv, (u16) adapter->psmode);
914
915                 break;
916
917         case MACREG_INT_CODE_PS_AWAKE:
918                 lbs_deb_cmd("EVENT: awake\n");
919
920                 /* handle unexpected PS AWAKE event */
921                 if (adapter->psstate == PS_STATE_FULL_POWER) {
922                         lbs_deb_cmd(
923                                "EVENT: In FULL POWER mode - ignore PS AWAKE\n");
924                         break;
925                 }
926
927                 adapter->psstate = PS_STATE_AWAKE;
928
929                 if (adapter->needtowakeup) {
930                         /*
931                          * wait for the command processing to finish
932                          * before resuming sending
933                          * adapter->needtowakeup will be set to FALSE
934                          * in libertas_ps_wakeup()
935                          */
936                         lbs_deb_cmd("waking up ...\n");
937                         libertas_ps_wakeup(priv, 0);
938                 }
939                 break;
940
941         case MACREG_INT_CODE_MIC_ERR_UNICAST:
942                 lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
943                 handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST);
944                 break;
945
946         case MACREG_INT_CODE_MIC_ERR_MULTICAST:
947                 lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
948                 handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
949                 break;
950         case MACREG_INT_CODE_MIB_CHANGED:
951         case MACREG_INT_CODE_INIT_DONE:
952                 break;
953
954         case MACREG_INT_CODE_ADHOC_BCN_LOST:
955                 lbs_deb_cmd("EVENT: ADHOC beacon lost\n");
956                 break;
957
958         case MACREG_INT_CODE_RSSI_LOW:
959                 lbs_pr_alert("EVENT: rssi low\n");
960                 break;
961         case MACREG_INT_CODE_SNR_LOW:
962                 lbs_pr_alert("EVENT: snr low\n");
963                 break;
964         case MACREG_INT_CODE_MAX_FAIL:
965                 lbs_pr_alert("EVENT: max fail\n");
966                 break;
967         case MACREG_INT_CODE_RSSI_HIGH:
968                 lbs_pr_alert("EVENT: rssi high\n");
969                 break;
970         case MACREG_INT_CODE_SNR_HIGH:
971                 lbs_pr_alert("EVENT: snr high\n");
972                 break;
973
974         case MACREG_INT_CODE_MESH_AUTO_STARTED:
975                 /* Ignore spurious autostart events if autostart is disabled */
976                 if (!priv->mesh_autostart_enabled) {
977                         lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n");
978                         break;
979                 }
980                 lbs_pr_info("EVENT: MESH_AUTO_STARTED\n");
981                 adapter->connect_status = LIBERTAS_CONNECTED;
982                 if (priv->mesh_open == 1) {
983                         netif_wake_queue(priv->mesh_dev);
984                         netif_carrier_on(priv->mesh_dev);
985                 }
986                 adapter->mode = IW_MODE_ADHOC;
987                 schedule_work(&priv->sync_channel);
988                 break;
989
990         default:
991                 lbs_pr_alert("EVENT: unknown event id 0x%04x\n",
992                        eventcause >> SBI_EVENT_CAUSE_SHIFT);
993                 break;
994         }
995
996         spin_lock_irq(&adapter->driver_lock);
997         adapter->eventcause = 0;
998         spin_unlock_irq(&adapter->driver_lock);
999
1000         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
1001         return ret;
1002 }