Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[deliverable/linux.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 <linux/kfifo.h>
7 #include <linux/sched.h>
8 #include <linux/slab.h>
9
10 #include "host.h"
11 #include "decl.h"
12 #include "defs.h"
13 #include "dev.h"
14 #include "assoc.h"
15 #include "wext.h"
16 #include "scan.h"
17 #include "cmd.h"
18
19
20 static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
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 case CMD_802_11_HOST_SLEEP_CFG:
74 return 1;
75 default:
76 break;
77 }
78 return 0;
79 }
80
81 /**
82 * @brief This function checks if the command is allowed.
83 *
84 * @param priv A pointer to lbs_private structure
85 * @return allowed or not allowed.
86 */
87
88 static int lbs_is_cmd_allowed(struct lbs_private *priv)
89 {
90 int ret = 1;
91
92 lbs_deb_enter(LBS_DEB_CMD);
93
94 if (!priv->is_auto_deep_sleep_enabled) {
95 if (priv->is_deep_sleep) {
96 lbs_deb_cmd("command not allowed in deep sleep\n");
97 ret = 0;
98 }
99 }
100
101 lbs_deb_leave(LBS_DEB_CMD);
102 return ret;
103 }
104
105 /**
106 * @brief Updates the hardware details like MAC address and regulatory region
107 *
108 * @param priv A pointer to struct lbs_private structure
109 *
110 * @return 0 on success, error on failure
111 */
112 int lbs_update_hw_spec(struct lbs_private *priv)
113 {
114 struct cmd_ds_get_hw_spec cmd;
115 int ret = -1;
116 u32 i;
117
118 lbs_deb_enter(LBS_DEB_CMD);
119
120 memset(&cmd, 0, sizeof(cmd));
121 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
122 memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN);
123 ret = lbs_cmd_with_response(priv, CMD_GET_HW_SPEC, &cmd);
124 if (ret)
125 goto out;
126
127 priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo);
128
129 /* The firmware release is in an interesting format: the patch
130 * level is in the most significant nibble ... so fix that: */
131 priv->fwrelease = le32_to_cpu(cmd.fwrelease);
132 priv->fwrelease = (priv->fwrelease << 8) |
133 (priv->fwrelease >> 24 & 0xff);
134
135 /* Some firmware capabilities:
136 * CF card firmware 5.0.16p0: cap 0x00000303
137 * USB dongle firmware 5.110.17p2: cap 0x00000303
138 */
139 lbs_pr_info("%pM, fw %u.%u.%up%u, cap 0x%08x\n",
140 cmd.permanentaddr,
141 priv->fwrelease >> 24 & 0xff,
142 priv->fwrelease >> 16 & 0xff,
143 priv->fwrelease >> 8 & 0xff,
144 priv->fwrelease & 0xff,
145 priv->fwcapinfo);
146 lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
147 cmd.hwifversion, cmd.version);
148
149 /* Clamp region code to 8-bit since FW spec indicates that it should
150 * only ever be 8-bit, even though the field size is 16-bit. Some firmware
151 * returns non-zero high 8 bits here.
152 *
153 * Firmware version 4.0.102 used in CF8381 has region code shifted. We
154 * need to check for this problem and handle it properly.
155 */
156 if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V4)
157 priv->regioncode = (le16_to_cpu(cmd.regioncode) >> 8) & 0xFF;
158 else
159 priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF;
160
161 for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
162 /* use the region code to search for the index */
163 if (priv->regioncode == lbs_region_code_to_index[i])
164 break;
165 }
166
167 /* if it's unidentified region code, use the default (USA) */
168 if (i >= MRVDRV_MAX_REGION_CODE) {
169 priv->regioncode = 0x10;
170 lbs_pr_info("unidentified region code; using the default (USA)\n");
171 }
172
173 if (priv->current_addr[0] == 0xff)
174 memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
175
176 memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN);
177 if (priv->mesh_dev)
178 memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
179
180 if (lbs_set_regiontable(priv, priv->regioncode, 0)) {
181 ret = -1;
182 goto out;
183 }
184
185 out:
186 lbs_deb_leave(LBS_DEB_CMD);
187 return ret;
188 }
189
190 static int lbs_ret_host_sleep_cfg(struct lbs_private *priv, unsigned long dummy,
191 struct cmd_header *resp)
192 {
193 lbs_deb_enter(LBS_DEB_CMD);
194 if (priv->wol_criteria == EHS_REMOVE_WAKEUP) {
195 priv->is_host_sleep_configured = 0;
196 if (priv->psstate == PS_STATE_FULL_POWER) {
197 priv->is_host_sleep_activated = 0;
198 wake_up_interruptible(&priv->host_sleep_q);
199 }
200 } else {
201 priv->is_host_sleep_configured = 1;
202 }
203 lbs_deb_leave(LBS_DEB_CMD);
204 return 0;
205 }
206
207 int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
208 struct wol_config *p_wol_config)
209 {
210 struct cmd_ds_host_sleep cmd_config;
211 int ret;
212
213 cmd_config.hdr.size = cpu_to_le16(sizeof(cmd_config));
214 cmd_config.criteria = cpu_to_le32(criteria);
215 cmd_config.gpio = priv->wol_gpio;
216 cmd_config.gap = priv->wol_gap;
217
218 if (p_wol_config != NULL)
219 memcpy((uint8_t *)&cmd_config.wol_conf, (uint8_t *)p_wol_config,
220 sizeof(struct wol_config));
221 else
222 cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE;
223
224 ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config.hdr,
225 le16_to_cpu(cmd_config.hdr.size),
226 lbs_ret_host_sleep_cfg, 0);
227 if (!ret) {
228 if (p_wol_config)
229 memcpy((uint8_t *) p_wol_config,
230 (uint8_t *)&cmd_config.wol_conf,
231 sizeof(struct wol_config));
232 } else {
233 lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret);
234 }
235
236 return ret;
237 }
238 EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);
239
240 static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd,
241 u16 cmd_action)
242 {
243 struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode;
244
245 lbs_deb_enter(LBS_DEB_CMD);
246
247 cmd->command = cpu_to_le16(CMD_802_11_PS_MODE);
248 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) +
249 sizeof(struct cmd_header));
250 psm->action = cpu_to_le16(cmd_action);
251 psm->multipledtim = 0;
252 switch (cmd_action) {
253 case CMD_SUBCMD_ENTER_PS:
254 lbs_deb_cmd("PS command:" "SubCode- Enter PS\n");
255
256 psm->locallisteninterval = 0;
257 psm->nullpktinterval = 0;
258 psm->multipledtim =
259 cpu_to_le16(MRVDRV_DEFAULT_MULTIPLE_DTIM);
260 break;
261
262 case CMD_SUBCMD_EXIT_PS:
263 lbs_deb_cmd("PS command:" "SubCode- Exit PS\n");
264 break;
265
266 case CMD_SUBCMD_SLEEP_CONFIRMED:
267 lbs_deb_cmd("PS command: SubCode- sleep confirm\n");
268 break;
269
270 default:
271 break;
272 }
273
274 lbs_deb_leave(LBS_DEB_CMD);
275 return 0;
276 }
277
278 int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
279 struct sleep_params *sp)
280 {
281 struct cmd_ds_802_11_sleep_params cmd;
282 int ret;
283
284 lbs_deb_enter(LBS_DEB_CMD);
285
286 if (cmd_action == CMD_ACT_GET) {
287 memset(&cmd, 0, sizeof(cmd));
288 } else {
289 cmd.error = cpu_to_le16(sp->sp_error);
290 cmd.offset = cpu_to_le16(sp->sp_offset);
291 cmd.stabletime = cpu_to_le16(sp->sp_stabletime);
292 cmd.calcontrol = sp->sp_calcontrol;
293 cmd.externalsleepclk = sp->sp_extsleepclk;
294 cmd.reserved = cpu_to_le16(sp->sp_reserved);
295 }
296 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
297 cmd.action = cpu_to_le16(cmd_action);
298
299 ret = lbs_cmd_with_response(priv, CMD_802_11_SLEEP_PARAMS, &cmd);
300
301 if (!ret) {
302 lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, "
303 "calcontrol 0x%x extsleepclk 0x%x\n",
304 le16_to_cpu(cmd.error), le16_to_cpu(cmd.offset),
305 le16_to_cpu(cmd.stabletime), cmd.calcontrol,
306 cmd.externalsleepclk);
307
308 sp->sp_error = le16_to_cpu(cmd.error);
309 sp->sp_offset = le16_to_cpu(cmd.offset);
310 sp->sp_stabletime = le16_to_cpu(cmd.stabletime);
311 sp->sp_calcontrol = cmd.calcontrol;
312 sp->sp_extsleepclk = cmd.externalsleepclk;
313 sp->sp_reserved = le16_to_cpu(cmd.reserved);
314 }
315
316 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
317 return 0;
318 }
319
320 static int lbs_wait_for_ds_awake(struct lbs_private *priv)
321 {
322 int ret = 0;
323
324 lbs_deb_enter(LBS_DEB_CMD);
325
326 if (priv->is_deep_sleep) {
327 if (!wait_event_interruptible_timeout(priv->ds_awake_q,
328 !priv->is_deep_sleep, (10 * HZ))) {
329 lbs_pr_err("ds_awake_q: timer expired\n");
330 ret = -1;
331 }
332 }
333
334 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
335 return ret;
336 }
337
338 int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)
339 {
340 int ret = 0;
341
342 lbs_deb_enter(LBS_DEB_CMD);
343
344 if (deep_sleep) {
345 if (priv->is_deep_sleep != 1) {
346 lbs_deb_cmd("deep sleep: sleep\n");
347 BUG_ON(!priv->enter_deep_sleep);
348 ret = priv->enter_deep_sleep(priv);
349 if (!ret) {
350 netif_stop_queue(priv->dev);
351 netif_carrier_off(priv->dev);
352 }
353 } else {
354 lbs_pr_err("deep sleep: already enabled\n");
355 }
356 } else {
357 if (priv->is_deep_sleep) {
358 lbs_deb_cmd("deep sleep: wakeup\n");
359 BUG_ON(!priv->exit_deep_sleep);
360 ret = priv->exit_deep_sleep(priv);
361 if (!ret) {
362 ret = lbs_wait_for_ds_awake(priv);
363 if (ret)
364 lbs_pr_err("deep sleep: wakeup"
365 "failed\n");
366 }
367 }
368 }
369
370 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
371 return ret;
372 }
373
374 /**
375 * @brief Set an SNMP MIB value
376 *
377 * @param priv A pointer to struct lbs_private structure
378 * @param oid The OID to set in the firmware
379 * @param val Value to set the OID to
380 *
381 * @return 0 on success, error on failure
382 */
383 int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val)
384 {
385 struct cmd_ds_802_11_snmp_mib cmd;
386 int ret;
387
388 lbs_deb_enter(LBS_DEB_CMD);
389
390 memset(&cmd, 0, sizeof (cmd));
391 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
392 cmd.action = cpu_to_le16(CMD_ACT_SET);
393 cmd.oid = cpu_to_le16((u16) oid);
394
395 switch (oid) {
396 case SNMP_MIB_OID_BSS_TYPE:
397 cmd.bufsize = cpu_to_le16(sizeof(u8));
398 cmd.value[0] = val;
399 break;
400 case SNMP_MIB_OID_11D_ENABLE:
401 case SNMP_MIB_OID_FRAG_THRESHOLD:
402 case SNMP_MIB_OID_RTS_THRESHOLD:
403 case SNMP_MIB_OID_SHORT_RETRY_LIMIT:
404 case SNMP_MIB_OID_LONG_RETRY_LIMIT:
405 cmd.bufsize = cpu_to_le16(sizeof(u16));
406 *((__le16 *)(&cmd.value)) = cpu_to_le16(val);
407 break;
408 default:
409 lbs_deb_cmd("SNMP_CMD: (set) unhandled OID 0x%x\n", oid);
410 ret = -EINVAL;
411 goto out;
412 }
413
414 lbs_deb_cmd("SNMP_CMD: (set) oid 0x%x, oid size 0x%x, value 0x%x\n",
415 le16_to_cpu(cmd.oid), le16_to_cpu(cmd.bufsize), val);
416
417 ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
418
419 out:
420 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
421 return ret;
422 }
423
424 /**
425 * @brief Get an SNMP MIB value
426 *
427 * @param priv A pointer to struct lbs_private structure
428 * @param oid The OID to retrieve from the firmware
429 * @param out_val Location for the returned value
430 *
431 * @return 0 on success, error on failure
432 */
433 int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val)
434 {
435 struct cmd_ds_802_11_snmp_mib cmd;
436 int ret;
437
438 lbs_deb_enter(LBS_DEB_CMD);
439
440 memset(&cmd, 0, sizeof (cmd));
441 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
442 cmd.action = cpu_to_le16(CMD_ACT_GET);
443 cmd.oid = cpu_to_le16(oid);
444
445 ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
446 if (ret)
447 goto out;
448
449 switch (le16_to_cpu(cmd.bufsize)) {
450 case sizeof(u8):
451 *out_val = cmd.value[0];
452 break;
453 case sizeof(u16):
454 *out_val = le16_to_cpu(*((__le16 *)(&cmd.value)));
455 break;
456 default:
457 lbs_deb_cmd("SNMP_CMD: (get) unhandled OID 0x%x size %d\n",
458 oid, le16_to_cpu(cmd.bufsize));
459 break;
460 }
461
462 out:
463 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
464 return ret;
465 }
466
467 /**
468 * @brief Get the min, max, and current TX power
469 *
470 * @param priv A pointer to struct lbs_private structure
471 * @param curlevel Current power level in dBm
472 * @param minlevel Minimum supported power level in dBm (optional)
473 * @param maxlevel Maximum supported power level in dBm (optional)
474 *
475 * @return 0 on success, error on failure
476 */
477 int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
478 s16 *maxlevel)
479 {
480 struct cmd_ds_802_11_rf_tx_power cmd;
481 int ret;
482
483 lbs_deb_enter(LBS_DEB_CMD);
484
485 memset(&cmd, 0, sizeof(cmd));
486 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
487 cmd.action = cpu_to_le16(CMD_ACT_GET);
488
489 ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
490 if (ret == 0) {
491 *curlevel = le16_to_cpu(cmd.curlevel);
492 if (minlevel)
493 *minlevel = cmd.minlevel;
494 if (maxlevel)
495 *maxlevel = cmd.maxlevel;
496 }
497
498 lbs_deb_leave(LBS_DEB_CMD);
499 return ret;
500 }
501
502 /**
503 * @brief Set the TX power
504 *
505 * @param priv A pointer to struct lbs_private structure
506 * @param dbm The desired power level in dBm
507 *
508 * @return 0 on success, error on failure
509 */
510 int lbs_set_tx_power(struct lbs_private *priv, s16 dbm)
511 {
512 struct cmd_ds_802_11_rf_tx_power cmd;
513 int ret;
514
515 lbs_deb_enter(LBS_DEB_CMD);
516
517 memset(&cmd, 0, sizeof(cmd));
518 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
519 cmd.action = cpu_to_le16(CMD_ACT_SET);
520 cmd.curlevel = cpu_to_le16(dbm);
521
522 lbs_deb_cmd("SET_RF_TX_POWER: %d dBm\n", dbm);
523
524 ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
525
526 lbs_deb_leave(LBS_DEB_CMD);
527 return ret;
528 }
529
530 static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
531 u16 cmd_action, void *pdata_buf)
532 {
533 struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor;
534
535 cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE);
536 cmd->size =
537 cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) +
538 sizeof(struct cmd_header));
539
540 monitor->action = cpu_to_le16(cmd_action);
541 if (cmd_action == CMD_ACT_SET) {
542 monitor->mode =
543 cpu_to_le16((u16) (*(u32 *) pdata_buf));
544 }
545
546 return 0;
547 }
548
549 /**
550 * @brief Get the radio channel
551 *
552 * @param priv A pointer to struct lbs_private structure
553 *
554 * @return The channel on success, error on failure
555 */
556 static int lbs_get_channel(struct lbs_private *priv)
557 {
558 struct cmd_ds_802_11_rf_channel cmd;
559 int ret = 0;
560
561 lbs_deb_enter(LBS_DEB_CMD);
562
563 memset(&cmd, 0, sizeof(cmd));
564 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
565 cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET);
566
567 ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
568 if (ret)
569 goto out;
570
571 ret = le16_to_cpu(cmd.channel);
572 lbs_deb_cmd("current radio channel is %d\n", ret);
573
574 out:
575 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
576 return ret;
577 }
578
579 int lbs_update_channel(struct lbs_private *priv)
580 {
581 int ret;
582
583 /* the channel in f/w could be out of sync; get the current channel */
584 lbs_deb_enter(LBS_DEB_ASSOC);
585
586 ret = lbs_get_channel(priv);
587 if (ret > 0) {
588 priv->channel = ret;
589 ret = 0;
590 }
591 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
592 return ret;
593 }
594
595 /**
596 * @brief Set the radio channel
597 *
598 * @param priv A pointer to struct lbs_private structure
599 * @param channel The desired channel, or 0 to clear a locked channel
600 *
601 * @return 0 on success, error on failure
602 */
603 int lbs_set_channel(struct lbs_private *priv, u8 channel)
604 {
605 struct cmd_ds_802_11_rf_channel cmd;
606 #ifdef DEBUG
607 u8 old_channel = priv->channel;
608 #endif
609 int ret = 0;
610
611 lbs_deb_enter(LBS_DEB_CMD);
612
613 memset(&cmd, 0, sizeof(cmd));
614 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
615 cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
616 cmd.channel = cpu_to_le16(channel);
617
618 ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
619 if (ret)
620 goto out;
621
622 priv->channel = (uint8_t) le16_to_cpu(cmd.channel);
623 lbs_deb_cmd("channel switch from %d to %d\n", old_channel,
624 priv->channel);
625
626 out:
627 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
628 return ret;
629 }
630
631 static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
632 u8 cmd_action, void *pdata_buf)
633 {
634 struct lbs_offset_value *offval;
635
636 lbs_deb_enter(LBS_DEB_CMD);
637
638 offval = (struct lbs_offset_value *)pdata_buf;
639
640 switch (le16_to_cpu(cmdptr->command)) {
641 case CMD_MAC_REG_ACCESS:
642 {
643 struct cmd_ds_mac_reg_access *macreg;
644
645 cmdptr->size =
646 cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access)
647 + sizeof(struct cmd_header));
648 macreg =
649 (struct cmd_ds_mac_reg_access *)&cmdptr->params.
650 macreg;
651
652 macreg->action = cpu_to_le16(cmd_action);
653 macreg->offset = cpu_to_le16((u16) offval->offset);
654 macreg->value = cpu_to_le32(offval->value);
655
656 break;
657 }
658
659 case CMD_BBP_REG_ACCESS:
660 {
661 struct cmd_ds_bbp_reg_access *bbpreg;
662
663 cmdptr->size =
664 cpu_to_le16(sizeof
665 (struct cmd_ds_bbp_reg_access)
666 + sizeof(struct cmd_header));
667 bbpreg =
668 (struct cmd_ds_bbp_reg_access *)&cmdptr->params.
669 bbpreg;
670
671 bbpreg->action = cpu_to_le16(cmd_action);
672 bbpreg->offset = cpu_to_le16((u16) offval->offset);
673 bbpreg->value = (u8) offval->value;
674
675 break;
676 }
677
678 case CMD_RF_REG_ACCESS:
679 {
680 struct cmd_ds_rf_reg_access *rfreg;
681
682 cmdptr->size =
683 cpu_to_le16(sizeof
684 (struct cmd_ds_rf_reg_access) +
685 sizeof(struct cmd_header));
686 rfreg =
687 (struct cmd_ds_rf_reg_access *)&cmdptr->params.
688 rfreg;
689
690 rfreg->action = cpu_to_le16(cmd_action);
691 rfreg->offset = cpu_to_le16((u16) offval->offset);
692 rfreg->value = (u8) offval->value;
693
694 break;
695 }
696
697 default:
698 break;
699 }
700
701 lbs_deb_leave(LBS_DEB_CMD);
702 return 0;
703 }
704
705 static void lbs_queue_cmd(struct lbs_private *priv,
706 struct cmd_ctrl_node *cmdnode)
707 {
708 unsigned long flags;
709 int addtail = 1;
710
711 lbs_deb_enter(LBS_DEB_HOST);
712
713 if (!cmdnode) {
714 lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n");
715 goto done;
716 }
717 if (!cmdnode->cmdbuf->size) {
718 lbs_deb_host("DNLD_CMD: cmd size is zero\n");
719 goto done;
720 }
721 cmdnode->result = 0;
722
723 /* Exit_PS command needs to be queued in the header always. */
724 if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) {
725 struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf[1];
726
727 if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
728 if (priv->psstate != PS_STATE_FULL_POWER)
729 addtail = 0;
730 }
731 }
732
733 if (le16_to_cpu(cmdnode->cmdbuf->command) ==
734 CMD_802_11_WAKEUP_CONFIRM)
735 addtail = 0;
736
737 spin_lock_irqsave(&priv->driver_lock, flags);
738
739 if (addtail)
740 list_add_tail(&cmdnode->list, &priv->cmdpendingq);
741 else
742 list_add(&cmdnode->list, &priv->cmdpendingq);
743
744 spin_unlock_irqrestore(&priv->driver_lock, flags);
745
746 lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
747 le16_to_cpu(cmdnode->cmdbuf->command));
748
749 done:
750 lbs_deb_leave(LBS_DEB_HOST);
751 }
752
753 static void lbs_submit_command(struct lbs_private *priv,
754 struct cmd_ctrl_node *cmdnode)
755 {
756 unsigned long flags;
757 struct cmd_header *cmd;
758 uint16_t cmdsize;
759 uint16_t command;
760 int timeo = 3 * HZ;
761 int ret;
762
763 lbs_deb_enter(LBS_DEB_HOST);
764
765 cmd = cmdnode->cmdbuf;
766
767 spin_lock_irqsave(&priv->driver_lock, flags);
768 priv->cur_cmd = cmdnode;
769 priv->cur_cmd_retcode = 0;
770 spin_unlock_irqrestore(&priv->driver_lock, flags);
771
772 cmdsize = le16_to_cpu(cmd->size);
773 command = le16_to_cpu(cmd->command);
774
775 /* These commands take longer */
776 if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE)
777 timeo = 5 * HZ;
778
779 lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
780 command, le16_to_cpu(cmd->seqnum), cmdsize);
781 lbs_deb_hex(LBS_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
782
783 ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
784
785 if (ret) {
786 lbs_pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret);
787 /* Let the timer kick in and retry, and potentially reset
788 the whole thing if the condition persists */
789 timeo = HZ/4;
790 }
791
792 if (command == CMD_802_11_DEEP_SLEEP) {
793 if (priv->is_auto_deep_sleep_enabled) {
794 priv->wakeup_dev_required = 1;
795 priv->dnld_sent = 0;
796 }
797 priv->is_deep_sleep = 1;
798 lbs_complete_command(priv, cmdnode, 0);
799 } else {
800 /* Setup the timer after transmit command */
801 mod_timer(&priv->command_timer, jiffies + timeo);
802 }
803
804 lbs_deb_leave(LBS_DEB_HOST);
805 }
806
807 /**
808 * This function inserts command node to cmdfreeq
809 * after cleans it. Requires priv->driver_lock held.
810 */
811 static void __lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
812 struct cmd_ctrl_node *cmdnode)
813 {
814 lbs_deb_enter(LBS_DEB_HOST);
815
816 if (!cmdnode)
817 goto out;
818
819 cmdnode->callback = NULL;
820 cmdnode->callback_arg = 0;
821
822 memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);
823
824 list_add_tail(&cmdnode->list, &priv->cmdfreeq);
825 out:
826 lbs_deb_leave(LBS_DEB_HOST);
827 }
828
829 static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
830 struct cmd_ctrl_node *ptempcmd)
831 {
832 unsigned long flags;
833
834 spin_lock_irqsave(&priv->driver_lock, flags);
835 __lbs_cleanup_and_insert_cmd(priv, ptempcmd);
836 spin_unlock_irqrestore(&priv->driver_lock, flags);
837 }
838
839 void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
840 int result)
841 {
842 if (cmd == priv->cur_cmd)
843 priv->cur_cmd_retcode = result;
844
845 cmd->result = result;
846 cmd->cmdwaitqwoken = 1;
847 wake_up_interruptible(&cmd->cmdwait_q);
848
849 if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)
850 __lbs_cleanup_and_insert_cmd(priv, cmd);
851 priv->cur_cmd = NULL;
852 }
853
854 int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on)
855 {
856 struct cmd_ds_802_11_radio_control cmd;
857 int ret = -EINVAL;
858
859 lbs_deb_enter(LBS_DEB_CMD);
860
861 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
862 cmd.action = cpu_to_le16(CMD_ACT_SET);
863
864 /* Only v8 and below support setting the preamble */
865 if (priv->fwrelease < 0x09000000) {
866 switch (preamble) {
867 case RADIO_PREAMBLE_SHORT:
868 case RADIO_PREAMBLE_AUTO:
869 case RADIO_PREAMBLE_LONG:
870 cmd.control = cpu_to_le16(preamble);
871 break;
872 default:
873 goto out;
874 }
875 }
876
877 if (radio_on)
878 cmd.control |= cpu_to_le16(0x1);
879 else {
880 cmd.control &= cpu_to_le16(~0x1);
881 priv->txpower_cur = 0;
882 }
883
884 lbs_deb_cmd("RADIO_CONTROL: radio %s, preamble %d\n",
885 radio_on ? "ON" : "OFF", preamble);
886
887 priv->radio_on = radio_on;
888
889 ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
890
891 out:
892 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
893 return ret;
894 }
895
896 void lbs_set_mac_control(struct lbs_private *priv)
897 {
898 struct cmd_ds_mac_control cmd;
899
900 lbs_deb_enter(LBS_DEB_CMD);
901
902 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
903 cmd.action = cpu_to_le16(priv->mac_control);
904 cmd.reserved = 0;
905
906 lbs_cmd_async(priv, CMD_MAC_CONTROL, &cmd.hdr, sizeof(cmd));
907
908 lbs_deb_leave(LBS_DEB_CMD);
909 }
910
911 /**
912 * @brief This function prepare the command before send to firmware.
913 *
914 * @param priv A pointer to struct lbs_private structure
915 * @param cmd_no command number
916 * @param cmd_action command action: GET or SET
917 * @param wait_option wait option: wait response or not
918 * @param cmd_oid cmd oid: treated as sub command
919 * @param pdata_buf A pointer to informaion buffer
920 * @return 0 or -1
921 */
922 int lbs_prepare_and_send_command(struct lbs_private *priv,
923 u16 cmd_no,
924 u16 cmd_action,
925 u16 wait_option, u32 cmd_oid, void *pdata_buf)
926 {
927 int ret = 0;
928 struct cmd_ctrl_node *cmdnode;
929 struct cmd_ds_command *cmdptr;
930 unsigned long flags;
931
932 lbs_deb_enter(LBS_DEB_HOST);
933
934 if (!priv) {
935 lbs_deb_host("PREP_CMD: priv is NULL\n");
936 ret = -1;
937 goto done;
938 }
939
940 if (priv->surpriseremoved) {
941 lbs_deb_host("PREP_CMD: card removed\n");
942 ret = -1;
943 goto done;
944 }
945
946 if (!lbs_is_cmd_allowed(priv)) {
947 ret = -EBUSY;
948 goto done;
949 }
950
951 cmdnode = lbs_get_cmd_ctrl_node(priv);
952
953 if (cmdnode == NULL) {
954 lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
955
956 /* Wake up main thread to execute next command */
957 wake_up_interruptible(&priv->waitq);
958 ret = -1;
959 goto done;
960 }
961
962 cmdnode->callback = NULL;
963 cmdnode->callback_arg = (unsigned long)pdata_buf;
964
965 cmdptr = (struct cmd_ds_command *)cmdnode->cmdbuf;
966
967 lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no);
968
969 /* Set sequence number, command and INT option */
970 priv->seqnum++;
971 cmdptr->seqnum = cpu_to_le16(priv->seqnum);
972
973 cmdptr->command = cpu_to_le16(cmd_no);
974 cmdptr->result = 0;
975
976 switch (cmd_no) {
977 case CMD_802_11_PS_MODE:
978 ret = lbs_cmd_802_11_ps_mode(cmdptr, cmd_action);
979 break;
980
981 case CMD_MAC_REG_ACCESS:
982 case CMD_BBP_REG_ACCESS:
983 case CMD_RF_REG_ACCESS:
984 ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf);
985 break;
986
987 case CMD_802_11_MONITOR_MODE:
988 ret = lbs_cmd_802_11_monitor_mode(cmdptr,
989 cmd_action, pdata_buf);
990 break;
991
992 case CMD_802_11_RSSI:
993 ret = lbs_cmd_802_11_rssi(priv, cmdptr);
994 break;
995
996 case CMD_802_11_SET_AFC:
997 case CMD_802_11_GET_AFC:
998
999 cmdptr->command = cpu_to_le16(cmd_no);
1000 cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
1001 sizeof(struct cmd_header));
1002
1003 memmove(&cmdptr->params.afc,
1004 pdata_buf, sizeof(struct cmd_ds_802_11_afc));
1005
1006 ret = 0;
1007 goto done;
1008
1009 case CMD_802_11_TPC_CFG:
1010 cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG);
1011 cmdptr->size =
1012 cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) +
1013 sizeof(struct cmd_header));
1014
1015 memmove(&cmdptr->params.tpccfg,
1016 pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg));
1017
1018 ret = 0;
1019 break;
1020
1021 #ifdef CONFIG_LIBERTAS_MESH
1022
1023 case CMD_BT_ACCESS:
1024 ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf);
1025 break;
1026
1027 case CMD_FWT_ACCESS:
1028 ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf);
1029 break;
1030
1031 #endif
1032
1033 case CMD_802_11_BEACON_CTRL:
1034 ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
1035 break;
1036 case CMD_802_11_DEEP_SLEEP:
1037 cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP);
1038 cmdptr->size = cpu_to_le16(sizeof(struct cmd_header));
1039 break;
1040 default:
1041 lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
1042 ret = -1;
1043 break;
1044 }
1045
1046 /* return error, since the command preparation failed */
1047 if (ret != 0) {
1048 lbs_deb_host("PREP_CMD: command preparation failed\n");
1049 lbs_cleanup_and_insert_cmd(priv, cmdnode);
1050 ret = -1;
1051 goto done;
1052 }
1053
1054 cmdnode->cmdwaitqwoken = 0;
1055
1056 lbs_queue_cmd(priv, cmdnode);
1057 wake_up_interruptible(&priv->waitq);
1058
1059 if (wait_option & CMD_OPTION_WAITFORRSP) {
1060 lbs_deb_host("PREP_CMD: wait for response\n");
1061 might_sleep();
1062 wait_event_interruptible(cmdnode->cmdwait_q,
1063 cmdnode->cmdwaitqwoken);
1064 }
1065
1066 spin_lock_irqsave(&priv->driver_lock, flags);
1067 if (priv->cur_cmd_retcode) {
1068 lbs_deb_host("PREP_CMD: command failed with return code %d\n",
1069 priv->cur_cmd_retcode);
1070 priv->cur_cmd_retcode = 0;
1071 ret = -1;
1072 }
1073 spin_unlock_irqrestore(&priv->driver_lock, flags);
1074
1075 done:
1076 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1077 return ret;
1078 }
1079
1080 /**
1081 * @brief This function allocates the command buffer and link
1082 * it to command free queue.
1083 *
1084 * @param priv A pointer to struct lbs_private structure
1085 * @return 0 or -1
1086 */
1087 int lbs_allocate_cmd_buffer(struct lbs_private *priv)
1088 {
1089 int ret = 0;
1090 u32 bufsize;
1091 u32 i;
1092 struct cmd_ctrl_node *cmdarray;
1093
1094 lbs_deb_enter(LBS_DEB_HOST);
1095
1096 /* Allocate and initialize the command array */
1097 bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;
1098 if (!(cmdarray = kzalloc(bufsize, GFP_KERNEL))) {
1099 lbs_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
1100 ret = -1;
1101 goto done;
1102 }
1103 priv->cmd_array = cmdarray;
1104
1105 /* Allocate and initialize each command buffer in the command array */
1106 for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
1107 cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL);
1108 if (!cmdarray[i].cmdbuf) {
1109 lbs_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
1110 ret = -1;
1111 goto done;
1112 }
1113 }
1114
1115 for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
1116 init_waitqueue_head(&cmdarray[i].cmdwait_q);
1117 lbs_cleanup_and_insert_cmd(priv, &cmdarray[i]);
1118 }
1119 ret = 0;
1120
1121 done:
1122 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1123 return ret;
1124 }
1125
1126 /**
1127 * @brief This function frees the command buffer.
1128 *
1129 * @param priv A pointer to struct lbs_private structure
1130 * @return 0 or -1
1131 */
1132 int lbs_free_cmd_buffer(struct lbs_private *priv)
1133 {
1134 struct cmd_ctrl_node *cmdarray;
1135 unsigned int i;
1136
1137 lbs_deb_enter(LBS_DEB_HOST);
1138
1139 /* need to check if cmd array is allocated or not */
1140 if (priv->cmd_array == NULL) {
1141 lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
1142 goto done;
1143 }
1144
1145 cmdarray = priv->cmd_array;
1146
1147 /* Release shared memory buffers */
1148 for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
1149 if (cmdarray[i].cmdbuf) {
1150 kfree(cmdarray[i].cmdbuf);
1151 cmdarray[i].cmdbuf = NULL;
1152 }
1153 }
1154
1155 /* Release cmd_ctrl_node */
1156 if (priv->cmd_array) {
1157 kfree(priv->cmd_array);
1158 priv->cmd_array = NULL;
1159 }
1160
1161 done:
1162 lbs_deb_leave(LBS_DEB_HOST);
1163 return 0;
1164 }
1165
1166 /**
1167 * @brief This function gets a free command node if available in
1168 * command free queue.
1169 *
1170 * @param priv A pointer to struct lbs_private structure
1171 * @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL
1172 */
1173 static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv)
1174 {
1175 struct cmd_ctrl_node *tempnode;
1176 unsigned long flags;
1177
1178 lbs_deb_enter(LBS_DEB_HOST);
1179
1180 if (!priv)
1181 return NULL;
1182
1183 spin_lock_irqsave(&priv->driver_lock, flags);
1184
1185 if (!list_empty(&priv->cmdfreeq)) {
1186 tempnode = list_first_entry(&priv->cmdfreeq,
1187 struct cmd_ctrl_node, list);
1188 list_del(&tempnode->list);
1189 } else {
1190 lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
1191 tempnode = NULL;
1192 }
1193
1194 spin_unlock_irqrestore(&priv->driver_lock, flags);
1195
1196 lbs_deb_leave(LBS_DEB_HOST);
1197 return tempnode;
1198 }
1199
1200 /**
1201 * @brief This function executes next command in command
1202 * pending queue. It will put firmware back to PS mode
1203 * if applicable.
1204 *
1205 * @param priv A pointer to struct lbs_private structure
1206 * @return 0 or -1
1207 */
1208 int lbs_execute_next_command(struct lbs_private *priv)
1209 {
1210 struct cmd_ctrl_node *cmdnode = NULL;
1211 struct cmd_header *cmd;
1212 unsigned long flags;
1213 int ret = 0;
1214
1215 /* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
1216 * only caller to us is lbs_thread() and we get even when a
1217 * data packet is received */
1218 lbs_deb_enter(LBS_DEB_THREAD);
1219
1220 spin_lock_irqsave(&priv->driver_lock, flags);
1221
1222 if (priv->cur_cmd) {
1223 lbs_pr_alert( "EXEC_NEXT_CMD: already processing command!\n");
1224 spin_unlock_irqrestore(&priv->driver_lock, flags);
1225 ret = -1;
1226 goto done;
1227 }
1228
1229 if (!list_empty(&priv->cmdpendingq)) {
1230 cmdnode = list_first_entry(&priv->cmdpendingq,
1231 struct cmd_ctrl_node, list);
1232 }
1233
1234 spin_unlock_irqrestore(&priv->driver_lock, flags);
1235
1236 if (cmdnode) {
1237 cmd = cmdnode->cmdbuf;
1238
1239 if (is_command_allowed_in_ps(le16_to_cpu(cmd->command))) {
1240 if ((priv->psstate == PS_STATE_SLEEP) ||
1241 (priv->psstate == PS_STATE_PRE_SLEEP)) {
1242 lbs_deb_host(
1243 "EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d\n",
1244 le16_to_cpu(cmd->command),
1245 priv->psstate);
1246 ret = -1;
1247 goto done;
1248 }
1249 lbs_deb_host("EXEC_NEXT_CMD: OK to send command "
1250 "0x%04x in psstate %d\n",
1251 le16_to_cpu(cmd->command), priv->psstate);
1252 } else if (priv->psstate != PS_STATE_FULL_POWER) {
1253 /*
1254 * 1. Non-PS command:
1255 * Queue it. set needtowakeup to TRUE if current state
1256 * is SLEEP, otherwise call lbs_ps_wakeup to send Exit_PS.
1257 * 2. PS command but not Exit_PS:
1258 * Ignore it.
1259 * 3. PS command Exit_PS:
1260 * Set needtowakeup to TRUE if current state is SLEEP,
1261 * otherwise send this command down to firmware
1262 * immediately.
1263 */
1264 if (cmd->command != cpu_to_le16(CMD_802_11_PS_MODE)) {
1265 /* Prepare to send Exit PS,
1266 * this non PS command will be sent later */
1267 if ((priv->psstate == PS_STATE_SLEEP)
1268 || (priv->psstate == PS_STATE_PRE_SLEEP)
1269 ) {
1270 /* w/ new scheme, it will not reach here.
1271 since it is blocked in main_thread. */
1272 priv->needtowakeup = 1;
1273 } else
1274 lbs_ps_wakeup(priv, 0);
1275
1276 ret = 0;
1277 goto done;
1278 } else {
1279 /*
1280 * PS command. Ignore it if it is not Exit_PS.
1281 * otherwise send it down immediately.
1282 */
1283 struct cmd_ds_802_11_ps_mode *psm = (void *)&cmd[1];
1284
1285 lbs_deb_host(
1286 "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n",
1287 psm->action);
1288 if (psm->action !=
1289 cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
1290 lbs_deb_host(
1291 "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
1292 list_del(&cmdnode->list);
1293 spin_lock_irqsave(&priv->driver_lock, flags);
1294 lbs_complete_command(priv, cmdnode, 0);
1295 spin_unlock_irqrestore(&priv->driver_lock, flags);
1296
1297 ret = 0;
1298 goto done;
1299 }
1300
1301 if ((priv->psstate == PS_STATE_SLEEP) ||
1302 (priv->psstate == PS_STATE_PRE_SLEEP)) {
1303 lbs_deb_host(
1304 "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
1305 list_del(&cmdnode->list);
1306 spin_lock_irqsave(&priv->driver_lock, flags);
1307 lbs_complete_command(priv, cmdnode, 0);
1308 spin_unlock_irqrestore(&priv->driver_lock, flags);
1309 priv->needtowakeup = 1;
1310
1311 ret = 0;
1312 goto done;
1313 }
1314
1315 lbs_deb_host(
1316 "EXEC_NEXT_CMD: sending EXIT_PS\n");
1317 }
1318 }
1319 list_del(&cmdnode->list);
1320 lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
1321 le16_to_cpu(cmd->command));
1322 lbs_submit_command(priv, cmdnode);
1323 } else {
1324 /*
1325 * check if in power save mode, if yes, put the device back
1326 * to PS mode
1327 */
1328 if ((priv->psmode != LBS802_11POWERMODECAM) &&
1329 (priv->psstate == PS_STATE_FULL_POWER) &&
1330 ((priv->connect_status == LBS_CONNECTED) ||
1331 lbs_mesh_connected(priv))) {
1332 if (priv->secinfo.WPAenabled ||
1333 priv->secinfo.WPA2enabled) {
1334 /* check for valid WPA group keys */
1335 if (priv->wpa_mcast_key.len ||
1336 priv->wpa_unicast_key.len) {
1337 lbs_deb_host(
1338 "EXEC_NEXT_CMD: WPA enabled and GTK_SET"
1339 " go back to PS_SLEEP");
1340 lbs_ps_sleep(priv, 0);
1341 }
1342 } else {
1343 lbs_deb_host(
1344 "EXEC_NEXT_CMD: cmdpendingq empty, "
1345 "go back to PS_SLEEP");
1346 lbs_ps_sleep(priv, 0);
1347 }
1348 }
1349 }
1350
1351 ret = 0;
1352 done:
1353 lbs_deb_leave(LBS_DEB_THREAD);
1354 return ret;
1355 }
1356
1357 static void lbs_send_confirmsleep(struct lbs_private *priv)
1358 {
1359 unsigned long flags;
1360 int ret;
1361
1362 lbs_deb_enter(LBS_DEB_HOST);
1363 lbs_deb_hex(LBS_DEB_HOST, "sleep confirm", (u8 *) &confirm_sleep,
1364 sizeof(confirm_sleep));
1365
1366 ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep,
1367 sizeof(confirm_sleep));
1368 if (ret) {
1369 lbs_pr_alert("confirm_sleep failed\n");
1370 goto out;
1371 }
1372
1373 spin_lock_irqsave(&priv->driver_lock, flags);
1374
1375 /* We don't get a response on the sleep-confirmation */
1376 priv->dnld_sent = DNLD_RES_RECEIVED;
1377
1378 if (priv->is_host_sleep_configured) {
1379 priv->is_host_sleep_activated = 1;
1380 wake_up_interruptible(&priv->host_sleep_q);
1381 }
1382
1383 /* If nothing to do, go back to sleep (?) */
1384 if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx])
1385 priv->psstate = PS_STATE_SLEEP;
1386
1387 spin_unlock_irqrestore(&priv->driver_lock, flags);
1388
1389 out:
1390 lbs_deb_leave(LBS_DEB_HOST);
1391 }
1392
1393 void lbs_ps_sleep(struct lbs_private *priv, int wait_option)
1394 {
1395 lbs_deb_enter(LBS_DEB_HOST);
1396
1397 /*
1398 * PS is currently supported only in Infrastructure mode
1399 * Remove this check if it is to be supported in IBSS mode also
1400 */
1401
1402 lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1403 CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL);
1404
1405 lbs_deb_leave(LBS_DEB_HOST);
1406 }
1407
1408 /**
1409 * @brief This function sends Exit_PS command to firmware.
1410 *
1411 * @param priv A pointer to struct lbs_private structure
1412 * @param wait_option wait response or not
1413 * @return n/a
1414 */
1415 void lbs_ps_wakeup(struct lbs_private *priv, int wait_option)
1416 {
1417 __le32 Localpsmode;
1418
1419 lbs_deb_enter(LBS_DEB_HOST);
1420
1421 Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
1422
1423 lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1424 CMD_SUBCMD_EXIT_PS,
1425 wait_option, 0, &Localpsmode);
1426
1427 lbs_deb_leave(LBS_DEB_HOST);
1428 }
1429
1430 /**
1431 * @brief This function checks condition and prepares to
1432 * send sleep confirm command to firmware if ok.
1433 *
1434 * @param priv A pointer to struct lbs_private structure
1435 * @param psmode Power Saving mode
1436 * @return n/a
1437 */
1438 void lbs_ps_confirm_sleep(struct lbs_private *priv)
1439 {
1440 unsigned long flags =0;
1441 int allowed = 1;
1442
1443 lbs_deb_enter(LBS_DEB_HOST);
1444
1445 spin_lock_irqsave(&priv->driver_lock, flags);
1446 if (priv->dnld_sent) {
1447 allowed = 0;
1448 lbs_deb_host("dnld_sent was set\n");
1449 }
1450
1451 /* In-progress command? */
1452 if (priv->cur_cmd) {
1453 allowed = 0;
1454 lbs_deb_host("cur_cmd was set\n");
1455 }
1456
1457 /* Pending events or command responses? */
1458 if (kfifo_len(&priv->event_fifo) || priv->resp_len[priv->resp_idx]) {
1459 allowed = 0;
1460 lbs_deb_host("pending events or command responses\n");
1461 }
1462 spin_unlock_irqrestore(&priv->driver_lock, flags);
1463
1464 if (allowed) {
1465 lbs_deb_host("sending lbs_ps_confirm_sleep\n");
1466 lbs_send_confirmsleep(priv);
1467 } else {
1468 lbs_deb_host("sleep confirm has been delayed\n");
1469 }
1470
1471 lbs_deb_leave(LBS_DEB_HOST);
1472 }
1473
1474
1475 /**
1476 * @brief Configures the transmission power control functionality.
1477 *
1478 * @param priv A pointer to struct lbs_private structure
1479 * @param enable Transmission power control enable
1480 * @param p0 Power level when link quality is good (dBm).
1481 * @param p1 Power level when link quality is fair (dBm).
1482 * @param p2 Power level when link quality is poor (dBm).
1483 * @param usesnr Use Signal to Noise Ratio in TPC
1484 *
1485 * @return 0 on success
1486 */
1487 int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
1488 int8_t p2, int usesnr)
1489 {
1490 struct cmd_ds_802_11_tpc_cfg cmd;
1491 int ret;
1492
1493 memset(&cmd, 0, sizeof(cmd));
1494 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1495 cmd.action = cpu_to_le16(CMD_ACT_SET);
1496 cmd.enable = !!enable;
1497 cmd.usesnr = !!usesnr;
1498 cmd.P0 = p0;
1499 cmd.P1 = p1;
1500 cmd.P2 = p2;
1501
1502 ret = lbs_cmd_with_response(priv, CMD_802_11_TPC_CFG, &cmd);
1503
1504 return ret;
1505 }
1506
1507 /**
1508 * @brief Configures the power adaptation settings.
1509 *
1510 * @param priv A pointer to struct lbs_private structure
1511 * @param enable Power adaptation enable
1512 * @param p0 Power level for 1, 2, 5.5 and 11 Mbps (dBm).
1513 * @param p1 Power level for 6, 9, 12, 18, 22, 24 and 36 Mbps (dBm).
1514 * @param p2 Power level for 48 and 54 Mbps (dBm).
1515 *
1516 * @return 0 on Success
1517 */
1518
1519 int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
1520 int8_t p1, int8_t p2)
1521 {
1522 struct cmd_ds_802_11_pa_cfg cmd;
1523 int ret;
1524
1525 memset(&cmd, 0, sizeof(cmd));
1526 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1527 cmd.action = cpu_to_le16(CMD_ACT_SET);
1528 cmd.enable = !!enable;
1529 cmd.P0 = p0;
1530 cmd.P1 = p1;
1531 cmd.P2 = p2;
1532
1533 ret = lbs_cmd_with_response(priv, CMD_802_11_PA_CFG , &cmd);
1534
1535 return ret;
1536 }
1537
1538
1539 struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
1540 uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
1541 int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
1542 unsigned long callback_arg)
1543 {
1544 struct cmd_ctrl_node *cmdnode;
1545
1546 lbs_deb_enter(LBS_DEB_HOST);
1547
1548 if (priv->surpriseremoved) {
1549 lbs_deb_host("PREP_CMD: card removed\n");
1550 cmdnode = ERR_PTR(-ENOENT);
1551 goto done;
1552 }
1553
1554 if (!lbs_is_cmd_allowed(priv)) {
1555 cmdnode = ERR_PTR(-EBUSY);
1556 goto done;
1557 }
1558
1559 cmdnode = lbs_get_cmd_ctrl_node(priv);
1560 if (cmdnode == NULL) {
1561 lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
1562
1563 /* Wake up main thread to execute next command */
1564 wake_up_interruptible(&priv->waitq);
1565 cmdnode = ERR_PTR(-ENOBUFS);
1566 goto done;
1567 }
1568
1569 cmdnode->callback = callback;
1570 cmdnode->callback_arg = callback_arg;
1571
1572 /* Copy the incoming command to the buffer */
1573 memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size);
1574
1575 /* Set sequence number, clean result, move to buffer */
1576 priv->seqnum++;
1577 cmdnode->cmdbuf->command = cpu_to_le16(command);
1578 cmdnode->cmdbuf->size = cpu_to_le16(in_cmd_size);
1579 cmdnode->cmdbuf->seqnum = cpu_to_le16(priv->seqnum);
1580 cmdnode->cmdbuf->result = 0;
1581
1582 lbs_deb_host("PREP_CMD: command 0x%04x\n", command);
1583
1584 cmdnode->cmdwaitqwoken = 0;
1585 lbs_queue_cmd(priv, cmdnode);
1586 wake_up_interruptible(&priv->waitq);
1587
1588 done:
1589 lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode);
1590 return cmdnode;
1591 }
1592
1593 void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
1594 struct cmd_header *in_cmd, int in_cmd_size)
1595 {
1596 lbs_deb_enter(LBS_DEB_CMD);
1597 __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
1598 lbs_cmd_async_callback, 0);
1599 lbs_deb_leave(LBS_DEB_CMD);
1600 }
1601
1602 int __lbs_cmd(struct lbs_private *priv, uint16_t command,
1603 struct cmd_header *in_cmd, int in_cmd_size,
1604 int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
1605 unsigned long callback_arg)
1606 {
1607 struct cmd_ctrl_node *cmdnode;
1608 unsigned long flags;
1609 int ret = 0;
1610
1611 lbs_deb_enter(LBS_DEB_HOST);
1612
1613 cmdnode = __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
1614 callback, callback_arg);
1615 if (IS_ERR(cmdnode)) {
1616 ret = PTR_ERR(cmdnode);
1617 goto done;
1618 }
1619
1620 might_sleep();
1621 wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);
1622
1623 spin_lock_irqsave(&priv->driver_lock, flags);
1624 ret = cmdnode->result;
1625 if (ret)
1626 lbs_pr_info("PREP_CMD: command 0x%04x failed: %d\n",
1627 command, ret);
1628
1629 __lbs_cleanup_and_insert_cmd(priv, cmdnode);
1630 spin_unlock_irqrestore(&priv->driver_lock, flags);
1631
1632 done:
1633 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1634 return ret;
1635 }
1636 EXPORT_SYMBOL_GPL(__lbs_cmd);
This page took 0.065005 seconds and 6 git commands to generate.