Linux-libre 2.6.32.58-gnu1
[librecmc/linux-libre.git] / drivers / net / wireless / libertas / cmd.c
1 /**
2   * This file contains the handling of command.
3   * It prepares command and sends it to firmware when it is ready.
4   */
5
6 #include <net/iw_handler.h>
7 #include <net/lib80211.h>
8 #include <linux/kfifo.h>
9 #include <linux/sched.h>
10 #include "host.h"
11 #include "hostcmd.h"
12 #include "decl.h"
13 #include "defs.h"
14 #include "dev.h"
15 #include "assoc.h"
16 #include "wext.h"
17 #include "cmd.h"
18
19 static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
20
21
22 /**
23  *  @brief Simple callback that copies response back into command
24  *
25  *  @param priv         A pointer to struct lbs_private structure
26  *  @param extra        A pointer to the original command structure for which
27  *                      'resp' is a response
28  *  @param resp         A pointer to the command response
29  *
30  *  @return             0 on success, error on failure
31  */
32 int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
33                      struct cmd_header *resp)
34 {
35         struct cmd_header *buf = (void *)extra;
36         uint16_t copy_len;
37
38         copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
39         memcpy(buf, resp, copy_len);
40         return 0;
41 }
42 EXPORT_SYMBOL_GPL(lbs_cmd_copyback);
43
44 /**
45  *  @brief Simple callback that ignores the result. Use this if
46  *  you just want to send a command to the hardware, but don't
47  *  care for the result.
48  *
49  *  @param priv         ignored
50  *  @param extra        ignored
51  *  @param resp         ignored
52  *
53  *  @return             0 for success
54  */
55 static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra,
56                      struct cmd_header *resp)
57 {
58         return 0;
59 }
60
61
62 /**
63  *  @brief Checks whether a command is allowed in Power Save mode
64  *
65  *  @param command the command ID
66  *  @return        1 if allowed, 0 if not allowed
67  */
68 static u8 is_command_allowed_in_ps(u16 cmd)
69 {
70         switch (cmd) {
71         case CMD_802_11_RSSI:
72                 return 1;
73         default:
74                 break;
75         }
76         return 0;
77 }
78
79 /**
80  *  @brief Updates the hardware details like MAC address and regulatory region
81  *
82  *  @param priv         A pointer to struct lbs_private structure
83  *
84  *  @return             0 on success, error on failure
85  */
86 int lbs_update_hw_spec(struct lbs_private *priv)
87 {
88         struct cmd_ds_get_hw_spec cmd;
89         int ret = -1;
90         u32 i;
91
92         lbs_deb_enter(LBS_DEB_CMD);
93
94         memset(&cmd, 0, sizeof(cmd));
95         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
96         memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN);
97         ret = lbs_cmd_with_response(priv, CMD_GET_HW_SPEC, &cmd);
98         if (ret)
99                 goto out;
100
101         priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo);
102
103         /* The firmware release is in an interesting format: the patch
104          * level is in the most significant nibble ... so fix that: */
105         priv->fwrelease = le32_to_cpu(cmd.fwrelease);
106         priv->fwrelease = (priv->fwrelease << 8) |
107                 (priv->fwrelease >> 24 & 0xff);
108
109         /* Some firmware capabilities:
110          * CF card    firmware 5.0.16p0:   cap 0x00000303
111          * USB dongle firmware 5.110.17p2: cap 0x00000303
112          */
113         lbs_pr_info("%pM, fw %u.%u.%up%u, cap 0x%08x\n",
114                 cmd.permanentaddr,
115                 priv->fwrelease >> 24 & 0xff,
116                 priv->fwrelease >> 16 & 0xff,
117                 priv->fwrelease >>  8 & 0xff,
118                 priv->fwrelease       & 0xff,
119                 priv->fwcapinfo);
120         lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
121                     cmd.hwifversion, cmd.version);
122
123         /* Determine mesh_fw_ver from fwrelease and fwcapinfo */
124         /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */
125         /* 5.110.22 have mesh command with 0xa3 command id */
126         /* 10.0.0.p0 FW brings in mesh config command with different id */
127         /* Check FW version MSB and initialize mesh_fw_ver */
128         if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5)
129                 priv->mesh_fw_ver = MESH_FW_OLD;
130         else if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) &&
131                 (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK))
132                 priv->mesh_fw_ver = MESH_FW_NEW;
133         else
134                 priv->mesh_fw_ver = MESH_NONE;
135
136         /* Clamp region code to 8-bit since FW spec indicates that it should
137          * only ever be 8-bit, even though the field size is 16-bit.  Some firmware
138          * returns non-zero high 8 bits here.
139          *
140          * Firmware version 4.0.102 used in CF8381 has region code shifted.  We
141          * need to check for this problem and handle it properly.
142          */
143         if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V4)
144                 priv->regioncode = (le16_to_cpu(cmd.regioncode) >> 8) & 0xFF;
145         else
146                 priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF;
147
148         for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
149                 /* use the region code to search for the index */
150                 if (priv->regioncode == lbs_region_code_to_index[i])
151                         break;
152         }
153
154         /* if it's unidentified region code, use the default (USA) */
155         if (i >= MRVDRV_MAX_REGION_CODE) {
156                 priv->regioncode = 0x10;
157                 lbs_pr_info("unidentified region code; using the default (USA)\n");
158         }
159
160         if (priv->current_addr[0] == 0xff)
161                 memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
162
163         memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN);
164         if (priv->mesh_dev)
165                 memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
166
167         if (lbs_set_regiontable(priv, priv->regioncode, 0)) {
168                 ret = -1;
169                 goto out;
170         }
171
172         if (lbs_set_universaltable(priv, 0)) {
173                 ret = -1;
174                 goto out;
175         }
176
177 out:
178         lbs_deb_leave(LBS_DEB_CMD);
179         return ret;
180 }
181
182 int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
183                 struct wol_config *p_wol_config)
184 {
185         struct cmd_ds_host_sleep cmd_config;
186         int ret;
187
188         cmd_config.hdr.size = cpu_to_le16(sizeof(cmd_config));
189         cmd_config.criteria = cpu_to_le32(criteria);
190         cmd_config.gpio = priv->wol_gpio;
191         cmd_config.gap = priv->wol_gap;
192
193         if (p_wol_config != NULL)
194                 memcpy((uint8_t *)&cmd_config.wol_conf, (uint8_t *)p_wol_config,
195                                 sizeof(struct wol_config));
196         else
197                 cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE;
198
199         ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config);
200         if (!ret) {
201                 if (criteria) {
202                         lbs_deb_cmd("Set WOL criteria to %x\n", criteria);
203                         priv->wol_criteria = criteria;
204                 } else
205                         memcpy((uint8_t *) p_wol_config,
206                                         (uint8_t *)&cmd_config.wol_conf,
207                                         sizeof(struct wol_config));
208         } else {
209                 lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret);
210         }
211
212         return ret;
213 }
214 EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);
215
216 static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd,
217                                    u16 cmd_action)
218 {
219         struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode;
220
221         lbs_deb_enter(LBS_DEB_CMD);
222
223         cmd->command = cpu_to_le16(CMD_802_11_PS_MODE);
224         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) +
225                                 S_DS_GEN);
226         psm->action = cpu_to_le16(cmd_action);
227         psm->multipledtim = 0;
228         switch (cmd_action) {
229         case CMD_SUBCMD_ENTER_PS:
230                 lbs_deb_cmd("PS command:" "SubCode- Enter PS\n");
231
232                 psm->locallisteninterval = 0;
233                 psm->nullpktinterval = 0;
234                 psm->multipledtim =
235                     cpu_to_le16(MRVDRV_DEFAULT_MULTIPLE_DTIM);
236                 break;
237
238         case CMD_SUBCMD_EXIT_PS:
239                 lbs_deb_cmd("PS command:" "SubCode- Exit PS\n");
240                 break;
241
242         case CMD_SUBCMD_SLEEP_CONFIRMED:
243                 lbs_deb_cmd("PS command: SubCode- sleep confirm\n");
244                 break;
245
246         default:
247                 break;
248         }
249
250         lbs_deb_leave(LBS_DEB_CMD);
251         return 0;
252 }
253
254 int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv,
255                                       uint16_t cmd_action, uint16_t *timeout)
256 {
257         struct cmd_ds_802_11_inactivity_timeout cmd;
258         int ret;
259
260         lbs_deb_enter(LBS_DEB_CMD);
261
262         cmd.hdr.command = cpu_to_le16(CMD_802_11_INACTIVITY_TIMEOUT);
263         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
264
265         cmd.action = cpu_to_le16(cmd_action);
266
267         if (cmd_action == CMD_ACT_SET)
268                 cmd.timeout = cpu_to_le16(*timeout);
269         else
270                 cmd.timeout = 0;
271
272         ret = lbs_cmd_with_response(priv, CMD_802_11_INACTIVITY_TIMEOUT, &cmd);
273
274         if (!ret)
275                 *timeout = le16_to_cpu(cmd.timeout);
276
277         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
278         return 0;
279 }
280
281 int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
282                                 struct sleep_params *sp)
283 {
284         struct cmd_ds_802_11_sleep_params cmd;
285         int ret;
286
287         lbs_deb_enter(LBS_DEB_CMD);
288
289         if (cmd_action == CMD_ACT_GET) {
290                 memset(&cmd, 0, sizeof(cmd));
291         } else {
292                 cmd.error = cpu_to_le16(sp->sp_error);
293                 cmd.offset = cpu_to_le16(sp->sp_offset);
294                 cmd.stabletime = cpu_to_le16(sp->sp_stabletime);
295                 cmd.calcontrol = sp->sp_calcontrol;
296                 cmd.externalsleepclk = sp->sp_extsleepclk;
297                 cmd.reserved = cpu_to_le16(sp->sp_reserved);
298         }
299         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
300         cmd.action = cpu_to_le16(cmd_action);
301
302         ret = lbs_cmd_with_response(priv, CMD_802_11_SLEEP_PARAMS, &cmd);
303
304         if (!ret) {
305                 lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, "
306                             "calcontrol 0x%x extsleepclk 0x%x\n",
307                             le16_to_cpu(cmd.error), le16_to_cpu(cmd.offset),
308                             le16_to_cpu(cmd.stabletime), cmd.calcontrol,
309                             cmd.externalsleepclk);
310
311                 sp->sp_error = le16_to_cpu(cmd.error);
312                 sp->sp_offset = le16_to_cpu(cmd.offset);
313                 sp->sp_stabletime = le16_to_cpu(cmd.stabletime);
314                 sp->sp_calcontrol = cmd.calcontrol;
315                 sp->sp_extsleepclk = cmd.externalsleepclk;
316                 sp->sp_reserved = le16_to_cpu(cmd.reserved);
317         }
318
319         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
320         return 0;
321 }
322
323 int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
324                            struct assoc_request *assoc)
325 {
326         struct cmd_ds_802_11_set_wep cmd;
327         int ret = 0;
328
329         lbs_deb_enter(LBS_DEB_CMD);
330
331         memset(&cmd, 0, sizeof(cmd));
332         cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP);
333         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
334
335         cmd.action = cpu_to_le16(cmd_action);
336
337         if (cmd_action == CMD_ACT_ADD) {
338                 int i;
339
340                 /* default tx key index */
341                 cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx &
342                                            CMD_WEP_KEY_INDEX_MASK);
343
344                 /* Copy key types and material to host command structure */
345                 for (i = 0; i < 4; i++) {
346                         struct enc_key *pkey = &assoc->wep_keys[i];
347
348                         switch (pkey->len) {
349                         case KEY_LEN_WEP_40:
350                                 cmd.keytype[i] = CMD_TYPE_WEP_40_BIT;
351                                 memmove(cmd.keymaterial[i], pkey->key, pkey->len);
352                                 lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i);
353                                 break;
354                         case KEY_LEN_WEP_104:
355                                 cmd.keytype[i] = CMD_TYPE_WEP_104_BIT;
356                                 memmove(cmd.keymaterial[i], pkey->key, pkey->len);
357                                 lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i);
358                                 break;
359                         case 0:
360                                 break;
361                         default:
362                                 lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n",
363                                             i, pkey->len);
364                                 ret = -1;
365                                 goto done;
366                                 break;
367                         }
368                 }
369         } else if (cmd_action == CMD_ACT_REMOVE) {
370                 /* ACT_REMOVE clears _all_ WEP keys */
371
372                 /* default tx key index */
373                 cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx &
374                                            CMD_WEP_KEY_INDEX_MASK);
375                 lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx);
376         }
377
378         ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
379 done:
380         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
381         return ret;
382 }
383
384 int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
385                               uint16_t *enable)
386 {
387         struct cmd_ds_802_11_enable_rsn cmd;
388         int ret;
389
390         lbs_deb_enter(LBS_DEB_CMD);
391
392         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
393         cmd.action = cpu_to_le16(cmd_action);
394
395         if (cmd_action == CMD_ACT_GET)
396                 cmd.enable = 0;
397         else {
398                 if (*enable)
399                         cmd.enable = cpu_to_le16(CMD_ENABLE_RSN);
400                 else
401                         cmd.enable = cpu_to_le16(CMD_DISABLE_RSN);
402                 lbs_deb_cmd("ENABLE_RSN: %d\n", *enable);
403         }
404
405         ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd);
406         if (!ret && cmd_action == CMD_ACT_GET)
407                 *enable = le16_to_cpu(cmd.enable);
408
409         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
410         return ret;
411 }
412
413 static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam,
414                             struct enc_key *key)
415 {
416         lbs_deb_enter(LBS_DEB_CMD);
417
418         if (key->flags & KEY_INFO_WPA_ENABLED)
419                 keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
420         if (key->flags & KEY_INFO_WPA_UNICAST)
421                 keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
422         if (key->flags & KEY_INFO_WPA_MCAST)
423                 keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
424
425         keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
426         keyparam->keytypeid = cpu_to_le16(key->type);
427         keyparam->keylen = cpu_to_le16(key->len);
428         memcpy(keyparam->key, key->key, key->len);
429
430         /* Length field doesn't include the {type,length} header */
431         keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4);
432         lbs_deb_leave(LBS_DEB_CMD);
433 }
434
435 int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
436                                 struct assoc_request *assoc)
437 {
438         struct cmd_ds_802_11_key_material cmd;
439         int ret = 0;
440         int index = 0;
441
442         lbs_deb_enter(LBS_DEB_CMD);
443
444         cmd.action = cpu_to_le16(cmd_action);
445         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
446
447         if (cmd_action == CMD_ACT_GET) {
448                 cmd.hdr.size = cpu_to_le16(S_DS_GEN + 2);
449         } else {
450                 memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet));
451
452                 if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) {
453                         set_one_wpa_key(&cmd.keyParamSet[index],
454                                         &assoc->wpa_unicast_key);
455                         index++;
456                 }
457
458                 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) {
459                         set_one_wpa_key(&cmd.keyParamSet[index],
460                                         &assoc->wpa_mcast_key);
461                         index++;
462                 }
463
464                 /* The common header and as many keys as we included */
465                 cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd),
466                                                     keyParamSet[index]));
467         }
468         ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
469         /* Copy the returned key to driver private data */
470         if (!ret && cmd_action == CMD_ACT_GET) {
471                 void *buf_ptr = cmd.keyParamSet;
472                 void *resp_end = &(&cmd)[1];
473
474                 while (buf_ptr < resp_end) {
475                         struct MrvlIEtype_keyParamSet *keyparam = buf_ptr;
476                         struct enc_key *key;
477                         uint16_t param_set_len = le16_to_cpu(keyparam->length);
478                         uint16_t key_len = le16_to_cpu(keyparam->keylen);
479                         uint16_t key_flags = le16_to_cpu(keyparam->keyinfo);
480                         uint16_t key_type = le16_to_cpu(keyparam->keytypeid);
481                         void *end;
482
483                         end = (void *)keyparam + sizeof(keyparam->type)
484                                 + sizeof(keyparam->length) + param_set_len;
485
486                         /* Make sure we don't access past the end of the IEs */
487                         if (end > resp_end)
488                                 break;
489
490                         if (key_flags & KEY_INFO_WPA_UNICAST)
491                                 key = &priv->wpa_unicast_key;
492                         else if (key_flags & KEY_INFO_WPA_MCAST)
493                                 key = &priv->wpa_mcast_key;
494                         else
495                                 break;
496
497                         /* Copy returned key into driver */
498                         memset(key, 0, sizeof(struct enc_key));
499                         if (key_len > sizeof(key->key))
500                                 break;
501                         key->type = key_type;
502                         key->flags = key_flags;
503                         key->len = key_len;
504                         memcpy(key->key, keyparam->key, key->len);
505
506                         buf_ptr = end + 1;
507                 }
508         }
509
510         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
511         return ret;
512 }
513
514 /**
515  *  @brief Set an SNMP MIB value
516  *
517  *  @param priv         A pointer to struct lbs_private structure
518  *  @param oid          The OID to set in the firmware
519  *  @param val          Value to set the OID to
520  *
521  *  @return             0 on success, error on failure
522  */
523 int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val)
524 {
525         struct cmd_ds_802_11_snmp_mib cmd;
526         int ret;
527
528         lbs_deb_enter(LBS_DEB_CMD);
529
530         memset(&cmd, 0, sizeof (cmd));
531         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
532         cmd.action = cpu_to_le16(CMD_ACT_SET);
533         cmd.oid = cpu_to_le16((u16) oid);
534
535         switch (oid) {
536         case SNMP_MIB_OID_BSS_TYPE:
537                 cmd.bufsize = cpu_to_le16(sizeof(u8));
538                 cmd.value[0] = (val == IW_MODE_ADHOC) ? 2 : 1;
539                 break;
540         case SNMP_MIB_OID_11D_ENABLE:
541         case SNMP_MIB_OID_FRAG_THRESHOLD:
542         case SNMP_MIB_OID_RTS_THRESHOLD:
543         case SNMP_MIB_OID_SHORT_RETRY_LIMIT:
544         case SNMP_MIB_OID_LONG_RETRY_LIMIT:
545                 cmd.bufsize = cpu_to_le16(sizeof(u16));
546                 *((__le16 *)(&cmd.value)) = cpu_to_le16(val);
547                 break;
548         default:
549                 lbs_deb_cmd("SNMP_CMD: (set) unhandled OID 0x%x\n", oid);
550                 ret = -EINVAL;
551                 goto out;
552         }
553
554         lbs_deb_cmd("SNMP_CMD: (set) oid 0x%x, oid size 0x%x, value 0x%x\n",
555                     le16_to_cpu(cmd.oid), le16_to_cpu(cmd.bufsize), val);
556
557         ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
558
559 out:
560         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
561         return ret;
562 }
563
564 /**
565  *  @brief Get an SNMP MIB value
566  *
567  *  @param priv         A pointer to struct lbs_private structure
568  *  @param oid          The OID to retrieve from the firmware
569  *  @param out_val      Location for the returned value
570  *
571  *  @return             0 on success, error on failure
572  */
573 int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val)
574 {
575         struct cmd_ds_802_11_snmp_mib cmd;
576         int ret;
577
578         lbs_deb_enter(LBS_DEB_CMD);
579
580         memset(&cmd, 0, sizeof (cmd));
581         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
582         cmd.action = cpu_to_le16(CMD_ACT_GET);
583         cmd.oid = cpu_to_le16(oid);
584
585         ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
586         if (ret)
587                 goto out;
588
589         switch (le16_to_cpu(cmd.bufsize)) {
590         case sizeof(u8):
591                 if (oid == SNMP_MIB_OID_BSS_TYPE) {
592                         if (cmd.value[0] == 2)
593                                 *out_val = IW_MODE_ADHOC;
594                         else
595                                 *out_val = IW_MODE_INFRA;
596                 } else
597                         *out_val = cmd.value[0];
598                 break;
599         case sizeof(u16):
600                 *out_val = le16_to_cpu(*((__le16 *)(&cmd.value)));
601                 break;
602         default:
603                 lbs_deb_cmd("SNMP_CMD: (get) unhandled OID 0x%x size %d\n",
604                             oid, le16_to_cpu(cmd.bufsize));
605                 break;
606         }
607
608 out:
609         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
610         return ret;
611 }
612
613 /**
614  *  @brief Get the min, max, and current TX power
615  *
616  *  @param priv         A pointer to struct lbs_private structure
617  *  @param curlevel     Current power level in dBm
618  *  @param minlevel     Minimum supported power level in dBm (optional)
619  *  @param maxlevel     Maximum supported power level in dBm (optional)
620  *
621  *  @return             0 on success, error on failure
622  */
623 int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
624                      s16 *maxlevel)
625 {
626         struct cmd_ds_802_11_rf_tx_power cmd;
627         int ret;
628
629         lbs_deb_enter(LBS_DEB_CMD);
630
631         memset(&cmd, 0, sizeof(cmd));
632         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
633         cmd.action = cpu_to_le16(CMD_ACT_GET);
634
635         ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
636         if (ret == 0) {
637                 *curlevel = le16_to_cpu(cmd.curlevel);
638                 if (minlevel)
639                         *minlevel = cmd.minlevel;
640                 if (maxlevel)
641                         *maxlevel = cmd.maxlevel;
642         }
643
644         lbs_deb_leave(LBS_DEB_CMD);
645         return ret;
646 }
647
648 /**
649  *  @brief Set the TX power
650  *
651  *  @param priv         A pointer to struct lbs_private structure
652  *  @param dbm          The desired power level in dBm
653  *
654  *  @return             0 on success, error on failure
655  */
656 int lbs_set_tx_power(struct lbs_private *priv, s16 dbm)
657 {
658         struct cmd_ds_802_11_rf_tx_power cmd;
659         int ret;
660
661         lbs_deb_enter(LBS_DEB_CMD);
662
663         memset(&cmd, 0, sizeof(cmd));
664         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
665         cmd.action = cpu_to_le16(CMD_ACT_SET);
666         cmd.curlevel = cpu_to_le16(dbm);
667
668         lbs_deb_cmd("SET_RF_TX_POWER: %d dBm\n", dbm);
669
670         ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
671
672         lbs_deb_leave(LBS_DEB_CMD);
673         return ret;
674 }
675
676 static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
677                                       u16 cmd_action, void *pdata_buf)
678 {
679         struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor;
680
681         cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE);
682         cmd->size =
683             cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) +
684                              S_DS_GEN);
685
686         monitor->action = cpu_to_le16(cmd_action);
687         if (cmd_action == CMD_ACT_SET) {
688                 monitor->mode =
689                     cpu_to_le16((u16) (*(u32 *) pdata_buf));
690         }
691
692         return 0;
693 }
694
695 static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok)
696 {
697 /*              Bit     Rate
698 *               15:13 Reserved
699 *               12    54 Mbps
700 *               11    48 Mbps
701 *               10    36 Mbps
702 *               9     24 Mbps
703 *               8     18 Mbps
704 *               7     12 Mbps
705 *               6     9 Mbps
706 *               5     6 Mbps
707 *               4     Reserved
708 *               3     11 Mbps
709 *               2     5.5 Mbps
710 *               1     2 Mbps
711 *               0     1 Mbps
712 **/
713
714         uint16_t ratemask;
715         int i = lbs_data_rate_to_fw_index(rate);
716         if (lower_rates_ok)
717                 ratemask = (0x1fef >> (12 - i));
718         else
719                 ratemask = (1 << i);
720         return cpu_to_le16(ratemask);
721 }
722
723 int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
724                                       uint16_t cmd_action)
725 {
726         struct cmd_ds_802_11_rate_adapt_rateset cmd;
727         int ret;
728
729         lbs_deb_enter(LBS_DEB_CMD);
730
731         if (!priv->cur_rate && !priv->enablehwauto)
732                 return -EINVAL;
733
734         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
735
736         cmd.action = cpu_to_le16(cmd_action);
737         cmd.enablehwauto = cpu_to_le16(priv->enablehwauto);
738         cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto);
739         ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd);
740         if (!ret && cmd_action == CMD_ACT_GET) {
741                 priv->ratebitmap = le16_to_cpu(cmd.bitmap);
742                 priv->enablehwauto = le16_to_cpu(cmd.enablehwauto);
743         }
744
745         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
746         return ret;
747 }
748 EXPORT_SYMBOL_GPL(lbs_cmd_802_11_rate_adapt_rateset);
749
750 /**
751  *  @brief Set the data rate
752  *
753  *  @param priv         A pointer to struct lbs_private structure
754  *  @param rate         The desired data rate, or 0 to clear a locked rate
755  *
756  *  @return             0 on success, error on failure
757  */
758 int lbs_set_data_rate(struct lbs_private *priv, u8 rate)
759 {
760         struct cmd_ds_802_11_data_rate cmd;
761         int ret = 0;
762
763         lbs_deb_enter(LBS_DEB_CMD);
764
765         memset(&cmd, 0, sizeof(cmd));
766         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
767
768         if (rate > 0) {
769                 cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE);
770                 cmd.rates[0] = lbs_data_rate_to_fw_index(rate);
771                 if (cmd.rates[0] == 0) {
772                         lbs_deb_cmd("DATA_RATE: invalid requested rate of"
773                                     " 0x%02X\n", rate);
774                         ret = 0;
775                         goto out;
776                 }
777                 lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]);
778         } else {
779                 cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO);
780                 lbs_deb_cmd("DATA_RATE: setting auto\n");
781         }
782
783         ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd);
784         if (ret)
785                 goto out;
786
787         lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof (cmd));
788
789         /* FIXME: get actual rates FW can do if this command actually returns
790          * all data rates supported.
791          */
792         priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]);
793         lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate);
794
795 out:
796         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
797         return ret;
798 }
799
800 /**
801  *  @brief Get the radio channel
802  *
803  *  @param priv         A pointer to struct lbs_private structure
804  *
805  *  @return             The channel on success, error on failure
806  */
807 int lbs_get_channel(struct lbs_private *priv)
808 {
809         struct cmd_ds_802_11_rf_channel cmd;
810         int ret = 0;
811
812         lbs_deb_enter(LBS_DEB_CMD);
813
814         memset(&cmd, 0, sizeof(cmd));
815         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
816         cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET);
817
818         ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
819         if (ret)
820                 goto out;
821
822         ret = le16_to_cpu(cmd.channel);
823         lbs_deb_cmd("current radio channel is %d\n", ret);
824
825 out:
826         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
827         return ret;
828 }
829
830 int lbs_update_channel(struct lbs_private *priv)
831 {
832         int ret;
833
834         /* the channel in f/w could be out of sync; get the current channel */
835         lbs_deb_enter(LBS_DEB_ASSOC);
836
837         ret = lbs_get_channel(priv);
838         if (ret > 0) {
839                 priv->curbssparams.channel = ret;
840                 ret = 0;
841         }
842         lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
843         return ret;
844 }
845
846 /**
847  *  @brief Set the radio channel
848  *
849  *  @param priv         A pointer to struct lbs_private structure
850  *  @param channel      The desired channel, or 0 to clear a locked channel
851  *
852  *  @return             0 on success, error on failure
853  */
854 int lbs_set_channel(struct lbs_private *priv, u8 channel)
855 {
856         struct cmd_ds_802_11_rf_channel cmd;
857 #ifdef DEBUG
858         u8 old_channel = priv->curbssparams.channel;
859 #endif
860         int ret = 0;
861
862         lbs_deb_enter(LBS_DEB_CMD);
863
864         memset(&cmd, 0, sizeof(cmd));
865         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
866         cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
867         cmd.channel = cpu_to_le16(channel);
868
869         ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
870         if (ret)
871                 goto out;
872
873         priv->curbssparams.channel = (uint8_t) le16_to_cpu(cmd.channel);
874         lbs_deb_cmd("channel switch from %d to %d\n", old_channel,
875                 priv->curbssparams.channel);
876
877 out:
878         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
879         return ret;
880 }
881
882 static int lbs_cmd_802_11_rssi(struct lbs_private *priv,
883                                 struct cmd_ds_command *cmd)
884 {
885
886         lbs_deb_enter(LBS_DEB_CMD);
887         cmd->command = cpu_to_le16(CMD_802_11_RSSI);
888         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN);
889         cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
890
891         /* reset Beacon SNR/NF/RSSI values */
892         priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
893         priv->SNR[TYPE_BEACON][TYPE_AVG] = 0;
894         priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
895         priv->NF[TYPE_BEACON][TYPE_AVG] = 0;
896         priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
897         priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
898
899         lbs_deb_leave(LBS_DEB_CMD);
900         return 0;
901 }
902
903 static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
904                                u8 cmd_action, void *pdata_buf)
905 {
906         struct lbs_offset_value *offval;
907
908         lbs_deb_enter(LBS_DEB_CMD);
909
910         offval = (struct lbs_offset_value *)pdata_buf;
911
912         switch (le16_to_cpu(cmdptr->command)) {
913         case CMD_MAC_REG_ACCESS:
914                 {
915                         struct cmd_ds_mac_reg_access *macreg;
916
917                         cmdptr->size =
918                             cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access)
919                                         + S_DS_GEN);
920                         macreg =
921                             (struct cmd_ds_mac_reg_access *)&cmdptr->params.
922                             macreg;
923
924                         macreg->action = cpu_to_le16(cmd_action);
925                         macreg->offset = cpu_to_le16((u16) offval->offset);
926                         macreg->value = cpu_to_le32(offval->value);
927
928                         break;
929                 }
930
931         case CMD_BBP_REG_ACCESS:
932                 {
933                         struct cmd_ds_bbp_reg_access *bbpreg;
934
935                         cmdptr->size =
936                             cpu_to_le16(sizeof
937                                              (struct cmd_ds_bbp_reg_access)
938                                              + S_DS_GEN);
939                         bbpreg =
940                             (struct cmd_ds_bbp_reg_access *)&cmdptr->params.
941                             bbpreg;
942
943                         bbpreg->action = cpu_to_le16(cmd_action);
944                         bbpreg->offset = cpu_to_le16((u16) offval->offset);
945                         bbpreg->value = (u8) offval->value;
946
947                         break;
948                 }
949
950         case CMD_RF_REG_ACCESS:
951                 {
952                         struct cmd_ds_rf_reg_access *rfreg;
953
954                         cmdptr->size =
955                             cpu_to_le16(sizeof
956                                              (struct cmd_ds_rf_reg_access) +
957                                              S_DS_GEN);
958                         rfreg =
959                             (struct cmd_ds_rf_reg_access *)&cmdptr->params.
960                             rfreg;
961
962                         rfreg->action = cpu_to_le16(cmd_action);
963                         rfreg->offset = cpu_to_le16((u16) offval->offset);
964                         rfreg->value = (u8) offval->value;
965
966                         break;
967                 }
968
969         default:
970                 break;
971         }
972
973         lbs_deb_leave(LBS_DEB_CMD);
974         return 0;
975 }
976
977 static int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
978                                u16 cmd_action, void *pdata_buf)
979 {
980         struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
981         lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
982
983         cmd->command = cpu_to_le16(CMD_BT_ACCESS);
984         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN);
985         cmd->result = 0;
986         bt_access->action = cpu_to_le16(cmd_action);
987
988         switch (cmd_action) {
989         case CMD_ACT_BT_ACCESS_ADD:
990                 memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN);
991                 lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", bt_access->addr1, 6);
992                 break;
993         case CMD_ACT_BT_ACCESS_DEL:
994                 memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN);
995                 lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", bt_access->addr1, 6);
996                 break;
997         case CMD_ACT_BT_ACCESS_LIST:
998                 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
999                 break;
1000         case CMD_ACT_BT_ACCESS_RESET:
1001                 break;
1002         case CMD_ACT_BT_ACCESS_SET_INVERT:
1003                 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
1004                 break;
1005         case CMD_ACT_BT_ACCESS_GET_INVERT:
1006                 break;
1007         default:
1008                 break;
1009         }
1010         lbs_deb_leave(LBS_DEB_CMD);
1011         return 0;
1012 }
1013
1014 static int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
1015                                u16 cmd_action, void *pdata_buf)
1016 {
1017         struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
1018         lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
1019
1020         cmd->command = cpu_to_le16(CMD_FWT_ACCESS);
1021         cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + S_DS_GEN);
1022         cmd->result = 0;
1023
1024         if (pdata_buf)
1025                 memcpy(fwt_access, pdata_buf, sizeof(*fwt_access));
1026         else
1027                 memset(fwt_access, 0, sizeof(*fwt_access));
1028
1029         fwt_access->action = cpu_to_le16(cmd_action);
1030
1031         lbs_deb_leave(LBS_DEB_CMD);
1032         return 0;
1033 }
1034
1035 int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
1036                     struct cmd_ds_mesh_access *cmd)
1037 {
1038         int ret;
1039
1040         lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
1041
1042         cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
1043         cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
1044         cmd->hdr.result = 0;
1045
1046         cmd->action = cpu_to_le16(cmd_action);
1047
1048         ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
1049
1050         lbs_deb_leave(LBS_DEB_CMD);
1051         return ret;
1052 }
1053
1054 static int __lbs_mesh_config_send(struct lbs_private *priv,
1055                                   struct cmd_ds_mesh_config *cmd,
1056                                   uint16_t action, uint16_t type)
1057 {
1058         int ret;
1059         u16 command = CMD_MESH_CONFIG_OLD;
1060
1061         lbs_deb_enter(LBS_DEB_CMD);
1062
1063         /*
1064          * Command id is 0xac for v10 FW along with mesh interface
1065          * id in bits 14-13-12.
1066          */
1067         if (priv->mesh_fw_ver == MESH_FW_NEW)
1068                 command = CMD_MESH_CONFIG |
1069                           (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);
1070
1071         cmd->hdr.command = cpu_to_le16(command);
1072         cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
1073         cmd->hdr.result = 0;
1074
1075         cmd->type = cpu_to_le16(type);
1076         cmd->action = cpu_to_le16(action);
1077
1078         ret = lbs_cmd_with_response(priv, command, cmd);
1079
1080         lbs_deb_leave(LBS_DEB_CMD);
1081         return ret;
1082 }
1083
1084 int lbs_mesh_config_send(struct lbs_private *priv,
1085                          struct cmd_ds_mesh_config *cmd,
1086                          uint16_t action, uint16_t type)
1087 {
1088         int ret;
1089
1090         if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG))
1091                 return -EOPNOTSUPP;
1092
1093         ret = __lbs_mesh_config_send(priv, cmd, action, type);
1094         return ret;
1095 }
1096
1097 /* This function is the CMD_MESH_CONFIG legacy function.  It only handles the
1098  * START and STOP actions.  The extended actions supported by CMD_MESH_CONFIG
1099  * are all handled by preparing a struct cmd_ds_mesh_config and passing it to
1100  * lbs_mesh_config_send.
1101  */
1102 int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
1103 {
1104         struct cmd_ds_mesh_config cmd;
1105         struct mrvl_meshie *ie;
1106         DECLARE_SSID_BUF(ssid);
1107
1108         memset(&cmd, 0, sizeof(cmd));
1109         cmd.channel = cpu_to_le16(chan);
1110         ie = (struct mrvl_meshie *)cmd.data;
1111
1112         switch (action) {
1113         case CMD_ACT_MESH_CONFIG_START:
1114                 ie->id = WLAN_EID_GENERIC;
1115                 ie->val.oui[0] = 0x00;
1116                 ie->val.oui[1] = 0x50;
1117                 ie->val.oui[2] = 0x43;
1118                 ie->val.type = MARVELL_MESH_IE_TYPE;
1119                 ie->val.subtype = MARVELL_MESH_IE_SUBTYPE;
1120                 ie->val.version = MARVELL_MESH_IE_VERSION;
1121                 ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP;
1122                 ie->val.active_metric_id = MARVELL_MESH_METRIC_ID;
1123                 ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
1124                 ie->val.mesh_id_len = priv->mesh_ssid_len;
1125                 memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
1126                 ie->len = sizeof(struct mrvl_meshie_val) -
1127                         IW_ESSID_MAX_SIZE + priv->mesh_ssid_len;
1128                 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
1129                 break;
1130         case CMD_ACT_MESH_CONFIG_STOP:
1131                 break;
1132         default:
1133                 return -1;
1134         }
1135         lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
1136                     action, priv->mesh_tlv, chan,
1137                     print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
1138
1139         return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
1140 }
1141
1142 static int lbs_cmd_bcn_ctrl(struct lbs_private * priv,
1143                                 struct cmd_ds_command *cmd,
1144                                 u16 cmd_action)
1145 {
1146         struct cmd_ds_802_11_beacon_control
1147                 *bcn_ctrl = &cmd->params.bcn_ctrl;
1148
1149         lbs_deb_enter(LBS_DEB_CMD);
1150         cmd->size =
1151             cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control)
1152                              + S_DS_GEN);
1153         cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL);
1154
1155         bcn_ctrl->action = cpu_to_le16(cmd_action);
1156         bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable);
1157         bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period);
1158
1159         lbs_deb_leave(LBS_DEB_CMD);
1160         return 0;
1161 }
1162
1163 static void lbs_queue_cmd(struct lbs_private *priv,
1164                           struct cmd_ctrl_node *cmdnode)
1165 {
1166         unsigned long flags;
1167         int addtail = 1;
1168
1169         lbs_deb_enter(LBS_DEB_HOST);
1170
1171         if (!cmdnode) {
1172                 lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n");
1173                 goto done;
1174         }
1175         if (!cmdnode->cmdbuf->size) {
1176                 lbs_deb_host("DNLD_CMD: cmd size is zero\n");
1177                 goto done;
1178         }
1179         cmdnode->result = 0;
1180
1181         /* Exit_PS command needs to be queued in the header always. */
1182         if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) {
1183                 struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf[1];
1184
1185                 if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
1186                         if (priv->psstate != PS_STATE_FULL_POWER)
1187                                 addtail = 0;
1188                 }
1189         }
1190
1191         spin_lock_irqsave(&priv->driver_lock, flags);
1192
1193         if (addtail)
1194                 list_add_tail(&cmdnode->list, &priv->cmdpendingq);
1195         else
1196                 list_add(&cmdnode->list, &priv->cmdpendingq);
1197
1198         spin_unlock_irqrestore(&priv->driver_lock, flags);
1199
1200         lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
1201                      le16_to_cpu(cmdnode->cmdbuf->command));
1202
1203 done:
1204         lbs_deb_leave(LBS_DEB_HOST);
1205 }
1206
1207 static void lbs_submit_command(struct lbs_private *priv,
1208                                struct cmd_ctrl_node *cmdnode)
1209 {
1210         unsigned long flags;
1211         struct cmd_header *cmd;
1212         uint16_t cmdsize;
1213         uint16_t command;
1214         int timeo = 3 * HZ;
1215         int ret;
1216
1217         lbs_deb_enter(LBS_DEB_HOST);
1218
1219         cmd = cmdnode->cmdbuf;
1220
1221         spin_lock_irqsave(&priv->driver_lock, flags);
1222         priv->cur_cmd = cmdnode;
1223         priv->cur_cmd_retcode = 0;
1224         spin_unlock_irqrestore(&priv->driver_lock, flags);
1225
1226         cmdsize = le16_to_cpu(cmd->size);
1227         command = le16_to_cpu(cmd->command);
1228
1229         /* These commands take longer */
1230         if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE)
1231                 timeo = 5 * HZ;
1232
1233         lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
1234                      command, le16_to_cpu(cmd->seqnum), cmdsize);
1235         lbs_deb_hex(LBS_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
1236
1237         ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
1238
1239         if (ret) {
1240                 lbs_pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret);
1241                 /* Let the timer kick in and retry, and potentially reset
1242                    the whole thing if the condition persists */
1243                 timeo = HZ/4;
1244         }
1245
1246         /* Setup the timer after transmit command */
1247         mod_timer(&priv->command_timer, jiffies + timeo);
1248
1249         lbs_deb_leave(LBS_DEB_HOST);
1250 }
1251
1252 /**
1253  *  This function inserts command node to cmdfreeq
1254  *  after cleans it. Requires priv->driver_lock held.
1255  */
1256 static void __lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
1257                                          struct cmd_ctrl_node *cmdnode)
1258 {
1259         lbs_deb_enter(LBS_DEB_HOST);
1260
1261         if (!cmdnode)
1262                 goto out;
1263
1264         cmdnode->callback = NULL;
1265         cmdnode->callback_arg = 0;
1266
1267         memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);
1268
1269         list_add_tail(&cmdnode->list, &priv->cmdfreeq);
1270  out:
1271         lbs_deb_leave(LBS_DEB_HOST);
1272 }
1273
1274 static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
1275         struct cmd_ctrl_node *ptempcmd)
1276 {
1277         unsigned long flags;
1278
1279         spin_lock_irqsave(&priv->driver_lock, flags);
1280         __lbs_cleanup_and_insert_cmd(priv, ptempcmd);
1281         spin_unlock_irqrestore(&priv->driver_lock, flags);
1282 }
1283
1284 void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
1285                           int result)
1286 {
1287         if (cmd == priv->cur_cmd)
1288                 priv->cur_cmd_retcode = result;
1289
1290         cmd->result = result;
1291         cmd->cmdwaitqwoken = 1;
1292         wake_up_interruptible(&cmd->cmdwait_q);
1293
1294         if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)
1295                 __lbs_cleanup_and_insert_cmd(priv, cmd);
1296         priv->cur_cmd = NULL;
1297 }
1298
1299 int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on)
1300 {
1301         struct cmd_ds_802_11_radio_control cmd;
1302         int ret = -EINVAL;
1303
1304         lbs_deb_enter(LBS_DEB_CMD);
1305
1306         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1307         cmd.action = cpu_to_le16(CMD_ACT_SET);
1308
1309         /* Only v8 and below support setting the preamble */
1310         if (priv->fwrelease < 0x09000000) {
1311                 switch (preamble) {
1312                 case RADIO_PREAMBLE_SHORT:
1313                         if (!(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
1314                                 goto out;
1315                         /* Fall through */
1316                 case RADIO_PREAMBLE_AUTO:
1317                 case RADIO_PREAMBLE_LONG:
1318                         cmd.control = cpu_to_le16(preamble);
1319                         break;
1320                 default:
1321                         goto out;
1322                 }
1323         }
1324
1325         if (radio_on)
1326                 cmd.control |= cpu_to_le16(0x1);
1327         else {
1328                 cmd.control &= cpu_to_le16(~0x1);
1329                 priv->txpower_cur = 0;
1330         }
1331
1332         lbs_deb_cmd("RADIO_CONTROL: radio %s, preamble %d\n",
1333                     radio_on ? "ON" : "OFF", preamble);
1334
1335         priv->radio_on = radio_on;
1336
1337         ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
1338
1339 out:
1340         lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
1341         return ret;
1342 }
1343
1344 void lbs_set_mac_control(struct lbs_private *priv)
1345 {
1346         struct cmd_ds_mac_control cmd;
1347
1348         lbs_deb_enter(LBS_DEB_CMD);
1349
1350         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1351         cmd.action = cpu_to_le16(priv->mac_control);
1352         cmd.reserved = 0;
1353
1354         lbs_cmd_async(priv, CMD_MAC_CONTROL, &cmd.hdr, sizeof(cmd));
1355
1356         lbs_deb_leave(LBS_DEB_CMD);
1357 }
1358
1359 /**
1360  *  @brief This function prepare the command before send to firmware.
1361  *
1362  *  @param priv         A pointer to struct lbs_private structure
1363  *  @param cmd_no       command number
1364  *  @param cmd_action   command action: GET or SET
1365  *  @param wait_option  wait option: wait response or not
1366  *  @param cmd_oid      cmd oid: treated as sub command
1367  *  @param pdata_buf    A pointer to informaion buffer
1368  *  @return             0 or -1
1369  */
1370 int lbs_prepare_and_send_command(struct lbs_private *priv,
1371                           u16 cmd_no,
1372                           u16 cmd_action,
1373                           u16 wait_option, u32 cmd_oid, void *pdata_buf)
1374 {
1375         int ret = 0;
1376         struct cmd_ctrl_node *cmdnode;
1377         struct cmd_ds_command *cmdptr;
1378         unsigned long flags;
1379
1380         lbs_deb_enter(LBS_DEB_HOST);
1381
1382         if (!priv) {
1383                 lbs_deb_host("PREP_CMD: priv is NULL\n");
1384                 ret = -1;
1385                 goto done;
1386         }
1387
1388         if (priv->surpriseremoved) {
1389                 lbs_deb_host("PREP_CMD: card removed\n");
1390                 ret = -1;
1391                 goto done;
1392         }
1393
1394         cmdnode = lbs_get_cmd_ctrl_node(priv);
1395
1396         if (cmdnode == NULL) {
1397                 lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
1398
1399                 /* Wake up main thread to execute next command */
1400                 wake_up_interruptible(&priv->waitq);
1401                 ret = -1;
1402                 goto done;
1403         }
1404
1405         cmdnode->callback = NULL;
1406         cmdnode->callback_arg = (unsigned long)pdata_buf;
1407
1408         cmdptr = (struct cmd_ds_command *)cmdnode->cmdbuf;
1409
1410         lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no);
1411
1412         /* Set sequence number, command and INT option */
1413         priv->seqnum++;
1414         cmdptr->seqnum = cpu_to_le16(priv->seqnum);
1415
1416         cmdptr->command = cpu_to_le16(cmd_no);
1417         cmdptr->result = 0;
1418
1419         switch (cmd_no) {
1420         case CMD_802_11_PS_MODE:
1421                 ret = lbs_cmd_802_11_ps_mode(cmdptr, cmd_action);
1422                 break;
1423
1424         case CMD_MAC_REG_ACCESS:
1425         case CMD_BBP_REG_ACCESS:
1426         case CMD_RF_REG_ACCESS:
1427                 ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf);
1428                 break;
1429
1430         case CMD_802_11_MONITOR_MODE:
1431                 ret = lbs_cmd_802_11_monitor_mode(cmdptr,
1432                                           cmd_action, pdata_buf);
1433                 break;
1434
1435         case CMD_802_11_RSSI:
1436                 ret = lbs_cmd_802_11_rssi(priv, cmdptr);
1437                 break;
1438
1439         case CMD_802_11_SET_AFC:
1440         case CMD_802_11_GET_AFC:
1441
1442                 cmdptr->command = cpu_to_le16(cmd_no);
1443                 cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
1444                                            S_DS_GEN);
1445
1446                 memmove(&cmdptr->params.afc,
1447                         pdata_buf, sizeof(struct cmd_ds_802_11_afc));
1448
1449                 ret = 0;
1450                 goto done;
1451
1452         case CMD_802_11D_DOMAIN_INFO:
1453                 ret = lbs_cmd_802_11d_domain_info(priv, cmdptr,
1454                                                    cmd_no, cmd_action);
1455                 break;
1456
1457         case CMD_802_11_TPC_CFG:
1458                 cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG);
1459                 cmdptr->size =
1460                     cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) +
1461                                      S_DS_GEN);
1462
1463                 memmove(&cmdptr->params.tpccfg,
1464                         pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg));
1465
1466                 ret = 0;
1467                 break;
1468         case CMD_802_11_LED_GPIO_CTRL:
1469                 {
1470                         struct mrvl_ie_ledgpio *gpio =
1471                             (struct mrvl_ie_ledgpio*)
1472                             cmdptr->params.ledgpio.data;
1473
1474                         memmove(&cmdptr->params.ledgpio,
1475                                 pdata_buf,
1476                                 sizeof(struct cmd_ds_802_11_led_ctrl));
1477
1478                         cmdptr->command =
1479                             cpu_to_le16(CMD_802_11_LED_GPIO_CTRL);
1480
1481 #define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8
1482                         cmdptr->size =
1483                             cpu_to_le16(le16_to_cpu(gpio->header.len)
1484                                 + S_DS_GEN
1485                                 + ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN);
1486                         gpio->header.len = gpio->header.len;
1487
1488                         ret = 0;
1489                         break;
1490                 }
1491
1492         case CMD_BT_ACCESS:
1493                 ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf);
1494                 break;
1495
1496         case CMD_FWT_ACCESS:
1497                 ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf);
1498                 break;
1499
1500         case CMD_GET_TSF:
1501                 cmdptr->command = cpu_to_le16(CMD_GET_TSF);
1502                 cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) +
1503                                            S_DS_GEN);
1504                 ret = 0;
1505                 break;
1506         case CMD_802_11_BEACON_CTRL:
1507                 ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
1508                 break;
1509         default:
1510                 lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
1511                 ret = -1;
1512                 break;
1513         }
1514
1515         /* return error, since the command preparation failed */
1516         if (ret != 0) {
1517                 lbs_deb_host("PREP_CMD: command preparation failed\n");
1518                 lbs_cleanup_and_insert_cmd(priv, cmdnode);
1519                 ret = -1;
1520                 goto done;
1521         }
1522
1523         cmdnode->cmdwaitqwoken = 0;
1524
1525         lbs_queue_cmd(priv, cmdnode);
1526         wake_up_interruptible(&priv->waitq);
1527
1528         if (wait_option & CMD_OPTION_WAITFORRSP) {
1529                 lbs_deb_host("PREP_CMD: wait for response\n");
1530                 might_sleep();
1531                 wait_event_interruptible(cmdnode->cmdwait_q,
1532                                          cmdnode->cmdwaitqwoken);
1533         }
1534
1535         spin_lock_irqsave(&priv->driver_lock, flags);
1536         if (priv->cur_cmd_retcode) {
1537                 lbs_deb_host("PREP_CMD: command failed with return code %d\n",
1538                        priv->cur_cmd_retcode);
1539                 priv->cur_cmd_retcode = 0;
1540                 ret = -1;
1541         }
1542         spin_unlock_irqrestore(&priv->driver_lock, flags);
1543
1544 done:
1545         lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1546         return ret;
1547 }
1548
1549 /**
1550  *  @brief This function allocates the command buffer and link
1551  *  it to command free queue.
1552  *
1553  *  @param priv         A pointer to struct lbs_private structure
1554  *  @return             0 or -1
1555  */
1556 int lbs_allocate_cmd_buffer(struct lbs_private *priv)
1557 {
1558         int ret = 0;
1559         u32 bufsize;
1560         u32 i;
1561         struct cmd_ctrl_node *cmdarray;
1562
1563         lbs_deb_enter(LBS_DEB_HOST);
1564
1565         /* Allocate and initialize the command array */
1566         bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;
1567         if (!(cmdarray = kzalloc(bufsize, GFP_KERNEL))) {
1568                 lbs_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
1569                 ret = -1;
1570                 goto done;
1571         }
1572         priv->cmd_array = cmdarray;
1573
1574         /* Allocate and initialize each command buffer in the command array */
1575         for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
1576                 cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL);
1577                 if (!cmdarray[i].cmdbuf) {
1578                         lbs_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
1579                         ret = -1;
1580                         goto done;
1581                 }
1582         }
1583
1584         for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
1585                 init_waitqueue_head(&cmdarray[i].cmdwait_q);
1586                 lbs_cleanup_and_insert_cmd(priv, &cmdarray[i]);
1587         }
1588         ret = 0;
1589
1590 done:
1591         lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1592         return ret;
1593 }
1594
1595 /**
1596  *  @brief This function frees the command buffer.
1597  *
1598  *  @param priv         A pointer to struct lbs_private structure
1599  *  @return             0 or -1
1600  */
1601 int lbs_free_cmd_buffer(struct lbs_private *priv)
1602 {
1603         struct cmd_ctrl_node *cmdarray;
1604         unsigned int i;
1605
1606         lbs_deb_enter(LBS_DEB_HOST);
1607
1608         /* need to check if cmd array is allocated or not */
1609         if (priv->cmd_array == NULL) {
1610                 lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
1611                 goto done;
1612         }
1613
1614         cmdarray = priv->cmd_array;
1615
1616         /* Release shared memory buffers */
1617         for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
1618                 if (cmdarray[i].cmdbuf) {
1619                         kfree(cmdarray[i].cmdbuf);
1620                         cmdarray[i].cmdbuf = NULL;
1621                 }
1622         }
1623
1624         /* Release cmd_ctrl_node */
1625         if (priv->cmd_array) {
1626                 kfree(priv->cmd_array);
1627                 priv->cmd_array = NULL;
1628         }
1629
1630 done:
1631         lbs_deb_leave(LBS_DEB_HOST);
1632         return 0;
1633 }
1634
1635 /**
1636  *  @brief This function gets a free command node if available in
1637  *  command free queue.
1638  *
1639  *  @param priv         A pointer to struct lbs_private structure
1640  *  @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL
1641  */
1642 static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv)
1643 {
1644         struct cmd_ctrl_node *tempnode;
1645         unsigned long flags;
1646
1647         lbs_deb_enter(LBS_DEB_HOST);
1648
1649         if (!priv)
1650                 return NULL;
1651
1652         spin_lock_irqsave(&priv->driver_lock, flags);
1653
1654         if (!list_empty(&priv->cmdfreeq)) {
1655                 tempnode = list_first_entry(&priv->cmdfreeq,
1656                                             struct cmd_ctrl_node, list);
1657                 list_del(&tempnode->list);
1658         } else {
1659                 lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
1660                 tempnode = NULL;
1661         }
1662
1663         spin_unlock_irqrestore(&priv->driver_lock, flags);
1664
1665         lbs_deb_leave(LBS_DEB_HOST);
1666         return tempnode;
1667 }
1668
1669 /**
1670  *  @brief This function executes next command in command
1671  *  pending queue. It will put firmware back to PS mode
1672  *  if applicable.
1673  *
1674  *  @param priv     A pointer to struct lbs_private structure
1675  *  @return        0 or -1
1676  */
1677 int lbs_execute_next_command(struct lbs_private *priv)
1678 {
1679         struct cmd_ctrl_node *cmdnode = NULL;
1680         struct cmd_header *cmd;
1681         unsigned long flags;
1682         int ret = 0;
1683
1684         /* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
1685          * only caller to us is lbs_thread() and we get even when a
1686          * data packet is received */
1687         lbs_deb_enter(LBS_DEB_THREAD);
1688
1689         spin_lock_irqsave(&priv->driver_lock, flags);
1690
1691         if (priv->cur_cmd) {
1692                 lbs_pr_alert( "EXEC_NEXT_CMD: already processing command!\n");
1693                 spin_unlock_irqrestore(&priv->driver_lock, flags);
1694                 ret = -1;
1695                 goto done;
1696         }
1697
1698         if (!list_empty(&priv->cmdpendingq)) {
1699                 cmdnode = list_first_entry(&priv->cmdpendingq,
1700                                            struct cmd_ctrl_node, list);
1701         }
1702
1703         spin_unlock_irqrestore(&priv->driver_lock, flags);
1704
1705         if (cmdnode) {
1706                 cmd = cmdnode->cmdbuf;
1707
1708                 if (is_command_allowed_in_ps(le16_to_cpu(cmd->command))) {
1709                         if ((priv->psstate == PS_STATE_SLEEP) ||
1710                             (priv->psstate == PS_STATE_PRE_SLEEP)) {
1711                                 lbs_deb_host(
1712                                        "EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d\n",
1713                                        le16_to_cpu(cmd->command),
1714                                        priv->psstate);
1715                                 ret = -1;
1716                                 goto done;
1717                         }
1718                         lbs_deb_host("EXEC_NEXT_CMD: OK to send command "
1719                                      "0x%04x in psstate %d\n",
1720                                      le16_to_cpu(cmd->command), priv->psstate);
1721                 } else if (priv->psstate != PS_STATE_FULL_POWER) {
1722                         /*
1723                          * 1. Non-PS command:
1724                          * Queue it. set needtowakeup to TRUE if current state
1725                          * is SLEEP, otherwise call lbs_ps_wakeup to send Exit_PS.
1726                          * 2. PS command but not Exit_PS:
1727                          * Ignore it.
1728                          * 3. PS command Exit_PS:
1729                          * Set needtowakeup to TRUE if current state is SLEEP,
1730                          * otherwise send this command down to firmware
1731                          * immediately.
1732                          */
1733                         if (cmd->command != cpu_to_le16(CMD_802_11_PS_MODE)) {
1734                                 /*  Prepare to send Exit PS,
1735                                  *  this non PS command will be sent later */
1736                                 if ((priv->psstate == PS_STATE_SLEEP)
1737                                     || (priv->psstate == PS_STATE_PRE_SLEEP)
1738                                     ) {
1739                                         /* w/ new scheme, it will not reach here.
1740                                            since it is blocked in main_thread. */
1741                                         priv->needtowakeup = 1;
1742                                 } else
1743                                         lbs_ps_wakeup(priv, 0);
1744
1745                                 ret = 0;
1746                                 goto done;
1747                         } else {
1748                                 /*
1749                                  * PS command. Ignore it if it is not Exit_PS.
1750                                  * otherwise send it down immediately.
1751                                  */
1752                                 struct cmd_ds_802_11_ps_mode *psm = (void *)&cmd[1];
1753
1754                                 lbs_deb_host(
1755                                        "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n",
1756                                        psm->action);
1757                                 if (psm->action !=
1758                                     cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
1759                                         lbs_deb_host(
1760                                                "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
1761                                         spin_lock_irqsave(&priv->driver_lock, flags);
1762                                         list_del(&cmdnode->list);
1763                                         lbs_complete_command(priv, cmdnode, 0);
1764                                         spin_unlock_irqrestore(&priv->driver_lock, flags);
1765
1766                                         ret = 0;
1767                                         goto done;
1768                                 }
1769
1770                                 if ((priv->psstate == PS_STATE_SLEEP) ||
1771                                     (priv->psstate == PS_STATE_PRE_SLEEP)) {
1772                                         lbs_deb_host(
1773                                                "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
1774                                         spin_lock_irqsave(&priv->driver_lock, flags);
1775                                         list_del(&cmdnode->list);
1776                                         lbs_complete_command(priv, cmdnode, 0);
1777                                         spin_unlock_irqrestore(&priv->driver_lock, flags);
1778                                         priv->needtowakeup = 1;
1779
1780                                         ret = 0;
1781                                         goto done;
1782                                 }
1783
1784                                 lbs_deb_host(
1785                                        "EXEC_NEXT_CMD: sending EXIT_PS\n");
1786                         }
1787                 }
1788                 spin_lock_irqsave(&priv->driver_lock, flags);
1789                 list_del(&cmdnode->list);
1790                 spin_unlock_irqrestore(&priv->driver_lock, flags);
1791                 lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
1792                             le16_to_cpu(cmd->command));
1793                 lbs_submit_command(priv, cmdnode);
1794         } else {
1795                 /*
1796                  * check if in power save mode, if yes, put the device back
1797                  * to PS mode
1798                  */
1799                 if ((priv->psmode != LBS802_11POWERMODECAM) &&
1800                     (priv->psstate == PS_STATE_FULL_POWER) &&
1801                     ((priv->connect_status == LBS_CONNECTED) ||
1802                     (priv->mesh_connect_status == LBS_CONNECTED))) {
1803                         if (priv->secinfo.WPAenabled ||
1804                             priv->secinfo.WPA2enabled) {
1805                                 /* check for valid WPA group keys */
1806                                 if (priv->wpa_mcast_key.len ||
1807                                     priv->wpa_unicast_key.len) {
1808                                         lbs_deb_host(
1809                                                "EXEC_NEXT_CMD: WPA enabled and GTK_SET"
1810                                                " go back to PS_SLEEP");
1811                                         lbs_ps_sleep(priv, 0);
1812                                 }
1813                         } else {
1814                                 lbs_deb_host(
1815                                        "EXEC_NEXT_CMD: cmdpendingq empty, "
1816                                        "go back to PS_SLEEP");
1817                                 lbs_ps_sleep(priv, 0);
1818                         }
1819                 }
1820         }
1821
1822         ret = 0;
1823 done:
1824         lbs_deb_leave(LBS_DEB_THREAD);
1825         return ret;
1826 }
1827
1828 void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str)
1829 {
1830         union iwreq_data iwrq;
1831         u8 buf[50];
1832
1833         lbs_deb_enter(LBS_DEB_WEXT);
1834
1835         memset(&iwrq, 0, sizeof(union iwreq_data));
1836         memset(buf, 0, sizeof(buf));
1837
1838         snprintf(buf, sizeof(buf) - 1, "%s", str);
1839
1840         iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
1841
1842         /* Send Event to upper layer */
1843         lbs_deb_wext("event indication string %s\n", (char *)buf);
1844         lbs_deb_wext("event indication length %d\n", iwrq.data.length);
1845         lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str);
1846
1847         wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
1848
1849         lbs_deb_leave(LBS_DEB_WEXT);
1850 }
1851
1852 static void lbs_send_confirmsleep(struct lbs_private *priv)
1853 {
1854         unsigned long flags;
1855         int ret;
1856
1857         lbs_deb_enter(LBS_DEB_HOST);
1858         lbs_deb_hex(LBS_DEB_HOST, "sleep confirm", (u8 *) &confirm_sleep,
1859                 sizeof(confirm_sleep));
1860
1861         ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep,
1862                 sizeof(confirm_sleep));
1863         if (ret) {
1864                 lbs_pr_alert("confirm_sleep failed\n");
1865                 goto out;
1866         }
1867
1868         spin_lock_irqsave(&priv->driver_lock, flags);
1869
1870         /* We don't get a response on the sleep-confirmation */
1871         priv->dnld_sent = DNLD_RES_RECEIVED;
1872
1873         /* If nothing to do, go back to sleep (?) */
1874         if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx])
1875                 priv->psstate = PS_STATE_SLEEP;
1876
1877         spin_unlock_irqrestore(&priv->driver_lock, flags);
1878
1879 out:
1880         lbs_deb_leave(LBS_DEB_HOST);
1881 }
1882
1883 void lbs_ps_sleep(struct lbs_private *priv, int wait_option)
1884 {
1885         lbs_deb_enter(LBS_DEB_HOST);
1886
1887         /*
1888          * PS is currently supported only in Infrastructure mode
1889          * Remove this check if it is to be supported in IBSS mode also
1890          */
1891
1892         lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1893                               CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL);
1894
1895         lbs_deb_leave(LBS_DEB_HOST);
1896 }
1897
1898 /**
1899  *  @brief This function sends Exit_PS command to firmware.
1900  *
1901  *  @param priv         A pointer to struct lbs_private structure
1902  *  @param wait_option  wait response or not
1903  *  @return             n/a
1904  */
1905 void lbs_ps_wakeup(struct lbs_private *priv, int wait_option)
1906 {
1907         __le32 Localpsmode;
1908
1909         lbs_deb_enter(LBS_DEB_HOST);
1910
1911         Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
1912
1913         lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1914                               CMD_SUBCMD_EXIT_PS,
1915                               wait_option, 0, &Localpsmode);
1916
1917         lbs_deb_leave(LBS_DEB_HOST);
1918 }
1919
1920 /**
1921  *  @brief This function checks condition and prepares to
1922  *  send sleep confirm command to firmware if ok.
1923  *
1924  *  @param priv         A pointer to struct lbs_private structure
1925  *  @param psmode       Power Saving mode
1926  *  @return             n/a
1927  */
1928 void lbs_ps_confirm_sleep(struct lbs_private *priv)
1929 {
1930         unsigned long flags =0;
1931         int allowed = 1;
1932
1933         lbs_deb_enter(LBS_DEB_HOST);
1934
1935         spin_lock_irqsave(&priv->driver_lock, flags);
1936         if (priv->dnld_sent) {
1937                 allowed = 0;
1938                 lbs_deb_host("dnld_sent was set\n");
1939         }
1940
1941         /* In-progress command? */
1942         if (priv->cur_cmd) {
1943                 allowed = 0;
1944                 lbs_deb_host("cur_cmd was set\n");
1945         }
1946
1947         /* Pending events or command responses? */
1948         if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) {
1949                 allowed = 0;
1950                 lbs_deb_host("pending events or command responses\n");
1951         }
1952         spin_unlock_irqrestore(&priv->driver_lock, flags);
1953
1954         if (allowed) {
1955                 lbs_deb_host("sending lbs_ps_confirm_sleep\n");
1956                 lbs_send_confirmsleep(priv);
1957         } else {
1958                 lbs_deb_host("sleep confirm has been delayed\n");
1959         }
1960
1961         lbs_deb_leave(LBS_DEB_HOST);
1962 }
1963
1964
1965 /**
1966  * @brief Configures the transmission power control functionality.
1967  *
1968  * @param priv          A pointer to struct lbs_private structure
1969  * @param enable        Transmission power control enable
1970  * @param p0            Power level when link quality is good (dBm).
1971  * @param p1            Power level when link quality is fair (dBm).
1972  * @param p2            Power level when link quality is poor (dBm).
1973  * @param usesnr        Use Signal to Noise Ratio in TPC
1974  *
1975  * @return 0 on success
1976  */
1977 int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
1978                 int8_t p2, int usesnr)
1979 {
1980         struct cmd_ds_802_11_tpc_cfg cmd;
1981         int ret;
1982
1983         memset(&cmd, 0, sizeof(cmd));
1984         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1985         cmd.action = cpu_to_le16(CMD_ACT_SET);
1986         cmd.enable = !!enable;
1987         cmd.usesnr = !!usesnr;
1988         cmd.P0 = p0;
1989         cmd.P1 = p1;
1990         cmd.P2 = p2;
1991
1992         ret = lbs_cmd_with_response(priv, CMD_802_11_TPC_CFG, &cmd);
1993
1994         return ret;
1995 }
1996
1997 /**
1998  * @brief Configures the power adaptation settings.
1999  *
2000  * @param priv          A pointer to struct lbs_private structure
2001  * @param enable        Power adaptation enable
2002  * @param p0            Power level for 1, 2, 5.5 and 11 Mbps (dBm).
2003  * @param p1            Power level for 6, 9, 12, 18, 22, 24 and 36 Mbps (dBm).
2004  * @param p2            Power level for 48 and 54 Mbps (dBm).
2005  *
2006  * @return 0 on Success
2007  */
2008
2009 int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
2010                 int8_t p1, int8_t p2)
2011 {
2012         struct cmd_ds_802_11_pa_cfg cmd;
2013         int ret;
2014
2015         memset(&cmd, 0, sizeof(cmd));
2016         cmd.hdr.size = cpu_to_le16(sizeof(cmd));
2017         cmd.action = cpu_to_le16(CMD_ACT_SET);
2018         cmd.enable = !!enable;
2019         cmd.P0 = p0;
2020         cmd.P1 = p1;
2021         cmd.P2 = p2;
2022
2023         ret = lbs_cmd_with_response(priv, CMD_802_11_PA_CFG , &cmd);
2024
2025         return ret;
2026 }
2027
2028
2029 static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
2030         uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
2031         int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
2032         unsigned long callback_arg)
2033 {
2034         struct cmd_ctrl_node *cmdnode;
2035
2036         lbs_deb_enter(LBS_DEB_HOST);
2037
2038         if (priv->surpriseremoved) {
2039                 lbs_deb_host("PREP_CMD: card removed\n");
2040                 cmdnode = ERR_PTR(-ENOENT);
2041                 goto done;
2042         }
2043
2044         cmdnode = lbs_get_cmd_ctrl_node(priv);
2045         if (cmdnode == NULL) {
2046                 lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
2047
2048                 /* Wake up main thread to execute next command */
2049                 wake_up_interruptible(&priv->waitq);
2050                 cmdnode = ERR_PTR(-ENOBUFS);
2051                 goto done;
2052         }
2053
2054         cmdnode->callback = callback;
2055         cmdnode->callback_arg = callback_arg;
2056
2057         /* Copy the incoming command to the buffer */
2058         memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size);
2059
2060         /* Set sequence number, clean result, move to buffer */
2061         priv->seqnum++;
2062         cmdnode->cmdbuf->command = cpu_to_le16(command);
2063         cmdnode->cmdbuf->size    = cpu_to_le16(in_cmd_size);
2064         cmdnode->cmdbuf->seqnum  = cpu_to_le16(priv->seqnum);
2065         cmdnode->cmdbuf->result  = 0;
2066
2067         lbs_deb_host("PREP_CMD: command 0x%04x\n", command);
2068
2069         cmdnode->cmdwaitqwoken = 0;
2070         lbs_queue_cmd(priv, cmdnode);
2071         wake_up_interruptible(&priv->waitq);
2072
2073  done:
2074         lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode);
2075         return cmdnode;
2076 }
2077
2078 void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
2079         struct cmd_header *in_cmd, int in_cmd_size)
2080 {
2081         lbs_deb_enter(LBS_DEB_CMD);
2082         __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
2083                 lbs_cmd_async_callback, 0);
2084         lbs_deb_leave(LBS_DEB_CMD);
2085 }
2086
2087 int __lbs_cmd(struct lbs_private *priv, uint16_t command,
2088               struct cmd_header *in_cmd, int in_cmd_size,
2089               int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
2090               unsigned long callback_arg)
2091 {
2092         struct cmd_ctrl_node *cmdnode;
2093         unsigned long flags;
2094         int ret = 0;
2095
2096         lbs_deb_enter(LBS_DEB_HOST);
2097
2098         cmdnode = __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
2099                                   callback, callback_arg);
2100         if (IS_ERR(cmdnode)) {
2101                 ret = PTR_ERR(cmdnode);
2102                 goto done;
2103         }
2104
2105         might_sleep();
2106         wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);
2107
2108         spin_lock_irqsave(&priv->driver_lock, flags);
2109         ret = cmdnode->result;
2110         if (ret)
2111                 lbs_pr_info("PREP_CMD: command 0x%04x failed: %d\n",
2112                             command, ret);
2113
2114         __lbs_cleanup_and_insert_cmd(priv, cmdnode);
2115         spin_unlock_irqrestore(&priv->driver_lock, flags);
2116
2117 done:
2118         lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
2119         return ret;
2120 }
2121 EXPORT_SYMBOL_GPL(__lbs_cmd);
2122
2123