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