aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl3945-base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl3945-base.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c270
1 files changed, 21 insertions, 249 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 4474a4c3ddcd..c8a1bdeaa435 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -434,246 +434,17 @@ u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flag
434 434
435} 435}
436 436
437 437int iwl3945_send_statistics_request(struct iwl_priv *priv)
438/*************** HOST COMMAND QUEUE FUNCTIONS *****/
439
440#define IWL_CMD(x) case x: return #x
441#define HOST_COMPLETE_TIMEOUT (HZ / 2)
442
443/**
444 * iwl3945_enqueue_hcmd - enqueue a uCode command
445 * @priv: device private data point
446 * @cmd: a point to the ucode command structure
447 *
448 * The function returns < 0 values to indicate the operation is
449 * failed. On success, it turns the index (> 0) of command in the
450 * command queue.
451 */
452static int iwl3945_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
453{
454 struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
455 struct iwl_queue *q = &txq->q;
456 struct iwl_cmd *out_cmd;
457 u32 idx;
458 u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
459 dma_addr_t phys_addr;
460 int ret, len;
461 unsigned long flags;
462
463 /* If any of the command structures end up being larger than
464 * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
465 * we will need to increase the size of the TFD entries */
466 BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
467 !(cmd->meta.flags & CMD_SIZE_HUGE));
468
469
470 if (iwl_is_rfkill(priv)) {
471 IWL_DEBUG_INFO("Not sending command - RF KILL");
472 return -EIO;
473 }
474
475 if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
476 IWL_ERR(priv, "No space for Tx\n");
477 return -ENOSPC;
478 }
479
480 spin_lock_irqsave(&priv->hcmd_lock, flags);
481
482 idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE);
483 out_cmd = txq->cmd[idx];
484
485 out_cmd->hdr.cmd = cmd->id;
486 memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta));
487 memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len);
488
489 /* At this point, the out_cmd now has all of the incoming cmd
490 * information */
491
492 out_cmd->hdr.flags = 0;
493 out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) |
494 INDEX_TO_SEQ(q->write_ptr));
495 if (out_cmd->meta.flags & CMD_SIZE_HUGE)
496 out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
497
498 len = (idx == TFD_CMD_SLOTS) ?
499 IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd);
500
501 phys_addr = pci_map_single(priv->pci_dev, out_cmd,
502 len, PCI_DMA_TODEVICE);
503 pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr);
504 pci_unmap_len_set(&out_cmd->meta, len, len);
505 phys_addr += offsetof(struct iwl_cmd, hdr);
506
507 priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
508 phys_addr, fix_size,
509 1, U32_PAD(cmd->len));
510
511 IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, "
512 "%d bytes at %d[%d]:%d\n",
513 get_cmd_string(out_cmd->hdr.cmd),
514 out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
515 fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
516
517 txq->need_update = 1;
518
519 /* Increment and update queue's write index */
520 q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
521 ret = iwl_txq_update_write_ptr(priv, txq);
522
523 spin_unlock_irqrestore(&priv->hcmd_lock, flags);
524 return ret ? ret : idx;
525}
526
527static int iwl3945_send_cmd_async(struct iwl_priv *priv,
528 struct iwl_host_cmd *cmd)
529{
530 int ret;
531
532 BUG_ON(!(cmd->meta.flags & CMD_ASYNC));
533
534 /* An asynchronous command can not expect an SKB to be set. */
535 BUG_ON(cmd->meta.flags & CMD_WANT_SKB);
536
537 /* An asynchronous command MUST have a callback. */
538 BUG_ON(!cmd->meta.u.callback);
539
540 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
541 return -EBUSY;
542
543 ret = iwl3945_enqueue_hcmd(priv, cmd);
544 if (ret < 0) {
545 IWL_ERR(priv,
546 "Error sending %s: iwl3945_enqueue_hcmd failed: %d\n",
547 get_cmd_string(cmd->id), ret);
548 return ret;
549 }
550 return 0;
551}
552
553static int iwl3945_send_cmd_sync(struct iwl_priv *priv,
554 struct iwl_host_cmd *cmd)
555{
556 int cmd_idx;
557 int ret;
558
559 BUG_ON(cmd->meta.flags & CMD_ASYNC);
560
561 /* A synchronous command can not have a callback set. */
562 BUG_ON(cmd->meta.u.callback != NULL);
563
564 if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
565 IWL_ERR(priv,
566 "Error sending %s: Already sending a host command\n",
567 get_cmd_string(cmd->id));
568 ret = -EBUSY;
569 goto out;
570 }
571
572 set_bit(STATUS_HCMD_ACTIVE, &priv->status);
573
574 if (cmd->meta.flags & CMD_WANT_SKB)
575 cmd->meta.source = &cmd->meta;
576
577 cmd_idx = iwl3945_enqueue_hcmd(priv, cmd);
578 if (cmd_idx < 0) {
579 ret = cmd_idx;
580 IWL_ERR(priv,
581 "Error sending %s: iwl3945_enqueue_hcmd failed: %d\n",
582 get_cmd_string(cmd->id), ret);
583 goto out;
584 }
585
586 ret = wait_event_interruptible_timeout(priv->wait_command_queue,
587 !test_bit(STATUS_HCMD_ACTIVE, &priv->status),
588 HOST_COMPLETE_TIMEOUT);
589 if (!ret) {
590 if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
591 IWL_ERR(priv, "Error sending %s: time out after %dms\n",
592 get_cmd_string(cmd->id),
593 jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
594
595 clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
596 ret = -ETIMEDOUT;
597 goto cancel;
598 }
599 }
600
601 if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
602 IWL_DEBUG_INFO("Command %s aborted: RF KILL Switch\n",
603 get_cmd_string(cmd->id));
604 ret = -ECANCELED;
605 goto fail;
606 }
607 if (test_bit(STATUS_FW_ERROR, &priv->status)) {
608 IWL_DEBUG_INFO("Command %s failed: FW Error\n",
609 get_cmd_string(cmd->id));
610 ret = -EIO;
611 goto fail;
612 }
613 if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) {
614 IWL_ERR(priv, "Error: Response NULL in '%s'\n",
615 get_cmd_string(cmd->id));
616 ret = -EIO;
617 goto cancel;
618 }
619
620 ret = 0;
621 goto out;
622
623cancel:
624 if (cmd->meta.flags & CMD_WANT_SKB) {
625 struct iwl_cmd *qcmd;
626
627 /* Cancel the CMD_WANT_SKB flag for the cmd in the
628 * TX cmd queue. Otherwise in case the cmd comes
629 * in later, it will possibly set an invalid
630 * address (cmd->meta.source). */
631 qcmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx];
632 qcmd->meta.flags &= ~CMD_WANT_SKB;
633 }
634fail:
635 if (cmd->meta.u.skb) {
636 dev_kfree_skb_any(cmd->meta.u.skb);
637 cmd->meta.u.skb = NULL;
638 }
639out:
640 clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
641 return ret;
642}
643
644int iwl3945_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
645{
646 if (cmd->meta.flags & CMD_ASYNC)
647 return iwl3945_send_cmd_async(priv, cmd);
648
649 return iwl3945_send_cmd_sync(priv, cmd);
650}
651
652int iwl3945_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
653{ 438{
654 struct iwl_host_cmd cmd = { 439 u32 val = 0;
655 .id = id,
656 .len = len,
657 .data = data,
658 };
659
660 return iwl3945_send_cmd_sync(priv, &cmd);
661}
662 440
663static int __must_check iwl3945_send_cmd_u32(struct iwl_priv *priv, u8 id, u32 val)
664{
665 struct iwl_host_cmd cmd = { 441 struct iwl_host_cmd cmd = {
666 .id = id, 442 .id = REPLY_STATISTICS_CMD,
667 .len = sizeof(val), 443 .len = sizeof(val),
668 .data = &val, 444 .data = &val,
669 }; 445 };
670 446
671 return iwl3945_send_cmd_sync(priv, &cmd); 447 return iwl_send_cmd_sync(priv, &cmd);
672}
673
674int iwl3945_send_statistics_request(struct iwl_priv *priv)
675{
676 return iwl3945_send_cmd_u32(priv, REPLY_STATISTICS_CMD, 0);
677} 448}
678 449
679/** 450/**
@@ -864,7 +635,7 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
864 rxon_assoc.cck_basic_rates = priv->staging39_rxon.cck_basic_rates; 635 rxon_assoc.cck_basic_rates = priv->staging39_rxon.cck_basic_rates;
865 rxon_assoc.reserved = 0; 636 rxon_assoc.reserved = 0;
866 637
867 rc = iwl3945_send_cmd_sync(priv, &cmd); 638 rc = iwl_send_cmd_sync(priv, &cmd);
868 if (rc) 639 if (rc)
869 return rc; 640 return rc;
870 641
@@ -936,7 +707,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
936 IWL_DEBUG_INFO("Toggling associated bit on current RXON\n"); 707 IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
937 active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; 708 active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
938 709
939 rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON, 710 rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
940 sizeof(struct iwl3945_rxon_cmd), 711 sizeof(struct iwl3945_rxon_cmd),
941 &priv->active39_rxon); 712 &priv->active39_rxon);
942 713
@@ -960,7 +731,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
960 priv->staging_rxon.bssid_addr); 731 priv->staging_rxon.bssid_addr);
961 732
962 /* Apply the new configuration */ 733 /* Apply the new configuration */
963 rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON, 734 rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
964 sizeof(struct iwl3945_rxon_cmd), &priv->staging39_rxon); 735 sizeof(struct iwl3945_rxon_cmd), &priv->staging39_rxon);
965 if (rc) { 736 if (rc) {
966 IWL_ERR(priv, "Error setting new configuration (%d).\n", rc); 737 IWL_ERR(priv, "Error setting new configuration (%d).\n", rc);
@@ -1016,7 +787,7 @@ static int iwl3945_send_bt_config(struct iwl_priv *priv)
1016 .kill_cts_mask = 0, 787 .kill_cts_mask = 0,
1017 }; 788 };
1018 789
1019 return iwl3945_send_cmd_pdu(priv, REPLY_BT_CONFIG, 790 return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
1020 sizeof(bt_cmd), &bt_cmd); 791 sizeof(bt_cmd), &bt_cmd);
1021} 792}
1022 793
@@ -1037,7 +808,7 @@ static int iwl3945_send_scan_abort(struct iwl_priv *priv)
1037 return 0; 808 return 0;
1038 } 809 }
1039 810
1040 rc = iwl3945_send_cmd_sync(priv, &cmd); 811 rc = iwl_send_cmd_sync(priv, &cmd);
1041 if (rc) { 812 if (rc) {
1042 clear_bit(STATUS_SCAN_ABORTING, &priv->status); 813 clear_bit(STATUS_SCAN_ABORTING, &priv->status);
1043 return rc; 814 return rc;
@@ -1106,7 +877,7 @@ int iwl3945_send_add_station(struct iwl_priv *priv,
1106 else 877 else
1107 cmd.meta.flags |= CMD_WANT_SKB; 878 cmd.meta.flags |= CMD_WANT_SKB;
1108 879
1109 rc = iwl3945_send_cmd(priv, &cmd); 880 rc = iwl_send_cmd(priv, &cmd);
1110 881
1111 if (rc || (flags & CMD_ASYNC)) 882 if (rc || (flags & CMD_ASYNC))
1112 return rc; 883 return rc;
@@ -1300,7 +1071,7 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
1300 1071
1301 frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate); 1072 frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
1302 1073
1303 rc = iwl3945_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, 1074 rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
1304 &frame->u.cmd[0]); 1075 &frame->u.cmd[0]);
1305 1076
1306 iwl3945_free_frame(priv, frame); 1077 iwl3945_free_frame(priv, frame);
@@ -1513,7 +1284,7 @@ static int iwl3945_send_qos_params_command(struct iwl_priv *priv,
1513 struct iwl_qosparam_cmd *qos) 1284 struct iwl_qosparam_cmd *qos)
1514{ 1285{
1515 1286
1516 return iwl3945_send_cmd_pdu(priv, REPLY_QOS_PARAM, 1287 return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
1517 sizeof(struct iwl_qosparam_cmd), qos); 1288 sizeof(struct iwl_qosparam_cmd), qos);
1518} 1289}
1519 1290
@@ -1714,8 +1485,8 @@ static int iwl3945_send_power_mode(struct iwl_priv *priv, u32 mode)
1714 iwl3945_update_power_cmd(priv, &cmd, final_mode); 1485 iwl3945_update_power_cmd(priv, &cmd, final_mode);
1715 1486
1716 /* FIXME use get_hcmd_size 3945 command is 4 bytes shorter */ 1487 /* FIXME use get_hcmd_size 3945 command is 4 bytes shorter */
1717 rc = iwl3945_send_cmd_pdu(priv, POWER_TABLE_CMD, 1488 rc = iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
1718 sizeof(struct iwl3945_powertable_cmd), &cmd); 1489 sizeof(struct iwl3945_powertable_cmd), &cmd);
1719 1490
1720 if (final_mode == IWL_POWER_MODE_CAM) 1491 if (final_mode == IWL_POWER_MODE_CAM)
1721 clear_bit(STATUS_POWER_PMI, &priv->status); 1492 clear_bit(STATUS_POWER_PMI, &priv->status);
@@ -2601,7 +2372,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
2601 spectrum.flags |= RXON_FLG_BAND_24G_MSK | 2372 spectrum.flags |= RXON_FLG_BAND_24G_MSK |
2602 RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK; 2373 RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
2603 2374
2604 rc = iwl3945_send_cmd_sync(priv, &cmd); 2375 rc = iwl_send_cmd_sync(priv, &cmd);
2605 if (rc) 2376 if (rc)
2606 return rc; 2377 return rc;
2607 2378
@@ -3431,7 +3202,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
3431 3202
3432 if (reclaim) { 3203 if (reclaim) {
3433 /* Invoke any callbacks, transfer the skb to caller, and 3204 /* Invoke any callbacks, transfer the skb to caller, and
3434 * fire off the (possibly) blocking iwl3945_send_cmd() 3205 * fire off the (possibly) blocking iwl_send_cmd()
3435 * as we reclaim the driver command queue */ 3206 * as we reclaim the driver command queue */
3436 if (rxb && rxb->skb) 3207 if (rxb && rxb->skb)
3437 iwl3945_tx_cmd_complete(priv, rxb); 3208 iwl3945_tx_cmd_complete(priv, rxb);
@@ -5607,7 +5378,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
5607 scan->len = cpu_to_le16(cmd.len); 5378 scan->len = cpu_to_le16(cmd.len);
5608 5379
5609 set_bit(STATUS_SCAN_HW, &priv->status); 5380 set_bit(STATUS_SCAN_HW, &priv->status);
5610 rc = iwl3945_send_cmd_sync(priv, &cmd); 5381 rc = iwl_send_cmd_sync(priv, &cmd);
5611 if (rc) 5382 if (rc)
5612 goto done; 5383 goto done;
5613 5384
@@ -5699,7 +5470,7 @@ static void iwl3945_post_associate(struct iwl_priv *priv)
5699 5470
5700 memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); 5471 memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
5701 iwl3945_setup_rxon_timing(priv); 5472 iwl3945_setup_rxon_timing(priv);
5702 rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON_TIMING, 5473 rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
5703 sizeof(priv->rxon_timing), &priv->rxon_timing); 5474 sizeof(priv->rxon_timing), &priv->rxon_timing);
5704 if (rc) 5475 if (rc)
5705 IWL_WARN(priv, "REPLY_RXON_TIMING failed - " 5476 IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
@@ -6066,8 +5837,9 @@ static void iwl3945_config_ap(struct iwl_priv *priv)
6066 /* RXON Timing */ 5837 /* RXON Timing */
6067 memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); 5838 memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
6068 iwl3945_setup_rxon_timing(priv); 5839 iwl3945_setup_rxon_timing(priv);
6069 rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON_TIMING, 5840 rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
6070 sizeof(priv->rxon_timing), &priv->rxon_timing); 5841 sizeof(priv->rxon_timing),
5842 &priv->rxon_timing);
6071 if (rc) 5843 if (rc)
6072 IWL_WARN(priv, "REPLY_RXON_TIMING failed - " 5844 IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
6073 "Attempting to continue.\n"); 5845 "Attempting to continue.\n");