cmd.c 44.8 KB
Newer Older
1 2 3 4 5
/**
  * This file contains the handling of command.
  * It prepares command and sends it to firmware when it is ready.
  */

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"
K
Kiran Divekar 已提交
12
#include "cfg.h"
13
#include "cmd.h"
14

D
Dan Williams 已提交
15 16
#define CAL_NF(nf)		((s32)(-(s32)(nf)))
#define CAL_RSSI(snr, nf)	((s32)((s32)(snr) + CAL_NF(nf)))
17

18
static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
19

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
/**
 *  @brief Simple callback that copies response back into command
 *
 *  @param priv    	A pointer to struct lbs_private structure
 *  @param extra  	A pointer to the original command structure for which
 *                      'resp' is a response
 *  @param resp         A pointer to the command response
 *
 *  @return 	   	0 on success, error on failure
 */
int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
		     struct cmd_header *resp)
{
	struct cmd_header *buf = (void *)extra;
	uint16_t copy_len;

	copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
	memcpy(buf, resp, copy_len);
	return 0;
}
EXPORT_SYMBOL_GPL(lbs_cmd_copyback);

/**
 *  @brief Simple callback that ignores the result. Use this if
 *  you just want to send a command to the hardware, but don't
 *  care for the result.
 *
 *  @param priv         ignored
 *  @param extra        ignored
 *  @param resp         ignored
 *
 *  @return 	   	0 for success
 */
static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra,
		     struct cmd_header *resp)
{
	return 0;
}


60
/**
61
 *  @brief Checks whether a command is allowed in Power Save mode
62 63
 *
 *  @param command the command ID
64
 *  @return 	   1 if allowed, 0 if not allowed
65
 */
66
static u8 is_command_allowed_in_ps(u16 cmd)
67
{
68 69 70
	switch (cmd) {
	case CMD_802_11_RSSI:
		return 1;
71 72
	case CMD_802_11_HOST_SLEEP_CFG:
		return 1;
73 74
	default:
		break;
75 76 77 78
	}
	return 0;
}

79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
/**
 *  @brief This function checks if the command is allowed.
 *
 *  @param priv         A pointer to lbs_private structure
 *  @return             allowed or not allowed.
 */

static int lbs_is_cmd_allowed(struct lbs_private *priv)
{
	int ret = 1;

	lbs_deb_enter(LBS_DEB_CMD);

	if (!priv->is_auto_deep_sleep_enabled) {
		if (priv->is_deep_sleep) {
			lbs_deb_cmd("command not allowed in deep sleep\n");
			ret = 0;
		}
	}

	lbs_deb_leave(LBS_DEB_CMD);
	return ret;
}

103 104 105 106 107 108 109 110
/**
 *  @brief Updates the hardware details like MAC address and regulatory region
 *
 *  @param priv    	A pointer to struct lbs_private structure
 *
 *  @return 	   	0 on success, error on failure
 */
int lbs_update_hw_spec(struct lbs_private *priv)
111
{
112 113 114
	struct cmd_ds_get_hw_spec cmd;
	int ret = -1;
	u32 i;
115

116
	lbs_deb_enter(LBS_DEB_CMD);
117

118 119 120
	memset(&cmd, 0, sizeof(cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN);
121
	ret = lbs_cmd_with_response(priv, CMD_GET_HW_SPEC, &cmd);
122 123 124 125 126
	if (ret)
		goto out;

	priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo);

127 128 129 130 131 132 133 134 135 136
	/* The firmware release is in an interesting format: the patch
	 * level is in the most significant nibble ... so fix that: */
	priv->fwrelease = le32_to_cpu(cmd.fwrelease);
	priv->fwrelease = (priv->fwrelease << 8) |
		(priv->fwrelease >> 24 & 0xff);

	/* Some firmware capabilities:
	 * CF card    firmware 5.0.16p0:   cap 0x00000303
	 * USB dongle firmware 5.110.17p2: cap 0x00000303
	 */
J
Johannes Berg 已提交
137 138
	lbs_pr_info("%pM, fw %u.%u.%up%u, cap 0x%08x\n",
		cmd.permanentaddr,
139 140 141 142 143
		priv->fwrelease >> 24 & 0xff,
		priv->fwrelease >> 16 & 0xff,
		priv->fwrelease >>  8 & 0xff,
		priv->fwrelease       & 0xff,
		priv->fwcapinfo);
144 145 146 147 148 149
	lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
		    cmd.hwifversion, cmd.version);

	/* Clamp region code to 8-bit since FW spec indicates that it should
	 * only ever be 8-bit, even though the field size is 16-bit.  Some firmware
	 * returns non-zero high 8 bits here.
150 151 152
	 *
	 * Firmware version 4.0.102 used in CF8381 has region code shifted.  We
	 * need to check for this problem and handle it properly.
153
	 */
154 155 156 157
	if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V4)
		priv->regioncode = (le16_to_cpu(cmd.regioncode) >> 8) & 0xFF;
	else
		priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF;
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172

	for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
		/* use the region code to search for the index */
		if (priv->regioncode == lbs_region_code_to_index[i])
			break;
	}

	/* if it's unidentified region code, use the default (USA) */
	if (i >= MRVDRV_MAX_REGION_CODE) {
		priv->regioncode = 0x10;
		lbs_pr_info("unidentified region code; using the default (USA)\n");
	}

	if (priv->current_addr[0] == 0xff)
		memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
173

174 175 176 177 178
	memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN);
	if (priv->mesh_dev)
		memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);

out:
179
	lbs_deb_leave(LBS_DEB_CMD);
180
	return ret;
181 182
}

183 184 185 186
static int lbs_ret_host_sleep_cfg(struct lbs_private *priv, unsigned long dummy,
			struct cmd_header *resp)
{
	lbs_deb_enter(LBS_DEB_CMD);
187
	if (priv->is_host_sleep_activated) {
188 189 190 191 192 193 194 195 196 197 198 199
		priv->is_host_sleep_configured = 0;
		if (priv->psstate == PS_STATE_FULL_POWER) {
			priv->is_host_sleep_activated = 0;
			wake_up_interruptible(&priv->host_sleep_q);
		}
	} else {
		priv->is_host_sleep_configured = 1;
	}
	lbs_deb_leave(LBS_DEB_CMD);
	return 0;
}

200 201
int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
		struct wol_config *p_wol_config)
202 203 204 205
{
	struct cmd_ds_host_sleep cmd_config;
	int ret;

206
	cmd_config.hdr.size = cpu_to_le16(sizeof(cmd_config));
207
	cmd_config.criteria = cpu_to_le32(criteria);
208 209
	cmd_config.gpio = priv->wol_gpio;
	cmd_config.gap = priv->wol_gap;
210

211 212 213 214 215 216
	if (p_wol_config != NULL)
		memcpy((uint8_t *)&cmd_config.wol_conf, (uint8_t *)p_wol_config,
				sizeof(struct wol_config));
	else
		cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE;

217 218 219
	ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config.hdr,
			le16_to_cpu(cmd_config.hdr.size),
			lbs_ret_host_sleep_cfg, 0);
220
	if (!ret) {
221
		if (p_wol_config)
222 223 224
			memcpy((uint8_t *) p_wol_config,
					(uint8_t *)&cmd_config.wol_conf,
					sizeof(struct wol_config));
225
	} else {
226 227
		lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret);
	}
228

229 230 231 232
	return ret;
}
EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);

233 234 235 236 237 238 239 240 241 242 243
/**
 *  @brief Sets the Power Save mode
 *
 *  @param priv    	A pointer to struct lbs_private structure
 *  @param cmd_action	The Power Save operation (PS_MODE_ACTION_ENTER_PS or
 *                         PS_MODE_ACTION_EXIT_PS)
 *  @param block	Whether to block on a response or not
 *
 *  @return 	   	0 on success, error on failure
 */
int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block)
244
{
245 246
	struct cmd_ds_802_11_ps_mode cmd;
	int ret = 0;
247

248
	lbs_deb_enter(LBS_DEB_CMD);
249

250 251 252
	memset(&cmd, 0, sizeof(cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(cmd_action);
253

254 255 256 257 258 259 260 261 262 263 264 265
	if (cmd_action == PS_MODE_ACTION_ENTER_PS) {
		lbs_deb_cmd("PS_MODE: action ENTER_PS\n");
		cmd.multipledtim = cpu_to_le16(1);  /* Default DTIM multiple */
	} else if (cmd_action == PS_MODE_ACTION_EXIT_PS) {
		lbs_deb_cmd("PS_MODE: action EXIT_PS\n");
	} else {
		/* We don't handle CONFIRM_SLEEP here because it needs to
		 * be fastpathed to the firmware.
		 */
		lbs_deb_cmd("PS_MODE: unknown action 0x%X\n", cmd_action);
		ret = -EOPNOTSUPP;
		goto out;
266 267
	}

268 269 270 271 272 273 274 275
	if (block)
		ret = lbs_cmd_with_response(priv, CMD_802_11_PS_MODE, &cmd);
	else
		lbs_cmd_async(priv, CMD_802_11_PS_MODE, &cmd.hdr, sizeof (cmd));

out:
	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
	return ret;
276 277
}

278 279
int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
				struct sleep_params *sp)
280
{
281 282
	struct cmd_ds_802_11_sleep_params cmd;
	int ret;
283

284
	lbs_deb_enter(LBS_DEB_CMD);
285

286
	if (cmd_action == CMD_ACT_GET) {
287 288 289 290 291 292 293 294
		memset(&cmd, 0, sizeof(cmd));
	} else {
		cmd.error = cpu_to_le16(sp->sp_error);
		cmd.offset = cpu_to_le16(sp->sp_offset);
		cmd.stabletime = cpu_to_le16(sp->sp_stabletime);
		cmd.calcontrol = sp->sp_calcontrol;
		cmd.externalsleepclk = sp->sp_extsleepclk;
		cmd.reserved = cpu_to_le16(sp->sp_reserved);
295
	}
296 297
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(cmd_action);
298

299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
	ret = lbs_cmd_with_response(priv, CMD_802_11_SLEEP_PARAMS, &cmd);

	if (!ret) {
		lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, "
			    "calcontrol 0x%x extsleepclk 0x%x\n",
			    le16_to_cpu(cmd.error), le16_to_cpu(cmd.offset),
			    le16_to_cpu(cmd.stabletime), cmd.calcontrol,
			    cmd.externalsleepclk);

		sp->sp_error = le16_to_cpu(cmd.error);
		sp->sp_offset = le16_to_cpu(cmd.offset);
		sp->sp_stabletime = le16_to_cpu(cmd.stabletime);
		sp->sp_calcontrol = cmd.calcontrol;
		sp->sp_extsleepclk = cmd.externalsleepclk;
		sp->sp_reserved = le16_to_cpu(cmd.reserved);
	}

	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
317 318 319
	return 0;
}

320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
static int lbs_wait_for_ds_awake(struct lbs_private *priv)
{
	int ret = 0;

	lbs_deb_enter(LBS_DEB_CMD);

	if (priv->is_deep_sleep) {
		if (!wait_event_interruptible_timeout(priv->ds_awake_q,
					!priv->is_deep_sleep, (10 * HZ))) {
			lbs_pr_err("ds_awake_q: timer expired\n");
			ret = -1;
		}
	}

	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
	return ret;
}

int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)
{
	int ret =  0;

	lbs_deb_enter(LBS_DEB_CMD);

	if (deep_sleep) {
		if (priv->is_deep_sleep != 1) {
			lbs_deb_cmd("deep sleep: sleep\n");
			BUG_ON(!priv->enter_deep_sleep);
			ret = priv->enter_deep_sleep(priv);
			if (!ret) {
				netif_stop_queue(priv->dev);
				netif_carrier_off(priv->dev);
			}
		} else {
			lbs_pr_err("deep sleep: already enabled\n");
		}
	} else {
		if (priv->is_deep_sleep) {
			lbs_deb_cmd("deep sleep: wakeup\n");
			BUG_ON(!priv->exit_deep_sleep);
			ret = priv->exit_deep_sleep(priv);
			if (!ret) {
				ret = lbs_wait_for_ds_awake(priv);
				if (ret)
					lbs_pr_err("deep sleep: wakeup"
							"failed\n");
			}
		}
	}

	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
	return ret;
}

374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
static int lbs_ret_host_sleep_activate(struct lbs_private *priv,
		unsigned long dummy,
		struct cmd_header *cmd)
{
	lbs_deb_enter(LBS_DEB_FW);
	priv->is_host_sleep_activated = 1;
	wake_up_interruptible(&priv->host_sleep_q);
	lbs_deb_leave(LBS_DEB_FW);
	return 0;
}

int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep)
{
	struct cmd_header cmd;
	int ret = 0;
	uint32_t criteria = EHS_REMOVE_WAKEUP;

	lbs_deb_enter(LBS_DEB_CMD);

	if (host_sleep) {
		if (priv->is_host_sleep_activated != 1) {
			memset(&cmd, 0, sizeof(cmd));
			ret = lbs_host_sleep_cfg(priv, priv->wol_criteria,
					(struct wol_config *)NULL);
			if (ret) {
				lbs_pr_info("Host sleep configuration failed: "
						"%d\n", ret);
				return ret;
			}
			if (priv->psstate == PS_STATE_FULL_POWER) {
				ret = __lbs_cmd(priv,
						CMD_802_11_HOST_SLEEP_ACTIVATE,
						&cmd,
						sizeof(cmd),
						lbs_ret_host_sleep_activate, 0);
				if (ret)
					lbs_pr_info("HOST_SLEEP_ACTIVATE "
							"failed: %d\n", ret);
			}

			if (!wait_event_interruptible_timeout(
						priv->host_sleep_q,
						priv->is_host_sleep_activated,
						(10 * HZ))) {
				lbs_pr_err("host_sleep_q: timer expired\n");
				ret = -1;
			}
		} else {
			lbs_pr_err("host sleep: already enabled\n");
		}
	} else {
		if (priv->is_host_sleep_activated)
			ret = lbs_host_sleep_cfg(priv, criteria,
					(struct wol_config *)NULL);
	}

	return ret;
}

433 434 435 436 437 438 439 440 441 442
/**
 *  @brief Set an SNMP MIB value
 *
 *  @param priv    	A pointer to struct lbs_private structure
 *  @param oid  	The OID to set in the firmware
 *  @param val  	Value to set the OID to
 *
 *  @return 	   	0 on success, error on failure
 */
int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val)
443
{
444 445
	struct cmd_ds_802_11_snmp_mib cmd;
	int ret;
446

447
	lbs_deb_enter(LBS_DEB_CMD);
448

449 450 451 452
	memset(&cmd, 0, sizeof (cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_ACT_SET);
	cmd.oid = cpu_to_le16((u16) oid);
453

454 455 456
	switch (oid) {
	case SNMP_MIB_OID_BSS_TYPE:
		cmd.bufsize = cpu_to_le16(sizeof(u8));
457
		cmd.value[0] = val;
458 459 460 461 462 463 464 465
		break;
	case SNMP_MIB_OID_11D_ENABLE:
	case SNMP_MIB_OID_FRAG_THRESHOLD:
	case SNMP_MIB_OID_RTS_THRESHOLD:
	case SNMP_MIB_OID_SHORT_RETRY_LIMIT:
	case SNMP_MIB_OID_LONG_RETRY_LIMIT:
		cmd.bufsize = cpu_to_le16(sizeof(u16));
		*((__le16 *)(&cmd.value)) = cpu_to_le16(val);
466
		break;
467 468 469 470
	default:
		lbs_deb_cmd("SNMP_CMD: (set) unhandled OID 0x%x\n", oid);
		ret = -EINVAL;
		goto out;
471 472
	}

473 474
	lbs_deb_cmd("SNMP_CMD: (set) oid 0x%x, oid size 0x%x, value 0x%x\n",
		    le16_to_cpu(cmd.oid), le16_to_cpu(cmd.bufsize), val);
475

476
	ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
477

478 479 480 481
out:
	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
	return ret;
}
482

483 484 485 486 487 488 489 490 491 492 493 494 495
/**
 *  @brief Get an SNMP MIB value
 *
 *  @param priv    	A pointer to struct lbs_private structure
 *  @param oid  	The OID to retrieve from the firmware
 *  @param out_val  	Location for the returned value
 *
 *  @return 	   	0 on success, error on failure
 */
int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val)
{
	struct cmd_ds_802_11_snmp_mib cmd;
	int ret;
496

497
	lbs_deb_enter(LBS_DEB_CMD);
498

499 500 501 502
	memset(&cmd, 0, sizeof (cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_ACT_GET);
	cmd.oid = cpu_to_le16(oid);
503

504 505 506
	ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
	if (ret)
		goto out;
507

508 509
	switch (le16_to_cpu(cmd.bufsize)) {
	case sizeof(u8):
510
		*out_val = cmd.value[0];
511 512 513
		break;
	case sizeof(u16):
		*out_val = le16_to_cpu(*((__le16 *)(&cmd.value)));
514 515
		break;
	default:
516 517
		lbs_deb_cmd("SNMP_CMD: (get) unhandled OID 0x%x size %d\n",
		            oid, le16_to_cpu(cmd.bufsize));
518 519 520
		break;
	}

521 522 523
out:
	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
	return ret;
524 525
}

526 527 528 529 530 531 532 533 534 535 536 537
/**
 *  @brief Get the min, max, and current TX power
 *
 *  @param priv    	A pointer to struct lbs_private structure
 *  @param curlevel  	Current power level in dBm
 *  @param minlevel  	Minimum supported power level in dBm (optional)
 *  @param maxlevel  	Maximum supported power level in dBm (optional)
 *
 *  @return 	   	0 on success, error on failure
 */
int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
		     s16 *maxlevel)
538
{
539 540
	struct cmd_ds_802_11_rf_tx_power cmd;
	int ret;
541

542
	lbs_deb_enter(LBS_DEB_CMD);
543

544 545 546 547 548 549 550 551
	memset(&cmd, 0, sizeof(cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_ACT_GET);

	ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
	if (ret == 0) {
		*curlevel = le16_to_cpu(cmd.curlevel);
		if (minlevel)
552
			*minlevel = cmd.minlevel;
553
		if (maxlevel)
554
			*maxlevel = cmd.maxlevel;
555
	}
556

557 558 559
	lbs_deb_leave(LBS_DEB_CMD);
	return ret;
}
560

561 562 563 564 565 566 567 568 569 570 571 572
/**
 *  @brief Set the TX power
 *
 *  @param priv    	A pointer to struct lbs_private structure
 *  @param dbm  	The desired power level in dBm
 *
 *  @return 	   	0 on success, error on failure
 */
int lbs_set_tx_power(struct lbs_private *priv, s16 dbm)
{
	struct cmd_ds_802_11_rf_tx_power cmd;
	int ret;
573

574
	lbs_deb_enter(LBS_DEB_CMD);
575

576 577 578 579
	memset(&cmd, 0, sizeof(cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_ACT_SET);
	cmd.curlevel = cpu_to_le16(dbm);
580

581 582 583
	lbs_deb_cmd("SET_RF_TX_POWER: %d dBm\n", dbm);

	ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
584 585

	lbs_deb_leave(LBS_DEB_CMD);
586
	return ret;
587 588
}

589 590 591 592 593 594 595 596 597
/**
 *  @brief Enable or disable monitor mode (only implemented on OLPC usb8388 FW)
 *
 *  @param priv        A pointer to struct lbs_private structure
 *  @param enable      1 to enable monitor mode, 0 to disable
 *
 *  @return            0 on success, error on failure
 */
int lbs_set_monitor_mode(struct lbs_private *priv, int enable)
598
{
599 600
	struct cmd_ds_802_11_monitor_mode cmd;
	int ret;
601

602 603 604 605 606
	memset(&cmd, 0, sizeof(cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_ACT_SET);
	if (enable)
		cmd.mode = cpu_to_le16(0x1);
607

608 609 610 611 612 613
	lbs_deb_cmd("SET_MONITOR_MODE: %d\n", enable);

	ret = lbs_cmd_with_response(priv, CMD_802_11_MONITOR_MODE, &cmd);
	if (ret == 0) {
		priv->dev->type = enable ? ARPHRD_IEEE80211_RADIOTAP :
						ARPHRD_ETHER;
614 615
	}

616 617
	lbs_deb_leave(LBS_DEB_CMD);
	return ret;
618 619
}

620 621 622 623 624 625 626
/**
 *  @brief Get the radio channel
 *
 *  @param priv    	A pointer to struct lbs_private structure
 *
 *  @return 	   	The channel on success, error on failure
 */
627
static int lbs_get_channel(struct lbs_private *priv)
628
{
629 630
	struct cmd_ds_802_11_rf_channel cmd;
	int ret = 0;
631

632
	lbs_deb_enter(LBS_DEB_CMD);
633

634
	memset(&cmd, 0, sizeof(cmd));
635 636
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET);
637

638
	ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
639 640
	if (ret)
		goto out;
641

642 643
	ret = le16_to_cpu(cmd.channel);
	lbs_deb_cmd("current radio channel is %d\n", ret);
644 645 646 647 648 649

out:
	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
	return ret;
}

650 651 652 653 654 655 656 657 658
int lbs_update_channel(struct lbs_private *priv)
{
	int ret;

	/* the channel in f/w could be out of sync; get the current channel */
	lbs_deb_enter(LBS_DEB_ASSOC);

	ret = lbs_get_channel(priv);
	if (ret > 0) {
659
		priv->channel = ret;
660 661 662 663 664 665
		ret = 0;
	}
	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
	return ret;
}

666 667 668 669 670 671 672 673 674 675 676
/**
 *  @brief Set the radio channel
 *
 *  @param priv    	A pointer to struct lbs_private structure
 *  @param channel  	The desired channel, or 0 to clear a locked channel
 *
 *  @return 	   	0 on success, error on failure
 */
int lbs_set_channel(struct lbs_private *priv, u8 channel)
{
	struct cmd_ds_802_11_rf_channel cmd;
677
#ifdef DEBUG
678
	u8 old_channel = priv->channel;
679
#endif
680 681 682 683
	int ret = 0;

	lbs_deb_enter(LBS_DEB_CMD);

684
	memset(&cmd, 0, sizeof(cmd));
685 686 687 688
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
	cmd.channel = cpu_to_le16(channel);

689
	ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
690 691 692
	if (ret)
		goto out;

693
	priv->channel = (uint8_t) le16_to_cpu(cmd.channel);
694
	lbs_deb_cmd("channel switch from %d to %d\n", old_channel,
695
		priv->channel);
696 697 698 699

out:
	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
	return ret;
700 701
}

D
Dan Williams 已提交
702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
/**
 *  @brief Get current RSSI and noise floor
 *
 *  @param priv		A pointer to struct lbs_private structure
 *  @param rssi		On successful return, signal level in mBm
 *
 *  @return 	   	The channel on success, error on failure
 */
int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf)
{
	struct cmd_ds_802_11_rssi cmd;
	int ret = 0;

	lbs_deb_enter(LBS_DEB_CMD);

	BUG_ON(rssi == NULL);
	BUG_ON(nf == NULL);

	memset(&cmd, 0, sizeof(cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	/* Average SNR over last 8 beacons */
	cmd.n_or_snr = cpu_to_le16(8);

	ret = lbs_cmd_with_response(priv, CMD_802_11_RSSI, &cmd);
	if (ret == 0) {
		*nf = CAL_NF(le16_to_cpu(cmd.nf));
		*rssi = CAL_RSSI(le16_to_cpu(cmd.n_or_snr), le16_to_cpu(cmd.nf));
	}

	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
	return ret;
}

735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857
/**
 *  @brief Send regulatory and 802.11d domain information to the firmware
 *
 *  @param priv		pointer to struct lbs_private
 *  @param request	cfg80211 regulatory request structure
 *  @param bands	the device's supported bands and channels
 *
 *  @return		0 on success, error code on failure
*/
int lbs_set_11d_domain_info(struct lbs_private *priv,
			    struct regulatory_request *request,
			    struct ieee80211_supported_band **bands)
{
	struct cmd_ds_802_11d_domain_info cmd;
	struct mrvl_ie_domain_param_set *domain = &cmd.domain;
	struct ieee80211_country_ie_triplet *t;
	enum ieee80211_band band;
	struct ieee80211_channel *ch;
	u8 num_triplet = 0;
	u8 num_parsed_chan = 0;
	u8 first_channel = 0, next_chan = 0, max_pwr = 0;
	u8 i, flag = 0;
	size_t triplet_size;
	int ret;

	lbs_deb_enter(LBS_DEB_11D);

	memset(&cmd, 0, sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_ACT_SET);

	lbs_deb_11d("Setting country code '%c%c'\n",
		    request->alpha2[0], request->alpha2[1]);

	domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);

	/* Set country code */
	domain->country_code[0] = request->alpha2[0];
	domain->country_code[1] = request->alpha2[1];
	domain->country_code[2] = ' ';

	/* Now set up the channel triplets; firmware is somewhat picky here
	 * and doesn't validate channel numbers and spans; hence it would
	 * interpret a triplet of (36, 4, 20) as channels 36, 37, 38, 39.  Since
	 * the last 3 aren't valid channels, the driver is responsible for
	 * splitting that up into 4 triplet pairs of (36, 1, 20) + (40, 1, 20)
	 * etc.
	 */
	for (band = 0;
	     (band < IEEE80211_NUM_BANDS) && (num_triplet < MAX_11D_TRIPLETS);
	     band++) {

		if (!bands[band])
			continue;

		for (i = 0;
		     (i < bands[band]->n_channels) && (num_triplet < MAX_11D_TRIPLETS);
		     i++) {
			ch = &bands[band]->channels[i];
			if (ch->flags & IEEE80211_CHAN_DISABLED)
				continue;

			if (!flag) {
				flag = 1;
				next_chan = first_channel = (u32) ch->hw_value;
				max_pwr = ch->max_power;
				num_parsed_chan = 1;
				continue;
			}

			if ((ch->hw_value == next_chan + 1) &&
					(ch->max_power == max_pwr)) {
				/* Consolidate adjacent channels */
				next_chan++;
				num_parsed_chan++;
			} else {
				/* Add this triplet */
				lbs_deb_11d("11D triplet (%d, %d, %d)\n",
					first_channel, num_parsed_chan,
					max_pwr);
				t = &domain->triplet[num_triplet];
				t->chans.first_channel = first_channel;
				t->chans.num_channels = num_parsed_chan;
				t->chans.max_power = max_pwr;
				num_triplet++;
				flag = 0;
			}
		}

		if (flag) {
			/* Add last triplet */
			lbs_deb_11d("11D triplet (%d, %d, %d)\n", first_channel,
				num_parsed_chan, max_pwr);
			t = &domain->triplet[num_triplet];
			t->chans.first_channel = first_channel;
			t->chans.num_channels = num_parsed_chan;
			t->chans.max_power = max_pwr;
			num_triplet++;
		}
	}

	lbs_deb_11d("# triplets %d\n", num_triplet);

	/* Set command header sizes */
	triplet_size = num_triplet * sizeof(struct ieee80211_country_ie_triplet);
	domain->header.len = cpu_to_le16(sizeof(domain->country_code) +
					triplet_size);

	lbs_deb_hex(LBS_DEB_11D, "802.11D domain param set",
			(u8 *) &cmd.domain.country_code,
			le16_to_cpu(domain->header.len));

	cmd.hdr.size = cpu_to_le16(sizeof(cmd.hdr) +
				   sizeof(cmd.action) +
				   sizeof(cmd.domain.header) +
				   sizeof(cmd.domain.country_code) +
				   triplet_size);

	ret = lbs_cmd_with_response(priv, CMD_802_11D_DOMAIN_INFO, &cmd);

	lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
	return ret;
}

858 859 860 861 862 863 864 865 866 867 868 869
/**
 *  @brief Read a MAC, Baseband, or RF register
 *
 *  @param priv		pointer to struct lbs_private
 *  @param cmd		register command, one of CMD_MAC_REG_ACCESS,
 *                        CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS
 *  @param offset       byte offset of the register to get
 *  @param value        on success, the value of the register at 'offset'
 *
 *  @return		0 on success, error code on failure
*/
int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)
870
{
871 872
	struct cmd_ds_reg_access cmd;
	int ret = 0;
873

874
	lbs_deb_enter(LBS_DEB_CMD);
875

876
	BUG_ON(value == NULL);
877

878 879 880
	memset(&cmd, 0, sizeof(cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_ACT_GET);
881

882 883 884 885 886 887
	if (reg != CMD_MAC_REG_ACCESS &&
	    reg != CMD_BBP_REG_ACCESS &&
	    reg != CMD_RF_REG_ACCESS) {
		ret = -EINVAL;
		goto out;
	}
888

889 890 891 892 893 894 895
	ret = lbs_cmd_with_response(priv, reg, &cmd);
	if (ret) {
		if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)
			*value = cmd.value.bbp_rf;
		else if (reg == CMD_MAC_REG_ACCESS)
			*value = le32_to_cpu(cmd.value.mac);
	}
896

897 898 899 900
out:
	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
	return ret;
}
901

902 903 904 905 906 907 908 909 910 911 912 913 914 915 916
/**
 *  @brief Write a MAC, Baseband, or RF register
 *
 *  @param priv		pointer to struct lbs_private
 *  @param cmd		register command, one of CMD_MAC_REG_ACCESS,
 *                        CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS
 *  @param offset       byte offset of the register to set
 *  @param value        the value to write to the register at 'offset'
 *
 *  @return		0 on success, error code on failure
*/
int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value)
{
	struct cmd_ds_reg_access cmd;
	int ret = 0;
917

918
	lbs_deb_enter(LBS_DEB_CMD);
919

920 921 922
	memset(&cmd, 0, sizeof(cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_ACT_SET);
923

924 925 926 927 928 929 930
	if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)
		cmd.value.bbp_rf = (u8) (value & 0xFF);
	else if (reg == CMD_MAC_REG_ACCESS)
		cmd.value.mac = cpu_to_le32(value);
	else {
		ret = -EINVAL;
		goto out;
931 932
	}

933 934 935 936 937
	ret = lbs_cmd_with_response(priv, reg, &cmd);

out:
	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
	return ret;
938 939
}

940 941
static void lbs_queue_cmd(struct lbs_private *priv,
			  struct cmd_ctrl_node *cmdnode)
942 943
{
	unsigned long flags;
944
	int addtail = 1;
945

946
	lbs_deb_enter(LBS_DEB_HOST);
947

948 949
	if (!cmdnode) {
		lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n");
950 951
		goto done;
	}
952 953 954 955
	if (!cmdnode->cmdbuf->size) {
		lbs_deb_host("DNLD_CMD: cmd size is zero\n");
		goto done;
	}
956
	cmdnode->result = 0;
957 958

	/* Exit_PS command needs to be queued in the header always. */
959
	if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) {
960
		struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf;
961

962
		if (psm->action == cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
963
			if (priv->psstate != PS_STATE_FULL_POWER)
964 965 966 967
				addtail = 0;
		}
	}

968
	if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_WAKEUP_CONFIRM)
969 970
		addtail = 0;

971
	spin_lock_irqsave(&priv->driver_lock, flags);
972

973
	if (addtail)
974
		list_add_tail(&cmdnode->list, &priv->cmdpendingq);
975
	else
976
		list_add(&cmdnode->list, &priv->cmdpendingq);
977

978
	spin_unlock_irqrestore(&priv->driver_lock, flags);
979

980
	lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
981
		     le16_to_cpu(cmdnode->cmdbuf->command));
982 983

done:
984
	lbs_deb_leave(LBS_DEB_HOST);
985 986
}

987 988
static void lbs_submit_command(struct lbs_private *priv,
			       struct cmd_ctrl_node *cmdnode)
989 990
{
	unsigned long flags;
991
	struct cmd_header *cmd;
992 993
	uint16_t cmdsize;
	uint16_t command;
994
	int timeo = 3 * HZ;
995
	int ret;
996

997
	lbs_deb_enter(LBS_DEB_HOST);
998

999
	cmd = cmdnode->cmdbuf;
1000

1001 1002 1003 1004
	spin_lock_irqsave(&priv->driver_lock, flags);
	priv->cur_cmd = cmdnode;
	priv->cur_cmd_retcode = 0;
	spin_unlock_irqrestore(&priv->driver_lock, flags);
1005

1006 1007
	cmdsize = le16_to_cpu(cmd->size);
	command = le16_to_cpu(cmd->command);
1008

1009
	/* These commands take longer */
1010
	if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE)
1011
		timeo = 5 * HZ;
1012

H
Holger Schurig 已提交
1013 1014
	lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
		     command, le16_to_cpu(cmd->seqnum), cmdsize);
1015
	lbs_deb_hex(LBS_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
1016

1017
	ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
1018

1019 1020
	if (ret) {
		lbs_pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret);
1021 1022
		/* Let the timer kick in and retry, and potentially reset
		   the whole thing if the condition persists */
1023
		timeo = HZ/4;
1024
	}
1025

1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
	if (command == CMD_802_11_DEEP_SLEEP) {
		if (priv->is_auto_deep_sleep_enabled) {
			priv->wakeup_dev_required = 1;
			priv->dnld_sent = 0;
		}
		priv->is_deep_sleep = 1;
		lbs_complete_command(priv, cmdnode, 0);
	} else {
		/* Setup the timer after transmit command */
		mod_timer(&priv->command_timer, jiffies + timeo);
	}
1037

1038
	lbs_deb_leave(LBS_DEB_HOST);
1039 1040 1041 1042
}

/**
 *  This function inserts command node to cmdfreeq
1043
 *  after cleans it. Requires priv->driver_lock held.
1044
 */
1045
static void __lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
1046
					 struct cmd_ctrl_node *cmdnode)
1047
{
1048 1049 1050 1051 1052 1053 1054
	lbs_deb_enter(LBS_DEB_HOST);

	if (!cmdnode)
		goto out;

	cmdnode->callback = NULL;
	cmdnode->callback_arg = 0;
1055

1056
	memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);
1057

1058 1059 1060
	list_add_tail(&cmdnode->list, &priv->cmdfreeq);
 out:
	lbs_deb_leave(LBS_DEB_HOST);
1061 1062
}

1063 1064
static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
	struct cmd_ctrl_node *ptempcmd)
1065 1066 1067
{
	unsigned long flags;

1068
	spin_lock_irqsave(&priv->driver_lock, flags);
1069
	__lbs_cleanup_and_insert_cmd(priv, ptempcmd);
1070
	spin_unlock_irqrestore(&priv->driver_lock, flags);
1071 1072
}

1073 1074 1075 1076 1077
void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
			  int result)
{
	if (cmd == priv->cur_cmd)
		priv->cur_cmd_retcode = result;
1078

1079
	cmd->result = result;
1080 1081 1082
	cmd->cmdwaitqwoken = 1;
	wake_up_interruptible(&cmd->cmdwait_q);

1083
	if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)
1084
		__lbs_cleanup_and_insert_cmd(priv, cmd);
1085 1086 1087
	priv->cur_cmd = NULL;
}

1088
int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on)
1089
{
1090
	struct cmd_ds_802_11_radio_control cmd;
1091
	int ret = -EINVAL;
1092

1093
	lbs_deb_enter(LBS_DEB_CMD);
1094

1095 1096 1097
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_ACT_SET);

1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109
	/* Only v8 and below support setting the preamble */
	if (priv->fwrelease < 0x09000000) {
		switch (preamble) {
		case RADIO_PREAMBLE_SHORT:
		case RADIO_PREAMBLE_AUTO:
		case RADIO_PREAMBLE_LONG:
			cmd.control = cpu_to_le16(preamble);
			break;
		default:
			goto out;
		}
	}
1110

1111 1112 1113 1114 1115
	if (radio_on)
		cmd.control |= cpu_to_le16(0x1);
	else {
		cmd.control &= cpu_to_le16(~0x1);
		priv->txpower_cur = 0;
1116
	}
1117

1118 1119
	lbs_deb_cmd("RADIO_CONTROL: radio %s, preamble %d\n",
		    radio_on ? "ON" : "OFF", preamble);
1120

1121
	priv->radio_on = radio_on;
1122 1123

	ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
1124

1125
out:
1126
	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
1127 1128 1129
	return ret;
}

1130
void lbs_set_mac_control(struct lbs_private *priv)
1131
{
1132
	struct cmd_ds_mac_control cmd;
1133

1134
	lbs_deb_enter(LBS_DEB_CMD);
1135

1136
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1137
	cmd.action = cpu_to_le16(priv->mac_control);
1138 1139
	cmd.reserved = 0;

1140
	lbs_cmd_async(priv, CMD_MAC_CONTROL, &cmd.hdr, sizeof(cmd));
1141

1142
	lbs_deb_leave(LBS_DEB_CMD);
1143 1144 1145 1146 1147
}

/**
 *  @brief This function prepare the command before send to firmware.
 *
1148
 *  @param priv		A pointer to struct lbs_private structure
1149 1150 1151 1152 1153 1154 1155
 *  @param cmd_no	command number
 *  @param cmd_action	command action: GET or SET
 *  @param wait_option	wait option: wait response or not
 *  @param cmd_oid	cmd oid: treated as sub command
 *  @param pdata_buf	A pointer to informaion buffer
 *  @return 		0 or -1
 */
1156
int lbs_prepare_and_send_command(struct lbs_private *priv,
1157 1158 1159 1160 1161 1162
			  u16 cmd_no,
			  u16 cmd_action,
			  u16 wait_option, u32 cmd_oid, void *pdata_buf)
{
	int ret = 0;
	struct cmd_ctrl_node *cmdnode;
1163
	struct cmd_header *cmdptr;
1164 1165
	unsigned long flags;

1166
	lbs_deb_enter(LBS_DEB_HOST);
1167

1168 1169
	if (!priv) {
		lbs_deb_host("PREP_CMD: priv is NULL\n");
1170 1171 1172 1173
		ret = -1;
		goto done;
	}

1174
	if (priv->surpriseremoved) {
1175
		lbs_deb_host("PREP_CMD: card removed\n");
1176 1177 1178 1179
		ret = -1;
		goto done;
	}

1180 1181 1182 1183 1184
	if (!lbs_is_cmd_allowed(priv)) {
		ret = -EBUSY;
		goto done;
	}

1185
	cmdnode = lbs_get_cmd_ctrl_node(priv);
1186 1187

	if (cmdnode == NULL) {
1188
		lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
1189 1190

		/* Wake up main thread to execute next command */
1191
		wake_up_interruptible(&priv->waitq);
1192 1193 1194 1195
		ret = -1;
		goto done;
	}

1196 1197
	cmdnode->callback = NULL;
	cmdnode->callback_arg = (unsigned long)pdata_buf;
1198

1199
	cmdptr = (struct cmd_header *)cmdnode->cmdbuf;
1200

1201
	lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no);
1202 1203

	/* Set sequence number, command and INT option */
1204 1205
	priv->seqnum++;
	cmdptr->seqnum = cpu_to_le16(priv->seqnum);
1206

1207
	cmdptr->command = cpu_to_le16(cmd_no);
1208 1209 1210
	cmdptr->result = 0;

	switch (cmd_no) {
1211 1212
	case CMD_802_11_DEEP_SLEEP:
		cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP);
1213
		cmdptr->size = cpu_to_le16(sizeof(struct cmd_header));
1214
		break;
1215
	default:
1216
		lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
1217 1218 1219 1220 1221 1222
		ret = -1;
		break;
	}

	/* return error, since the command preparation failed */
	if (ret != 0) {
1223
		lbs_deb_host("PREP_CMD: command preparation failed\n");
1224
		lbs_cleanup_and_insert_cmd(priv, cmdnode);
1225 1226 1227 1228 1229 1230
		ret = -1;
		goto done;
	}

	cmdnode->cmdwaitqwoken = 0;

1231
	lbs_queue_cmd(priv, cmdnode);
1232
	wake_up_interruptible(&priv->waitq);
1233

1234
	if (wait_option & CMD_OPTION_WAITFORRSP) {
1235
		lbs_deb_host("PREP_CMD: wait for response\n");
1236 1237 1238 1239 1240
		might_sleep();
		wait_event_interruptible(cmdnode->cmdwait_q,
					 cmdnode->cmdwaitqwoken);
	}

1241 1242
	spin_lock_irqsave(&priv->driver_lock, flags);
	if (priv->cur_cmd_retcode) {
1243
		lbs_deb_host("PREP_CMD: command failed with return code %d\n",
1244 1245
		       priv->cur_cmd_retcode);
		priv->cur_cmd_retcode = 0;
1246 1247
		ret = -1;
	}
1248
	spin_unlock_irqrestore(&priv->driver_lock, flags);
1249 1250

done:
1251
	lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1252 1253 1254 1255 1256 1257 1258
	return ret;
}

/**
 *  @brief This function allocates the command buffer and link
 *  it to command free queue.
 *
1259
 *  @param priv		A pointer to struct lbs_private structure
1260 1261
 *  @return 		0 or -1
 */
1262
int lbs_allocate_cmd_buffer(struct lbs_private *priv)
1263 1264
{
	int ret = 0;
1265
	u32 bufsize;
1266
	u32 i;
1267
	struct cmd_ctrl_node *cmdarray;
1268

1269
	lbs_deb_enter(LBS_DEB_HOST);
1270

1271 1272 1273
	/* Allocate and initialize the command array */
	bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;
	if (!(cmdarray = kzalloc(bufsize, GFP_KERNEL))) {
1274
		lbs_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
1275 1276 1277
		ret = -1;
		goto done;
	}
1278
	priv->cmd_array = cmdarray;
1279

1280 1281 1282 1283
	/* Allocate and initialize each command buffer in the command array */
	for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
		cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL);
		if (!cmdarray[i].cmdbuf) {
1284
			lbs_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
1285 1286 1287 1288 1289
			ret = -1;
			goto done;
		}
	}

1290 1291 1292
	for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
		init_waitqueue_head(&cmdarray[i].cmdwait_q);
		lbs_cleanup_and_insert_cmd(priv, &cmdarray[i]);
1293 1294
	}
	ret = 0;
1295 1296

done:
1297
	lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1298 1299 1300 1301 1302 1303
	return ret;
}

/**
 *  @brief This function frees the command buffer.
 *
1304
 *  @param priv		A pointer to struct lbs_private structure
1305 1306
 *  @return 		0 or -1
 */
1307
int lbs_free_cmd_buffer(struct lbs_private *priv)
1308
{
1309
	struct cmd_ctrl_node *cmdarray;
1310 1311
	unsigned int i;

1312
	lbs_deb_enter(LBS_DEB_HOST);
1313 1314

	/* need to check if cmd array is allocated or not */
1315
	if (priv->cmd_array == NULL) {
1316
		lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
1317 1318 1319
		goto done;
	}

1320
	cmdarray = priv->cmd_array;
1321 1322

	/* Release shared memory buffers */
1323 1324 1325 1326
	for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
		if (cmdarray[i].cmdbuf) {
			kfree(cmdarray[i].cmdbuf);
			cmdarray[i].cmdbuf = NULL;
1327 1328 1329 1330
		}
	}

	/* Release cmd_ctrl_node */
1331 1332 1333
	if (priv->cmd_array) {
		kfree(priv->cmd_array);
		priv->cmd_array = NULL;
1334 1335 1336
	}

done:
1337
	lbs_deb_leave(LBS_DEB_HOST);
1338 1339 1340 1341 1342 1343 1344
	return 0;
}

/**
 *  @brief This function gets a free command node if available in
 *  command free queue.
 *
1345
 *  @param priv		A pointer to struct lbs_private structure
1346 1347
 *  @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL
 */
1348
static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv)
1349 1350 1351 1352
{
	struct cmd_ctrl_node *tempnode;
	unsigned long flags;

1353 1354
	lbs_deb_enter(LBS_DEB_HOST);

1355
	if (!priv)
1356 1357
		return NULL;

1358
	spin_lock_irqsave(&priv->driver_lock, flags);
1359

1360 1361
	if (!list_empty(&priv->cmdfreeq)) {
		tempnode = list_first_entry(&priv->cmdfreeq,
1362 1363
					    struct cmd_ctrl_node, list);
		list_del(&tempnode->list);
1364
	} else {
1365
		lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
1366 1367 1368
		tempnode = NULL;
	}

1369
	spin_unlock_irqrestore(&priv->driver_lock, flags);
1370

1371
	lbs_deb_leave(LBS_DEB_HOST);
1372 1373 1374 1375 1376
	return tempnode;
}

/**
 *  @brief This function executes next command in command
1377
 *  pending queue. It will put firmware back to PS mode
1378 1379
 *  if applicable.
 *
1380
 *  @param priv     A pointer to struct lbs_private structure
1381 1382
 *  @return 	   0 or -1
 */
1383
int lbs_execute_next_command(struct lbs_private *priv)
1384 1385
{
	struct cmd_ctrl_node *cmdnode = NULL;
1386
	struct cmd_header *cmd;
1387 1388 1389
	unsigned long flags;
	int ret = 0;

1390 1391 1392
	/* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
	 * only caller to us is lbs_thread() and we get even when a
	 * data packet is received */
1393
	lbs_deb_enter(LBS_DEB_THREAD);
1394

1395
	spin_lock_irqsave(&priv->driver_lock, flags);
1396

1397
	if (priv->cur_cmd) {
1398
		lbs_pr_alert( "EXEC_NEXT_CMD: already processing command!\n");
1399
		spin_unlock_irqrestore(&priv->driver_lock, flags);
1400 1401 1402 1403
		ret = -1;
		goto done;
	}

1404 1405
	if (!list_empty(&priv->cmdpendingq)) {
		cmdnode = list_first_entry(&priv->cmdpendingq,
1406
					   struct cmd_ctrl_node, list);
1407 1408
	}

1409
	spin_unlock_irqrestore(&priv->driver_lock, flags);
1410 1411

	if (cmdnode) {
1412
		cmd = cmdnode->cmdbuf;
1413

1414
		if (is_command_allowed_in_ps(le16_to_cpu(cmd->command))) {
1415 1416
			if ((priv->psstate == PS_STATE_SLEEP) ||
			    (priv->psstate == PS_STATE_PRE_SLEEP)) {
1417 1418
				lbs_deb_host(
				       "EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d\n",
1419
				       le16_to_cpu(cmd->command),
1420
				       priv->psstate);
1421 1422 1423
				ret = -1;
				goto done;
			}
1424
			lbs_deb_host("EXEC_NEXT_CMD: OK to send command "
1425 1426
				     "0x%04x in psstate %d\n",
				     le16_to_cpu(cmd->command), priv->psstate);
1427
		} else if (priv->psstate != PS_STATE_FULL_POWER) {
1428 1429 1430
			/*
			 * 1. Non-PS command:
			 * Queue it. set needtowakeup to TRUE if current state
1431 1432
			 * is SLEEP, otherwise call send EXIT_PS.
			 * 2. PS command but not EXIT_PS:
1433
			 * Ignore it.
1434
			 * 3. PS command EXIT_PS:
1435 1436 1437 1438
			 * Set needtowakeup to TRUE if current state is SLEEP,
			 * otherwise send this command down to firmware
			 * immediately.
			 */
1439
			if (cmd->command != cpu_to_le16(CMD_802_11_PS_MODE)) {
1440 1441
				/*  Prepare to send Exit PS,
				 *  this non PS command will be sent later */
1442 1443
				if ((priv->psstate == PS_STATE_SLEEP)
				    || (priv->psstate == PS_STATE_PRE_SLEEP)
1444 1445 1446
				    ) {
					/* w/ new scheme, it will not reach here.
					   since it is blocked in main_thread. */
1447
					priv->needtowakeup = 1;
1448 1449 1450 1451 1452
				} else {
					lbs_set_ps_mode(priv,
							PS_MODE_ACTION_EXIT_PS,
							false);
				}
1453 1454 1455 1456 1457 1458 1459 1460

				ret = 0;
				goto done;
			} else {
				/*
				 * PS command. Ignore it if it is not Exit_PS.
				 * otherwise send it down immediately.
				 */
1461
				struct cmd_ds_802_11_ps_mode *psm = (void *)&cmd[1];
1462

1463 1464
				lbs_deb_host(
				       "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n",
1465 1466
				       psm->action);
				if (psm->action !=
1467
				    cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
1468 1469
					lbs_deb_host(
					       "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
1470
					list_del(&cmdnode->list);
1471 1472 1473
					spin_lock_irqsave(&priv->driver_lock, flags);
					lbs_complete_command(priv, cmdnode, 0);
					spin_unlock_irqrestore(&priv->driver_lock, flags);
1474 1475 1476 1477 1478

					ret = 0;
					goto done;
				}

1479 1480
				if ((priv->psstate == PS_STATE_SLEEP) ||
				    (priv->psstate == PS_STATE_PRE_SLEEP)) {
1481 1482
					lbs_deb_host(
					       "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
1483
					list_del(&cmdnode->list);
1484 1485 1486
					spin_lock_irqsave(&priv->driver_lock, flags);
					lbs_complete_command(priv, cmdnode, 0);
					spin_unlock_irqrestore(&priv->driver_lock, flags);
1487
					priv->needtowakeup = 1;
1488 1489 1490 1491 1492

					ret = 0;
					goto done;
				}

1493 1494
				lbs_deb_host(
				       "EXEC_NEXT_CMD: sending EXIT_PS\n");
1495 1496
			}
		}
1497
		list_del(&cmdnode->list);
1498
		lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
1499
			    le16_to_cpu(cmd->command));
1500
		lbs_submit_command(priv, cmdnode);
1501 1502 1503 1504 1505
	} else {
		/*
		 * check if in power save mode, if yes, put the device back
		 * to PS mode
		 */
K
Kiran Divekar 已提交
1506 1507 1508 1509 1510 1511 1512 1513 1514
#ifdef TODO
		/*
		 * This was the old code for libertas+wext. Someone that
		 * understands this beast should re-code it in a sane way.
		 *
		 * I actually don't understand why this is related to WPA
		 * and to connection status, shouldn't powering should be
		 * independ of such things?
		 */
1515 1516 1517
		if ((priv->psmode != LBS802_11POWERMODECAM) &&
		    (priv->psstate == PS_STATE_FULL_POWER) &&
		    ((priv->connect_status == LBS_CONNECTED) ||
1518
		    lbs_mesh_connected(priv))) {
1519 1520
			if (priv->secinfo.WPAenabled ||
			    priv->secinfo.WPA2enabled) {
1521
				/* check for valid WPA group keys */
1522 1523
				if (priv->wpa_mcast_key.len ||
				    priv->wpa_unicast_key.len) {
1524
					lbs_deb_host(
1525 1526
					       "EXEC_NEXT_CMD: WPA enabled and GTK_SET"
					       " go back to PS_SLEEP");
1527 1528 1529
					lbs_set_ps_mode(priv,
							PS_MODE_ACTION_ENTER_PS,
							false);
1530 1531
				}
			} else {
1532 1533 1534
				lbs_deb_host(
				       "EXEC_NEXT_CMD: cmdpendingq empty, "
				       "go back to PS_SLEEP");
1535 1536
				lbs_set_ps_mode(priv, PS_MODE_ACTION_ENTER_PS,
						false);
1537 1538
			}
		}
K
Kiran Divekar 已提交
1539
#endif
1540 1541 1542 1543
	}

	ret = 0;
done:
1544
	lbs_deb_leave(LBS_DEB_THREAD);
1545 1546 1547
	return ret;
}

1548
static void lbs_send_confirmsleep(struct lbs_private *priv)
1549 1550
{
	unsigned long flags;
1551
	int ret;
1552

1553
	lbs_deb_enter(LBS_DEB_HOST);
1554 1555
	lbs_deb_hex(LBS_DEB_HOST, "sleep confirm", (u8 *) &confirm_sleep,
		sizeof(confirm_sleep));
1556

1557 1558
	ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep,
		sizeof(confirm_sleep));
1559
	if (ret) {
1560
		lbs_pr_alert("confirm_sleep failed\n");
1561
		goto out;
1562
	}
1563 1564 1565

	spin_lock_irqsave(&priv->driver_lock, flags);

1566 1567 1568
	/* We don't get a response on the sleep-confirmation */
	priv->dnld_sent = DNLD_RES_RECEIVED;

1569 1570 1571 1572 1573
	if (priv->is_host_sleep_configured) {
		priv->is_host_sleep_activated = 1;
		wake_up_interruptible(&priv->host_sleep_q);
	}

1574
	/* If nothing to do, go back to sleep (?) */
S
Stefani Seibold 已提交
1575
	if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx])
1576 1577 1578 1579 1580
		priv->psstate = PS_STATE_SLEEP;

	spin_unlock_irqrestore(&priv->driver_lock, flags);

out:
1581
	lbs_deb_leave(LBS_DEB_HOST);
1582 1583 1584 1585 1586 1587
}

/**
 *  @brief This function checks condition and prepares to
 *  send sleep confirm command to firmware if ok.
 *
1588
 *  @param priv    	A pointer to struct lbs_private structure
1589 1590 1591
 *  @param psmode  	Power Saving mode
 *  @return 	   	n/a
 */
1592
void lbs_ps_confirm_sleep(struct lbs_private *priv)
1593 1594
{
	unsigned long flags =0;
1595
	int allowed = 1;
1596

1597
	lbs_deb_enter(LBS_DEB_HOST);
1598

1599
	spin_lock_irqsave(&priv->driver_lock, flags);
1600
	if (priv->dnld_sent) {
1601
		allowed = 0;
1602
		lbs_deb_host("dnld_sent was set\n");
1603 1604
	}

1605
	/* In-progress command? */
1606
	if (priv->cur_cmd) {
1607
		allowed = 0;
1608
		lbs_deb_host("cur_cmd was set\n");
1609
	}
1610 1611

	/* Pending events or command responses? */
S
Stefani Seibold 已提交
1612
	if (kfifo_len(&priv->event_fifo) || priv->resp_len[priv->resp_idx]) {
1613
		allowed = 0;
1614
		lbs_deb_host("pending events or command responses\n");
1615
	}
1616
	spin_unlock_irqrestore(&priv->driver_lock, flags);
1617 1618

	if (allowed) {
1619
		lbs_deb_host("sending lbs_ps_confirm_sleep\n");
1620
		lbs_send_confirmsleep(priv);
1621
	} else {
1622
		lbs_deb_host("sleep confirm has been delayed\n");
1623 1624
	}

1625
	lbs_deb_leave(LBS_DEB_HOST);
1626
}
1627 1628


1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650
/**
 * @brief Configures the transmission power control functionality.
 *
 * @param priv		A pointer to struct lbs_private structure
 * @param enable	Transmission power control enable
 * @param p0		Power level when link quality is good (dBm).
 * @param p1		Power level when link quality is fair (dBm).
 * @param p2		Power level when link quality is poor (dBm).
 * @param usesnr	Use Signal to Noise Ratio in TPC
 *
 * @return 0 on success
 */
int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
		int8_t p2, int usesnr)
{
	struct cmd_ds_802_11_tpc_cfg cmd;
	int ret;

	memset(&cmd, 0, sizeof(cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_ACT_SET);
	cmd.enable = !!enable;
1651
	cmd.usesnr = !!usesnr;
1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692
	cmd.P0 = p0;
	cmd.P1 = p1;
	cmd.P2 = p2;

	ret = lbs_cmd_with_response(priv, CMD_802_11_TPC_CFG, &cmd);

	return ret;
}

/**
 * @brief Configures the power adaptation settings.
 *
 * @param priv		A pointer to struct lbs_private structure
 * @param enable	Power adaptation enable
 * @param p0		Power level for 1, 2, 5.5 and 11 Mbps (dBm).
 * @param p1		Power level for 6, 9, 12, 18, 22, 24 and 36 Mbps (dBm).
 * @param p2		Power level for 48 and 54 Mbps (dBm).
 *
 * @return 0 on Success
 */

int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
		int8_t p1, int8_t p2)
{
	struct cmd_ds_802_11_pa_cfg cmd;
	int ret;

	memset(&cmd, 0, sizeof(cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_ACT_SET);
	cmd.enable = !!enable;
	cmd.P0 = p0;
	cmd.P1 = p1;
	cmd.P2 = p2;

	ret = lbs_cmd_with_response(priv, CMD_802_11_PA_CFG , &cmd);

	return ret;
}


1693
struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
1694 1695 1696
	uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
	int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
	unsigned long callback_arg)
1697 1698 1699 1700 1701
{
	struct cmd_ctrl_node *cmdnode;

	lbs_deb_enter(LBS_DEB_HOST);

1702
	if (priv->surpriseremoved) {
1703
		lbs_deb_host("PREP_CMD: card removed\n");
1704
		cmdnode = ERR_PTR(-ENOENT);
1705 1706 1707
		goto done;
	}

1708 1709 1710 1711 1712
	if (!lbs_is_cmd_allowed(priv)) {
		cmdnode = ERR_PTR(-EBUSY);
		goto done;
	}

1713 1714 1715 1716 1717 1718
	cmdnode = lbs_get_cmd_ctrl_node(priv);
	if (cmdnode == NULL) {
		lbs_deb_host("PREP_CMD: cmdnode is NULL\n");

		/* Wake up main thread to execute next command */
		wake_up_interruptible(&priv->waitq);
1719
		cmdnode = ERR_PTR(-ENOBUFS);
1720 1721 1722
		goto done;
	}

1723
	cmdnode->callback = callback;
1724
	cmdnode->callback_arg = callback_arg;
1725

1726
	/* Copy the incoming command to the buffer */
1727
	memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size);
1728

1729
	/* Set sequence number, clean result, move to buffer */
1730
	priv->seqnum++;
1731 1732 1733 1734
	cmdnode->cmdbuf->command = cpu_to_le16(command);
	cmdnode->cmdbuf->size    = cpu_to_le16(in_cmd_size);
	cmdnode->cmdbuf->seqnum  = cpu_to_le16(priv->seqnum);
	cmdnode->cmdbuf->result  = 0;
1735 1736 1737 1738

	lbs_deb_host("PREP_CMD: command 0x%04x\n", command);

	cmdnode->cmdwaitqwoken = 0;
1739
	lbs_queue_cmd(priv, cmdnode);
1740 1741
	wake_up_interruptible(&priv->waitq);

1742 1743 1744 1745 1746
 done:
	lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode);
	return cmdnode;
}

1747 1748 1749 1750 1751 1752 1753 1754 1755
void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
	struct cmd_header *in_cmd, int in_cmd_size)
{
	lbs_deb_enter(LBS_DEB_CMD);
	__lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
		lbs_cmd_async_callback, 0);
	lbs_deb_leave(LBS_DEB_CMD);
}

1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773
int __lbs_cmd(struct lbs_private *priv, uint16_t command,
	      struct cmd_header *in_cmd, int in_cmd_size,
	      int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
	      unsigned long callback_arg)
{
	struct cmd_ctrl_node *cmdnode;
	unsigned long flags;
	int ret = 0;

	lbs_deb_enter(LBS_DEB_HOST);

	cmdnode = __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
				  callback, callback_arg);
	if (IS_ERR(cmdnode)) {
		ret = PTR_ERR(cmdnode);
		goto done;
	}

1774 1775 1776
	might_sleep();
	wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);

1777
	spin_lock_irqsave(&priv->driver_lock, flags);
1778 1779 1780 1781
	ret = cmdnode->result;
	if (ret)
		lbs_pr_info("PREP_CMD: command 0x%04x failed: %d\n",
			    command, ret);
1782

1783
	__lbs_cleanup_and_insert_cmd(priv, cmdnode);
1784
	spin_unlock_irqrestore(&priv->driver_lock, flags);
1785 1786 1787 1788 1789

done:
	lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
	return ret;
}
1790
EXPORT_SYMBOL_GPL(__lbs_cmd);