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