Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at c9a28fa7b9ac19b676deefa0a171ce7df8755c08 2149 lines 56 kB view raw
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 <net/iw_handler.h> 7#include "host.h" 8#include "hostcmd.h" 9#include "decl.h" 10#include "defs.h" 11#include "dev.h" 12#include "join.h" 13#include "wext.h" 14#include "cmd.h" 15 16static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); 17static void lbs_set_cmd_ctrl_node(struct lbs_private *priv, 18 struct cmd_ctrl_node *ptempnode, 19 void *pdata_buf); 20 21 22/** 23 * @brief Checks whether a command is allowed in Power Save mode 24 * 25 * @param command the command ID 26 * @return 1 if allowed, 0 if not allowed 27 */ 28static u8 is_command_allowed_in_ps(u16 cmd) 29{ 30 switch (cmd) { 31 case CMD_802_11_RSSI: 32 return 1; 33 default: 34 break; 35 } 36 return 0; 37} 38 39/** 40 * @brief Updates the hardware details like MAC address and regulatory region 41 * 42 * @param priv A pointer to struct lbs_private structure 43 * 44 * @return 0 on success, error on failure 45 */ 46int lbs_update_hw_spec(struct lbs_private *priv) 47{ 48 struct cmd_ds_get_hw_spec cmd; 49 int ret = -1; 50 u32 i; 51 DECLARE_MAC_BUF(mac); 52 53 lbs_deb_enter(LBS_DEB_CMD); 54 55 memset(&cmd, 0, sizeof(cmd)); 56 cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 57 memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN); 58 ret = lbs_cmd_with_response(priv, CMD_GET_HW_SPEC, &cmd); 59 if (ret) 60 goto out; 61 62 priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo); 63 64 /* The firmware release is in an interesting format: the patch 65 * level is in the most significant nibble ... so fix that: */ 66 priv->fwrelease = le32_to_cpu(cmd.fwrelease); 67 priv->fwrelease = (priv->fwrelease << 8) | 68 (priv->fwrelease >> 24 & 0xff); 69 70 /* Some firmware capabilities: 71 * CF card firmware 5.0.16p0: cap 0x00000303 72 * USB dongle firmware 5.110.17p2: cap 0x00000303 73 */ 74 printk("libertas: %s, fw %u.%u.%up%u, cap 0x%08x\n", 75 print_mac(mac, cmd.permanentaddr), 76 priv->fwrelease >> 24 & 0xff, 77 priv->fwrelease >> 16 & 0xff, 78 priv->fwrelease >> 8 & 0xff, 79 priv->fwrelease & 0xff, 80 priv->fwcapinfo); 81 lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", 82 cmd.hwifversion, cmd.version); 83 84 /* Clamp region code to 8-bit since FW spec indicates that it should 85 * only ever be 8-bit, even though the field size is 16-bit. Some firmware 86 * returns non-zero high 8 bits here. 87 */ 88 priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF; 89 90 for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) { 91 /* use the region code to search for the index */ 92 if (priv->regioncode == lbs_region_code_to_index[i]) 93 break; 94 } 95 96 /* if it's unidentified region code, use the default (USA) */ 97 if (i >= MRVDRV_MAX_REGION_CODE) { 98 priv->regioncode = 0x10; 99 lbs_pr_info("unidentified region code; using the default (USA)\n"); 100 } 101 102 if (priv->current_addr[0] == 0xff) 103 memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN); 104 105 memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN); 106 if (priv->mesh_dev) 107 memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN); 108 109 if (lbs_set_regiontable(priv, priv->regioncode, 0)) { 110 ret = -1; 111 goto out; 112 } 113 114 if (lbs_set_universaltable(priv, 0)) { 115 ret = -1; 116 goto out; 117 } 118 119out: 120 lbs_deb_leave(LBS_DEB_CMD); 121 return ret; 122} 123 124int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria) 125{ 126 struct cmd_ds_host_sleep cmd_config; 127 int ret; 128 129 cmd_config.hdr.size = cpu_to_le16(sizeof(cmd_config)); 130 cmd_config.criteria = cpu_to_le32(criteria); 131 cmd_config.gpio = priv->wol_gpio; 132 cmd_config.gap = priv->wol_gap; 133 134 ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config); 135 if (!ret) { 136 lbs_deb_cmd("Set WOL criteria to %x\n", criteria); 137 priv->wol_criteria = criteria; 138 } else { 139 lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret); 140 } 141 142 return ret; 143} 144EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg); 145 146static int lbs_cmd_802_11_ps_mode(struct lbs_private *priv, 147 struct cmd_ds_command *cmd, 148 u16 cmd_action) 149{ 150 struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode; 151 152 lbs_deb_enter(LBS_DEB_CMD); 153 154 cmd->command = cpu_to_le16(CMD_802_11_PS_MODE); 155 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) + 156 S_DS_GEN); 157 psm->action = cpu_to_le16(cmd_action); 158 psm->multipledtim = 0; 159 switch (cmd_action) { 160 case CMD_SUBCMD_ENTER_PS: 161 lbs_deb_cmd("PS command:" "SubCode- Enter PS\n"); 162 163 psm->locallisteninterval = 0; 164 psm->nullpktinterval = 0; 165 psm->multipledtim = 166 cpu_to_le16(MRVDRV_DEFAULT_MULTIPLE_DTIM); 167 break; 168 169 case CMD_SUBCMD_EXIT_PS: 170 lbs_deb_cmd("PS command:" "SubCode- Exit PS\n"); 171 break; 172 173 case CMD_SUBCMD_SLEEP_CONFIRMED: 174 lbs_deb_cmd("PS command: SubCode- sleep confirm\n"); 175 break; 176 177 default: 178 break; 179 } 180 181 lbs_deb_leave(LBS_DEB_CMD); 182 return 0; 183} 184 185int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv, 186 uint16_t cmd_action, uint16_t *timeout) 187{ 188 struct cmd_ds_802_11_inactivity_timeout cmd; 189 int ret; 190 191 lbs_deb_enter(LBS_DEB_CMD); 192 193 cmd.hdr.command = cpu_to_le16(CMD_802_11_INACTIVITY_TIMEOUT); 194 cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 195 196 cmd.action = cpu_to_le16(cmd_action); 197 198 if (cmd_action == CMD_ACT_SET) 199 cmd.timeout = cpu_to_le16(*timeout); 200 else 201 cmd.timeout = 0; 202 203 ret = lbs_cmd_with_response(priv, CMD_802_11_INACTIVITY_TIMEOUT, &cmd); 204 205 if (!ret) 206 *timeout = le16_to_cpu(cmd.timeout); 207 208 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); 209 return 0; 210} 211 212int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, 213 struct sleep_params *sp) 214{ 215 struct cmd_ds_802_11_sleep_params cmd; 216 int ret; 217 218 lbs_deb_enter(LBS_DEB_CMD); 219 220 if (cmd_action == CMD_ACT_GET) { 221 memset(&cmd, 0, sizeof(cmd)); 222 } else { 223 cmd.error = cpu_to_le16(sp->sp_error); 224 cmd.offset = cpu_to_le16(sp->sp_offset); 225 cmd.stabletime = cpu_to_le16(sp->sp_stabletime); 226 cmd.calcontrol = sp->sp_calcontrol; 227 cmd.externalsleepclk = sp->sp_extsleepclk; 228 cmd.reserved = cpu_to_le16(sp->sp_reserved); 229 } 230 cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 231 cmd.action = cpu_to_le16(cmd_action); 232 233 ret = lbs_cmd_with_response(priv, CMD_802_11_SLEEP_PARAMS, &cmd); 234 235 if (!ret) { 236 lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, " 237 "calcontrol 0x%x extsleepclk 0x%x\n", 238 le16_to_cpu(cmd.error), le16_to_cpu(cmd.offset), 239 le16_to_cpu(cmd.stabletime), cmd.calcontrol, 240 cmd.externalsleepclk); 241 242 sp->sp_error = le16_to_cpu(cmd.error); 243 sp->sp_offset = le16_to_cpu(cmd.offset); 244 sp->sp_stabletime = le16_to_cpu(cmd.stabletime); 245 sp->sp_calcontrol = cmd.calcontrol; 246 sp->sp_extsleepclk = cmd.externalsleepclk; 247 sp->sp_reserved = le16_to_cpu(cmd.reserved); 248 } 249 250 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); 251 return 0; 252} 253 254int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, 255 struct assoc_request *assoc) 256{ 257 struct cmd_ds_802_11_set_wep cmd; 258 int ret = 0; 259 260 lbs_deb_enter(LBS_DEB_CMD); 261 262 cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP); 263 cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 264 265 cmd.action = cpu_to_le16(cmd_action); 266 267 if (cmd_action == CMD_ACT_ADD) { 268 int i; 269 270 /* default tx key index */ 271 cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx & 272 CMD_WEP_KEY_INDEX_MASK); 273 274 /* Copy key types and material to host command structure */ 275 for (i = 0; i < 4; i++) { 276 struct enc_key *pkey = &assoc->wep_keys[i]; 277 278 switch (pkey->len) { 279 case KEY_LEN_WEP_40: 280 cmd.keytype[i] = CMD_TYPE_WEP_40_BIT; 281 memmove(cmd.keymaterial[i], pkey->key, pkey->len); 282 lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i); 283 break; 284 case KEY_LEN_WEP_104: 285 cmd.keytype[i] = CMD_TYPE_WEP_104_BIT; 286 memmove(cmd.keymaterial[i], pkey->key, pkey->len); 287 lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i); 288 break; 289 case 0: 290 break; 291 default: 292 lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n", 293 i, pkey->len); 294 ret = -1; 295 goto done; 296 break; 297 } 298 } 299 } else if (cmd_action == CMD_ACT_REMOVE) { 300 /* ACT_REMOVE clears _all_ WEP keys */ 301 302 /* default tx key index */ 303 cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx & 304 CMD_WEP_KEY_INDEX_MASK); 305 lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx); 306 } 307 308 ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd); 309done: 310 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); 311 return ret; 312} 313 314int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, 315 uint16_t *enable) 316{ 317 struct cmd_ds_802_11_enable_rsn cmd; 318 int ret; 319 320 lbs_deb_enter(LBS_DEB_CMD); 321 322 cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 323 cmd.action = cpu_to_le16(cmd_action); 324 325 if (cmd_action == CMD_ACT_SET) { 326 if (*enable) 327 cmd.enable = cpu_to_le16(CMD_ENABLE_RSN); 328 else 329 cmd.enable = cpu_to_le16(CMD_DISABLE_RSN); 330 lbs_deb_cmd("ENABLE_RSN: %d\n", *enable); 331 } 332 333 ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd); 334 if (!ret && cmd_action == CMD_ACT_GET) 335 *enable = le16_to_cpu(cmd.enable); 336 337 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); 338 return ret; 339} 340 341static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset, 342 struct enc_key * pkey) 343{ 344 lbs_deb_enter(LBS_DEB_CMD); 345 346 if (pkey->flags & KEY_INFO_WPA_ENABLED) { 347 pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED); 348 } 349 if (pkey->flags & KEY_INFO_WPA_UNICAST) { 350 pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST); 351 } 352 if (pkey->flags & KEY_INFO_WPA_MCAST) { 353 pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST); 354 } 355 356 pkeyparamset->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL); 357 pkeyparamset->keytypeid = cpu_to_le16(pkey->type); 358 pkeyparamset->keylen = cpu_to_le16(pkey->len); 359 memcpy(pkeyparamset->key, pkey->key, pkey->len); 360 pkeyparamset->length = cpu_to_le16( sizeof(pkeyparamset->keytypeid) 361 + sizeof(pkeyparamset->keyinfo) 362 + sizeof(pkeyparamset->keylen) 363 + sizeof(pkeyparamset->key)); 364 lbs_deb_leave(LBS_DEB_CMD); 365} 366 367static int lbs_cmd_802_11_key_material(struct lbs_private *priv, 368 struct cmd_ds_command *cmd, 369 u16 cmd_action, 370 u32 cmd_oid, void *pdata_buf) 371{ 372 struct cmd_ds_802_11_key_material *pkeymaterial = 373 &cmd->params.keymaterial; 374 struct assoc_request * assoc_req = pdata_buf; 375 int ret = 0; 376 int index = 0; 377 378 lbs_deb_enter(LBS_DEB_CMD); 379 380 cmd->command = cpu_to_le16(CMD_802_11_KEY_MATERIAL); 381 pkeymaterial->action = cpu_to_le16(cmd_action); 382 383 if (cmd_action == CMD_ACT_GET) { 384 cmd->size = cpu_to_le16(S_DS_GEN + sizeof (pkeymaterial->action)); 385 ret = 0; 386 goto done; 387 } 388 389 memset(&pkeymaterial->keyParamSet, 0, sizeof(pkeymaterial->keyParamSet)); 390 391 if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { 392 set_one_wpa_key(&pkeymaterial->keyParamSet[index], 393 &assoc_req->wpa_unicast_key); 394 index++; 395 } 396 397 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) { 398 set_one_wpa_key(&pkeymaterial->keyParamSet[index], 399 &assoc_req->wpa_mcast_key); 400 index++; 401 } 402 403 cmd->size = cpu_to_le16( S_DS_GEN 404 + sizeof (pkeymaterial->action) 405 + (index * sizeof(struct MrvlIEtype_keyParamSet))); 406 407 ret = 0; 408 409done: 410 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); 411 return ret; 412} 413 414static int lbs_cmd_802_11_reset(struct lbs_private *priv, 415 struct cmd_ds_command *cmd, int cmd_action) 416{ 417 struct cmd_ds_802_11_reset *reset = &cmd->params.reset; 418 419 lbs_deb_enter(LBS_DEB_CMD); 420 421 cmd->command = cpu_to_le16(CMD_802_11_RESET); 422 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset) + S_DS_GEN); 423 reset->action = cpu_to_le16(cmd_action); 424 425 lbs_deb_leave(LBS_DEB_CMD); 426 return 0; 427} 428 429static int lbs_cmd_802_11_get_log(struct lbs_private *priv, 430 struct cmd_ds_command *cmd) 431{ 432 lbs_deb_enter(LBS_DEB_CMD); 433 cmd->command = cpu_to_le16(CMD_802_11_GET_LOG); 434 cmd->size = 435 cpu_to_le16(sizeof(struct cmd_ds_802_11_get_log) + S_DS_GEN); 436 437 lbs_deb_leave(LBS_DEB_CMD); 438 return 0; 439} 440 441static int lbs_cmd_802_11_get_stat(struct lbs_private *priv, 442 struct cmd_ds_command *cmd) 443{ 444 lbs_deb_enter(LBS_DEB_CMD); 445 cmd->command = cpu_to_le16(CMD_802_11_GET_STAT); 446 cmd->size = 447 cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) + S_DS_GEN); 448 449 lbs_deb_leave(LBS_DEB_CMD); 450 return 0; 451} 452 453static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv, 454 struct cmd_ds_command *cmd, 455 int cmd_action, 456 int cmd_oid, void *pdata_buf) 457{ 458 struct cmd_ds_802_11_snmp_mib *pSNMPMIB = &cmd->params.smib; 459 u8 ucTemp; 460 461 lbs_deb_enter(LBS_DEB_CMD); 462 463 lbs_deb_cmd("SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid); 464 465 cmd->command = cpu_to_le16(CMD_802_11_SNMP_MIB); 466 cmd->size = cpu_to_le16(sizeof(*pSNMPMIB) + S_DS_GEN); 467 468 switch (cmd_oid) { 469 case OID_802_11_INFRASTRUCTURE_MODE: 470 { 471 u8 mode = (u8) (size_t) pdata_buf; 472 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET); 473 pSNMPMIB->oid = cpu_to_le16((u16) DESIRED_BSSTYPE_I); 474 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u8)); 475 if (mode == IW_MODE_ADHOC) { 476 ucTemp = SNMP_MIB_VALUE_ADHOC; 477 } else { 478 /* Infra and Auto modes */ 479 ucTemp = SNMP_MIB_VALUE_INFRA; 480 } 481 482 memmove(pSNMPMIB->value, &ucTemp, sizeof(u8)); 483 484 break; 485 } 486 487 case OID_802_11D_ENABLE: 488 { 489 u32 ulTemp; 490 491 pSNMPMIB->oid = cpu_to_le16((u16) DOT11D_I); 492 493 if (cmd_action == CMD_ACT_SET) { 494 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET); 495 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16)); 496 ulTemp = *(u32 *)pdata_buf; 497 *((__le16 *)(pSNMPMIB->value)) = 498 cpu_to_le16((u16) ulTemp); 499 } 500 break; 501 } 502 503 case OID_802_11_FRAGMENTATION_THRESHOLD: 504 { 505 u32 ulTemp; 506 507 pSNMPMIB->oid = cpu_to_le16((u16) FRAGTHRESH_I); 508 509 if (cmd_action == CMD_ACT_GET) { 510 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET); 511 } else if (cmd_action == CMD_ACT_SET) { 512 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET); 513 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16)); 514 ulTemp = *((u32 *) pdata_buf); 515 *((__le16 *)(pSNMPMIB->value)) = 516 cpu_to_le16((u16) ulTemp); 517 518 } 519 520 break; 521 } 522 523 case OID_802_11_RTS_THRESHOLD: 524 { 525 526 u32 ulTemp; 527 pSNMPMIB->oid = cpu_to_le16(RTSTHRESH_I); 528 529 if (cmd_action == CMD_ACT_GET) { 530 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET); 531 } else if (cmd_action == CMD_ACT_SET) { 532 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET); 533 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16)); 534 ulTemp = *((u32 *)pdata_buf); 535 *(__le16 *)(pSNMPMIB->value) = 536 cpu_to_le16((u16) ulTemp); 537 538 } 539 break; 540 } 541 case OID_802_11_TX_RETRYCOUNT: 542 pSNMPMIB->oid = cpu_to_le16((u16) SHORT_RETRYLIM_I); 543 544 if (cmd_action == CMD_ACT_GET) { 545 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET); 546 } else if (cmd_action == CMD_ACT_SET) { 547 pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET); 548 pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16)); 549 *((__le16 *)(pSNMPMIB->value)) = 550 cpu_to_le16((u16) priv->txretrycount); 551 } 552 553 break; 554 default: 555 break; 556 } 557 558 lbs_deb_cmd( 559 "SNMP_CMD: command=0x%x, size=0x%x, seqnum=0x%x, result=0x%x\n", 560 le16_to_cpu(cmd->command), le16_to_cpu(cmd->size), 561 le16_to_cpu(cmd->seqnum), le16_to_cpu(cmd->result)); 562 563 lbs_deb_cmd( 564 "SNMP_CMD: action 0x%x, oid 0x%x, oidsize 0x%x, value 0x%x\n", 565 le16_to_cpu(pSNMPMIB->querytype), le16_to_cpu(pSNMPMIB->oid), 566 le16_to_cpu(pSNMPMIB->bufsize), 567 le16_to_cpu(*(__le16 *) pSNMPMIB->value)); 568 569 lbs_deb_leave(LBS_DEB_CMD); 570 return 0; 571} 572 573static int lbs_cmd_802_11_rf_tx_power(struct lbs_private *priv, 574 struct cmd_ds_command *cmd, 575 u16 cmd_action, void *pdata_buf) 576{ 577 578 struct cmd_ds_802_11_rf_tx_power *prtp = &cmd->params.txp; 579 580 lbs_deb_enter(LBS_DEB_CMD); 581 582 cmd->size = 583 cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) + S_DS_GEN); 584 cmd->command = cpu_to_le16(CMD_802_11_RF_TX_POWER); 585 prtp->action = cpu_to_le16(cmd_action); 586 587 lbs_deb_cmd("RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n", 588 le16_to_cpu(cmd->size), le16_to_cpu(cmd->command), 589 le16_to_cpu(prtp->action)); 590 591 switch (cmd_action) { 592 case CMD_ACT_TX_POWER_OPT_GET: 593 prtp->action = cpu_to_le16(CMD_ACT_GET); 594 prtp->currentlevel = 0; 595 break; 596 597 case CMD_ACT_TX_POWER_OPT_SET_HIGH: 598 prtp->action = cpu_to_le16(CMD_ACT_SET); 599 prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_HIGH); 600 break; 601 602 case CMD_ACT_TX_POWER_OPT_SET_MID: 603 prtp->action = cpu_to_le16(CMD_ACT_SET); 604 prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_MID); 605 break; 606 607 case CMD_ACT_TX_POWER_OPT_SET_LOW: 608 prtp->action = cpu_to_le16(CMD_ACT_SET); 609 prtp->currentlevel = cpu_to_le16(*((u16 *) pdata_buf)); 610 break; 611 } 612 613 lbs_deb_leave(LBS_DEB_CMD); 614 return 0; 615} 616 617static int lbs_cmd_802_11_monitor_mode(struct lbs_private *priv, 618 struct cmd_ds_command *cmd, 619 u16 cmd_action, void *pdata_buf) 620{ 621 struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor; 622 623 cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE); 624 cmd->size = 625 cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) + 626 S_DS_GEN); 627 628 monitor->action = cpu_to_le16(cmd_action); 629 if (cmd_action == CMD_ACT_SET) { 630 monitor->mode = 631 cpu_to_le16((u16) (*(u32 *) pdata_buf)); 632 } 633 634 return 0; 635} 636 637static int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, 638 struct cmd_ds_command *cmd, 639 u16 cmd_action) 640{ 641 struct cmd_ds_802_11_rate_adapt_rateset 642 *rateadapt = &cmd->params.rateset; 643 644 lbs_deb_enter(LBS_DEB_CMD); 645 cmd->size = 646 cpu_to_le16(sizeof(struct cmd_ds_802_11_rate_adapt_rateset) 647 + S_DS_GEN); 648 cmd->command = cpu_to_le16(CMD_802_11_RATE_ADAPT_RATESET); 649 650 rateadapt->action = cpu_to_le16(cmd_action); 651 rateadapt->enablehwauto = cpu_to_le16(priv->enablehwauto); 652 rateadapt->bitmap = cpu_to_le16(priv->ratebitmap); 653 654 lbs_deb_leave(LBS_DEB_CMD); 655 return 0; 656} 657 658/** 659 * @brief Get the current data rate 660 * 661 * @param priv A pointer to struct lbs_private structure 662 * 663 * @return The data rate on success, error on failure 664 */ 665int lbs_get_data_rate(struct lbs_private *priv) 666{ 667 struct cmd_ds_802_11_data_rate cmd; 668 int ret = -1; 669 670 lbs_deb_enter(LBS_DEB_CMD); 671 672 memset(&cmd, 0, sizeof(cmd)); 673 cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 674 cmd.action = cpu_to_le16(CMD_ACT_GET_TX_RATE); 675 676 ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd); 677 if (ret) 678 goto out; 679 680 lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof (cmd)); 681 682 ret = (int) lbs_fw_index_to_data_rate(cmd.rates[0]); 683 lbs_deb_cmd("DATA_RATE: current rate 0x%02x\n", ret); 684 685out: 686 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); 687 return ret; 688} 689 690/** 691 * @brief Set the data rate 692 * 693 * @param priv A pointer to struct lbs_private structure 694 * @param rate The desired data rate, or 0 to clear a locked rate 695 * 696 * @return 0 on success, error on failure 697 */ 698int lbs_set_data_rate(struct lbs_private *priv, u8 rate) 699{ 700 struct cmd_ds_802_11_data_rate cmd; 701 int ret = 0; 702 703 lbs_deb_enter(LBS_DEB_CMD); 704 705 memset(&cmd, 0, sizeof(cmd)); 706 cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 707 708 if (rate > 0) { 709 cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE); 710 cmd.rates[0] = lbs_data_rate_to_fw_index(rate); 711 if (cmd.rates[0] == 0) { 712 lbs_deb_cmd("DATA_RATE: invalid requested rate of" 713 " 0x%02X\n", rate); 714 ret = 0; 715 goto out; 716 } 717 lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]); 718 } else { 719 cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO); 720 lbs_deb_cmd("DATA_RATE: setting auto\n"); 721 } 722 723 ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd); 724 if (ret) 725 goto out; 726 727 lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof (cmd)); 728 729 /* FIXME: get actual rates FW can do if this command actually returns 730 * all data rates supported. 731 */ 732 priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]); 733 lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate); 734 735out: 736 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); 737 return ret; 738} 739 740static int lbs_cmd_mac_multicast_adr(struct lbs_private *priv, 741 struct cmd_ds_command *cmd, 742 u16 cmd_action) 743{ 744 struct cmd_ds_mac_multicast_adr *pMCastAdr = &cmd->params.madr; 745 746 lbs_deb_enter(LBS_DEB_CMD); 747 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) + 748 S_DS_GEN); 749 cmd->command = cpu_to_le16(CMD_MAC_MULTICAST_ADR); 750 751 lbs_deb_cmd("MULTICAST_ADR: setting %d addresses\n", pMCastAdr->nr_of_adrs); 752 pMCastAdr->action = cpu_to_le16(cmd_action); 753 pMCastAdr->nr_of_adrs = 754 cpu_to_le16((u16) priv->nr_of_multicastmacaddr); 755 memcpy(pMCastAdr->maclist, priv->multicastlist, 756 priv->nr_of_multicastmacaddr * ETH_ALEN); 757 758 lbs_deb_leave(LBS_DEB_CMD); 759 return 0; 760} 761 762/** 763 * @brief Get the radio channel 764 * 765 * @param priv A pointer to struct lbs_private structure 766 * 767 * @return The channel on success, error on failure 768 */ 769int lbs_get_channel(struct lbs_private *priv) 770{ 771 struct cmd_ds_802_11_rf_channel cmd; 772 int ret = 0; 773 774 lbs_deb_enter(LBS_DEB_CMD); 775 776 cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 777 cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET); 778 779 ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd); 780 if (ret) 781 goto out; 782 783 ret = le16_to_cpu(cmd.channel); 784 lbs_deb_cmd("current radio channel is %d\n", ret); 785 786out: 787 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); 788 return ret; 789} 790 791/** 792 * @brief Set the radio channel 793 * 794 * @param priv A pointer to struct lbs_private structure 795 * @param channel The desired channel, or 0 to clear a locked channel 796 * 797 * @return 0 on success, error on failure 798 */ 799int lbs_set_channel(struct lbs_private *priv, u8 channel) 800{ 801 struct cmd_ds_802_11_rf_channel cmd; 802 u8 old_channel = priv->curbssparams.channel; 803 int ret = 0; 804 805 lbs_deb_enter(LBS_DEB_CMD); 806 807 cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 808 cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET); 809 cmd.channel = cpu_to_le16(channel); 810 811 ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd); 812 if (ret) 813 goto out; 814 815 priv->curbssparams.channel = (uint8_t) le16_to_cpu(cmd.channel); 816 lbs_deb_cmd("channel switch from %d to %d\n", old_channel, 817 priv->curbssparams.channel); 818 819out: 820 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); 821 return ret; 822} 823 824static int lbs_cmd_802_11_rssi(struct lbs_private *priv, 825 struct cmd_ds_command *cmd) 826{ 827 828 lbs_deb_enter(LBS_DEB_CMD); 829 cmd->command = cpu_to_le16(CMD_802_11_RSSI); 830 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN); 831 cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR); 832 833 /* reset Beacon SNR/NF/RSSI values */ 834 priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0; 835 priv->SNR[TYPE_BEACON][TYPE_AVG] = 0; 836 priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0; 837 priv->NF[TYPE_BEACON][TYPE_AVG] = 0; 838 priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0; 839 priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0; 840 841 lbs_deb_leave(LBS_DEB_CMD); 842 return 0; 843} 844 845static int lbs_cmd_reg_access(struct lbs_private *priv, 846 struct cmd_ds_command *cmdptr, 847 u8 cmd_action, void *pdata_buf) 848{ 849 struct lbs_offset_value *offval; 850 851 lbs_deb_enter(LBS_DEB_CMD); 852 853 offval = (struct lbs_offset_value *)pdata_buf; 854 855 switch (le16_to_cpu(cmdptr->command)) { 856 case CMD_MAC_REG_ACCESS: 857 { 858 struct cmd_ds_mac_reg_access *macreg; 859 860 cmdptr->size = 861 cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access) 862 + S_DS_GEN); 863 macreg = 864 (struct cmd_ds_mac_reg_access *)&cmdptr->params. 865 macreg; 866 867 macreg->action = cpu_to_le16(cmd_action); 868 macreg->offset = cpu_to_le16((u16) offval->offset); 869 macreg->value = cpu_to_le32(offval->value); 870 871 break; 872 } 873 874 case CMD_BBP_REG_ACCESS: 875 { 876 struct cmd_ds_bbp_reg_access *bbpreg; 877 878 cmdptr->size = 879 cpu_to_le16(sizeof 880 (struct cmd_ds_bbp_reg_access) 881 + S_DS_GEN); 882 bbpreg = 883 (struct cmd_ds_bbp_reg_access *)&cmdptr->params. 884 bbpreg; 885 886 bbpreg->action = cpu_to_le16(cmd_action); 887 bbpreg->offset = cpu_to_le16((u16) offval->offset); 888 bbpreg->value = (u8) offval->value; 889 890 break; 891 } 892 893 case CMD_RF_REG_ACCESS: 894 { 895 struct cmd_ds_rf_reg_access *rfreg; 896 897 cmdptr->size = 898 cpu_to_le16(sizeof 899 (struct cmd_ds_rf_reg_access) + 900 S_DS_GEN); 901 rfreg = 902 (struct cmd_ds_rf_reg_access *)&cmdptr->params. 903 rfreg; 904 905 rfreg->action = cpu_to_le16(cmd_action); 906 rfreg->offset = cpu_to_le16((u16) offval->offset); 907 rfreg->value = (u8) offval->value; 908 909 break; 910 } 911 912 default: 913 break; 914 } 915 916 lbs_deb_leave(LBS_DEB_CMD); 917 return 0; 918} 919 920static int lbs_cmd_802_11_mac_address(struct lbs_private *priv, 921 struct cmd_ds_command *cmd, 922 u16 cmd_action) 923{ 924 925 lbs_deb_enter(LBS_DEB_CMD); 926 cmd->command = cpu_to_le16(CMD_802_11_MAC_ADDRESS); 927 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) + 928 S_DS_GEN); 929 cmd->result = 0; 930 931 cmd->params.macadd.action = cpu_to_le16(cmd_action); 932 933 if (cmd_action == CMD_ACT_SET) { 934 memcpy(cmd->params.macadd.macadd, 935 priv->current_addr, ETH_ALEN); 936 lbs_deb_hex(LBS_DEB_CMD, "SET_CMD: MAC addr", priv->current_addr, 6); 937 } 938 939 lbs_deb_leave(LBS_DEB_CMD); 940 return 0; 941} 942 943static int lbs_cmd_802_11_eeprom_access(struct lbs_private *priv, 944 struct cmd_ds_command *cmd, 945 int cmd_action, void *pdata_buf) 946{ 947 struct lbs_ioctl_regrdwr *ea = pdata_buf; 948 949 lbs_deb_enter(LBS_DEB_CMD); 950 951 cmd->command = cpu_to_le16(CMD_802_11_EEPROM_ACCESS); 952 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) + 953 S_DS_GEN); 954 cmd->result = 0; 955 956 cmd->params.rdeeprom.action = cpu_to_le16(ea->action); 957 cmd->params.rdeeprom.offset = cpu_to_le16(ea->offset); 958 cmd->params.rdeeprom.bytecount = cpu_to_le16(ea->NOB); 959 cmd->params.rdeeprom.value = 0; 960 961 lbs_deb_leave(LBS_DEB_CMD); 962 return 0; 963} 964 965static int lbs_cmd_bt_access(struct lbs_private *priv, 966 struct cmd_ds_command *cmd, 967 u16 cmd_action, void *pdata_buf) 968{ 969 struct cmd_ds_bt_access *bt_access = &cmd->params.bt; 970 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); 971 972 cmd->command = cpu_to_le16(CMD_BT_ACCESS); 973 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN); 974 cmd->result = 0; 975 bt_access->action = cpu_to_le16(cmd_action); 976 977 switch (cmd_action) { 978 case CMD_ACT_BT_ACCESS_ADD: 979 memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN); 980 lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", bt_access->addr1, 6); 981 break; 982 case CMD_ACT_BT_ACCESS_DEL: 983 memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN); 984 lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", bt_access->addr1, 6); 985 break; 986 case CMD_ACT_BT_ACCESS_LIST: 987 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); 988 break; 989 case CMD_ACT_BT_ACCESS_RESET: 990 break; 991 case CMD_ACT_BT_ACCESS_SET_INVERT: 992 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); 993 break; 994 case CMD_ACT_BT_ACCESS_GET_INVERT: 995 break; 996 default: 997 break; 998 } 999 lbs_deb_leave(LBS_DEB_CMD); 1000 return 0; 1001} 1002 1003static int lbs_cmd_fwt_access(struct lbs_private *priv, 1004 struct cmd_ds_command *cmd, 1005 u16 cmd_action, void *pdata_buf) 1006{ 1007 struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt; 1008 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); 1009 1010 cmd->command = cpu_to_le16(CMD_FWT_ACCESS); 1011 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + S_DS_GEN); 1012 cmd->result = 0; 1013 1014 if (pdata_buf) 1015 memcpy(fwt_access, pdata_buf, sizeof(*fwt_access)); 1016 else 1017 memset(fwt_access, 0, sizeof(*fwt_access)); 1018 1019 fwt_access->action = cpu_to_le16(cmd_action); 1020 1021 lbs_deb_leave(LBS_DEB_CMD); 1022 return 0; 1023} 1024 1025int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, 1026 struct cmd_ds_mesh_access *cmd) 1027{ 1028 int ret; 1029 1030 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); 1031 1032 cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS); 1033 cmd->hdr.size = cpu_to_le16(sizeof(*cmd)); 1034 cmd->hdr.result = 0; 1035 1036 cmd->action = cpu_to_le16(cmd_action); 1037 1038 ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd); 1039 1040 lbs_deb_leave(LBS_DEB_CMD); 1041 return ret; 1042} 1043EXPORT_SYMBOL_GPL(lbs_mesh_access); 1044 1045int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan) 1046{ 1047 struct cmd_ds_mesh_config cmd; 1048 1049 memset(&cmd, 0, sizeof(cmd)); 1050 cmd.action = cpu_to_le16(enable); 1051 cmd.channel = cpu_to_le16(chan); 1052 cmd.type = cpu_to_le16(priv->mesh_tlv); 1053 cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 1054 1055 if (enable) { 1056 cmd.length = cpu_to_le16(priv->mesh_ssid_len); 1057 memcpy(cmd.data, priv->mesh_ssid, priv->mesh_ssid_len); 1058 } 1059 lbs_deb_cmd("mesh config enable %d TLV %x channel %d SSID %s\n", 1060 enable, priv->mesh_tlv, chan, 1061 escape_essid(priv->mesh_ssid, priv->mesh_ssid_len)); 1062 return lbs_cmd_with_response(priv, CMD_MESH_CONFIG, &cmd); 1063} 1064 1065static int lbs_cmd_bcn_ctrl(struct lbs_private * priv, 1066 struct cmd_ds_command *cmd, 1067 u16 cmd_action) 1068{ 1069 struct cmd_ds_802_11_beacon_control 1070 *bcn_ctrl = &cmd->params.bcn_ctrl; 1071 1072 lbs_deb_enter(LBS_DEB_CMD); 1073 cmd->size = 1074 cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control) 1075 + S_DS_GEN); 1076 cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL); 1077 1078 bcn_ctrl->action = cpu_to_le16(cmd_action); 1079 bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable); 1080 bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period); 1081 1082 lbs_deb_leave(LBS_DEB_CMD); 1083 return 0; 1084} 1085 1086static void lbs_queue_cmd(struct lbs_private *priv, 1087 struct cmd_ctrl_node *cmdnode) 1088{ 1089 unsigned long flags; 1090 int addtail = 1; 1091 1092 lbs_deb_enter(LBS_DEB_HOST); 1093 1094 if (!cmdnode) { 1095 lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n"); 1096 goto done; 1097 } 1098 if (!cmdnode->cmdbuf->size) { 1099 lbs_deb_host("DNLD_CMD: cmd size is zero\n"); 1100 goto done; 1101 } 1102 cmdnode->result = 0; 1103 1104 /* Exit_PS command needs to be queued in the header always. */ 1105 if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) { 1106 struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf[1]; 1107 1108 if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) { 1109 if (priv->psstate != PS_STATE_FULL_POWER) 1110 addtail = 0; 1111 } 1112 } 1113 1114 spin_lock_irqsave(&priv->driver_lock, flags); 1115 1116 if (addtail) 1117 list_add_tail(&cmdnode->list, &priv->cmdpendingq); 1118 else 1119 list_add(&cmdnode->list, &priv->cmdpendingq); 1120 1121 spin_unlock_irqrestore(&priv->driver_lock, flags); 1122 1123 lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n", 1124 le16_to_cpu(cmdnode->cmdbuf->command)); 1125 1126done: 1127 lbs_deb_leave(LBS_DEB_HOST); 1128} 1129 1130static void lbs_submit_command(struct lbs_private *priv, 1131 struct cmd_ctrl_node *cmdnode) 1132{ 1133 unsigned long flags; 1134 struct cmd_header *cmd; 1135 uint16_t cmdsize; 1136 uint16_t command; 1137 int timeo = 5 * HZ; 1138 int ret; 1139 1140 lbs_deb_enter(LBS_DEB_HOST); 1141 1142 cmd = cmdnode->cmdbuf; 1143 1144 spin_lock_irqsave(&priv->driver_lock, flags); 1145 priv->cur_cmd = cmdnode; 1146 priv->cur_cmd_retcode = 0; 1147 spin_unlock_irqrestore(&priv->driver_lock, flags); 1148 1149 cmdsize = le16_to_cpu(cmd->size); 1150 command = le16_to_cpu(cmd->command); 1151 1152 /* These commands take longer */ 1153 if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE || 1154 command == CMD_802_11_AUTHENTICATE) 1155 timeo = 10 * HZ; 1156 1157 lbs_deb_host("DNLD_CMD: command 0x%04x, seq %d, size %d, jiffies %lu\n", 1158 command, le16_to_cpu(cmd->seqnum), cmdsize, jiffies); 1159 lbs_deb_hex(LBS_DEB_HOST, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize); 1160 1161 ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize); 1162 1163 if (ret) { 1164 lbs_pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret); 1165 /* Let the timer kick in and retry, and potentially reset 1166 the whole thing if the condition persists */ 1167 timeo = HZ; 1168 } else 1169 lbs_deb_cmd("DNLD_CMD: sent command 0x%04x, jiffies %lu\n", 1170 command, jiffies); 1171 1172 /* Setup the timer after transmit command */ 1173 mod_timer(&priv->command_timer, jiffies + timeo); 1174 1175 lbs_deb_leave(LBS_DEB_HOST); 1176} 1177 1178static int lbs_cmd_mac_control(struct lbs_private *priv, 1179 struct cmd_ds_command *cmd) 1180{ 1181 struct cmd_ds_mac_control *mac = &cmd->params.macctrl; 1182 1183 lbs_deb_enter(LBS_DEB_CMD); 1184 1185 cmd->command = cpu_to_le16(CMD_MAC_CONTROL); 1186 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN); 1187 mac->action = cpu_to_le16(priv->currentpacketfilter); 1188 1189 lbs_deb_cmd("MAC_CONTROL: action 0x%x, size %d\n", 1190 le16_to_cpu(mac->action), le16_to_cpu(cmd->size)); 1191 1192 lbs_deb_leave(LBS_DEB_CMD); 1193 return 0; 1194} 1195 1196/** 1197 * This function inserts command node to cmdfreeq 1198 * after cleans it. Requires priv->driver_lock held. 1199 */ 1200static void __lbs_cleanup_and_insert_cmd(struct lbs_private *priv, 1201 struct cmd_ctrl_node *cmdnode) 1202{ 1203 lbs_deb_enter(LBS_DEB_HOST); 1204 1205 if (!cmdnode) 1206 goto out; 1207 1208 cmdnode->callback = NULL; 1209 cmdnode->callback_arg = 0; 1210 1211 memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE); 1212 1213 list_add_tail(&cmdnode->list, &priv->cmdfreeq); 1214 out: 1215 lbs_deb_leave(LBS_DEB_HOST); 1216} 1217 1218static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv, 1219 struct cmd_ctrl_node *ptempcmd) 1220{ 1221 unsigned long flags; 1222 1223 spin_lock_irqsave(&priv->driver_lock, flags); 1224 __lbs_cleanup_and_insert_cmd(priv, ptempcmd); 1225 spin_unlock_irqrestore(&priv->driver_lock, flags); 1226} 1227 1228void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, 1229 int result) 1230{ 1231 if (cmd == priv->cur_cmd) 1232 priv->cur_cmd_retcode = result; 1233 1234 cmd->result = result; 1235 cmd->cmdwaitqwoken = 1; 1236 wake_up_interruptible(&cmd->cmdwait_q); 1237 1238 if (!cmd->callback) 1239 __lbs_cleanup_and_insert_cmd(priv, cmd); 1240 priv->cur_cmd = NULL; 1241} 1242 1243int lbs_set_radio_control(struct lbs_private *priv) 1244{ 1245 int ret = 0; 1246 struct cmd_ds_802_11_radio_control cmd; 1247 1248 lbs_deb_enter(LBS_DEB_CMD); 1249 1250 cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 1251 cmd.action = cpu_to_le16(CMD_ACT_SET); 1252 1253 switch (priv->preamble) { 1254 case CMD_TYPE_SHORT_PREAMBLE: 1255 cmd.control = cpu_to_le16(SET_SHORT_PREAMBLE); 1256 break; 1257 1258 case CMD_TYPE_LONG_PREAMBLE: 1259 cmd.control = cpu_to_le16(SET_LONG_PREAMBLE); 1260 break; 1261 1262 case CMD_TYPE_AUTO_PREAMBLE: 1263 default: 1264 cmd.control = cpu_to_le16(SET_AUTO_PREAMBLE); 1265 break; 1266 } 1267 1268 if (priv->radioon) 1269 cmd.control |= cpu_to_le16(TURN_ON_RF); 1270 else 1271 cmd.control &= cpu_to_le16(~TURN_ON_RF); 1272 1273 lbs_deb_cmd("RADIO_SET: radio %d, preamble %d\n", priv->radioon, 1274 priv->preamble); 1275 1276 ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd); 1277 1278 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); 1279 return ret; 1280} 1281 1282int lbs_set_mac_packet_filter(struct lbs_private *priv) 1283{ 1284 int ret = 0; 1285 1286 lbs_deb_enter(LBS_DEB_CMD); 1287 1288 /* Send MAC control command to station */ 1289 ret = lbs_prepare_and_send_command(priv, 1290 CMD_MAC_CONTROL, 0, 0, 0, NULL); 1291 1292 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); 1293 return ret; 1294} 1295 1296/** 1297 * @brief This function prepare the command before send to firmware. 1298 * 1299 * @param priv A pointer to struct lbs_private structure 1300 * @param cmd_no command number 1301 * @param cmd_action command action: GET or SET 1302 * @param wait_option wait option: wait response or not 1303 * @param cmd_oid cmd oid: treated as sub command 1304 * @param pdata_buf A pointer to informaion buffer 1305 * @return 0 or -1 1306 */ 1307int lbs_prepare_and_send_command(struct lbs_private *priv, 1308 u16 cmd_no, 1309 u16 cmd_action, 1310 u16 wait_option, u32 cmd_oid, void *pdata_buf) 1311{ 1312 int ret = 0; 1313 struct cmd_ctrl_node *cmdnode; 1314 struct cmd_ds_command *cmdptr; 1315 unsigned long flags; 1316 1317 lbs_deb_enter(LBS_DEB_HOST); 1318 1319 if (!priv) { 1320 lbs_deb_host("PREP_CMD: priv is NULL\n"); 1321 ret = -1; 1322 goto done; 1323 } 1324 1325 if (priv->surpriseremoved) { 1326 lbs_deb_host("PREP_CMD: card removed\n"); 1327 ret = -1; 1328 goto done; 1329 } 1330 1331 cmdnode = lbs_get_cmd_ctrl_node(priv); 1332 1333 if (cmdnode == NULL) { 1334 lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); 1335 1336 /* Wake up main thread to execute next command */ 1337 wake_up_interruptible(&priv->waitq); 1338 ret = -1; 1339 goto done; 1340 } 1341 1342 lbs_set_cmd_ctrl_node(priv, cmdnode, pdata_buf); 1343 1344 cmdptr = (struct cmd_ds_command *)cmdnode->cmdbuf; 1345 1346 lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no); 1347 1348 /* Set sequence number, command and INT option */ 1349 priv->seqnum++; 1350 cmdptr->seqnum = cpu_to_le16(priv->seqnum); 1351 1352 cmdptr->command = cpu_to_le16(cmd_no); 1353 cmdptr->result = 0; 1354 1355 switch (cmd_no) { 1356 case CMD_802_11_PS_MODE: 1357 ret = lbs_cmd_802_11_ps_mode(priv, cmdptr, cmd_action); 1358 break; 1359 1360 case CMD_802_11_SCAN: 1361 ret = lbs_cmd_80211_scan(priv, cmdptr, pdata_buf); 1362 break; 1363 1364 case CMD_MAC_CONTROL: 1365 ret = lbs_cmd_mac_control(priv, cmdptr); 1366 break; 1367 1368 case CMD_802_11_ASSOCIATE: 1369 case CMD_802_11_REASSOCIATE: 1370 ret = lbs_cmd_80211_associate(priv, cmdptr, pdata_buf); 1371 break; 1372 1373 case CMD_802_11_DEAUTHENTICATE: 1374 ret = lbs_cmd_80211_deauthenticate(priv, cmdptr); 1375 break; 1376 1377 case CMD_802_11_AD_HOC_START: 1378 ret = lbs_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf); 1379 break; 1380 case CMD_CODE_DNLD: 1381 break; 1382 1383 case CMD_802_11_RESET: 1384 ret = lbs_cmd_802_11_reset(priv, cmdptr, cmd_action); 1385 break; 1386 1387 case CMD_802_11_GET_LOG: 1388 ret = lbs_cmd_802_11_get_log(priv, cmdptr); 1389 break; 1390 1391 case CMD_802_11_AUTHENTICATE: 1392 ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf); 1393 break; 1394 1395 case CMD_802_11_GET_STAT: 1396 ret = lbs_cmd_802_11_get_stat(priv, cmdptr); 1397 break; 1398 1399 case CMD_802_11_SNMP_MIB: 1400 ret = lbs_cmd_802_11_snmp_mib(priv, cmdptr, 1401 cmd_action, cmd_oid, pdata_buf); 1402 break; 1403 1404 case CMD_MAC_REG_ACCESS: 1405 case CMD_BBP_REG_ACCESS: 1406 case CMD_RF_REG_ACCESS: 1407 ret = lbs_cmd_reg_access(priv, cmdptr, cmd_action, pdata_buf); 1408 break; 1409 1410 case CMD_802_11_RF_TX_POWER: 1411 ret = lbs_cmd_802_11_rf_tx_power(priv, cmdptr, 1412 cmd_action, pdata_buf); 1413 break; 1414 1415 case CMD_802_11_RATE_ADAPT_RATESET: 1416 ret = lbs_cmd_802_11_rate_adapt_rateset(priv, 1417 cmdptr, cmd_action); 1418 break; 1419 1420 case CMD_MAC_MULTICAST_ADR: 1421 ret = lbs_cmd_mac_multicast_adr(priv, cmdptr, cmd_action); 1422 break; 1423 1424 case CMD_802_11_MONITOR_MODE: 1425 ret = lbs_cmd_802_11_monitor_mode(priv, cmdptr, 1426 cmd_action, pdata_buf); 1427 break; 1428 1429 case CMD_802_11_AD_HOC_JOIN: 1430 ret = lbs_cmd_80211_ad_hoc_join(priv, cmdptr, pdata_buf); 1431 break; 1432 1433 case CMD_802_11_RSSI: 1434 ret = lbs_cmd_802_11_rssi(priv, cmdptr); 1435 break; 1436 1437 case CMD_802_11_AD_HOC_STOP: 1438 ret = lbs_cmd_80211_ad_hoc_stop(priv, cmdptr); 1439 break; 1440 1441 case CMD_802_11_KEY_MATERIAL: 1442 ret = lbs_cmd_802_11_key_material(priv, cmdptr, cmd_action, 1443 cmd_oid, pdata_buf); 1444 break; 1445 1446 case CMD_802_11_PAIRWISE_TSC: 1447 break; 1448 case CMD_802_11_GROUP_TSC: 1449 break; 1450 1451 case CMD_802_11_MAC_ADDRESS: 1452 ret = lbs_cmd_802_11_mac_address(priv, cmdptr, cmd_action); 1453 break; 1454 1455 case CMD_802_11_EEPROM_ACCESS: 1456 ret = lbs_cmd_802_11_eeprom_access(priv, cmdptr, 1457 cmd_action, pdata_buf); 1458 break; 1459 1460 case CMD_802_11_SET_AFC: 1461 case CMD_802_11_GET_AFC: 1462 1463 cmdptr->command = cpu_to_le16(cmd_no); 1464 cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) + 1465 S_DS_GEN); 1466 1467 memmove(&cmdptr->params.afc, 1468 pdata_buf, sizeof(struct cmd_ds_802_11_afc)); 1469 1470 ret = 0; 1471 goto done; 1472 1473 case CMD_802_11D_DOMAIN_INFO: 1474 ret = lbs_cmd_802_11d_domain_info(priv, cmdptr, 1475 cmd_no, cmd_action); 1476 break; 1477 1478 case CMD_802_11_TPC_CFG: 1479 cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG); 1480 cmdptr->size = 1481 cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) + 1482 S_DS_GEN); 1483 1484 memmove(&cmdptr->params.tpccfg, 1485 pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg)); 1486 1487 ret = 0; 1488 break; 1489 case CMD_802_11_LED_GPIO_CTRL: 1490 { 1491 struct mrvlietypes_ledgpio *gpio = 1492 (struct mrvlietypes_ledgpio*) 1493 cmdptr->params.ledgpio.data; 1494 1495 memmove(&cmdptr->params.ledgpio, 1496 pdata_buf, 1497 sizeof(struct cmd_ds_802_11_led_ctrl)); 1498 1499 cmdptr->command = 1500 cpu_to_le16(CMD_802_11_LED_GPIO_CTRL); 1501 1502#define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8 1503 cmdptr->size = 1504 cpu_to_le16(le16_to_cpu(gpio->header.len) 1505 + S_DS_GEN 1506 + ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN); 1507 gpio->header.len = gpio->header.len; 1508 1509 ret = 0; 1510 break; 1511 } 1512 1513 case CMD_802_11_PWR_CFG: 1514 cmdptr->command = cpu_to_le16(CMD_802_11_PWR_CFG); 1515 cmdptr->size = 1516 cpu_to_le16(sizeof(struct cmd_ds_802_11_pwr_cfg) + 1517 S_DS_GEN); 1518 memmove(&cmdptr->params.pwrcfg, pdata_buf, 1519 sizeof(struct cmd_ds_802_11_pwr_cfg)); 1520 1521 ret = 0; 1522 break; 1523 case CMD_BT_ACCESS: 1524 ret = lbs_cmd_bt_access(priv, cmdptr, cmd_action, pdata_buf); 1525 break; 1526 1527 case CMD_FWT_ACCESS: 1528 ret = lbs_cmd_fwt_access(priv, cmdptr, cmd_action, pdata_buf); 1529 break; 1530 1531 case CMD_GET_TSF: 1532 cmdptr->command = cpu_to_le16(CMD_GET_TSF); 1533 cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) + 1534 S_DS_GEN); 1535 ret = 0; 1536 break; 1537 case CMD_802_11_BEACON_CTRL: 1538 ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); 1539 break; 1540 default: 1541 lbs_deb_host("PREP_CMD: unknown command 0x%04x\n", cmd_no); 1542 ret = -1; 1543 break; 1544 } 1545 1546 /* return error, since the command preparation failed */ 1547 if (ret != 0) { 1548 lbs_deb_host("PREP_CMD: command preparation failed\n"); 1549 lbs_cleanup_and_insert_cmd(priv, cmdnode); 1550 ret = -1; 1551 goto done; 1552 } 1553 1554 cmdnode->cmdwaitqwoken = 0; 1555 1556 lbs_queue_cmd(priv, cmdnode); 1557 wake_up_interruptible(&priv->waitq); 1558 1559 if (wait_option & CMD_OPTION_WAITFORRSP) { 1560 lbs_deb_host("PREP_CMD: wait for response\n"); 1561 might_sleep(); 1562 wait_event_interruptible(cmdnode->cmdwait_q, 1563 cmdnode->cmdwaitqwoken); 1564 } 1565 1566 spin_lock_irqsave(&priv->driver_lock, flags); 1567 if (priv->cur_cmd_retcode) { 1568 lbs_deb_host("PREP_CMD: command failed with return code %d\n", 1569 priv->cur_cmd_retcode); 1570 priv->cur_cmd_retcode = 0; 1571 ret = -1; 1572 } 1573 spin_unlock_irqrestore(&priv->driver_lock, flags); 1574 1575done: 1576 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); 1577 return ret; 1578} 1579EXPORT_SYMBOL_GPL(lbs_prepare_and_send_command); 1580 1581/** 1582 * @brief This function allocates the command buffer and link 1583 * it to command free queue. 1584 * 1585 * @param priv A pointer to struct lbs_private structure 1586 * @return 0 or -1 1587 */ 1588int lbs_allocate_cmd_buffer(struct lbs_private *priv) 1589{ 1590 int ret = 0; 1591 u32 bufsize; 1592 u32 i; 1593 struct cmd_ctrl_node *cmdarray; 1594 1595 lbs_deb_enter(LBS_DEB_HOST); 1596 1597 /* Allocate and initialize the command array */ 1598 bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS; 1599 if (!(cmdarray = kzalloc(bufsize, GFP_KERNEL))) { 1600 lbs_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n"); 1601 ret = -1; 1602 goto done; 1603 } 1604 priv->cmd_array = cmdarray; 1605 1606 /* Allocate and initialize each command buffer in the command array */ 1607 for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) { 1608 cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL); 1609 if (!cmdarray[i].cmdbuf) { 1610 lbs_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n"); 1611 ret = -1; 1612 goto done; 1613 } 1614 } 1615 1616 for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) { 1617 init_waitqueue_head(&cmdarray[i].cmdwait_q); 1618 lbs_cleanup_and_insert_cmd(priv, &cmdarray[i]); 1619 } 1620 ret = 0; 1621 1622done: 1623 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); 1624 return ret; 1625} 1626 1627/** 1628 * @brief This function frees the command buffer. 1629 * 1630 * @param priv A pointer to struct lbs_private structure 1631 * @return 0 or -1 1632 */ 1633int lbs_free_cmd_buffer(struct lbs_private *priv) 1634{ 1635 struct cmd_ctrl_node *cmdarray; 1636 unsigned int i; 1637 1638 lbs_deb_enter(LBS_DEB_HOST); 1639 1640 /* need to check if cmd array is allocated or not */ 1641 if (priv->cmd_array == NULL) { 1642 lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n"); 1643 goto done; 1644 } 1645 1646 cmdarray = priv->cmd_array; 1647 1648 /* Release shared memory buffers */ 1649 for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) { 1650 if (cmdarray[i].cmdbuf) { 1651 kfree(cmdarray[i].cmdbuf); 1652 cmdarray[i].cmdbuf = NULL; 1653 } 1654 } 1655 1656 /* Release cmd_ctrl_node */ 1657 if (priv->cmd_array) { 1658 kfree(priv->cmd_array); 1659 priv->cmd_array = NULL; 1660 } 1661 1662done: 1663 lbs_deb_leave(LBS_DEB_HOST); 1664 return 0; 1665} 1666 1667/** 1668 * @brief This function gets a free command node if available in 1669 * command free queue. 1670 * 1671 * @param priv A pointer to struct lbs_private structure 1672 * @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL 1673 */ 1674static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv) 1675{ 1676 struct cmd_ctrl_node *tempnode; 1677 unsigned long flags; 1678 1679 lbs_deb_enter(LBS_DEB_HOST); 1680 1681 if (!priv) 1682 return NULL; 1683 1684 spin_lock_irqsave(&priv->driver_lock, flags); 1685 1686 if (!list_empty(&priv->cmdfreeq)) { 1687 tempnode = list_first_entry(&priv->cmdfreeq, 1688 struct cmd_ctrl_node, list); 1689 list_del(&tempnode->list); 1690 } else { 1691 lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n"); 1692 tempnode = NULL; 1693 } 1694 1695 spin_unlock_irqrestore(&priv->driver_lock, flags); 1696 1697 lbs_deb_leave(LBS_DEB_HOST); 1698 return tempnode; 1699} 1700 1701/** 1702 * @brief This function cleans command node. 1703 * 1704 * @param ptempnode A pointer to cmdCtrlNode structure 1705 * @return n/a 1706 */ 1707 1708/** 1709 * @brief This function initializes the command node. 1710 * 1711 * @param priv A pointer to struct lbs_private structure 1712 * @param ptempnode A pointer to cmd_ctrl_node structure 1713 * @param pdata_buf A pointer to informaion buffer 1714 * @return 0 or -1 1715 */ 1716static void lbs_set_cmd_ctrl_node(struct lbs_private *priv, 1717 struct cmd_ctrl_node *ptempnode, 1718 void *pdata_buf) 1719{ 1720 lbs_deb_enter(LBS_DEB_HOST); 1721 1722 if (!ptempnode) 1723 return; 1724 1725 ptempnode->callback = NULL; 1726 ptempnode->callback_arg = (unsigned long)pdata_buf; 1727 1728 lbs_deb_leave(LBS_DEB_HOST); 1729} 1730 1731/** 1732 * @brief This function executes next command in command 1733 * pending queue. It will put fimware back to PS mode 1734 * if applicable. 1735 * 1736 * @param priv A pointer to struct lbs_private structure 1737 * @return 0 or -1 1738 */ 1739int lbs_execute_next_command(struct lbs_private *priv) 1740{ 1741 struct cmd_ctrl_node *cmdnode = NULL; 1742 struct cmd_header *cmd; 1743 unsigned long flags; 1744 int ret = 0; 1745 1746 // Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the 1747 // only caller to us is lbs_thread() and we get even when a 1748 // data packet is received 1749 lbs_deb_enter(LBS_DEB_THREAD); 1750 1751 spin_lock_irqsave(&priv->driver_lock, flags); 1752 1753 if (priv->cur_cmd) { 1754 lbs_pr_alert( "EXEC_NEXT_CMD: already processing command!\n"); 1755 spin_unlock_irqrestore(&priv->driver_lock, flags); 1756 ret = -1; 1757 goto done; 1758 } 1759 1760 if (!list_empty(&priv->cmdpendingq)) { 1761 cmdnode = list_first_entry(&priv->cmdpendingq, 1762 struct cmd_ctrl_node, list); 1763 } 1764 1765 spin_unlock_irqrestore(&priv->driver_lock, flags); 1766 1767 if (cmdnode) { 1768 cmd = cmdnode->cmdbuf; 1769 1770 if (is_command_allowed_in_ps(le16_to_cpu(cmd->command))) { 1771 if ((priv->psstate == PS_STATE_SLEEP) || 1772 (priv->psstate == PS_STATE_PRE_SLEEP)) { 1773 lbs_deb_host( 1774 "EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d\n", 1775 le16_to_cpu(cmd->command), 1776 priv->psstate); 1777 ret = -1; 1778 goto done; 1779 } 1780 lbs_deb_host("EXEC_NEXT_CMD: OK to send command " 1781 "0x%04x in psstate %d\n", 1782 le16_to_cpu(cmd->command), priv->psstate); 1783 } else if (priv->psstate != PS_STATE_FULL_POWER) { 1784 /* 1785 * 1. Non-PS command: 1786 * Queue it. set needtowakeup to TRUE if current state 1787 * is SLEEP, otherwise call lbs_ps_wakeup to send Exit_PS. 1788 * 2. PS command but not Exit_PS: 1789 * Ignore it. 1790 * 3. PS command Exit_PS: 1791 * Set needtowakeup to TRUE if current state is SLEEP, 1792 * otherwise send this command down to firmware 1793 * immediately. 1794 */ 1795 if (cmd->command != cpu_to_le16(CMD_802_11_PS_MODE)) { 1796 /* Prepare to send Exit PS, 1797 * this non PS command will be sent later */ 1798 if ((priv->psstate == PS_STATE_SLEEP) 1799 || (priv->psstate == PS_STATE_PRE_SLEEP) 1800 ) { 1801 /* w/ new scheme, it will not reach here. 1802 since it is blocked in main_thread. */ 1803 priv->needtowakeup = 1; 1804 } else 1805 lbs_ps_wakeup(priv, 0); 1806 1807 ret = 0; 1808 goto done; 1809 } else { 1810 /* 1811 * PS command. Ignore it if it is not Exit_PS. 1812 * otherwise send it down immediately. 1813 */ 1814 struct cmd_ds_802_11_ps_mode *psm = (void *)&cmd[1]; 1815 1816 lbs_deb_host( 1817 "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n", 1818 psm->action); 1819 if (psm->action != 1820 cpu_to_le16(CMD_SUBCMD_EXIT_PS)) { 1821 lbs_deb_host( 1822 "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n"); 1823 list_del(&cmdnode->list); 1824 spin_lock_irqsave(&priv->driver_lock, flags); 1825 lbs_complete_command(priv, cmdnode, 0); 1826 spin_unlock_irqrestore(&priv->driver_lock, flags); 1827 1828 ret = 0; 1829 goto done; 1830 } 1831 1832 if ((priv->psstate == PS_STATE_SLEEP) || 1833 (priv->psstate == PS_STATE_PRE_SLEEP)) { 1834 lbs_deb_host( 1835 "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n"); 1836 list_del(&cmdnode->list); 1837 spin_lock_irqsave(&priv->driver_lock, flags); 1838 lbs_complete_command(priv, cmdnode, 0); 1839 spin_unlock_irqrestore(&priv->driver_lock, flags); 1840 priv->needtowakeup = 1; 1841 1842 ret = 0; 1843 goto done; 1844 } 1845 1846 lbs_deb_host( 1847 "EXEC_NEXT_CMD: sending EXIT_PS\n"); 1848 } 1849 } 1850 list_del(&cmdnode->list); 1851 lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n", 1852 le16_to_cpu(cmd->command)); 1853 lbs_submit_command(priv, cmdnode); 1854 } else { 1855 /* 1856 * check if in power save mode, if yes, put the device back 1857 * to PS mode 1858 */ 1859 if ((priv->psmode != LBS802_11POWERMODECAM) && 1860 (priv->psstate == PS_STATE_FULL_POWER) && 1861 ((priv->connect_status == LBS_CONNECTED) || 1862 (priv->mesh_connect_status == LBS_CONNECTED))) { 1863 if (priv->secinfo.WPAenabled || 1864 priv->secinfo.WPA2enabled) { 1865 /* check for valid WPA group keys */ 1866 if (priv->wpa_mcast_key.len || 1867 priv->wpa_unicast_key.len) { 1868 lbs_deb_host( 1869 "EXEC_NEXT_CMD: WPA enabled and GTK_SET" 1870 " go back to PS_SLEEP"); 1871 lbs_ps_sleep(priv, 0); 1872 } 1873 } else { 1874 lbs_deb_host( 1875 "EXEC_NEXT_CMD: cmdpendingq empty, " 1876 "go back to PS_SLEEP"); 1877 lbs_ps_sleep(priv, 0); 1878 } 1879 } 1880 } 1881 1882 ret = 0; 1883done: 1884 lbs_deb_leave(LBS_DEB_THREAD); 1885 return ret; 1886} 1887 1888void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str) 1889{ 1890 union iwreq_data iwrq; 1891 u8 buf[50]; 1892 1893 lbs_deb_enter(LBS_DEB_WEXT); 1894 1895 memset(&iwrq, 0, sizeof(union iwreq_data)); 1896 memset(buf, 0, sizeof(buf)); 1897 1898 snprintf(buf, sizeof(buf) - 1, "%s", str); 1899 1900 iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN; 1901 1902 /* Send Event to upper layer */ 1903 lbs_deb_wext("event indication string %s\n", (char *)buf); 1904 lbs_deb_wext("event indication length %d\n", iwrq.data.length); 1905 lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str); 1906 1907 wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf); 1908 1909 lbs_deb_leave(LBS_DEB_WEXT); 1910} 1911 1912static int sendconfirmsleep(struct lbs_private *priv, u8 *cmdptr, u16 size) 1913{ 1914 unsigned long flags; 1915 int ret = 0; 1916 1917 lbs_deb_enter(LBS_DEB_HOST); 1918 1919 lbs_deb_host("SEND_SLEEPC_CMD: before download, cmd size %d\n", 1920 size); 1921 1922 lbs_deb_hex(LBS_DEB_HOST, "sleep confirm command", cmdptr, size); 1923 1924 ret = priv->hw_host_to_card(priv, MVMS_CMD, cmdptr, size); 1925 1926 spin_lock_irqsave(&priv->driver_lock, flags); 1927 if (priv->intcounter || priv->currenttxskb) 1928 lbs_deb_host("SEND_SLEEPC_CMD: intcounter %d, currenttxskb %p\n", 1929 priv->intcounter, priv->currenttxskb); 1930 spin_unlock_irqrestore(&priv->driver_lock, flags); 1931 1932 if (ret) { 1933 lbs_pr_alert( 1934 "SEND_SLEEPC_CMD: Host to Card failed for Confirm Sleep\n"); 1935 } else { 1936 spin_lock_irqsave(&priv->driver_lock, flags); 1937 if (!priv->intcounter) { 1938 priv->psstate = PS_STATE_SLEEP; 1939 } else { 1940 lbs_deb_host("SEND_SLEEPC_CMD: after sent, intcounter %d\n", 1941 priv->intcounter); 1942 } 1943 spin_unlock_irqrestore(&priv->driver_lock, flags); 1944 1945 lbs_deb_host("SEND_SLEEPC_CMD: sent confirm sleep\n"); 1946 } 1947 1948 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); 1949 return ret; 1950} 1951 1952void lbs_ps_sleep(struct lbs_private *priv, int wait_option) 1953{ 1954 lbs_deb_enter(LBS_DEB_HOST); 1955 1956 /* 1957 * PS is currently supported only in Infrastructure mode 1958 * Remove this check if it is to be supported in IBSS mode also 1959 */ 1960 1961 lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE, 1962 CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL); 1963 1964 lbs_deb_leave(LBS_DEB_HOST); 1965} 1966 1967/** 1968 * @brief This function sends Exit_PS command to firmware. 1969 * 1970 * @param priv A pointer to struct lbs_private structure 1971 * @param wait_option wait response or not 1972 * @return n/a 1973 */ 1974void lbs_ps_wakeup(struct lbs_private *priv, int wait_option) 1975{ 1976 __le32 Localpsmode; 1977 1978 lbs_deb_enter(LBS_DEB_HOST); 1979 1980 Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM); 1981 1982 lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE, 1983 CMD_SUBCMD_EXIT_PS, 1984 wait_option, 0, &Localpsmode); 1985 1986 lbs_deb_leave(LBS_DEB_HOST); 1987} 1988 1989/** 1990 * @brief This function checks condition and prepares to 1991 * send sleep confirm command to firmware if ok. 1992 * 1993 * @param priv A pointer to struct lbs_private structure 1994 * @param psmode Power Saving mode 1995 * @return n/a 1996 */ 1997void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode) 1998{ 1999 unsigned long flags =0; 2000 u8 allowed = 1; 2001 2002 lbs_deb_enter(LBS_DEB_HOST); 2003 2004 if (priv->dnld_sent) { 2005 allowed = 0; 2006 lbs_deb_host("dnld_sent was set\n"); 2007 } 2008 2009 spin_lock_irqsave(&priv->driver_lock, flags); 2010 if (priv->cur_cmd) { 2011 allowed = 0; 2012 lbs_deb_host("cur_cmd was set\n"); 2013 } 2014 if (priv->intcounter > 0) { 2015 allowed = 0; 2016 lbs_deb_host("intcounter %d\n", priv->intcounter); 2017 } 2018 spin_unlock_irqrestore(&priv->driver_lock, flags); 2019 2020 if (allowed) { 2021 lbs_deb_host("sending lbs_ps_confirm_sleep\n"); 2022 sendconfirmsleep(priv, (u8 *) & priv->lbs_ps_confirm_sleep, 2023 sizeof(struct PS_CMD_ConfirmSleep)); 2024 } else { 2025 lbs_deb_host("sleep confirm has been delayed\n"); 2026 } 2027 2028 lbs_deb_leave(LBS_DEB_HOST); 2029} 2030 2031 2032/** 2033 * @brief Simple callback that copies response back into command 2034 * 2035 * @param priv A pointer to struct lbs_private structure 2036 * @param extra A pointer to the original command structure for which 2037 * 'resp' is a response 2038 * @param resp A pointer to the command response 2039 * 2040 * @return 0 on success, error on failure 2041 */ 2042int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, 2043 struct cmd_header *resp) 2044{ 2045 struct cmd_header *buf = (void *)extra; 2046 uint16_t copy_len; 2047 2048 lbs_deb_enter(LBS_DEB_CMD); 2049 2050 copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size)); 2051 lbs_deb_cmd("Copying back %u bytes; command response was %u bytes, " 2052 "copy back buffer was %u bytes\n", copy_len, 2053 le16_to_cpu(resp->size), le16_to_cpu(buf->size)); 2054 memcpy(buf, resp, copy_len); 2055 2056 lbs_deb_leave(LBS_DEB_CMD); 2057 return 0; 2058} 2059EXPORT_SYMBOL_GPL(lbs_cmd_copyback); 2060 2061struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command, 2062 struct cmd_header *in_cmd, int in_cmd_size, 2063 int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), 2064 unsigned long callback_arg) 2065{ 2066 struct cmd_ctrl_node *cmdnode; 2067 2068 lbs_deb_enter(LBS_DEB_HOST); 2069 2070 if (priv->surpriseremoved) { 2071 lbs_deb_host("PREP_CMD: card removed\n"); 2072 cmdnode = ERR_PTR(-ENOENT); 2073 goto done; 2074 } 2075 2076 cmdnode = lbs_get_cmd_ctrl_node(priv); 2077 if (cmdnode == NULL) { 2078 lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); 2079 2080 /* Wake up main thread to execute next command */ 2081 wake_up_interruptible(&priv->waitq); 2082 cmdnode = ERR_PTR(-ENOBUFS); 2083 goto done; 2084 } 2085 2086 cmdnode->callback = callback; 2087 cmdnode->callback_arg = callback_arg; 2088 2089 /* Copy the incoming command to the buffer */ 2090 memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size); 2091 2092 /* Set sequence number, clean result, move to buffer */ 2093 priv->seqnum++; 2094 cmdnode->cmdbuf->command = cpu_to_le16(command); 2095 cmdnode->cmdbuf->size = cpu_to_le16(in_cmd_size); 2096 cmdnode->cmdbuf->seqnum = cpu_to_le16(priv->seqnum); 2097 cmdnode->cmdbuf->result = 0; 2098 2099 lbs_deb_host("PREP_CMD: command 0x%04x\n", command); 2100 2101 /* here was the big old switch() statement, which is now obsolete, 2102 * because the caller of lbs_cmd() sets up all of *cmd for us. */ 2103 2104 cmdnode->cmdwaitqwoken = 0; 2105 lbs_queue_cmd(priv, cmdnode); 2106 wake_up_interruptible(&priv->waitq); 2107 2108 done: 2109 lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode); 2110 return cmdnode; 2111} 2112 2113int __lbs_cmd(struct lbs_private *priv, uint16_t command, 2114 struct cmd_header *in_cmd, int in_cmd_size, 2115 int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), 2116 unsigned long callback_arg) 2117{ 2118 struct cmd_ctrl_node *cmdnode; 2119 unsigned long flags; 2120 int ret = 0; 2121 2122 lbs_deb_enter(LBS_DEB_HOST); 2123 2124 cmdnode = __lbs_cmd_async(priv, command, in_cmd, in_cmd_size, 2125 callback, callback_arg); 2126 if (IS_ERR(cmdnode)) { 2127 ret = PTR_ERR(cmdnode); 2128 goto done; 2129 } 2130 2131 might_sleep(); 2132 wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken); 2133 2134 spin_lock_irqsave(&priv->driver_lock, flags); 2135 ret = cmdnode->result; 2136 if (ret) 2137 lbs_pr_info("PREP_CMD: command 0x%04x failed: %d\n", 2138 command, ret); 2139 2140 __lbs_cleanup_and_insert_cmd(priv, cmdnode); 2141 spin_unlock_irqrestore(&priv->driver_lock, flags); 2142 2143done: 2144 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); 2145 return ret; 2146} 2147EXPORT_SYMBOL_GPL(__lbs_cmd); 2148 2149