diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/iwlwifi/iwl-3945.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-3945.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.c | 330 |
1 files changed, 133 insertions, 197 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index f059b49dc691..0728054a22d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/slab.h> | ||
30 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
31 | #include <linux/dma-mapping.h> | 32 | #include <linux/dma-mapping.h> |
32 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
@@ -45,9 +46,10 @@ | |||
45 | #include "iwl-sta.h" | 46 | #include "iwl-sta.h" |
46 | #include "iwl-3945.h" | 47 | #include "iwl-3945.h" |
47 | #include "iwl-eeprom.h" | 48 | #include "iwl-eeprom.h" |
48 | #include "iwl-helpers.h" | ||
49 | #include "iwl-core.h" | 49 | #include "iwl-core.h" |
50 | #include "iwl-agn-rs.h" | 50 | #include "iwl-helpers.h" |
51 | #include "iwl-led.h" | ||
52 | #include "iwl-3945-led.h" | ||
51 | 53 | ||
52 | #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ | 54 | #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ |
53 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ | 55 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ |
@@ -183,7 +185,7 @@ static int iwl3945_hwrate_to_plcp_idx(u8 plcp) | |||
183 | { | 185 | { |
184 | int idx; | 186 | int idx; |
185 | 187 | ||
186 | for (idx = 0; idx < IWL_RATE_COUNT; idx++) | 188 | for (idx = 0; idx < IWL_RATE_COUNT_3945; idx++) |
187 | if (iwl3945_rates[idx].plcp == plcp) | 189 | if (iwl3945_rates[idx].plcp == plcp) |
188 | return idx; | 190 | return idx; |
189 | return -1; | 191 | return -1; |
@@ -293,7 +295,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, | |||
293 | static void iwl3945_rx_reply_tx(struct iwl_priv *priv, | 295 | static void iwl3945_rx_reply_tx(struct iwl_priv *priv, |
294 | struct iwl_rx_mem_buffer *rxb) | 296 | struct iwl_rx_mem_buffer *rxb) |
295 | { | 297 | { |
296 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 298 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
297 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 299 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
298 | int txq_id = SEQ_TO_QUEUE(sequence); | 300 | int txq_id = SEQ_TO_QUEUE(sequence); |
299 | int index = SEQ_TO_INDEX(sequence); | 301 | int index = SEQ_TO_INDEX(sequence); |
@@ -353,16 +355,12 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, | |||
353 | void iwl3945_hw_rx_statistics(struct iwl_priv *priv, | 355 | void iwl3945_hw_rx_statistics(struct iwl_priv *priv, |
354 | struct iwl_rx_mem_buffer *rxb) | 356 | struct iwl_rx_mem_buffer *rxb) |
355 | { | 357 | { |
356 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 358 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
357 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | 359 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", |
358 | (int)sizeof(struct iwl3945_notif_statistics), | 360 | (int)sizeof(struct iwl3945_notif_statistics), |
359 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | 361 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); |
360 | 362 | ||
361 | memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39)); | 363 | memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39)); |
362 | |||
363 | iwl3945_led_background(priv); | ||
364 | |||
365 | priv->last_statistics_time = jiffies; | ||
366 | } | 364 | } |
367 | 365 | ||
368 | /****************************************************************************** | 366 | /****************************************************************************** |
@@ -545,14 +543,18 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
545 | struct iwl_rx_mem_buffer *rxb, | 543 | struct iwl_rx_mem_buffer *rxb, |
546 | struct ieee80211_rx_status *stats) | 544 | struct ieee80211_rx_status *stats) |
547 | { | 545 | { |
548 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 546 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
549 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); | 547 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); |
550 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | 548 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); |
551 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | 549 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); |
552 | short len = le16_to_cpu(rx_hdr->len); | 550 | u16 len = le16_to_cpu(rx_hdr->len); |
551 | struct sk_buff *skb; | ||
552 | int ret; | ||
553 | __le16 fc = hdr->frame_control; | ||
553 | 554 | ||
554 | /* We received data from the HW, so stop the watchdog */ | 555 | /* We received data from the HW, so stop the watchdog */ |
555 | if (unlikely((len + IWL39_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { | 556 | if (unlikely(len + IWL39_RX_FRAME_SIZE > |
557 | PAGE_SIZE << priv->hw_params.rx_page_order)) { | ||
556 | IWL_DEBUG_DROP(priv, "Corruption detected!\n"); | 558 | IWL_DEBUG_DROP(priv, "Corruption detected!\n"); |
557 | return; | 559 | return; |
558 | } | 560 | } |
@@ -564,24 +566,50 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
564 | return; | 566 | return; |
565 | } | 567 | } |
566 | 568 | ||
567 | skb_reserve(rxb->skb, (void *)rx_hdr->payload - (void *)pkt); | 569 | skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC); |
568 | /* Set the size of the skb to the size of the frame */ | 570 | if (!skb) { |
569 | skb_put(rxb->skb, le16_to_cpu(rx_hdr->len)); | 571 | IWL_ERR(priv, "alloc_skb failed\n"); |
572 | return; | ||
573 | } | ||
570 | 574 | ||
571 | if (!iwl3945_mod_params.sw_crypto) | 575 | if (!iwl3945_mod_params.sw_crypto) |
572 | iwl_set_decrypted_flag(priv, | 576 | iwl_set_decrypted_flag(priv, |
573 | (struct ieee80211_hdr *)rxb->skb->data, | 577 | (struct ieee80211_hdr *)rxb_addr(rxb), |
574 | le32_to_cpu(rx_end->status), stats); | 578 | le32_to_cpu(rx_end->status), stats); |
575 | 579 | ||
576 | #ifdef CONFIG_IWLWIFI_LEDS | 580 | skb_reserve(skb, IWL_LINK_HDR_MAX); |
577 | if (ieee80211_is_data(hdr->frame_control)) | 581 | skb_add_rx_frag(skb, 0, rxb->page, |
578 | priv->rxtxpackets += len; | 582 | (void *)rx_hdr->payload - (void *)pkt, len); |
579 | #endif | 583 | |
580 | iwl_update_stats(priv, false, hdr->frame_control, len); | 584 | /* mac80211 currently doesn't support paged SKB. Convert it to |
585 | * linear SKB for management frame and data frame requires | ||
586 | * software decryption or software defragementation. */ | ||
587 | if (ieee80211_is_mgmt(fc) || | ||
588 | ieee80211_has_protected(fc) || | ||
589 | ieee80211_has_morefrags(fc) || | ||
590 | le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) | ||
591 | ret = skb_linearize(skb); | ||
592 | else | ||
593 | ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ? | ||
594 | 0 : -ENOMEM; | ||
595 | |||
596 | if (ret) { | ||
597 | kfree_skb(skb); | ||
598 | goto out; | ||
599 | } | ||
600 | |||
601 | /* | ||
602 | * XXX: We cannot touch the page and its virtual memory (pkt) after | ||
603 | * here. It might have already been freed by the above skb change. | ||
604 | */ | ||
605 | |||
606 | iwl_update_stats(priv, false, fc, len); | ||
607 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | ||
581 | 608 | ||
582 | memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); | 609 | ieee80211_rx(priv->hw, skb); |
583 | ieee80211_rx_irqsafe(priv->hw, rxb->skb); | 610 | out: |
584 | rxb->skb = NULL; | 611 | priv->alloc_rxb_page--; |
612 | rxb->page = NULL; | ||
585 | } | 613 | } |
586 | 614 | ||
587 | #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) | 615 | #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) |
@@ -591,7 +619,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
591 | { | 619 | { |
592 | struct ieee80211_hdr *header; | 620 | struct ieee80211_hdr *header; |
593 | struct ieee80211_rx_status rx_status; | 621 | struct ieee80211_rx_status rx_status; |
594 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 622 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
595 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | 623 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); |
596 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | 624 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); |
597 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | 625 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); |
@@ -654,19 +682,13 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
654 | snr = rx_stats_sig_avg / rx_stats_noise_diff; | 682 | snr = rx_stats_sig_avg / rx_stats_noise_diff; |
655 | rx_status.noise = rx_status.signal - | 683 | rx_status.noise = rx_status.signal - |
656 | iwl3945_calc_db_from_ratio(snr); | 684 | iwl3945_calc_db_from_ratio(snr); |
657 | rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, | ||
658 | rx_status.noise); | ||
659 | |||
660 | /* If noise info not available, calculate signal quality indicator (%) | ||
661 | * using just the dBm signal level. */ | ||
662 | } else { | 685 | } else { |
663 | rx_status.noise = priv->last_rx_noise; | 686 | rx_status.noise = priv->last_rx_noise; |
664 | rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, 0); | ||
665 | } | 687 | } |
666 | 688 | ||
667 | 689 | ||
668 | IWL_DEBUG_STATS(priv, "Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n", | 690 | IWL_DEBUG_STATS(priv, "Rssi %d noise %d sig_avg %d noise_diff %d\n", |
669 | rx_status.signal, rx_status.noise, rx_status.qual, | 691 | rx_status.signal, rx_status.noise, |
670 | rx_stats_sig_avg, rx_stats_noise_diff); | 692 | rx_stats_sig_avg, rx_stats_noise_diff); |
671 | 693 | ||
672 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); | 694 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); |
@@ -784,36 +806,38 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, | |||
784 | int sta_id, int tx_id) | 806 | int sta_id, int tx_id) |
785 | { | 807 | { |
786 | u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value; | 808 | u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value; |
787 | u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT - 1); | 809 | u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT_3945); |
788 | u16 rate_mask; | 810 | u16 rate_mask; |
789 | int rate; | 811 | int rate; |
790 | u8 rts_retry_limit; | 812 | u8 rts_retry_limit; |
791 | u8 data_retry_limit; | 813 | u8 data_retry_limit; |
792 | __le32 tx_flags; | 814 | __le32 tx_flags; |
793 | __le16 fc = hdr->frame_control; | 815 | __le16 fc = hdr->frame_control; |
794 | struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; | 816 | struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload; |
795 | 817 | ||
796 | rate = iwl3945_rates[rate_index].plcp; | 818 | rate = iwl3945_rates[rate_index].plcp; |
797 | tx_flags = tx->tx_flags; | 819 | tx_flags = tx_cmd->tx_flags; |
798 | 820 | ||
799 | /* We need to figure out how to get the sta->supp_rates while | 821 | /* We need to figure out how to get the sta->supp_rates while |
800 | * in this running context */ | 822 | * in this running context */ |
801 | rate_mask = IWL_RATES_MASK; | 823 | rate_mask = IWL_RATES_MASK; |
802 | 824 | ||
825 | |||
826 | /* Set retry limit on DATA packets and Probe Responses*/ | ||
827 | if (ieee80211_is_probe_resp(fc)) | ||
828 | data_retry_limit = 3; | ||
829 | else | ||
830 | data_retry_limit = IWL_DEFAULT_TX_RETRY; | ||
831 | tx_cmd->data_retry_limit = data_retry_limit; | ||
832 | |||
803 | if (tx_id >= IWL_CMD_QUEUE_NUM) | 833 | if (tx_id >= IWL_CMD_QUEUE_NUM) |
804 | rts_retry_limit = 3; | 834 | rts_retry_limit = 3; |
805 | else | 835 | else |
806 | rts_retry_limit = 7; | 836 | rts_retry_limit = 7; |
807 | 837 | ||
808 | if (ieee80211_is_probe_resp(fc)) { | 838 | if (data_retry_limit < rts_retry_limit) |
809 | data_retry_limit = 3; | 839 | rts_retry_limit = data_retry_limit; |
810 | if (data_retry_limit < rts_retry_limit) | 840 | tx_cmd->rts_retry_limit = rts_retry_limit; |
811 | rts_retry_limit = data_retry_limit; | ||
812 | } else | ||
813 | data_retry_limit = IWL_DEFAULT_TX_RETRY; | ||
814 | |||
815 | if (priv->data_retry_limit != -1) | ||
816 | data_retry_limit = priv->data_retry_limit; | ||
817 | 841 | ||
818 | if (ieee80211_is_mgmt(fc)) { | 842 | if (ieee80211_is_mgmt(fc)) { |
819 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { | 843 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { |
@@ -831,22 +855,20 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, | |||
831 | } | 855 | } |
832 | } | 856 | } |
833 | 857 | ||
834 | tx->rts_retry_limit = rts_retry_limit; | 858 | tx_cmd->rate = rate; |
835 | tx->data_retry_limit = data_retry_limit; | 859 | tx_cmd->tx_flags = tx_flags; |
836 | tx->rate = rate; | ||
837 | tx->tx_flags = tx_flags; | ||
838 | 860 | ||
839 | /* OFDM */ | 861 | /* OFDM */ |
840 | tx->supp_rates[0] = | 862 | tx_cmd->supp_rates[0] = |
841 | ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF; | 863 | ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF; |
842 | 864 | ||
843 | /* CCK */ | 865 | /* CCK */ |
844 | tx->supp_rates[1] = (rate_mask & 0xF); | 866 | tx_cmd->supp_rates[1] = (rate_mask & 0xF); |
845 | 867 | ||
846 | IWL_DEBUG_RATE(priv, "Tx sta id: %d, rate: %d (plcp), flags: 0x%4X " | 868 | IWL_DEBUG_RATE(priv, "Tx sta id: %d, rate: %d (plcp), flags: 0x%4X " |
847 | "cck/ofdm mask: 0x%x/0x%x\n", sta_id, | 869 | "cck/ofdm mask: 0x%x/0x%x\n", sta_id, |
848 | tx->rate, le32_to_cpu(tx->tx_flags), | 870 | tx_cmd->rate, le32_to_cpu(tx_cmd->tx_flags), |
849 | tx->supp_rates[1], tx->supp_rates[0]); | 871 | tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]); |
850 | } | 872 | } |
851 | 873 | ||
852 | u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) | 874 | u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) |
@@ -962,6 +984,11 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) | |||
962 | 984 | ||
963 | iwl3945_hw_txq_ctx_free(priv); | 985 | iwl3945_hw_txq_ctx_free(priv); |
964 | 986 | ||
987 | /* allocate tx queue structure */ | ||
988 | rc = iwl_alloc_txq_mem(priv); | ||
989 | if (rc) | ||
990 | return rc; | ||
991 | |||
965 | /* Tx CMD queue */ | 992 | /* Tx CMD queue */ |
966 | rc = iwl3945_tx_reset(priv); | 993 | rc = iwl3945_tx_reset(priv); |
967 | if (rc) | 994 | if (rc) |
@@ -986,41 +1013,25 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) | |||
986 | return rc; | 1013 | return rc; |
987 | } | 1014 | } |
988 | 1015 | ||
1016 | |||
1017 | /* | ||
1018 | * Start up 3945's basic functionality after it has been reset | ||
1019 | * (e.g. after platform boot, or shutdown via iwl_apm_stop()) | ||
1020 | * NOTE: This does not load uCode nor start the embedded processor | ||
1021 | */ | ||
989 | static int iwl3945_apm_init(struct iwl_priv *priv) | 1022 | static int iwl3945_apm_init(struct iwl_priv *priv) |
990 | { | 1023 | { |
991 | int ret; | 1024 | int ret = iwl_apm_init(priv); |
992 | |||
993 | iwl_power_initialize(priv); | ||
994 | |||
995 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
996 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | ||
997 | 1025 | ||
998 | /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */ | 1026 | /* Clear APMG (NIC's internal power management) interrupts */ |
999 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | 1027 | iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0); |
1000 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); | 1028 | iwl_write_prph(priv, APMG_RTC_INT_STT_REG, 0xFFFFFFFF); |
1001 | |||
1002 | /* set "initialization complete" bit to move adapter | ||
1003 | * D0U* --> D0A* state */ | ||
1004 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
1005 | |||
1006 | ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | ||
1007 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
1008 | if (ret < 0) { | ||
1009 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | ||
1010 | goto out; | ||
1011 | } | ||
1012 | |||
1013 | /* enable DMA */ | ||
1014 | iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT | | ||
1015 | APMG_CLK_VAL_BSM_CLK_RQT); | ||
1016 | |||
1017 | udelay(20); | ||
1018 | 1029 | ||
1019 | /* disable L1-Active */ | 1030 | /* Reset radio chip */ |
1020 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | 1031 | iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); |
1021 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | 1032 | udelay(5); |
1033 | iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); | ||
1022 | 1034 | ||
1023 | out: | ||
1024 | return ret; | 1035 | return ret; |
1025 | } | 1036 | } |
1026 | 1037 | ||
@@ -1145,12 +1156,16 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv) | |||
1145 | int txq_id; | 1156 | int txq_id; |
1146 | 1157 | ||
1147 | /* Tx queues */ | 1158 | /* Tx queues */ |
1148 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | 1159 | if (priv->txq) |
1149 | if (txq_id == IWL_CMD_QUEUE_NUM) | 1160 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; |
1150 | iwl_cmd_queue_free(priv); | 1161 | txq_id++) |
1151 | else | 1162 | if (txq_id == IWL_CMD_QUEUE_NUM) |
1152 | iwl_tx_queue_free(priv, txq_id); | 1163 | iwl_cmd_queue_free(priv); |
1164 | else | ||
1165 | iwl_tx_queue_free(priv, txq_id); | ||
1153 | 1166 | ||
1167 | /* free tx queue structure */ | ||
1168 | iwl_free_txq_mem(priv); | ||
1154 | } | 1169 | } |
1155 | 1170 | ||
1156 | void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) | 1171 | void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) |
@@ -1159,6 +1174,7 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) | |||
1159 | 1174 | ||
1160 | /* stop SCD */ | 1175 | /* stop SCD */ |
1161 | iwl_write_prph(priv, ALM_SCD_MODE_REG, 0); | 1176 | iwl_write_prph(priv, ALM_SCD_MODE_REG, 0); |
1177 | iwl_write_prph(priv, ALM_SCD_TXFACT_REG, 0); | ||
1162 | 1178 | ||
1163 | /* reset TFD queues */ | 1179 | /* reset TFD queues */ |
1164 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | 1180 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { |
@@ -1171,85 +1187,6 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) | |||
1171 | iwl3945_hw_txq_ctx_free(priv); | 1187 | iwl3945_hw_txq_ctx_free(priv); |
1172 | } | 1188 | } |
1173 | 1189 | ||
1174 | static int iwl3945_apm_stop_master(struct iwl_priv *priv) | ||
1175 | { | ||
1176 | int ret = 0; | ||
1177 | unsigned long flags; | ||
1178 | |||
1179 | spin_lock_irqsave(&priv->lock, flags); | ||
1180 | |||
1181 | /* set stop master bit */ | ||
1182 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | ||
1183 | |||
1184 | iwl_poll_direct_bit(priv, CSR_RESET, | ||
1185 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | ||
1186 | |||
1187 | if (ret < 0) | ||
1188 | goto out; | ||
1189 | |||
1190 | out: | ||
1191 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1192 | IWL_DEBUG_INFO(priv, "stop master\n"); | ||
1193 | |||
1194 | return ret; | ||
1195 | } | ||
1196 | |||
1197 | static void iwl3945_apm_stop(struct iwl_priv *priv) | ||
1198 | { | ||
1199 | unsigned long flags; | ||
1200 | |||
1201 | iwl3945_apm_stop_master(priv); | ||
1202 | |||
1203 | spin_lock_irqsave(&priv->lock, flags); | ||
1204 | |||
1205 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
1206 | |||
1207 | udelay(10); | ||
1208 | /* clear "init complete" move adapter D0A* --> D0U state */ | ||
1209 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
1210 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1211 | } | ||
1212 | |||
1213 | static int iwl3945_apm_reset(struct iwl_priv *priv) | ||
1214 | { | ||
1215 | iwl3945_apm_stop_master(priv); | ||
1216 | |||
1217 | |||
1218 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
1219 | udelay(10); | ||
1220 | |||
1221 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
1222 | |||
1223 | iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | ||
1224 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
1225 | |||
1226 | iwl_write_prph(priv, APMG_CLK_CTRL_REG, | ||
1227 | APMG_CLK_VAL_BSM_CLK_RQT); | ||
1228 | |||
1229 | iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0); | ||
1230 | iwl_write_prph(priv, APMG_RTC_INT_STT_REG, | ||
1231 | 0xFFFFFFFF); | ||
1232 | |||
1233 | /* enable DMA */ | ||
1234 | iwl_write_prph(priv, APMG_CLK_EN_REG, | ||
1235 | APMG_CLK_VAL_DMA_CLK_RQT | | ||
1236 | APMG_CLK_VAL_BSM_CLK_RQT); | ||
1237 | udelay(10); | ||
1238 | |||
1239 | iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, | ||
1240 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
1241 | udelay(5); | ||
1242 | iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, | ||
1243 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
1244 | |||
1245 | /* Clear the 'host command active' bit... */ | ||
1246 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | ||
1247 | |||
1248 | wake_up_interruptible(&priv->wait_command_queue); | ||
1249 | |||
1250 | return 0; | ||
1251 | } | ||
1252 | |||
1253 | /** | 1190 | /** |
1254 | * iwl3945_hw_reg_adjust_power_by_temp | 1191 | * iwl3945_hw_reg_adjust_power_by_temp |
1255 | * return index delta into power gain settings table | 1192 | * return index delta into power gain settings table |
@@ -1858,7 +1795,7 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power) | |||
1858 | static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) | 1795 | static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) |
1859 | { | 1796 | { |
1860 | int rc = 0; | 1797 | int rc = 0; |
1861 | struct iwl_rx_packet *res = NULL; | 1798 | struct iwl_rx_packet *pkt; |
1862 | struct iwl3945_rxon_assoc_cmd rxon_assoc; | 1799 | struct iwl3945_rxon_assoc_cmd rxon_assoc; |
1863 | struct iwl_host_cmd cmd = { | 1800 | struct iwl_host_cmd cmd = { |
1864 | .id = REPLY_RXON_ASSOC, | 1801 | .id = REPLY_RXON_ASSOC, |
@@ -1887,14 +1824,13 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) | |||
1887 | if (rc) | 1824 | if (rc) |
1888 | return rc; | 1825 | return rc; |
1889 | 1826 | ||
1890 | res = (struct iwl_rx_packet *)cmd.reply_skb->data; | 1827 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
1891 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | 1828 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
1892 | IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n"); | 1829 | IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n"); |
1893 | rc = -EIO; | 1830 | rc = -EIO; |
1894 | } | 1831 | } |
1895 | 1832 | ||
1896 | priv->alloc_rxb_skb--; | 1833 | iwl_free_pages(priv, cmd.reply_page); |
1897 | dev_kfree_skb_any(cmd.reply_skb); | ||
1898 | 1834 | ||
1899 | return rc; | 1835 | return rc; |
1900 | } | 1836 | } |
@@ -2016,11 +1952,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
2016 | } | 1952 | } |
2017 | 1953 | ||
2018 | /* Add the broadcast address so we can send broadcast frames */ | 1954 | /* Add the broadcast address so we can send broadcast frames */ |
2019 | if (iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL) == | 1955 | priv->cfg->ops->lib->add_bcast_station(priv); |
2020 | IWL_INVALID_STATION) { | ||
2021 | IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n"); | ||
2022 | return -EIO; | ||
2023 | } | ||
2024 | 1956 | ||
2025 | /* If we have set the ASSOC_MSK and we are in BSS mode then | 1957 | /* If we have set the ASSOC_MSK and we are in BSS mode then |
2026 | * add the IWL_AP_ID to the station rate table */ | 1958 | * add the IWL_AP_ID to the station rate table */ |
@@ -2042,12 +1974,6 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
2042 | return 0; | 1974 | return 0; |
2043 | } | 1975 | } |
2044 | 1976 | ||
2045 | /* will add 3945 channel switch cmd handling later */ | ||
2046 | int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel) | ||
2047 | { | ||
2048 | return 0; | ||
2049 | } | ||
2050 | |||
2051 | /** | 1977 | /** |
2052 | * iwl3945_reg_txpower_periodic - called when time to check our temperature. | 1978 | * iwl3945_reg_txpower_periodic - called when time to check our temperature. |
2053 | * | 1979 | * |
@@ -2221,7 +2147,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv) | |||
2221 | 2147 | ||
2222 | /* fill in channel group's nominal powers for each rate */ | 2148 | /* fill in channel group's nominal powers for each rate */ |
2223 | for (rate_index = 0; | 2149 | for (rate_index = 0; |
2224 | rate_index < IWL_RATE_COUNT; rate_index++, clip_pwrs++) { | 2150 | rate_index < IWL_RATE_COUNT_3945; rate_index++, clip_pwrs++) { |
2225 | switch (rate_index) { | 2151 | switch (rate_index) { |
2226 | case IWL_RATE_36M_INDEX_TABLE: | 2152 | case IWL_RATE_36M_INDEX_TABLE: |
2227 | if (i == 0) /* B/G */ | 2153 | if (i == 0) /* B/G */ |
@@ -2545,11 +2471,9 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) | |||
2545 | memset((void *)&priv->hw_params, 0, | 2471 | memset((void *)&priv->hw_params, 0, |
2546 | sizeof(struct iwl_hw_params)); | 2472 | sizeof(struct iwl_hw_params)); |
2547 | 2473 | ||
2548 | priv->shared_virt = | 2474 | priv->shared_virt = dma_alloc_coherent(&priv->pci_dev->dev, |
2549 | pci_alloc_consistent(priv->pci_dev, | 2475 | sizeof(struct iwl3945_shared), |
2550 | sizeof(struct iwl3945_shared), | 2476 | &priv->shared_phys, GFP_KERNEL); |
2551 | &priv->shared_phys); | ||
2552 | |||
2553 | if (!priv->shared_virt) { | 2477 | if (!priv->shared_virt) { |
2554 | IWL_ERR(priv, "failed to allocate pci memory\n"); | 2478 | IWL_ERR(priv, "failed to allocate pci memory\n"); |
2555 | mutex_unlock(&priv->mutex); | 2479 | mutex_unlock(&priv->mutex); |
@@ -2557,11 +2481,10 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) | |||
2557 | } | 2481 | } |
2558 | 2482 | ||
2559 | /* Assign number of Usable TX queues */ | 2483 | /* Assign number of Usable TX queues */ |
2560 | priv->hw_params.max_txq_num = IWL39_NUM_QUEUES; | 2484 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; |
2561 | 2485 | ||
2562 | priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); | 2486 | priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); |
2563 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K; | 2487 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K); |
2564 | priv->hw_params.max_pkt_size = 2342; | ||
2565 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; | 2488 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; |
2566 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | 2489 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; |
2567 | priv->hw_params.max_stations = IWL3945_STATION_COUNT; | 2490 | priv->hw_params.max_stations = IWL3945_STATION_COUNT; |
@@ -2844,8 +2767,7 @@ static struct iwl_lib_ops iwl3945_lib = { | |||
2844 | .dump_nic_error_log = iwl3945_dump_nic_error_log, | 2767 | .dump_nic_error_log = iwl3945_dump_nic_error_log, |
2845 | .apm_ops = { | 2768 | .apm_ops = { |
2846 | .init = iwl3945_apm_init, | 2769 | .init = iwl3945_apm_init, |
2847 | .reset = iwl3945_apm_reset, | 2770 | .stop = iwl_apm_stop, |
2848 | .stop = iwl3945_apm_stop, | ||
2849 | .config = iwl3945_nic_config, | 2771 | .config = iwl3945_nic_config, |
2850 | .set_pwr_src = iwl3945_set_pwr_src, | 2772 | .set_pwr_src = iwl3945_set_pwr_src, |
2851 | }, | 2773 | }, |
@@ -2869,18 +2791,21 @@ static struct iwl_lib_ops iwl3945_lib = { | |||
2869 | .post_associate = iwl3945_post_associate, | 2791 | .post_associate = iwl3945_post_associate, |
2870 | .isr = iwl_isr_legacy, | 2792 | .isr = iwl_isr_legacy, |
2871 | .config_ap = iwl3945_config_ap, | 2793 | .config_ap = iwl3945_config_ap, |
2794 | .add_bcast_station = iwl3945_add_bcast_station, | ||
2872 | }; | 2795 | }; |
2873 | 2796 | ||
2874 | static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { | 2797 | static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { |
2875 | .get_hcmd_size = iwl3945_get_hcmd_size, | 2798 | .get_hcmd_size = iwl3945_get_hcmd_size, |
2876 | .build_addsta_hcmd = iwl3945_build_addsta_hcmd, | 2799 | .build_addsta_hcmd = iwl3945_build_addsta_hcmd, |
2800 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, | ||
2877 | }; | 2801 | }; |
2878 | 2802 | ||
2879 | static struct iwl_ops iwl3945_ops = { | 2803 | static const struct iwl_ops iwl3945_ops = { |
2880 | .ucode = &iwl3945_ucode, | 2804 | .ucode = &iwl3945_ucode, |
2881 | .lib = &iwl3945_lib, | 2805 | .lib = &iwl3945_lib, |
2882 | .hcmd = &iwl3945_hcmd, | 2806 | .hcmd = &iwl3945_hcmd, |
2883 | .utils = &iwl3945_hcmd_utils, | 2807 | .utils = &iwl3945_hcmd_utils, |
2808 | .led = &iwl3945_led_ops, | ||
2884 | }; | 2809 | }; |
2885 | 2810 | ||
2886 | static struct iwl_cfg iwl3945_bg_cfg = { | 2811 | static struct iwl_cfg iwl3945_bg_cfg = { |
@@ -2892,9 +2817,16 @@ static struct iwl_cfg iwl3945_bg_cfg = { | |||
2892 | .eeprom_size = IWL3945_EEPROM_IMG_SIZE, | 2817 | .eeprom_size = IWL3945_EEPROM_IMG_SIZE, |
2893 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, | 2818 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, |
2894 | .ops = &iwl3945_ops, | 2819 | .ops = &iwl3945_ops, |
2820 | .num_of_queues = IWL39_NUM_QUEUES, | ||
2895 | .mod_params = &iwl3945_mod_params, | 2821 | .mod_params = &iwl3945_mod_params, |
2822 | .pll_cfg_val = CSR39_ANA_PLL_CFG_VAL, | ||
2823 | .set_l0s = false, | ||
2824 | .use_bsm = true, | ||
2896 | .use_isr_legacy = true, | 2825 | .use_isr_legacy = true, |
2897 | .ht_greenfield_support = false, | 2826 | .ht_greenfield_support = false, |
2827 | .led_compensation = 64, | ||
2828 | .broken_powersave = true, | ||
2829 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
2898 | }; | 2830 | }; |
2899 | 2831 | ||
2900 | static struct iwl_cfg iwl3945_abg_cfg = { | 2832 | static struct iwl_cfg iwl3945_abg_cfg = { |
@@ -2906,12 +2838,16 @@ static struct iwl_cfg iwl3945_abg_cfg = { | |||
2906 | .eeprom_size = IWL3945_EEPROM_IMG_SIZE, | 2838 | .eeprom_size = IWL3945_EEPROM_IMG_SIZE, |
2907 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, | 2839 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, |
2908 | .ops = &iwl3945_ops, | 2840 | .ops = &iwl3945_ops, |
2841 | .num_of_queues = IWL39_NUM_QUEUES, | ||
2909 | .mod_params = &iwl3945_mod_params, | 2842 | .mod_params = &iwl3945_mod_params, |
2910 | .use_isr_legacy = true, | 2843 | .use_isr_legacy = true, |
2911 | .ht_greenfield_support = false, | 2844 | .ht_greenfield_support = false, |
2845 | .led_compensation = 64, | ||
2846 | .broken_powersave = true, | ||
2847 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
2912 | }; | 2848 | }; |
2913 | 2849 | ||
2914 | struct pci_device_id iwl3945_hw_card_ids[] = { | 2850 | DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { |
2915 | {IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)}, | 2851 | {IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)}, |
2916 | {IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)}, | 2852 | {IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)}, |
2917 | {IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)}, | 2853 | {IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)}, |