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