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