diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
28 files changed, 58 insertions, 14045 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index e1e3b1cf3cf..17d555f2215 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -1,18 +1,52 @@ | |||
1 | config IWLWIFI | 1 | config IWLAGN |
2 | tristate "Intel Wireless Wifi" | 2 | tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlagn) " |
3 | depends on PCI && MAC80211 | 3 | depends on PCI && MAC80211 |
4 | select FW_LOADER | 4 | select FW_LOADER |
5 | select NEW_LEDS | 5 | select NEW_LEDS |
6 | select LEDS_CLASS | 6 | select LEDS_CLASS |
7 | select LEDS_TRIGGERS | 7 | select LEDS_TRIGGERS |
8 | select MAC80211_LEDS | 8 | select MAC80211_LEDS |
9 | ---help--- | ||
10 | Select to build the driver supporting the: | ||
11 | |||
12 | Intel Wireless WiFi Link Next-Gen AGN | ||
13 | |||
14 | This option enables support for use with the following hardware: | ||
15 | Intel Wireless WiFi Link 6250AGN Adapter | ||
16 | Intel 6000 Series Wi-Fi Adapters (6200AGN and 6300AGN) | ||
17 | Intel WiFi Link 1000BGN | ||
18 | Intel Wireless WiFi 5150AGN | ||
19 | Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN | ||
20 | Intel 6005 Series Wi-Fi Adapters | ||
21 | Intel 6030 Series Wi-Fi Adapters | ||
22 | Intel Wireless WiFi Link 6150BGN 2 Adapter | ||
23 | Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN) | ||
24 | Intel 2000 Series Wi-Fi Adapters | ||
25 | |||
26 | |||
27 | This driver uses the kernel's mac80211 subsystem. | ||
28 | |||
29 | In order to use this driver, you will need a microcode (uCode) | ||
30 | image for it. You can obtain the microcode from: | ||
31 | |||
32 | <http://intellinuxwireless.org/>. | ||
33 | |||
34 | The microcode is typically installed in /lib/firmware. You can | ||
35 | look in the hotplug script /etc/hotplug/firmware.agent to | ||
36 | determine which directory FIRMWARE_DIR is set to when the script | ||
37 | runs. | ||
38 | |||
39 | If you want to compile the driver as a module ( = code which can be | ||
40 | inserted in and removed from the running kernel whenever you want), | ||
41 | say M here and read <file:Documentation/kbuild/modules.txt>. The | ||
42 | module will be called iwlagn. | ||
9 | 43 | ||
10 | menu "Debugging Options" | 44 | menu "Debugging Options" |
11 | depends on IWLWIFI | 45 | depends on IWLAGN |
12 | 46 | ||
13 | config IWLWIFI_DEBUG | 47 | config IWLWIFI_DEBUG |
14 | bool "Enable full debugging output in iwlagn and iwl3945 drivers" | 48 | bool "Enable full debugging output in the iwlagn driver" |
15 | depends on IWLWIFI | 49 | depends on IWLAGN |
16 | ---help--- | 50 | ---help--- |
17 | This option will enable debug tracing output for the iwlwifi drivers | 51 | This option will enable debug tracing output for the iwlwifi drivers |
18 | 52 | ||
@@ -37,7 +71,7 @@ config IWLWIFI_DEBUG | |||
37 | 71 | ||
38 | config IWLWIFI_DEBUGFS | 72 | config IWLWIFI_DEBUGFS |
39 | bool "iwlagn debugfs support" | 73 | bool "iwlagn debugfs support" |
40 | depends on IWLWIFI && MAC80211_DEBUGFS | 74 | depends on IWLAGN && MAC80211_DEBUGFS |
41 | ---help--- | 75 | ---help--- |
42 | Enable creation of debugfs files for the iwlwifi drivers. This | 76 | Enable creation of debugfs files for the iwlwifi drivers. This |
43 | is a low-impact option that allows getting insight into the | 77 | is a low-impact option that allows getting insight into the |
@@ -45,13 +79,13 @@ config IWLWIFI_DEBUGFS | |||
45 | 79 | ||
46 | config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE | 80 | config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE |
47 | bool "Experimental uCode support" | 81 | bool "Experimental uCode support" |
48 | depends on IWLWIFI && IWLWIFI_DEBUG | 82 | depends on IWLAGN && IWLWIFI_DEBUG |
49 | ---help--- | 83 | ---help--- |
50 | Enable use of experimental ucode for testing and debugging. | 84 | Enable use of experimental ucode for testing and debugging. |
51 | 85 | ||
52 | config IWLWIFI_DEVICE_TRACING | 86 | config IWLWIFI_DEVICE_TRACING |
53 | bool "iwlwifi device access tracing" | 87 | bool "iwlwifi device access tracing" |
54 | depends on IWLWIFI | 88 | depends on IWLAGN |
55 | depends on EVENT_TRACING | 89 | depends on EVENT_TRACING |
56 | help | 90 | help |
57 | Say Y here to trace all commands, including TX frames and IO | 91 | Say Y here to trace all commands, including TX frames and IO |
@@ -68,57 +102,9 @@ config IWLWIFI_DEVICE_TRACING | |||
68 | occur. | 102 | occur. |
69 | endmenu | 103 | endmenu |
70 | 104 | ||
71 | config IWLAGN | ||
72 | tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)" | ||
73 | depends on IWLWIFI | ||
74 | ---help--- | ||
75 | Select to build the driver supporting the: | ||
76 | |||
77 | Intel Wireless WiFi Link Next-Gen AGN | ||
78 | |||
79 | This driver uses the kernel's mac80211 subsystem. | ||
80 | |||
81 | In order to use this driver, you will need a microcode (uCode) | ||
82 | image for it. You can obtain the microcode from: | ||
83 | |||
84 | <http://intellinuxwireless.org/>. | ||
85 | |||
86 | The microcode is typically installed in /lib/firmware. You can | ||
87 | look in the hotplug script /etc/hotplug/firmware.agent to | ||
88 | determine which directory FIRMWARE_DIR is set to when the script | ||
89 | runs. | ||
90 | |||
91 | If you want to compile the driver as a module ( = code which can be | ||
92 | inserted in and removed from the running kernel whenever you want), | ||
93 | say M here and read <file:Documentation/kbuild/modules.txt>. The | ||
94 | module will be called iwlagn. | ||
95 | |||
96 | |||
97 | config IWL4965 | ||
98 | bool "Intel Wireless WiFi 4965AGN" | ||
99 | depends on IWLAGN | ||
100 | ---help--- | ||
101 | This option enables support for Intel Wireless WiFi Link 4965AGN | ||
102 | |||
103 | config IWL5000 | ||
104 | bool "Intel Wireless-N/Advanced-N/Ultimate-N WiFi Link" | ||
105 | depends on IWLAGN | ||
106 | ---help--- | ||
107 | This option enables support for use with the following hardware: | ||
108 | Intel Wireless WiFi Link 6250AGN Adapter | ||
109 | Intel 6000 Series Wi-Fi Adapters (6200AGN and 6300AGN) | ||
110 | Intel WiFi Link 1000BGN | ||
111 | Intel Wireless WiFi 5150AGN | ||
112 | Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN | ||
113 | Intel 6005 Series Wi-Fi Adapters | ||
114 | Intel 6030 Series Wi-Fi Adapters | ||
115 | Intel Wireless WiFi Link 6150BGN 2 Adapter | ||
116 | Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN) | ||
117 | Intel 2000 Series Wi-Fi Adapters | ||
118 | |||
119 | config IWL_P2P | 105 | config IWL_P2P |
120 | bool "iwlwifi experimental P2P support" | 106 | bool "iwlwifi experimental P2P support" |
121 | depends on IWL5000 | 107 | depends on IWLAGN |
122 | help | 108 | help |
123 | This option enables experimental P2P support for some devices | 109 | This option enables experimental P2P support for some devices |
124 | based on microcode support. Since P2P support is still under | 110 | based on microcode support. Since P2P support is still under |
@@ -132,27 +118,3 @@ config IWL_P2P | |||
132 | 118 | ||
133 | Say Y only if you want to experiment with P2P. | 119 | Say Y only if you want to experiment with P2P. |
134 | 120 | ||
135 | config IWL3945 | ||
136 | tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)" | ||
137 | depends on IWLWIFI | ||
138 | ---help--- | ||
139 | Select to build the driver supporting the: | ||
140 | |||
141 | Intel PRO/Wireless 3945ABG/BG Network Connection | ||
142 | |||
143 | This driver uses the kernel's mac80211 subsystem. | ||
144 | |||
145 | In order to use this driver, you will need a microcode (uCode) | ||
146 | image for it. You can obtain the microcode from: | ||
147 | |||
148 | <http://intellinuxwireless.org/>. | ||
149 | |||
150 | The microcode is typically installed in /lib/firmware. You can | ||
151 | look in the hotplug script /etc/hotplug/firmware.agent to | ||
152 | determine which directory FIRMWARE_DIR is set to when the script | ||
153 | runs. | ||
154 | |||
155 | If you want to compile the driver as a module ( = code which can be | ||
156 | inserted in and removed from the running kernel whenever you want), | ||
157 | say M here and read <file:Documentation/kbuild/modules.txt>. The | ||
158 | module will be called iwl3945. | ||
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 25be742c69c..aab7d15bd5e 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -1,36 +1,23 @@ | |||
1 | obj-$(CONFIG_IWLWIFI) += iwlcore.o | ||
2 | iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o | ||
3 | iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o | ||
4 | iwlcore-objs += iwl-scan.o iwl-led.o | ||
5 | iwlcore-$(CONFIG_IWL3945) += iwl-legacy.o | ||
6 | iwlcore-$(CONFIG_IWL4965) += iwl-legacy.o | ||
7 | iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | ||
8 | iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | ||
9 | |||
10 | # If 3945 is selected only, iwl-legacy.o will be added | ||
11 | # to iwlcore-m above, but it needs to be built in. | ||
12 | iwlcore-objs += $(iwlcore-m) | ||
13 | |||
14 | CFLAGS_iwl-devtrace.o := -I$(src) | ||
15 | |||
16 | # AGN | 1 | # AGN |
17 | obj-$(CONFIG_IWLAGN) += iwlagn.o | 2 | obj-$(CONFIG_IWLAGN) += iwlagn.o |
18 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o | 3 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o |
19 | iwlagn-objs += iwl-agn-ucode.o iwl-agn-tx.o | 4 | iwlagn-objs += iwl-agn-ucode.o iwl-agn-tx.o |
20 | iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o | 5 | iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o |
21 | iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o | 6 | iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o |
22 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o | ||
23 | 7 | ||
24 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o | 8 | iwlagn-objs += iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o |
25 | iwlagn-$(CONFIG_IWL5000) += iwl-agn-rxon.o iwl-agn-hcmd.o iwl-agn-ict.o | 9 | iwlagn-objs += iwl-rx.o iwl-tx.o iwl-sta.o |
26 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o | 10 | iwlagn-objs += iwl-scan.o iwl-led.o |
27 | iwlagn-$(CONFIG_IWL5000) += iwl-6000.o | 11 | iwlagn-objs += iwl-agn-rxon.o iwl-agn-hcmd.o iwl-agn-ict.o |
28 | iwlagn-$(CONFIG_IWL5000) += iwl-1000.o | 12 | iwlagn-objs += iwl-5000.o |
29 | iwlagn-$(CONFIG_IWL5000) += iwl-2000.o | 13 | iwlagn-objs += iwl-6000.o |
14 | iwlagn-objs += iwl-1000.o | ||
15 | iwlagn-objs += iwl-2000.o | ||
16 | |||
17 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o | ||
18 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | ||
19 | iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | ||
30 | 20 | ||
31 | # 3945 | 21 | CFLAGS_iwl-devtrace.o := -I$(src) |
32 | obj-$(CONFIG_IWL3945) += iwl3945.o | ||
33 | iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o | ||
34 | iwl3945-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-3945-debugfs.o | ||
35 | 22 | ||
36 | ccflags-y += -D__CHECK_ENDIAN__ | 23 | ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c deleted file mode 100644 index ef0835b01b6..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c +++ /dev/null | |||
@@ -1,522 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | *****************************************************************************/ | ||
28 | |||
29 | #include "iwl-3945-debugfs.h" | ||
30 | |||
31 | |||
32 | static int iwl3945_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) | ||
33 | { | ||
34 | int p = 0; | ||
35 | |||
36 | p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", | ||
37 | le32_to_cpu(priv->_3945.statistics.flag)); | ||
38 | if (le32_to_cpu(priv->_3945.statistics.flag) & | ||
39 | UCODE_STATISTICS_CLEAR_MSK) | ||
40 | p += scnprintf(buf + p, bufsz - p, | ||
41 | "\tStatistics have been cleared\n"); | ||
42 | p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", | ||
43 | (le32_to_cpu(priv->_3945.statistics.flag) & | ||
44 | UCODE_STATISTICS_FREQUENCY_MSK) | ||
45 | ? "2.4 GHz" : "5.2 GHz"); | ||
46 | p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", | ||
47 | (le32_to_cpu(priv->_3945.statistics.flag) & | ||
48 | UCODE_STATISTICS_NARROW_BAND_MSK) | ||
49 | ? "enabled" : "disabled"); | ||
50 | return p; | ||
51 | } | ||
52 | |||
53 | ssize_t iwl3945_ucode_rx_stats_read(struct file *file, | ||
54 | char __user *user_buf, | ||
55 | size_t count, loff_t *ppos) | ||
56 | { | ||
57 | struct iwl_priv *priv = file->private_data; | ||
58 | int pos = 0; | ||
59 | char *buf; | ||
60 | int bufsz = sizeof(struct iwl39_statistics_rx_phy) * 40 + | ||
61 | sizeof(struct iwl39_statistics_rx_non_phy) * 40 + 400; | ||
62 | ssize_t ret; | ||
63 | struct iwl39_statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; | ||
64 | struct iwl39_statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; | ||
65 | struct iwl39_statistics_rx_non_phy *general, *accum_general; | ||
66 | struct iwl39_statistics_rx_non_phy *delta_general, *max_general; | ||
67 | |||
68 | if (!iwl_is_alive(priv)) | ||
69 | return -EAGAIN; | ||
70 | |||
71 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
72 | if (!buf) { | ||
73 | IWL_ERR(priv, "Can not allocate Buffer\n"); | ||
74 | return -ENOMEM; | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | * The statistic information display here is based on | ||
79 | * the last statistics notification from uCode | ||
80 | * might not reflect the current uCode activity | ||
81 | */ | ||
82 | ofdm = &priv->_3945.statistics.rx.ofdm; | ||
83 | cck = &priv->_3945.statistics.rx.cck; | ||
84 | general = &priv->_3945.statistics.rx.general; | ||
85 | accum_ofdm = &priv->_3945.accum_statistics.rx.ofdm; | ||
86 | accum_cck = &priv->_3945.accum_statistics.rx.cck; | ||
87 | accum_general = &priv->_3945.accum_statistics.rx.general; | ||
88 | delta_ofdm = &priv->_3945.delta_statistics.rx.ofdm; | ||
89 | delta_cck = &priv->_3945.delta_statistics.rx.cck; | ||
90 | delta_general = &priv->_3945.delta_statistics.rx.general; | ||
91 | max_ofdm = &priv->_3945.max_delta.rx.ofdm; | ||
92 | max_cck = &priv->_3945.max_delta.rx.cck; | ||
93 | max_general = &priv->_3945.max_delta.rx.general; | ||
94 | |||
95 | pos += iwl3945_statistics_flag(priv, buf, bufsz); | ||
96 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
97 | "acumulative delta max\n", | ||
98 | "Statistics_Rx - OFDM:"); | ||
99 | pos += scnprintf(buf + pos, bufsz - pos, | ||
100 | " %-30s %10u %10u %10u %10u\n", | ||
101 | "ina_cnt:", le32_to_cpu(ofdm->ina_cnt), | ||
102 | accum_ofdm->ina_cnt, | ||
103 | delta_ofdm->ina_cnt, max_ofdm->ina_cnt); | ||
104 | pos += scnprintf(buf + pos, bufsz - pos, | ||
105 | " %-30s %10u %10u %10u %10u\n", | ||
106 | "fina_cnt:", | ||
107 | le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, | ||
108 | delta_ofdm->fina_cnt, max_ofdm->fina_cnt); | ||
109 | pos += scnprintf(buf + pos, bufsz - pos, | ||
110 | " %-30s %10u %10u %10u %10u\n", "plcp_err:", | ||
111 | le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, | ||
112 | delta_ofdm->plcp_err, max_ofdm->plcp_err); | ||
113 | pos += scnprintf(buf + pos, bufsz - pos, | ||
114 | " %-30s %10u %10u %10u %10u\n", "crc32_err:", | ||
115 | le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, | ||
116 | delta_ofdm->crc32_err, max_ofdm->crc32_err); | ||
117 | pos += scnprintf(buf + pos, bufsz - pos, | ||
118 | " %-30s %10u %10u %10u %10u\n", "overrun_err:", | ||
119 | le32_to_cpu(ofdm->overrun_err), | ||
120 | accum_ofdm->overrun_err, delta_ofdm->overrun_err, | ||
121 | max_ofdm->overrun_err); | ||
122 | pos += scnprintf(buf + pos, bufsz - pos, | ||
123 | " %-30s %10u %10u %10u %10u\n", | ||
124 | "early_overrun_err:", | ||
125 | le32_to_cpu(ofdm->early_overrun_err), | ||
126 | accum_ofdm->early_overrun_err, | ||
127 | delta_ofdm->early_overrun_err, | ||
128 | max_ofdm->early_overrun_err); | ||
129 | pos += scnprintf(buf + pos, bufsz - pos, | ||
130 | " %-30s %10u %10u %10u %10u\n", | ||
131 | "crc32_good:", le32_to_cpu(ofdm->crc32_good), | ||
132 | accum_ofdm->crc32_good, delta_ofdm->crc32_good, | ||
133 | max_ofdm->crc32_good); | ||
134 | pos += scnprintf(buf + pos, bufsz - pos, | ||
135 | " %-30s %10u %10u %10u %10u\n", "false_alarm_cnt:", | ||
136 | le32_to_cpu(ofdm->false_alarm_cnt), | ||
137 | accum_ofdm->false_alarm_cnt, | ||
138 | delta_ofdm->false_alarm_cnt, | ||
139 | max_ofdm->false_alarm_cnt); | ||
140 | pos += scnprintf(buf + pos, bufsz - pos, | ||
141 | " %-30s %10u %10u %10u %10u\n", | ||
142 | "fina_sync_err_cnt:", | ||
143 | le32_to_cpu(ofdm->fina_sync_err_cnt), | ||
144 | accum_ofdm->fina_sync_err_cnt, | ||
145 | delta_ofdm->fina_sync_err_cnt, | ||
146 | max_ofdm->fina_sync_err_cnt); | ||
147 | pos += scnprintf(buf + pos, bufsz - pos, | ||
148 | " %-30s %10u %10u %10u %10u\n", | ||
149 | "sfd_timeout:", | ||
150 | le32_to_cpu(ofdm->sfd_timeout), | ||
151 | accum_ofdm->sfd_timeout, | ||
152 | delta_ofdm->sfd_timeout, | ||
153 | max_ofdm->sfd_timeout); | ||
154 | pos += scnprintf(buf + pos, bufsz - pos, | ||
155 | " %-30s %10u %10u %10u %10u\n", | ||
156 | "fina_timeout:", | ||
157 | le32_to_cpu(ofdm->fina_timeout), | ||
158 | accum_ofdm->fina_timeout, | ||
159 | delta_ofdm->fina_timeout, | ||
160 | max_ofdm->fina_timeout); | ||
161 | pos += scnprintf(buf + pos, bufsz - pos, | ||
162 | " %-30s %10u %10u %10u %10u\n", | ||
163 | "unresponded_rts:", | ||
164 | le32_to_cpu(ofdm->unresponded_rts), | ||
165 | accum_ofdm->unresponded_rts, | ||
166 | delta_ofdm->unresponded_rts, | ||
167 | max_ofdm->unresponded_rts); | ||
168 | pos += scnprintf(buf + pos, bufsz - pos, | ||
169 | " %-30s %10u %10u %10u %10u\n", | ||
170 | "rxe_frame_lmt_ovrun:", | ||
171 | le32_to_cpu(ofdm->rxe_frame_limit_overrun), | ||
172 | accum_ofdm->rxe_frame_limit_overrun, | ||
173 | delta_ofdm->rxe_frame_limit_overrun, | ||
174 | max_ofdm->rxe_frame_limit_overrun); | ||
175 | pos += scnprintf(buf + pos, bufsz - pos, | ||
176 | " %-30s %10u %10u %10u %10u\n", | ||
177 | "sent_ack_cnt:", | ||
178 | le32_to_cpu(ofdm->sent_ack_cnt), | ||
179 | accum_ofdm->sent_ack_cnt, | ||
180 | delta_ofdm->sent_ack_cnt, | ||
181 | max_ofdm->sent_ack_cnt); | ||
182 | pos += scnprintf(buf + pos, bufsz - pos, | ||
183 | " %-30s %10u %10u %10u %10u\n", | ||
184 | "sent_cts_cnt:", | ||
185 | le32_to_cpu(ofdm->sent_cts_cnt), | ||
186 | accum_ofdm->sent_cts_cnt, | ||
187 | delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt); | ||
188 | |||
189 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
190 | "acumulative delta max\n", | ||
191 | "Statistics_Rx - CCK:"); | ||
192 | pos += scnprintf(buf + pos, bufsz - pos, | ||
193 | " %-30s %10u %10u %10u %10u\n", | ||
194 | "ina_cnt:", | ||
195 | le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, | ||
196 | delta_cck->ina_cnt, max_cck->ina_cnt); | ||
197 | pos += scnprintf(buf + pos, bufsz - pos, | ||
198 | " %-30s %10u %10u %10u %10u\n", | ||
199 | "fina_cnt:", | ||
200 | le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, | ||
201 | delta_cck->fina_cnt, max_cck->fina_cnt); | ||
202 | pos += scnprintf(buf + pos, bufsz - pos, | ||
203 | " %-30s %10u %10u %10u %10u\n", | ||
204 | "plcp_err:", | ||
205 | le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, | ||
206 | delta_cck->plcp_err, max_cck->plcp_err); | ||
207 | pos += scnprintf(buf + pos, bufsz - pos, | ||
208 | " %-30s %10u %10u %10u %10u\n", | ||
209 | "crc32_err:", | ||
210 | le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, | ||
211 | delta_cck->crc32_err, max_cck->crc32_err); | ||
212 | pos += scnprintf(buf + pos, bufsz - pos, | ||
213 | " %-30s %10u %10u %10u %10u\n", | ||
214 | "overrun_err:", | ||
215 | le32_to_cpu(cck->overrun_err), | ||
216 | accum_cck->overrun_err, | ||
217 | delta_cck->overrun_err, max_cck->overrun_err); | ||
218 | pos += scnprintf(buf + pos, bufsz - pos, | ||
219 | " %-30s %10u %10u %10u %10u\n", | ||
220 | "early_overrun_err:", | ||
221 | le32_to_cpu(cck->early_overrun_err), | ||
222 | accum_cck->early_overrun_err, | ||
223 | delta_cck->early_overrun_err, | ||
224 | max_cck->early_overrun_err); | ||
225 | pos += scnprintf(buf + pos, bufsz - pos, | ||
226 | " %-30s %10u %10u %10u %10u\n", | ||
227 | "crc32_good:", | ||
228 | le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, | ||
229 | delta_cck->crc32_good, | ||
230 | max_cck->crc32_good); | ||
231 | pos += scnprintf(buf + pos, bufsz - pos, | ||
232 | " %-30s %10u %10u %10u %10u\n", | ||
233 | "false_alarm_cnt:", | ||
234 | le32_to_cpu(cck->false_alarm_cnt), | ||
235 | accum_cck->false_alarm_cnt, | ||
236 | delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); | ||
237 | pos += scnprintf(buf + pos, bufsz - pos, | ||
238 | " %-30s %10u %10u %10u %10u\n", | ||
239 | "fina_sync_err_cnt:", | ||
240 | le32_to_cpu(cck->fina_sync_err_cnt), | ||
241 | accum_cck->fina_sync_err_cnt, | ||
242 | delta_cck->fina_sync_err_cnt, | ||
243 | max_cck->fina_sync_err_cnt); | ||
244 | pos += scnprintf(buf + pos, bufsz - pos, | ||
245 | " %-30s %10u %10u %10u %10u\n", | ||
246 | "sfd_timeout:", | ||
247 | le32_to_cpu(cck->sfd_timeout), | ||
248 | accum_cck->sfd_timeout, | ||
249 | delta_cck->sfd_timeout, max_cck->sfd_timeout); | ||
250 | pos += scnprintf(buf + pos, bufsz - pos, | ||
251 | " %-30s %10u %10u %10u %10u\n", | ||
252 | "fina_timeout:", | ||
253 | le32_to_cpu(cck->fina_timeout), | ||
254 | accum_cck->fina_timeout, | ||
255 | delta_cck->fina_timeout, max_cck->fina_timeout); | ||
256 | pos += scnprintf(buf + pos, bufsz - pos, | ||
257 | " %-30s %10u %10u %10u %10u\n", | ||
258 | "unresponded_rts:", | ||
259 | le32_to_cpu(cck->unresponded_rts), | ||
260 | accum_cck->unresponded_rts, | ||
261 | delta_cck->unresponded_rts, | ||
262 | max_cck->unresponded_rts); | ||
263 | pos += scnprintf(buf + pos, bufsz - pos, | ||
264 | " %-30s %10u %10u %10u %10u\n", | ||
265 | "rxe_frame_lmt_ovrun:", | ||
266 | le32_to_cpu(cck->rxe_frame_limit_overrun), | ||
267 | accum_cck->rxe_frame_limit_overrun, | ||
268 | delta_cck->rxe_frame_limit_overrun, | ||
269 | max_cck->rxe_frame_limit_overrun); | ||
270 | pos += scnprintf(buf + pos, bufsz - pos, | ||
271 | " %-30s %10u %10u %10u %10u\n", | ||
272 | "sent_ack_cnt:", | ||
273 | le32_to_cpu(cck->sent_ack_cnt), | ||
274 | accum_cck->sent_ack_cnt, | ||
275 | delta_cck->sent_ack_cnt, | ||
276 | max_cck->sent_ack_cnt); | ||
277 | pos += scnprintf(buf + pos, bufsz - pos, | ||
278 | " %-30s %10u %10u %10u %10u\n", | ||
279 | "sent_cts_cnt:", | ||
280 | le32_to_cpu(cck->sent_cts_cnt), | ||
281 | accum_cck->sent_cts_cnt, | ||
282 | delta_cck->sent_cts_cnt, | ||
283 | max_cck->sent_cts_cnt); | ||
284 | |||
285 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
286 | "acumulative delta max\n", | ||
287 | "Statistics_Rx - GENERAL:"); | ||
288 | pos += scnprintf(buf + pos, bufsz - pos, | ||
289 | " %-30s %10u %10u %10u %10u\n", | ||
290 | "bogus_cts:", | ||
291 | le32_to_cpu(general->bogus_cts), | ||
292 | accum_general->bogus_cts, | ||
293 | delta_general->bogus_cts, max_general->bogus_cts); | ||
294 | pos += scnprintf(buf + pos, bufsz - pos, | ||
295 | " %-30s %10u %10u %10u %10u\n", | ||
296 | "bogus_ack:", | ||
297 | le32_to_cpu(general->bogus_ack), | ||
298 | accum_general->bogus_ack, | ||
299 | delta_general->bogus_ack, max_general->bogus_ack); | ||
300 | pos += scnprintf(buf + pos, bufsz - pos, | ||
301 | " %-30s %10u %10u %10u %10u\n", | ||
302 | "non_bssid_frames:", | ||
303 | le32_to_cpu(general->non_bssid_frames), | ||
304 | accum_general->non_bssid_frames, | ||
305 | delta_general->non_bssid_frames, | ||
306 | max_general->non_bssid_frames); | ||
307 | pos += scnprintf(buf + pos, bufsz - pos, | ||
308 | " %-30s %10u %10u %10u %10u\n", | ||
309 | "filtered_frames:", | ||
310 | le32_to_cpu(general->filtered_frames), | ||
311 | accum_general->filtered_frames, | ||
312 | delta_general->filtered_frames, | ||
313 | max_general->filtered_frames); | ||
314 | pos += scnprintf(buf + pos, bufsz - pos, | ||
315 | " %-30s %10u %10u %10u %10u\n", | ||
316 | "non_channel_beacons:", | ||
317 | le32_to_cpu(general->non_channel_beacons), | ||
318 | accum_general->non_channel_beacons, | ||
319 | delta_general->non_channel_beacons, | ||
320 | max_general->non_channel_beacons); | ||
321 | |||
322 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
323 | kfree(buf); | ||
324 | return ret; | ||
325 | } | ||
326 | |||
327 | ssize_t iwl3945_ucode_tx_stats_read(struct file *file, | ||
328 | char __user *user_buf, | ||
329 | size_t count, loff_t *ppos) | ||
330 | { | ||
331 | struct iwl_priv *priv = file->private_data; | ||
332 | int pos = 0; | ||
333 | char *buf; | ||
334 | int bufsz = (sizeof(struct iwl39_statistics_tx) * 48) + 250; | ||
335 | ssize_t ret; | ||
336 | struct iwl39_statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; | ||
337 | |||
338 | if (!iwl_is_alive(priv)) | ||
339 | return -EAGAIN; | ||
340 | |||
341 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
342 | if (!buf) { | ||
343 | IWL_ERR(priv, "Can not allocate Buffer\n"); | ||
344 | return -ENOMEM; | ||
345 | } | ||
346 | |||
347 | /* | ||
348 | * The statistic information display here is based on | ||
349 | * the last statistics notification from uCode | ||
350 | * might not reflect the current uCode activity | ||
351 | */ | ||
352 | tx = &priv->_3945.statistics.tx; | ||
353 | accum_tx = &priv->_3945.accum_statistics.tx; | ||
354 | delta_tx = &priv->_3945.delta_statistics.tx; | ||
355 | max_tx = &priv->_3945.max_delta.tx; | ||
356 | pos += iwl3945_statistics_flag(priv, buf, bufsz); | ||
357 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
358 | "acumulative delta max\n", | ||
359 | "Statistics_Tx:"); | ||
360 | pos += scnprintf(buf + pos, bufsz - pos, | ||
361 | " %-30s %10u %10u %10u %10u\n", | ||
362 | "preamble:", | ||
363 | le32_to_cpu(tx->preamble_cnt), | ||
364 | accum_tx->preamble_cnt, | ||
365 | delta_tx->preamble_cnt, max_tx->preamble_cnt); | ||
366 | pos += scnprintf(buf + pos, bufsz - pos, | ||
367 | " %-30s %10u %10u %10u %10u\n", | ||
368 | "rx_detected_cnt:", | ||
369 | le32_to_cpu(tx->rx_detected_cnt), | ||
370 | accum_tx->rx_detected_cnt, | ||
371 | delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); | ||
372 | pos += scnprintf(buf + pos, bufsz - pos, | ||
373 | " %-30s %10u %10u %10u %10u\n", | ||
374 | "bt_prio_defer_cnt:", | ||
375 | le32_to_cpu(tx->bt_prio_defer_cnt), | ||
376 | accum_tx->bt_prio_defer_cnt, | ||
377 | delta_tx->bt_prio_defer_cnt, | ||
378 | max_tx->bt_prio_defer_cnt); | ||
379 | pos += scnprintf(buf + pos, bufsz - pos, | ||
380 | " %-30s %10u %10u %10u %10u\n", | ||
381 | "bt_prio_kill_cnt:", | ||
382 | le32_to_cpu(tx->bt_prio_kill_cnt), | ||
383 | accum_tx->bt_prio_kill_cnt, | ||
384 | delta_tx->bt_prio_kill_cnt, | ||
385 | max_tx->bt_prio_kill_cnt); | ||
386 | pos += scnprintf(buf + pos, bufsz - pos, | ||
387 | " %-30s %10u %10u %10u %10u\n", | ||
388 | "few_bytes_cnt:", | ||
389 | le32_to_cpu(tx->few_bytes_cnt), | ||
390 | accum_tx->few_bytes_cnt, | ||
391 | delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); | ||
392 | pos += scnprintf(buf + pos, bufsz - pos, | ||
393 | " %-30s %10u %10u %10u %10u\n", | ||
394 | "cts_timeout:", | ||
395 | le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, | ||
396 | delta_tx->cts_timeout, max_tx->cts_timeout); | ||
397 | pos += scnprintf(buf + pos, bufsz - pos, | ||
398 | " %-30s %10u %10u %10u %10u\n", | ||
399 | "ack_timeout:", | ||
400 | le32_to_cpu(tx->ack_timeout), | ||
401 | accum_tx->ack_timeout, | ||
402 | delta_tx->ack_timeout, max_tx->ack_timeout); | ||
403 | pos += scnprintf(buf + pos, bufsz - pos, | ||
404 | " %-30s %10u %10u %10u %10u\n", | ||
405 | "expected_ack_cnt:", | ||
406 | le32_to_cpu(tx->expected_ack_cnt), | ||
407 | accum_tx->expected_ack_cnt, | ||
408 | delta_tx->expected_ack_cnt, | ||
409 | max_tx->expected_ack_cnt); | ||
410 | pos += scnprintf(buf + pos, bufsz - pos, | ||
411 | " %-30s %10u %10u %10u %10u\n", | ||
412 | "actual_ack_cnt:", | ||
413 | le32_to_cpu(tx->actual_ack_cnt), | ||
414 | accum_tx->actual_ack_cnt, | ||
415 | delta_tx->actual_ack_cnt, | ||
416 | max_tx->actual_ack_cnt); | ||
417 | |||
418 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
419 | kfree(buf); | ||
420 | return ret; | ||
421 | } | ||
422 | |||
423 | ssize_t iwl3945_ucode_general_stats_read(struct file *file, | ||
424 | char __user *user_buf, | ||
425 | size_t count, loff_t *ppos) | ||
426 | { | ||
427 | struct iwl_priv *priv = file->private_data; | ||
428 | int pos = 0; | ||
429 | char *buf; | ||
430 | int bufsz = sizeof(struct iwl39_statistics_general) * 10 + 300; | ||
431 | ssize_t ret; | ||
432 | struct iwl39_statistics_general *general, *accum_general; | ||
433 | struct iwl39_statistics_general *delta_general, *max_general; | ||
434 | struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; | ||
435 | struct iwl39_statistics_div *div, *accum_div, *delta_div, *max_div; | ||
436 | |||
437 | if (!iwl_is_alive(priv)) | ||
438 | return -EAGAIN; | ||
439 | |||
440 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
441 | if (!buf) { | ||
442 | IWL_ERR(priv, "Can not allocate Buffer\n"); | ||
443 | return -ENOMEM; | ||
444 | } | ||
445 | |||
446 | /* | ||
447 | * The statistic information display here is based on | ||
448 | * the last statistics notification from uCode | ||
449 | * might not reflect the current uCode activity | ||
450 | */ | ||
451 | general = &priv->_3945.statistics.general; | ||
452 | dbg = &priv->_3945.statistics.general.dbg; | ||
453 | div = &priv->_3945.statistics.general.div; | ||
454 | accum_general = &priv->_3945.accum_statistics.general; | ||
455 | delta_general = &priv->_3945.delta_statistics.general; | ||
456 | max_general = &priv->_3945.max_delta.general; | ||
457 | accum_dbg = &priv->_3945.accum_statistics.general.dbg; | ||
458 | delta_dbg = &priv->_3945.delta_statistics.general.dbg; | ||
459 | max_dbg = &priv->_3945.max_delta.general.dbg; | ||
460 | accum_div = &priv->_3945.accum_statistics.general.div; | ||
461 | delta_div = &priv->_3945.delta_statistics.general.div; | ||
462 | max_div = &priv->_3945.max_delta.general.div; | ||
463 | pos += iwl3945_statistics_flag(priv, buf, bufsz); | ||
464 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
465 | "acumulative delta max\n", | ||
466 | "Statistics_General:"); | ||
467 | pos += scnprintf(buf + pos, bufsz - pos, | ||
468 | " %-30s %10u %10u %10u %10u\n", | ||
469 | "burst_check:", | ||
470 | le32_to_cpu(dbg->burst_check), | ||
471 | accum_dbg->burst_check, | ||
472 | delta_dbg->burst_check, max_dbg->burst_check); | ||
473 | pos += scnprintf(buf + pos, bufsz - pos, | ||
474 | " %-30s %10u %10u %10u %10u\n", | ||
475 | "burst_count:", | ||
476 | le32_to_cpu(dbg->burst_count), | ||
477 | accum_dbg->burst_count, | ||
478 | delta_dbg->burst_count, max_dbg->burst_count); | ||
479 | pos += scnprintf(buf + pos, bufsz - pos, | ||
480 | " %-30s %10u %10u %10u %10u\n", | ||
481 | "sleep_time:", | ||
482 | le32_to_cpu(general->sleep_time), | ||
483 | accum_general->sleep_time, | ||
484 | delta_general->sleep_time, max_general->sleep_time); | ||
485 | pos += scnprintf(buf + pos, bufsz - pos, | ||
486 | " %-30s %10u %10u %10u %10u\n", | ||
487 | "slots_out:", | ||
488 | le32_to_cpu(general->slots_out), | ||
489 | accum_general->slots_out, | ||
490 | delta_general->slots_out, max_general->slots_out); | ||
491 | pos += scnprintf(buf + pos, bufsz - pos, | ||
492 | " %-30s %10u %10u %10u %10u\n", | ||
493 | "slots_idle:", | ||
494 | le32_to_cpu(general->slots_idle), | ||
495 | accum_general->slots_idle, | ||
496 | delta_general->slots_idle, max_general->slots_idle); | ||
497 | pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n", | ||
498 | le32_to_cpu(general->ttl_timestamp)); | ||
499 | pos += scnprintf(buf + pos, bufsz - pos, | ||
500 | " %-30s %10u %10u %10u %10u\n", | ||
501 | "tx_on_a:", | ||
502 | le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, | ||
503 | delta_div->tx_on_a, max_div->tx_on_a); | ||
504 | pos += scnprintf(buf + pos, bufsz - pos, | ||
505 | " %-30s %10u %10u %10u %10u\n", | ||
506 | "tx_on_b:", | ||
507 | le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, | ||
508 | delta_div->tx_on_b, max_div->tx_on_b); | ||
509 | pos += scnprintf(buf + pos, bufsz - pos, | ||
510 | " %-30s %10u %10u %10u %10u\n", | ||
511 | "exec_time:", | ||
512 | le32_to_cpu(div->exec_time), accum_div->exec_time, | ||
513 | delta_div->exec_time, max_div->exec_time); | ||
514 | pos += scnprintf(buf + pos, bufsz - pos, | ||
515 | " %-30s %10u %10u %10u %10u\n", | ||
516 | "probe_time:", | ||
517 | le32_to_cpu(div->probe_time), accum_div->probe_time, | ||
518 | delta_div->probe_time, max_div->probe_time); | ||
519 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
520 | kfree(buf); | ||
521 | return ret; | ||
522 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h deleted file mode 100644 index 70809c53c21..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h +++ /dev/null | |||
@@ -1,60 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | *****************************************************************************/ | ||
28 | |||
29 | #include "iwl-dev.h" | ||
30 | #include "iwl-core.h" | ||
31 | #include "iwl-debug.h" | ||
32 | |||
33 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
34 | ssize_t iwl3945_ucode_rx_stats_read(struct file *file, char __user *user_buf, | ||
35 | size_t count, loff_t *ppos); | ||
36 | ssize_t iwl3945_ucode_tx_stats_read(struct file *file, char __user *user_buf, | ||
37 | size_t count, loff_t *ppos); | ||
38 | ssize_t iwl3945_ucode_general_stats_read(struct file *file, | ||
39 | char __user *user_buf, size_t count, | ||
40 | loff_t *ppos); | ||
41 | #else | ||
42 | static ssize_t iwl3945_ucode_rx_stats_read(struct file *file, | ||
43 | char __user *user_buf, size_t count, | ||
44 | loff_t *ppos) | ||
45 | { | ||
46 | return 0; | ||
47 | } | ||
48 | static ssize_t iwl3945_ucode_tx_stats_read(struct file *file, | ||
49 | char __user *user_buf, size_t count, | ||
50 | loff_t *ppos) | ||
51 | { | ||
52 | return 0; | ||
53 | } | ||
54 | static ssize_t iwl3945_ucode_general_stats_read(struct file *file, | ||
55 | char __user *user_buf, | ||
56 | size_t count, loff_t *ppos) | ||
57 | { | ||
58 | return 0; | ||
59 | } | ||
60 | #endif | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h deleted file mode 100644 index 2c9ed2b502a..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h +++ /dev/null | |||
@@ -1,188 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | #ifndef __iwl_3945_fh_h__ | ||
64 | #define __iwl_3945_fh_h__ | ||
65 | |||
66 | /************************************/ | ||
67 | /* iwl3945 Flow Handler Definitions */ | ||
68 | /************************************/ | ||
69 | |||
70 | /** | ||
71 | * This I/O area is directly read/writable by driver (e.g. Linux uses writel()) | ||
72 | * Addresses are offsets from device's PCI hardware base address. | ||
73 | */ | ||
74 | #define FH39_MEM_LOWER_BOUND (0x0800) | ||
75 | #define FH39_MEM_UPPER_BOUND (0x1000) | ||
76 | |||
77 | #define FH39_CBCC_TABLE (FH39_MEM_LOWER_BOUND + 0x140) | ||
78 | #define FH39_TFDB_TABLE (FH39_MEM_LOWER_BOUND + 0x180) | ||
79 | #define FH39_RCSR_TABLE (FH39_MEM_LOWER_BOUND + 0x400) | ||
80 | #define FH39_RSSR_TABLE (FH39_MEM_LOWER_BOUND + 0x4c0) | ||
81 | #define FH39_TCSR_TABLE (FH39_MEM_LOWER_BOUND + 0x500) | ||
82 | #define FH39_TSSR_TABLE (FH39_MEM_LOWER_BOUND + 0x680) | ||
83 | |||
84 | /* TFDB (Transmit Frame Buffer Descriptor) */ | ||
85 | #define FH39_TFDB(_ch, buf) (FH39_TFDB_TABLE + \ | ||
86 | ((_ch) * 2 + (buf)) * 0x28) | ||
87 | #define FH39_TFDB_CHNL_BUF_CTRL_REG(_ch) (FH39_TFDB_TABLE + 0x50 * (_ch)) | ||
88 | |||
89 | /* CBCC channel is [0,2] */ | ||
90 | #define FH39_CBCC(_ch) (FH39_CBCC_TABLE + (_ch) * 0x8) | ||
91 | #define FH39_CBCC_CTRL(_ch) (FH39_CBCC(_ch) + 0x00) | ||
92 | #define FH39_CBCC_BASE(_ch) (FH39_CBCC(_ch) + 0x04) | ||
93 | |||
94 | /* RCSR channel is [0,2] */ | ||
95 | #define FH39_RCSR(_ch) (FH39_RCSR_TABLE + (_ch) * 0x40) | ||
96 | #define FH39_RCSR_CONFIG(_ch) (FH39_RCSR(_ch) + 0x00) | ||
97 | #define FH39_RCSR_RBD_BASE(_ch) (FH39_RCSR(_ch) + 0x04) | ||
98 | #define FH39_RCSR_WPTR(_ch) (FH39_RCSR(_ch) + 0x20) | ||
99 | #define FH39_RCSR_RPTR_ADDR(_ch) (FH39_RCSR(_ch) + 0x24) | ||
100 | |||
101 | #define FH39_RSCSR_CHNL0_WPTR (FH39_RCSR_WPTR(0)) | ||
102 | |||
103 | /* RSSR */ | ||
104 | #define FH39_RSSR_CTRL (FH39_RSSR_TABLE + 0x000) | ||
105 | #define FH39_RSSR_STATUS (FH39_RSSR_TABLE + 0x004) | ||
106 | |||
107 | /* TCSR */ | ||
108 | #define FH39_TCSR(_ch) (FH39_TCSR_TABLE + (_ch) * 0x20) | ||
109 | #define FH39_TCSR_CONFIG(_ch) (FH39_TCSR(_ch) + 0x00) | ||
110 | #define FH39_TCSR_CREDIT(_ch) (FH39_TCSR(_ch) + 0x04) | ||
111 | #define FH39_TCSR_BUFF_STTS(_ch) (FH39_TCSR(_ch) + 0x08) | ||
112 | |||
113 | /* TSSR */ | ||
114 | #define FH39_TSSR_CBB_BASE (FH39_TSSR_TABLE + 0x000) | ||
115 | #define FH39_TSSR_MSG_CONFIG (FH39_TSSR_TABLE + 0x008) | ||
116 | #define FH39_TSSR_TX_STATUS (FH39_TSSR_TABLE + 0x010) | ||
117 | |||
118 | |||
119 | /* DBM */ | ||
120 | |||
121 | #define FH39_SRVC_CHNL (6) | ||
122 | |||
123 | #define FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE (20) | ||
124 | #define FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH (4) | ||
125 | |||
126 | #define FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN (0x08000000) | ||
127 | |||
128 | #define FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE (0x80000000) | ||
129 | |||
130 | #define FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE (0x20000000) | ||
131 | |||
132 | #define FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 (0x01000000) | ||
133 | |||
134 | #define FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST (0x00001000) | ||
135 | |||
136 | #define FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH (0x00000000) | ||
137 | |||
138 | #define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF (0x00000000) | ||
139 | #define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER (0x00000001) | ||
140 | |||
141 | #define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL (0x00000000) | ||
142 | #define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL (0x00000008) | ||
143 | |||
144 | #define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD (0x00200000) | ||
145 | |||
146 | #define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT (0x00000000) | ||
147 | |||
148 | #define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000) | ||
149 | #define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000) | ||
150 | |||
151 | #define FH39_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID (0x00004000) | ||
152 | |||
153 | #define FH39_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR (0x00000001) | ||
154 | |||
155 | #define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON (0xFF000000) | ||
156 | #define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON (0x00FF0000) | ||
157 | |||
158 | #define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B (0x00000400) | ||
159 | |||
160 | #define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON (0x00000100) | ||
161 | #define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON (0x00000080) | ||
162 | |||
163 | #define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH (0x00000020) | ||
164 | #define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH (0x00000005) | ||
165 | |||
166 | #define FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch) (BIT(_ch) << 24) | ||
167 | #define FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch) (BIT(_ch) << 16) | ||
168 | |||
169 | #define FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_ch) \ | ||
170 | (FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch) | \ | ||
171 | FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch)) | ||
172 | |||
173 | #define FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000) | ||
174 | |||
175 | struct iwl3945_tfd_tb { | ||
176 | __le32 addr; | ||
177 | __le32 len; | ||
178 | } __packed; | ||
179 | |||
180 | struct iwl3945_tfd { | ||
181 | __le32 control_flags; | ||
182 | struct iwl3945_tfd_tb tbs[4]; | ||
183 | u8 __pad[28]; | ||
184 | } __packed; | ||
185 | |||
186 | |||
187 | #endif /* __iwl_3945_fh_h__ */ | ||
188 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h deleted file mode 100644 index 65b5834da28..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ /dev/null | |||
@@ -1,294 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | /* | ||
64 | * Please use this file (iwl-3945-hw.h) only for hardware-related definitions. | ||
65 | * Please use iwl-commands.h for uCode API definitions. | ||
66 | * Please use iwl-3945.h for driver implementation definitions. | ||
67 | */ | ||
68 | |||
69 | #ifndef __iwl_3945_hw__ | ||
70 | #define __iwl_3945_hw__ | ||
71 | |||
72 | #include "iwl-eeprom.h" | ||
73 | |||
74 | /* RSSI to dBm */ | ||
75 | #define IWL39_RSSI_OFFSET 95 | ||
76 | |||
77 | #define IWL_DEFAULT_TX_POWER 0x0F | ||
78 | |||
79 | /* | ||
80 | * EEPROM related constants, enums, and structures. | ||
81 | */ | ||
82 | #define EEPROM_SKU_CAP_OP_MODE_MRC (1 << 7) | ||
83 | |||
84 | /* | ||
85 | * Mapping of a Tx power level, at factory calibration temperature, | ||
86 | * to a radio/DSP gain table index. | ||
87 | * One for each of 5 "sample" power levels in each band. | ||
88 | * v_det is measured at the factory, using the 3945's built-in power amplifier | ||
89 | * (PA) output voltage detector. This same detector is used during Tx of | ||
90 | * long packets in normal operation to provide feedback as to proper output | ||
91 | * level. | ||
92 | * Data copied from EEPROM. | ||
93 | * DO NOT ALTER THIS STRUCTURE!!! | ||
94 | */ | ||
95 | struct iwl3945_eeprom_txpower_sample { | ||
96 | u8 gain_index; /* index into power (gain) setup table ... */ | ||
97 | s8 power; /* ... for this pwr level for this chnl group */ | ||
98 | u16 v_det; /* PA output voltage */ | ||
99 | } __packed; | ||
100 | |||
101 | /* | ||
102 | * Mappings of Tx power levels -> nominal radio/DSP gain table indexes. | ||
103 | * One for each channel group (a.k.a. "band") (1 for BG, 4 for A). | ||
104 | * Tx power setup code interpolates between the 5 "sample" power levels | ||
105 | * to determine the nominal setup for a requested power level. | ||
106 | * Data copied from EEPROM. | ||
107 | * DO NOT ALTER THIS STRUCTURE!!! | ||
108 | */ | ||
109 | struct iwl3945_eeprom_txpower_group { | ||
110 | struct iwl3945_eeprom_txpower_sample samples[5]; /* 5 power levels */ | ||
111 | s32 a, b, c, d, e; /* coefficients for voltage->power | ||
112 | * formula (signed) */ | ||
113 | s32 Fa, Fb, Fc, Fd, Fe; /* these modify coeffs based on | ||
114 | * frequency (signed) */ | ||
115 | s8 saturation_power; /* highest power possible by h/w in this | ||
116 | * band */ | ||
117 | u8 group_channel; /* "representative" channel # in this band */ | ||
118 | s16 temperature; /* h/w temperature at factory calib this band | ||
119 | * (signed) */ | ||
120 | } __packed; | ||
121 | |||
122 | /* | ||
123 | * Temperature-based Tx-power compensation data, not band-specific. | ||
124 | * These coefficients are use to modify a/b/c/d/e coeffs based on | ||
125 | * difference between current temperature and factory calib temperature. | ||
126 | * Data copied from EEPROM. | ||
127 | */ | ||
128 | struct iwl3945_eeprom_temperature_corr { | ||
129 | u32 Ta; | ||
130 | u32 Tb; | ||
131 | u32 Tc; | ||
132 | u32 Td; | ||
133 | u32 Te; | ||
134 | } __packed; | ||
135 | |||
136 | /* | ||
137 | * EEPROM map | ||
138 | */ | ||
139 | struct iwl3945_eeprom { | ||
140 | u8 reserved0[16]; | ||
141 | u16 device_id; /* abs.ofs: 16 */ | ||
142 | u8 reserved1[2]; | ||
143 | u16 pmc; /* abs.ofs: 20 */ | ||
144 | u8 reserved2[20]; | ||
145 | u8 mac_address[6]; /* abs.ofs: 42 */ | ||
146 | u8 reserved3[58]; | ||
147 | u16 board_revision; /* abs.ofs: 106 */ | ||
148 | u8 reserved4[11]; | ||
149 | u8 board_pba_number[9]; /* abs.ofs: 119 */ | ||
150 | u8 reserved5[8]; | ||
151 | u16 version; /* abs.ofs: 136 */ | ||
152 | u8 sku_cap; /* abs.ofs: 138 */ | ||
153 | u8 leds_mode; /* abs.ofs: 139 */ | ||
154 | u16 oem_mode; | ||
155 | u16 wowlan_mode; /* abs.ofs: 142 */ | ||
156 | u16 leds_time_interval; /* abs.ofs: 144 */ | ||
157 | u8 leds_off_time; /* abs.ofs: 146 */ | ||
158 | u8 leds_on_time; /* abs.ofs: 147 */ | ||
159 | u8 almgor_m_version; /* abs.ofs: 148 */ | ||
160 | u8 antenna_switch_type; /* abs.ofs: 149 */ | ||
161 | u8 reserved6[42]; | ||
162 | u8 sku_id[4]; /* abs.ofs: 192 */ | ||
163 | |||
164 | /* | ||
165 | * Per-channel regulatory data. | ||
166 | * | ||
167 | * Each channel that *might* be supported by 3945 or 4965 has a fixed location | ||
168 | * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory | ||
169 | * txpower (MSB). | ||
170 | * | ||
171 | * Entries immediately below are for 20 MHz channel width. HT40 (40 MHz) | ||
172 | * channels (only for 4965, not supported by 3945) appear later in the EEPROM. | ||
173 | * | ||
174 | * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 | ||
175 | */ | ||
176 | u16 band_1_count; /* abs.ofs: 196 */ | ||
177 | struct iwl_eeprom_channel band_1_channels[14]; /* abs.ofs: 198 */ | ||
178 | |||
179 | /* | ||
180 | * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196, | ||
181 | * 5.0 GHz channels 7, 8, 11, 12, 16 | ||
182 | * (4915-5080MHz) (none of these is ever supported) | ||
183 | */ | ||
184 | u16 band_2_count; /* abs.ofs: 226 */ | ||
185 | struct iwl_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */ | ||
186 | |||
187 | /* | ||
188 | * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 | ||
189 | * (5170-5320MHz) | ||
190 | */ | ||
191 | u16 band_3_count; /* abs.ofs: 254 */ | ||
192 | struct iwl_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */ | ||
193 | |||
194 | /* | ||
195 | * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 | ||
196 | * (5500-5700MHz) | ||
197 | */ | ||
198 | u16 band_4_count; /* abs.ofs: 280 */ | ||
199 | struct iwl_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */ | ||
200 | |||
201 | /* | ||
202 | * 5.7 GHz channels 145, 149, 153, 157, 161, 165 | ||
203 | * (5725-5825MHz) | ||
204 | */ | ||
205 | u16 band_5_count; /* abs.ofs: 304 */ | ||
206 | struct iwl_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */ | ||
207 | |||
208 | u8 reserved9[194]; | ||
209 | |||
210 | /* | ||
211 | * 3945 Txpower calibration data. | ||
212 | */ | ||
213 | #define IWL_NUM_TX_CALIB_GROUPS 5 | ||
214 | struct iwl3945_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS]; | ||
215 | /* abs.ofs: 512 */ | ||
216 | struct iwl3945_eeprom_temperature_corr corrections; /* abs.ofs: 832 */ | ||
217 | u8 reserved16[172]; /* fill out to full 1024 byte block */ | ||
218 | } __packed; | ||
219 | |||
220 | #define IWL3945_EEPROM_IMG_SIZE 1024 | ||
221 | |||
222 | /* End of EEPROM */ | ||
223 | |||
224 | #define PCI_CFG_REV_ID_BIT_BASIC_SKU (0x40) /* bit 6 */ | ||
225 | #define PCI_CFG_REV_ID_BIT_RTP (0x80) /* bit 7 */ | ||
226 | |||
227 | /* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */ | ||
228 | #define IWL39_NUM_QUEUES 5 | ||
229 | #define IWL39_CMD_QUEUE_NUM 4 | ||
230 | |||
231 | #define IWL_DEFAULT_TX_RETRY 15 | ||
232 | |||
233 | /*********************************************/ | ||
234 | |||
235 | #define RFD_SIZE 4 | ||
236 | #define NUM_TFD_CHUNKS 4 | ||
237 | |||
238 | #define RX_QUEUE_SIZE 256 | ||
239 | #define RX_QUEUE_MASK 255 | ||
240 | #define RX_QUEUE_SIZE_LOG 8 | ||
241 | |||
242 | #define U32_PAD(n) ((4-(n))&0x3) | ||
243 | |||
244 | #define TFD_CTL_COUNT_SET(n) (n << 24) | ||
245 | #define TFD_CTL_COUNT_GET(ctl) ((ctl >> 24) & 7) | ||
246 | #define TFD_CTL_PAD_SET(n) (n << 28) | ||
247 | #define TFD_CTL_PAD_GET(ctl) (ctl >> 28) | ||
248 | |||
249 | /* Sizes and addresses for instruction and data memory (SRAM) in | ||
250 | * 3945's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ | ||
251 | #define IWL39_RTC_INST_LOWER_BOUND (0x000000) | ||
252 | #define IWL39_RTC_INST_UPPER_BOUND (0x014000) | ||
253 | |||
254 | #define IWL39_RTC_DATA_LOWER_BOUND (0x800000) | ||
255 | #define IWL39_RTC_DATA_UPPER_BOUND (0x808000) | ||
256 | |||
257 | #define IWL39_RTC_INST_SIZE (IWL39_RTC_INST_UPPER_BOUND - \ | ||
258 | IWL39_RTC_INST_LOWER_BOUND) | ||
259 | #define IWL39_RTC_DATA_SIZE (IWL39_RTC_DATA_UPPER_BOUND - \ | ||
260 | IWL39_RTC_DATA_LOWER_BOUND) | ||
261 | |||
262 | #define IWL39_MAX_INST_SIZE IWL39_RTC_INST_SIZE | ||
263 | #define IWL39_MAX_DATA_SIZE IWL39_RTC_DATA_SIZE | ||
264 | |||
265 | /* Size of uCode instruction memory in bootstrap state machine */ | ||
266 | #define IWL39_MAX_BSM_SIZE IWL39_RTC_INST_SIZE | ||
267 | |||
268 | static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr) | ||
269 | { | ||
270 | return (addr >= IWL39_RTC_DATA_LOWER_BOUND) && | ||
271 | (addr < IWL39_RTC_DATA_UPPER_BOUND); | ||
272 | } | ||
273 | |||
274 | /* Base physical address of iwl3945_shared is provided to FH_TSSR_CBB_BASE | ||
275 | * and &iwl3945_shared.rx_read_ptr[0] is provided to FH_RCSR_RPTR_ADDR(0) */ | ||
276 | struct iwl3945_shared { | ||
277 | __le32 tx_base_ptr[8]; | ||
278 | } __packed; | ||
279 | |||
280 | static inline u8 iwl3945_hw_get_rate(__le16 rate_n_flags) | ||
281 | { | ||
282 | return le16_to_cpu(rate_n_flags) & 0xFF; | ||
283 | } | ||
284 | |||
285 | static inline u16 iwl3945_hw_get_rate_n_flags(__le16 rate_n_flags) | ||
286 | { | ||
287 | return le16_to_cpu(rate_n_flags); | ||
288 | } | ||
289 | |||
290 | static inline __le16 iwl3945_hw_set_rate_n_flags(u8 rate, u16 flags) | ||
291 | { | ||
292 | return cpu_to_le16((u16)rate|flags); | ||
293 | } | ||
294 | #endif | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c deleted file mode 100644 index dc7c3a4167a..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. | ||
4 | * | ||
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 | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | * | ||
25 | *****************************************************************************/ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/pci.h> | ||
31 | #include <linux/dma-mapping.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/skbuff.h> | ||
34 | #include <linux/netdevice.h> | ||
35 | #include <linux/wireless.h> | ||
36 | #include <net/mac80211.h> | ||
37 | #include <linux/etherdevice.h> | ||
38 | #include <asm/unaligned.h> | ||
39 | |||
40 | #include "iwl-commands.h" | ||
41 | #include "iwl-3945.h" | ||
42 | #include "iwl-core.h" | ||
43 | #include "iwl-dev.h" | ||
44 | #include "iwl-3945-led.h" | ||
45 | |||
46 | |||
47 | /* Send led command */ | ||
48 | static int iwl3945_send_led_cmd(struct iwl_priv *priv, | ||
49 | struct iwl_led_cmd *led_cmd) | ||
50 | { | ||
51 | struct iwl_host_cmd cmd = { | ||
52 | .id = REPLY_LEDS_CMD, | ||
53 | .len = sizeof(struct iwl_led_cmd), | ||
54 | .data = led_cmd, | ||
55 | .flags = CMD_ASYNC, | ||
56 | .callback = NULL, | ||
57 | }; | ||
58 | |||
59 | return iwl_send_cmd(priv, &cmd); | ||
60 | } | ||
61 | |||
62 | const struct iwl_led_ops iwl3945_led_ops = { | ||
63 | .cmd = iwl3945_send_led_cmd, | ||
64 | }; | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h deleted file mode 100644 index ce990adc51e..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. | ||
4 | * | ||
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 | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | * | ||
25 | *****************************************************************************/ | ||
26 | |||
27 | #ifndef __iwl_3945_led_h__ | ||
28 | #define __iwl_3945_led_h__ | ||
29 | |||
30 | extern const struct iwl_led_ops iwl3945_led_ops; | ||
31 | |||
32 | #endif /* __iwl_3945_led_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c deleted file mode 100644 index 1f3e7e34fbc..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ /dev/null | |||
@@ -1,995 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. | ||
4 | * | ||
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 | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | * | ||
25 | *****************************************************************************/ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/skbuff.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/wireless.h> | ||
32 | #include <net/mac80211.h> | ||
33 | |||
34 | #include <linux/netdevice.h> | ||
35 | #include <linux/etherdevice.h> | ||
36 | #include <linux/delay.h> | ||
37 | |||
38 | #include <linux/workqueue.h> | ||
39 | |||
40 | #include "iwl-commands.h" | ||
41 | #include "iwl-3945.h" | ||
42 | #include "iwl-sta.h" | ||
43 | |||
44 | #define RS_NAME "iwl-3945-rs" | ||
45 | |||
46 | static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT_3945] = { | ||
47 | 7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202 | ||
48 | }; | ||
49 | |||
50 | static s32 iwl3945_expected_tpt_g_prot[IWL_RATE_COUNT_3945] = { | ||
51 | 7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125 | ||
52 | }; | ||
53 | |||
54 | static s32 iwl3945_expected_tpt_a[IWL_RATE_COUNT_3945] = { | ||
55 | 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186 | ||
56 | }; | ||
57 | |||
58 | static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT_3945] = { | ||
59 | 7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0 | ||
60 | }; | ||
61 | |||
62 | struct iwl3945_tpt_entry { | ||
63 | s8 min_rssi; | ||
64 | u8 index; | ||
65 | }; | ||
66 | |||
67 | static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = { | ||
68 | {-60, IWL_RATE_54M_INDEX}, | ||
69 | {-64, IWL_RATE_48M_INDEX}, | ||
70 | {-72, IWL_RATE_36M_INDEX}, | ||
71 | {-80, IWL_RATE_24M_INDEX}, | ||
72 | {-84, IWL_RATE_18M_INDEX}, | ||
73 | {-85, IWL_RATE_12M_INDEX}, | ||
74 | {-87, IWL_RATE_9M_INDEX}, | ||
75 | {-89, IWL_RATE_6M_INDEX} | ||
76 | }; | ||
77 | |||
78 | static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = { | ||
79 | {-60, IWL_RATE_54M_INDEX}, | ||
80 | {-64, IWL_RATE_48M_INDEX}, | ||
81 | {-68, IWL_RATE_36M_INDEX}, | ||
82 | {-80, IWL_RATE_24M_INDEX}, | ||
83 | {-84, IWL_RATE_18M_INDEX}, | ||
84 | {-85, IWL_RATE_12M_INDEX}, | ||
85 | {-86, IWL_RATE_11M_INDEX}, | ||
86 | {-88, IWL_RATE_5M_INDEX}, | ||
87 | {-90, IWL_RATE_2M_INDEX}, | ||
88 | {-92, IWL_RATE_1M_INDEX} | ||
89 | }; | ||
90 | |||
91 | #define IWL_RATE_MAX_WINDOW 62 | ||
92 | #define IWL_RATE_FLUSH (3*HZ) | ||
93 | #define IWL_RATE_WIN_FLUSH (HZ/2) | ||
94 | #define IWL39_RATE_HIGH_TH 11520 | ||
95 | #define IWL_SUCCESS_UP_TH 8960 | ||
96 | #define IWL_SUCCESS_DOWN_TH 10880 | ||
97 | #define IWL_RATE_MIN_FAILURE_TH 6 | ||
98 | #define IWL_RATE_MIN_SUCCESS_TH 8 | ||
99 | #define IWL_RATE_DECREASE_TH 1920 | ||
100 | #define IWL_RATE_RETRY_TH 15 | ||
101 | |||
102 | static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band) | ||
103 | { | ||
104 | u32 index = 0; | ||
105 | u32 table_size = 0; | ||
106 | struct iwl3945_tpt_entry *tpt_table = NULL; | ||
107 | |||
108 | if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL)) | ||
109 | rssi = IWL_MIN_RSSI_VAL; | ||
110 | |||
111 | switch (band) { | ||
112 | case IEEE80211_BAND_2GHZ: | ||
113 | tpt_table = iwl3945_tpt_table_g; | ||
114 | table_size = ARRAY_SIZE(iwl3945_tpt_table_g); | ||
115 | break; | ||
116 | |||
117 | case IEEE80211_BAND_5GHZ: | ||
118 | tpt_table = iwl3945_tpt_table_a; | ||
119 | table_size = ARRAY_SIZE(iwl3945_tpt_table_a); | ||
120 | break; | ||
121 | |||
122 | default: | ||
123 | BUG(); | ||
124 | break; | ||
125 | } | ||
126 | |||
127 | while ((index < table_size) && (rssi < tpt_table[index].min_rssi)) | ||
128 | index++; | ||
129 | |||
130 | index = min(index, (table_size - 1)); | ||
131 | |||
132 | return tpt_table[index].index; | ||
133 | } | ||
134 | |||
135 | static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window) | ||
136 | { | ||
137 | window->data = 0; | ||
138 | window->success_counter = 0; | ||
139 | window->success_ratio = -1; | ||
140 | window->counter = 0; | ||
141 | window->average_tpt = IWL_INVALID_VALUE; | ||
142 | window->stamp = 0; | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * iwl3945_rate_scale_flush_windows - flush out the rate scale windows | ||
147 | * | ||
148 | * Returns the number of windows that have gathered data but were | ||
149 | * not flushed. If there were any that were not flushed, then | ||
150 | * reschedule the rate flushing routine. | ||
151 | */ | ||
152 | static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta) | ||
153 | { | ||
154 | int unflushed = 0; | ||
155 | int i; | ||
156 | unsigned long flags; | ||
157 | struct iwl_priv *priv __maybe_unused = rs_sta->priv; | ||
158 | |||
159 | /* | ||
160 | * For each rate, if we have collected data on that rate | ||
161 | * and it has been more than IWL_RATE_WIN_FLUSH | ||
162 | * since we flushed, clear out the gathered statistics | ||
163 | */ | ||
164 | for (i = 0; i < IWL_RATE_COUNT_3945; i++) { | ||
165 | if (!rs_sta->win[i].counter) | ||
166 | continue; | ||
167 | |||
168 | spin_lock_irqsave(&rs_sta->lock, flags); | ||
169 | if (time_after(jiffies, rs_sta->win[i].stamp + | ||
170 | IWL_RATE_WIN_FLUSH)) { | ||
171 | IWL_DEBUG_RATE(priv, "flushing %d samples of rate " | ||
172 | "index %d\n", | ||
173 | rs_sta->win[i].counter, i); | ||
174 | iwl3945_clear_window(&rs_sta->win[i]); | ||
175 | } else | ||
176 | unflushed++; | ||
177 | spin_unlock_irqrestore(&rs_sta->lock, flags); | ||
178 | } | ||
179 | |||
180 | return unflushed; | ||
181 | } | ||
182 | |||
183 | #define IWL_RATE_FLUSH_MAX 5000 /* msec */ | ||
184 | #define IWL_RATE_FLUSH_MIN 50 /* msec */ | ||
185 | #define IWL_AVERAGE_PACKETS 1500 | ||
186 | |||
187 | static void iwl3945_bg_rate_scale_flush(unsigned long data) | ||
188 | { | ||
189 | struct iwl3945_rs_sta *rs_sta = (void *)data; | ||
190 | struct iwl_priv *priv __maybe_unused = rs_sta->priv; | ||
191 | int unflushed = 0; | ||
192 | unsigned long flags; | ||
193 | u32 packet_count, duration, pps; | ||
194 | |||
195 | IWL_DEBUG_RATE(priv, "enter\n"); | ||
196 | |||
197 | unflushed = iwl3945_rate_scale_flush_windows(rs_sta); | ||
198 | |||
199 | spin_lock_irqsave(&rs_sta->lock, flags); | ||
200 | |||
201 | /* Number of packets Rx'd since last time this timer ran */ | ||
202 | packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1; | ||
203 | |||
204 | rs_sta->last_tx_packets = rs_sta->tx_packets + 1; | ||
205 | |||
206 | if (unflushed) { | ||
207 | duration = | ||
208 | jiffies_to_msecs(jiffies - rs_sta->last_partial_flush); | ||
209 | |||
210 | IWL_DEBUG_RATE(priv, "Tx'd %d packets in %dms\n", | ||
211 | packet_count, duration); | ||
212 | |||
213 | /* Determine packets per second */ | ||
214 | if (duration) | ||
215 | pps = (packet_count * 1000) / duration; | ||
216 | else | ||
217 | pps = 0; | ||
218 | |||
219 | if (pps) { | ||
220 | duration = (IWL_AVERAGE_PACKETS * 1000) / pps; | ||
221 | if (duration < IWL_RATE_FLUSH_MIN) | ||
222 | duration = IWL_RATE_FLUSH_MIN; | ||
223 | else if (duration > IWL_RATE_FLUSH_MAX) | ||
224 | duration = IWL_RATE_FLUSH_MAX; | ||
225 | } else | ||
226 | duration = IWL_RATE_FLUSH_MAX; | ||
227 | |||
228 | rs_sta->flush_time = msecs_to_jiffies(duration); | ||
229 | |||
230 | IWL_DEBUG_RATE(priv, "new flush period: %d msec ave %d\n", | ||
231 | duration, packet_count); | ||
232 | |||
233 | mod_timer(&rs_sta->rate_scale_flush, jiffies + | ||
234 | rs_sta->flush_time); | ||
235 | |||
236 | rs_sta->last_partial_flush = jiffies; | ||
237 | } else { | ||
238 | rs_sta->flush_time = IWL_RATE_FLUSH; | ||
239 | rs_sta->flush_pending = 0; | ||
240 | } | ||
241 | /* If there weren't any unflushed entries, we don't schedule the timer | ||
242 | * to run again */ | ||
243 | |||
244 | rs_sta->last_flush = jiffies; | ||
245 | |||
246 | spin_unlock_irqrestore(&rs_sta->lock, flags); | ||
247 | |||
248 | IWL_DEBUG_RATE(priv, "leave\n"); | ||
249 | } | ||
250 | |||
251 | /** | ||
252 | * iwl3945_collect_tx_data - Update the success/failure sliding window | ||
253 | * | ||
254 | * We keep a sliding window of the last 64 packets transmitted | ||
255 | * at this rate. window->data contains the bitmask of successful | ||
256 | * packets. | ||
257 | */ | ||
258 | static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, | ||
259 | struct iwl3945_rate_scale_data *window, | ||
260 | int success, int retries, int index) | ||
261 | { | ||
262 | unsigned long flags; | ||
263 | s32 fail_count; | ||
264 | struct iwl_priv *priv __maybe_unused = rs_sta->priv; | ||
265 | |||
266 | if (!retries) { | ||
267 | IWL_DEBUG_RATE(priv, "leave: retries == 0 -- should be at least 1\n"); | ||
268 | return; | ||
269 | } | ||
270 | |||
271 | spin_lock_irqsave(&rs_sta->lock, flags); | ||
272 | |||
273 | /* | ||
274 | * Keep track of only the latest 62 tx frame attempts in this rate's | ||
275 | * history window; anything older isn't really relevant any more. | ||
276 | * If we have filled up the sliding window, drop the oldest attempt; | ||
277 | * if the oldest attempt (highest bit in bitmap) shows "success", | ||
278 | * subtract "1" from the success counter (this is the main reason | ||
279 | * we keep these bitmaps!). | ||
280 | * */ | ||
281 | while (retries > 0) { | ||
282 | if (window->counter >= IWL_RATE_MAX_WINDOW) { | ||
283 | |||
284 | /* remove earliest */ | ||
285 | window->counter = IWL_RATE_MAX_WINDOW - 1; | ||
286 | |||
287 | if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) { | ||
288 | window->data &= ~(1ULL << (IWL_RATE_MAX_WINDOW - 1)); | ||
289 | window->success_counter--; | ||
290 | } | ||
291 | } | ||
292 | |||
293 | /* Increment frames-attempted counter */ | ||
294 | window->counter++; | ||
295 | |||
296 | /* Shift bitmap by one frame (throw away oldest history), | ||
297 | * OR in "1", and increment "success" if this | ||
298 | * frame was successful. */ | ||
299 | window->data <<= 1; | ||
300 | if (success > 0) { | ||
301 | window->success_counter++; | ||
302 | window->data |= 0x1; | ||
303 | success--; | ||
304 | } | ||
305 | |||
306 | retries--; | ||
307 | } | ||
308 | |||
309 | /* Calculate current success ratio, avoid divide-by-0! */ | ||
310 | if (window->counter > 0) | ||
311 | window->success_ratio = 128 * (100 * window->success_counter) | ||
312 | / window->counter; | ||
313 | else | ||
314 | window->success_ratio = IWL_INVALID_VALUE; | ||
315 | |||
316 | fail_count = window->counter - window->success_counter; | ||
317 | |||
318 | /* Calculate average throughput, if we have enough history. */ | ||
319 | if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) || | ||
320 | (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH)) | ||
321 | window->average_tpt = ((window->success_ratio * | ||
322 | rs_sta->expected_tpt[index] + 64) / 128); | ||
323 | else | ||
324 | window->average_tpt = IWL_INVALID_VALUE; | ||
325 | |||
326 | /* Tag this window as having been updated */ | ||
327 | window->stamp = jiffies; | ||
328 | |||
329 | spin_unlock_irqrestore(&rs_sta->lock, flags); | ||
330 | |||
331 | } | ||
332 | |||
333 | /* | ||
334 | * Called after adding a new station to initialize rate scaling | ||
335 | */ | ||
336 | void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id) | ||
337 | { | ||
338 | struct ieee80211_hw *hw = priv->hw; | ||
339 | struct ieee80211_conf *conf = &priv->hw->conf; | ||
340 | struct iwl3945_sta_priv *psta; | ||
341 | struct iwl3945_rs_sta *rs_sta; | ||
342 | struct ieee80211_supported_band *sband; | ||
343 | int i; | ||
344 | |||
345 | IWL_DEBUG_INFO(priv, "enter\n"); | ||
346 | if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id) | ||
347 | goto out; | ||
348 | |||
349 | psta = (struct iwl3945_sta_priv *) sta->drv_priv; | ||
350 | rs_sta = &psta->rs_sta; | ||
351 | sband = hw->wiphy->bands[conf->channel->band]; | ||
352 | |||
353 | rs_sta->priv = priv; | ||
354 | |||
355 | rs_sta->start_rate = IWL_RATE_INVALID; | ||
356 | |||
357 | /* default to just 802.11b */ | ||
358 | rs_sta->expected_tpt = iwl3945_expected_tpt_b; | ||
359 | |||
360 | rs_sta->last_partial_flush = jiffies; | ||
361 | rs_sta->last_flush = jiffies; | ||
362 | rs_sta->flush_time = IWL_RATE_FLUSH; | ||
363 | rs_sta->last_tx_packets = 0; | ||
364 | |||
365 | rs_sta->rate_scale_flush.data = (unsigned long)rs_sta; | ||
366 | rs_sta->rate_scale_flush.function = iwl3945_bg_rate_scale_flush; | ||
367 | |||
368 | for (i = 0; i < IWL_RATE_COUNT_3945; i++) | ||
369 | iwl3945_clear_window(&rs_sta->win[i]); | ||
370 | |||
371 | /* TODO: what is a good starting rate for STA? About middle? Maybe not | ||
372 | * the lowest or the highest rate.. Could consider using RSSI from | ||
373 | * previous packets? Need to have IEEE 802.1X auth succeed immediately | ||
374 | * after assoc.. */ | ||
375 | |||
376 | for (i = sband->n_bitrates - 1; i >= 0; i--) { | ||
377 | if (sta->supp_rates[sband->band] & (1 << i)) { | ||
378 | rs_sta->last_txrate_idx = i; | ||
379 | break; | ||
380 | } | ||
381 | } | ||
382 | |||
383 | priv->_3945.sta_supp_rates = sta->supp_rates[sband->band]; | ||
384 | /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ | ||
385 | if (sband->band == IEEE80211_BAND_5GHZ) { | ||
386 | rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; | ||
387 | priv->_3945.sta_supp_rates = priv->_3945.sta_supp_rates << | ||
388 | IWL_FIRST_OFDM_RATE; | ||
389 | } | ||
390 | |||
391 | out: | ||
392 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; | ||
393 | |||
394 | IWL_DEBUG_INFO(priv, "leave\n"); | ||
395 | } | ||
396 | |||
397 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | ||
398 | { | ||
399 | return hw->priv; | ||
400 | } | ||
401 | |||
402 | /* rate scale requires free function to be implemented */ | ||
403 | static void rs_free(void *priv) | ||
404 | { | ||
405 | return; | ||
406 | } | ||
407 | |||
408 | static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) | ||
409 | { | ||
410 | struct iwl3945_rs_sta *rs_sta; | ||
411 | struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; | ||
412 | struct iwl_priv *priv __maybe_unused = iwl_priv; | ||
413 | |||
414 | IWL_DEBUG_RATE(priv, "enter\n"); | ||
415 | |||
416 | rs_sta = &psta->rs_sta; | ||
417 | |||
418 | spin_lock_init(&rs_sta->lock); | ||
419 | init_timer(&rs_sta->rate_scale_flush); | ||
420 | |||
421 | IWL_DEBUG_RATE(priv, "leave\n"); | ||
422 | |||
423 | return rs_sta; | ||
424 | } | ||
425 | |||
426 | static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta, | ||
427 | void *priv_sta) | ||
428 | { | ||
429 | struct iwl3945_rs_sta *rs_sta = priv_sta; | ||
430 | |||
431 | /* | ||
432 | * Be careful not to use any members of iwl3945_rs_sta (like trying | ||
433 | * to use iwl_priv to print out debugging) since it may not be fully | ||
434 | * initialized at this point. | ||
435 | */ | ||
436 | del_timer_sync(&rs_sta->rate_scale_flush); | ||
437 | } | ||
438 | |||
439 | |||
440 | /** | ||
441 | * rs_tx_status - Update rate control values based on Tx results | ||
442 | * | ||
443 | * NOTE: Uses iwl_priv->retry_rate for the # of retries attempted by | ||
444 | * the hardware for each rate. | ||
445 | */ | ||
446 | static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband, | ||
447 | struct ieee80211_sta *sta, void *priv_sta, | ||
448 | struct sk_buff *skb) | ||
449 | { | ||
450 | s8 retries = 0, current_count; | ||
451 | int scale_rate_index, first_index, last_index; | ||
452 | unsigned long flags; | ||
453 | struct iwl_priv *priv = (struct iwl_priv *)priv_rate; | ||
454 | struct iwl3945_rs_sta *rs_sta = priv_sta; | ||
455 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
456 | |||
457 | IWL_DEBUG_RATE(priv, "enter\n"); | ||
458 | |||
459 | retries = info->status.rates[0].count; | ||
460 | /* Sanity Check for retries */ | ||
461 | if (retries > IWL_RATE_RETRY_TH) | ||
462 | retries = IWL_RATE_RETRY_TH; | ||
463 | |||
464 | first_index = sband->bitrates[info->status.rates[0].idx].hw_value; | ||
465 | if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) { | ||
466 | IWL_DEBUG_RATE(priv, "leave: Rate out of bounds: %d\n", first_index); | ||
467 | return; | ||
468 | } | ||
469 | |||
470 | if (!priv_sta) { | ||
471 | IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n"); | ||
472 | return; | ||
473 | } | ||
474 | |||
475 | /* Treat uninitialized rate scaling data same as non-existing. */ | ||
476 | if (!rs_sta->priv) { | ||
477 | IWL_DEBUG_RATE(priv, "leave: STA priv data uninitialized!\n"); | ||
478 | return; | ||
479 | } | ||
480 | |||
481 | |||
482 | rs_sta->tx_packets++; | ||
483 | |||
484 | scale_rate_index = first_index; | ||
485 | last_index = first_index; | ||
486 | |||
487 | /* | ||
488 | * Update the window for each rate. We determine which rates | ||
489 | * were Tx'd based on the total number of retries vs. the number | ||
490 | * of retries configured for each rate -- currently set to the | ||
491 | * priv value 'retry_rate' vs. rate specific | ||
492 | * | ||
493 | * On exit from this while loop last_index indicates the rate | ||
494 | * at which the frame was finally transmitted (or failed if no | ||
495 | * ACK) | ||
496 | */ | ||
497 | while (retries > 1) { | ||
498 | if ((retries - 1) < priv->retry_rate) { | ||
499 | current_count = (retries - 1); | ||
500 | last_index = scale_rate_index; | ||
501 | } else { | ||
502 | current_count = priv->retry_rate; | ||
503 | last_index = iwl3945_rs_next_rate(priv, | ||
504 | scale_rate_index); | ||
505 | } | ||
506 | |||
507 | /* Update this rate accounting for as many retries | ||
508 | * as was used for it (per current_count) */ | ||
509 | iwl3945_collect_tx_data(rs_sta, | ||
510 | &rs_sta->win[scale_rate_index], | ||
511 | 0, current_count, scale_rate_index); | ||
512 | IWL_DEBUG_RATE(priv, "Update rate %d for %d retries.\n", | ||
513 | scale_rate_index, current_count); | ||
514 | |||
515 | retries -= current_count; | ||
516 | |||
517 | scale_rate_index = last_index; | ||
518 | } | ||
519 | |||
520 | |||
521 | /* Update the last index window with success/failure based on ACK */ | ||
522 | IWL_DEBUG_RATE(priv, "Update rate %d with %s.\n", | ||
523 | last_index, | ||
524 | (info->flags & IEEE80211_TX_STAT_ACK) ? | ||
525 | "success" : "failure"); | ||
526 | iwl3945_collect_tx_data(rs_sta, | ||
527 | &rs_sta->win[last_index], | ||
528 | info->flags & IEEE80211_TX_STAT_ACK, 1, last_index); | ||
529 | |||
530 | /* We updated the rate scale window -- if its been more than | ||
531 | * flush_time since the last run, schedule the flush | ||
532 | * again */ | ||
533 | spin_lock_irqsave(&rs_sta->lock, flags); | ||
534 | |||
535 | if (!rs_sta->flush_pending && | ||
536 | time_after(jiffies, rs_sta->last_flush + | ||
537 | rs_sta->flush_time)) { | ||
538 | |||
539 | rs_sta->last_partial_flush = jiffies; | ||
540 | rs_sta->flush_pending = 1; | ||
541 | mod_timer(&rs_sta->rate_scale_flush, | ||
542 | jiffies + rs_sta->flush_time); | ||
543 | } | ||
544 | |||
545 | spin_unlock_irqrestore(&rs_sta->lock, flags); | ||
546 | |||
547 | IWL_DEBUG_RATE(priv, "leave\n"); | ||
548 | } | ||
549 | |||
550 | static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, | ||
551 | u8 index, u16 rate_mask, enum ieee80211_band band) | ||
552 | { | ||
553 | u8 high = IWL_RATE_INVALID; | ||
554 | u8 low = IWL_RATE_INVALID; | ||
555 | struct iwl_priv *priv __maybe_unused = rs_sta->priv; | ||
556 | |||
557 | /* 802.11A walks to the next literal adjacent rate in | ||
558 | * the rate table */ | ||
559 | if (unlikely(band == IEEE80211_BAND_5GHZ)) { | ||
560 | int i; | ||
561 | u32 mask; | ||
562 | |||
563 | /* Find the previous rate that is in the rate mask */ | ||
564 | i = index - 1; | ||
565 | for (mask = (1 << i); i >= 0; i--, mask >>= 1) { | ||
566 | if (rate_mask & mask) { | ||
567 | low = i; | ||
568 | break; | ||
569 | } | ||
570 | } | ||
571 | |||
572 | /* Find the next rate that is in the rate mask */ | ||
573 | i = index + 1; | ||
574 | for (mask = (1 << i); i < IWL_RATE_COUNT_3945; | ||
575 | i++, mask <<= 1) { | ||
576 | if (rate_mask & mask) { | ||
577 | high = i; | ||
578 | break; | ||
579 | } | ||
580 | } | ||
581 | |||
582 | return (high << 8) | low; | ||
583 | } | ||
584 | |||
585 | low = index; | ||
586 | while (low != IWL_RATE_INVALID) { | ||
587 | if (rs_sta->tgg) | ||
588 | low = iwl3945_rates[low].prev_rs_tgg; | ||
589 | else | ||
590 | low = iwl3945_rates[low].prev_rs; | ||
591 | if (low == IWL_RATE_INVALID) | ||
592 | break; | ||
593 | if (rate_mask & (1 << low)) | ||
594 | break; | ||
595 | IWL_DEBUG_RATE(priv, "Skipping masked lower rate: %d\n", low); | ||
596 | } | ||
597 | |||
598 | high = index; | ||
599 | while (high != IWL_RATE_INVALID) { | ||
600 | if (rs_sta->tgg) | ||
601 | high = iwl3945_rates[high].next_rs_tgg; | ||
602 | else | ||
603 | high = iwl3945_rates[high].next_rs; | ||
604 | if (high == IWL_RATE_INVALID) | ||
605 | break; | ||
606 | if (rate_mask & (1 << high)) | ||
607 | break; | ||
608 | IWL_DEBUG_RATE(priv, "Skipping masked higher rate: %d\n", high); | ||
609 | } | ||
610 | |||
611 | return (high << 8) | low; | ||
612 | } | ||
613 | |||
614 | /** | ||
615 | * rs_get_rate - find the rate for the requested packet | ||
616 | * | ||
617 | * Returns the ieee80211_rate structure allocated by the driver. | ||
618 | * | ||
619 | * The rate control algorithm has no internal mapping between hw_mode's | ||
620 | * rate ordering and the rate ordering used by the rate control algorithm. | ||
621 | * | ||
622 | * The rate control algorithm uses a single table of rates that goes across | ||
623 | * the entire A/B/G spectrum vs. being limited to just one particular | ||
624 | * hw_mode. | ||
625 | * | ||
626 | * As such, we can't convert the index obtained below into the hw_mode's | ||
627 | * rate table and must reference the driver allocated rate table | ||
628 | * | ||
629 | */ | ||
630 | static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | ||
631 | void *priv_sta, struct ieee80211_tx_rate_control *txrc) | ||
632 | { | ||
633 | struct ieee80211_supported_band *sband = txrc->sband; | ||
634 | struct sk_buff *skb = txrc->skb; | ||
635 | u8 low = IWL_RATE_INVALID; | ||
636 | u8 high = IWL_RATE_INVALID; | ||
637 | u16 high_low; | ||
638 | int index; | ||
639 | struct iwl3945_rs_sta *rs_sta = priv_sta; | ||
640 | struct iwl3945_rate_scale_data *window = NULL; | ||
641 | int current_tpt = IWL_INVALID_VALUE; | ||
642 | int low_tpt = IWL_INVALID_VALUE; | ||
643 | int high_tpt = IWL_INVALID_VALUE; | ||
644 | u32 fail_count; | ||
645 | s8 scale_action = 0; | ||
646 | unsigned long flags; | ||
647 | u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0; | ||
648 | s8 max_rate_idx = -1; | ||
649 | struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r; | ||
650 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
651 | |||
652 | IWL_DEBUG_RATE(priv, "enter\n"); | ||
653 | |||
654 | /* Treat uninitialized rate scaling data same as non-existing. */ | ||
655 | if (rs_sta && !rs_sta->priv) { | ||
656 | IWL_DEBUG_RATE(priv, "Rate scaling information not initialized yet.\n"); | ||
657 | priv_sta = NULL; | ||
658 | } | ||
659 | |||
660 | if (rate_control_send_low(sta, priv_sta, txrc)) | ||
661 | return; | ||
662 | |||
663 | rate_mask = sta->supp_rates[sband->band]; | ||
664 | |||
665 | /* get user max rate if set */ | ||
666 | max_rate_idx = txrc->max_rate_idx; | ||
667 | if ((sband->band == IEEE80211_BAND_5GHZ) && (max_rate_idx != -1)) | ||
668 | max_rate_idx += IWL_FIRST_OFDM_RATE; | ||
669 | if ((max_rate_idx < 0) || (max_rate_idx >= IWL_RATE_COUNT)) | ||
670 | max_rate_idx = -1; | ||
671 | |||
672 | index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT_3945 - 1); | ||
673 | |||
674 | if (sband->band == IEEE80211_BAND_5GHZ) | ||
675 | rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; | ||
676 | |||
677 | spin_lock_irqsave(&rs_sta->lock, flags); | ||
678 | |||
679 | /* for recent assoc, choose best rate regarding | ||
680 | * to rssi value | ||
681 | */ | ||
682 | if (rs_sta->start_rate != IWL_RATE_INVALID) { | ||
683 | if (rs_sta->start_rate < index && | ||
684 | (rate_mask & (1 << rs_sta->start_rate))) | ||
685 | index = rs_sta->start_rate; | ||
686 | rs_sta->start_rate = IWL_RATE_INVALID; | ||
687 | } | ||
688 | |||
689 | /* force user max rate if set by user */ | ||
690 | if ((max_rate_idx != -1) && (max_rate_idx < index)) { | ||
691 | if (rate_mask & (1 << max_rate_idx)) | ||
692 | index = max_rate_idx; | ||
693 | } | ||
694 | |||
695 | window = &(rs_sta->win[index]); | ||
696 | |||
697 | fail_count = window->counter - window->success_counter; | ||
698 | |||
699 | if (((fail_count < IWL_RATE_MIN_FAILURE_TH) && | ||
700 | (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) { | ||
701 | spin_unlock_irqrestore(&rs_sta->lock, flags); | ||
702 | |||
703 | IWL_DEBUG_RATE(priv, "Invalid average_tpt on rate %d: " | ||
704 | "counter: %d, success_counter: %d, " | ||
705 | "expected_tpt is %sNULL\n", | ||
706 | index, | ||
707 | window->counter, | ||
708 | window->success_counter, | ||
709 | rs_sta->expected_tpt ? "not " : ""); | ||
710 | |||
711 | /* Can't calculate this yet; not enough history */ | ||
712 | window->average_tpt = IWL_INVALID_VALUE; | ||
713 | goto out; | ||
714 | |||
715 | } | ||
716 | |||
717 | current_tpt = window->average_tpt; | ||
718 | |||
719 | high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask, | ||
720 | sband->band); | ||
721 | low = high_low & 0xff; | ||
722 | high = (high_low >> 8) & 0xff; | ||
723 | |||
724 | /* If user set max rate, dont allow higher than user constrain */ | ||
725 | if ((max_rate_idx != -1) && (max_rate_idx < high)) | ||
726 | high = IWL_RATE_INVALID; | ||
727 | |||
728 | /* Collect Measured throughputs of adjacent rates */ | ||
729 | if (low != IWL_RATE_INVALID) | ||
730 | low_tpt = rs_sta->win[low].average_tpt; | ||
731 | |||
732 | if (high != IWL_RATE_INVALID) | ||
733 | high_tpt = rs_sta->win[high].average_tpt; | ||
734 | |||
735 | spin_unlock_irqrestore(&rs_sta->lock, flags); | ||
736 | |||
737 | scale_action = 0; | ||
738 | |||
739 | /* Low success ratio , need to drop the rate */ | ||
740 | if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) { | ||
741 | IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n"); | ||
742 | scale_action = -1; | ||
743 | /* No throughput measured yet for adjacent rates, | ||
744 | * try increase */ | ||
745 | } else if ((low_tpt == IWL_INVALID_VALUE) && | ||
746 | (high_tpt == IWL_INVALID_VALUE)) { | ||
747 | |||
748 | if (high != IWL_RATE_INVALID && window->success_ratio >= IWL_RATE_INCREASE_TH) | ||
749 | scale_action = 1; | ||
750 | else if (low != IWL_RATE_INVALID) | ||
751 | scale_action = 0; | ||
752 | |||
753 | /* Both adjacent throughputs are measured, but neither one has | ||
754 | * better throughput; we're using the best rate, don't change | ||
755 | * it! */ | ||
756 | } else if ((low_tpt != IWL_INVALID_VALUE) && | ||
757 | (high_tpt != IWL_INVALID_VALUE) && | ||
758 | (low_tpt < current_tpt) && (high_tpt < current_tpt)) { | ||
759 | |||
760 | IWL_DEBUG_RATE(priv, "No action -- low [%d] & high [%d] < " | ||
761 | "current_tpt [%d]\n", | ||
762 | low_tpt, high_tpt, current_tpt); | ||
763 | scale_action = 0; | ||
764 | |||
765 | /* At least one of the rates has better throughput */ | ||
766 | } else { | ||
767 | if (high_tpt != IWL_INVALID_VALUE) { | ||
768 | |||
769 | /* High rate has better throughput, Increase | ||
770 | * rate */ | ||
771 | if (high_tpt > current_tpt && | ||
772 | window->success_ratio >= IWL_RATE_INCREASE_TH) | ||
773 | scale_action = 1; | ||
774 | else { | ||
775 | IWL_DEBUG_RATE(priv, | ||
776 | "decrease rate because of high tpt\n"); | ||
777 | scale_action = 0; | ||
778 | } | ||
779 | } else if (low_tpt != IWL_INVALID_VALUE) { | ||
780 | if (low_tpt > current_tpt) { | ||
781 | IWL_DEBUG_RATE(priv, | ||
782 | "decrease rate because of low tpt\n"); | ||
783 | scale_action = -1; | ||
784 | } else if (window->success_ratio >= IWL_RATE_INCREASE_TH) { | ||
785 | /* Lower rate has better | ||
786 | * throughput,decrease rate */ | ||
787 | scale_action = 1; | ||
788 | } | ||
789 | } | ||
790 | } | ||
791 | |||
792 | /* Sanity check; asked for decrease, but success rate or throughput | ||
793 | * has been good at old rate. Don't change it. */ | ||
794 | if ((scale_action == -1) && (low != IWL_RATE_INVALID) && | ||
795 | ((window->success_ratio > IWL_RATE_HIGH_TH) || | ||
796 | (current_tpt > (100 * rs_sta->expected_tpt[low])))) | ||
797 | scale_action = 0; | ||
798 | |||
799 | switch (scale_action) { | ||
800 | case -1: | ||
801 | |||
802 | /* Decrese rate */ | ||
803 | if (low != IWL_RATE_INVALID) | ||
804 | index = low; | ||
805 | break; | ||
806 | |||
807 | case 1: | ||
808 | /* Increase rate */ | ||
809 | if (high != IWL_RATE_INVALID) | ||
810 | index = high; | ||
811 | |||
812 | break; | ||
813 | |||
814 | case 0: | ||
815 | default: | ||
816 | /* No change */ | ||
817 | break; | ||
818 | } | ||
819 | |||
820 | IWL_DEBUG_RATE(priv, "Selected %d (action %d) - low %d high %d\n", | ||
821 | index, scale_action, low, high); | ||
822 | |||
823 | out: | ||
824 | |||
825 | rs_sta->last_txrate_idx = index; | ||
826 | if (sband->band == IEEE80211_BAND_5GHZ) | ||
827 | info->control.rates[0].idx = rs_sta->last_txrate_idx - | ||
828 | IWL_FIRST_OFDM_RATE; | ||
829 | else | ||
830 | info->control.rates[0].idx = rs_sta->last_txrate_idx; | ||
831 | |||
832 | IWL_DEBUG_RATE(priv, "leave: %d\n", index); | ||
833 | } | ||
834 | |||
835 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
836 | static int iwl3945_open_file_generic(struct inode *inode, struct file *file) | ||
837 | { | ||
838 | file->private_data = inode->i_private; | ||
839 | return 0; | ||
840 | } | ||
841 | |||
842 | static ssize_t iwl3945_sta_dbgfs_stats_table_read(struct file *file, | ||
843 | char __user *user_buf, | ||
844 | size_t count, loff_t *ppos) | ||
845 | { | ||
846 | char *buff; | ||
847 | int desc = 0; | ||
848 | int j; | ||
849 | ssize_t ret; | ||
850 | struct iwl3945_rs_sta *lq_sta = file->private_data; | ||
851 | |||
852 | buff = kmalloc(1024, GFP_KERNEL); | ||
853 | if (!buff) | ||
854 | return -ENOMEM; | ||
855 | |||
856 | desc += sprintf(buff + desc, "tx packets=%d last rate index=%d\n" | ||
857 | "rate=0x%X flush time %d\n", | ||
858 | lq_sta->tx_packets, | ||
859 | lq_sta->last_txrate_idx, | ||
860 | lq_sta->start_rate, jiffies_to_msecs(lq_sta->flush_time)); | ||
861 | for (j = 0; j < IWL_RATE_COUNT_3945; j++) { | ||
862 | desc += sprintf(buff+desc, | ||
863 | "counter=%d success=%d %%=%d\n", | ||
864 | lq_sta->win[j].counter, | ||
865 | lq_sta->win[j].success_counter, | ||
866 | lq_sta->win[j].success_ratio); | ||
867 | } | ||
868 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); | ||
869 | kfree(buff); | ||
870 | return ret; | ||
871 | } | ||
872 | |||
873 | static const struct file_operations rs_sta_dbgfs_stats_table_ops = { | ||
874 | .read = iwl3945_sta_dbgfs_stats_table_read, | ||
875 | .open = iwl3945_open_file_generic, | ||
876 | .llseek = default_llseek, | ||
877 | }; | ||
878 | |||
879 | static void iwl3945_add_debugfs(void *priv, void *priv_sta, | ||
880 | struct dentry *dir) | ||
881 | { | ||
882 | struct iwl3945_rs_sta *lq_sta = priv_sta; | ||
883 | |||
884 | lq_sta->rs_sta_dbgfs_stats_table_file = | ||
885 | debugfs_create_file("rate_stats_table", 0600, dir, | ||
886 | lq_sta, &rs_sta_dbgfs_stats_table_ops); | ||
887 | |||
888 | } | ||
889 | |||
890 | static void iwl3945_remove_debugfs(void *priv, void *priv_sta) | ||
891 | { | ||
892 | struct iwl3945_rs_sta *lq_sta = priv_sta; | ||
893 | debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); | ||
894 | } | ||
895 | #endif | ||
896 | |||
897 | /* | ||
898 | * Initialization of rate scaling information is done by driver after | ||
899 | * the station is added. Since mac80211 calls this function before a | ||
900 | * station is added we ignore it. | ||
901 | */ | ||
902 | static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband, | ||
903 | struct ieee80211_sta *sta, void *priv_sta) | ||
904 | { | ||
905 | } | ||
906 | |||
907 | static struct rate_control_ops rs_ops = { | ||
908 | .module = NULL, | ||
909 | .name = RS_NAME, | ||
910 | .tx_status = rs_tx_status, | ||
911 | .get_rate = rs_get_rate, | ||
912 | .rate_init = rs_rate_init_stub, | ||
913 | .alloc = rs_alloc, | ||
914 | .free = rs_free, | ||
915 | .alloc_sta = rs_alloc_sta, | ||
916 | .free_sta = rs_free_sta, | ||
917 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
918 | .add_sta_debugfs = iwl3945_add_debugfs, | ||
919 | .remove_sta_debugfs = iwl3945_remove_debugfs, | ||
920 | #endif | ||
921 | |||
922 | }; | ||
923 | void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) | ||
924 | { | ||
925 | struct iwl_priv *priv = hw->priv; | ||
926 | s32 rssi = 0; | ||
927 | unsigned long flags; | ||
928 | struct iwl3945_rs_sta *rs_sta; | ||
929 | struct ieee80211_sta *sta; | ||
930 | struct iwl3945_sta_priv *psta; | ||
931 | |||
932 | IWL_DEBUG_RATE(priv, "enter\n"); | ||
933 | |||
934 | rcu_read_lock(); | ||
935 | |||
936 | sta = ieee80211_find_sta(priv->contexts[IWL_RXON_CTX_BSS].vif, | ||
937 | priv->stations[sta_id].sta.sta.addr); | ||
938 | if (!sta) { | ||
939 | IWL_DEBUG_RATE(priv, "Unable to find station to initialize rate scaling.\n"); | ||
940 | rcu_read_unlock(); | ||
941 | return; | ||
942 | } | ||
943 | |||
944 | psta = (void *) sta->drv_priv; | ||
945 | rs_sta = &psta->rs_sta; | ||
946 | |||
947 | spin_lock_irqsave(&rs_sta->lock, flags); | ||
948 | |||
949 | rs_sta->tgg = 0; | ||
950 | switch (priv->band) { | ||
951 | case IEEE80211_BAND_2GHZ: | ||
952 | /* TODO: this always does G, not a regression */ | ||
953 | if (priv->contexts[IWL_RXON_CTX_BSS].active.flags & | ||
954 | RXON_FLG_TGG_PROTECT_MSK) { | ||
955 | rs_sta->tgg = 1; | ||
956 | rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot; | ||
957 | } else | ||
958 | rs_sta->expected_tpt = iwl3945_expected_tpt_g; | ||
959 | break; | ||
960 | |||
961 | case IEEE80211_BAND_5GHZ: | ||
962 | rs_sta->expected_tpt = iwl3945_expected_tpt_a; | ||
963 | break; | ||
964 | case IEEE80211_NUM_BANDS: | ||
965 | BUG(); | ||
966 | break; | ||
967 | } | ||
968 | |||
969 | spin_unlock_irqrestore(&rs_sta->lock, flags); | ||
970 | |||
971 | rssi = priv->_3945.last_rx_rssi; | ||
972 | if (rssi == 0) | ||
973 | rssi = IWL_MIN_RSSI_VAL; | ||
974 | |||
975 | IWL_DEBUG_RATE(priv, "Network RSSI: %d\n", rssi); | ||
976 | |||
977 | rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band); | ||
978 | |||
979 | IWL_DEBUG_RATE(priv, "leave: rssi %d assign rate index: " | ||
980 | "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate, | ||
981 | iwl3945_rates[rs_sta->start_rate].plcp); | ||
982 | rcu_read_unlock(); | ||
983 | } | ||
984 | |||
985 | int iwl3945_rate_control_register(void) | ||
986 | { | ||
987 | return ieee80211_rate_control_register(&rs_ops); | ||
988 | } | ||
989 | |||
990 | void iwl3945_rate_control_unregister(void) | ||
991 | { | ||
992 | ieee80211_rate_control_unregister(&rs_ops); | ||
993 | } | ||
994 | |||
995 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c deleted file mode 100644 index 5b6932c2193..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ /dev/null | |||
@@ -1,2819 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. | ||
4 | * | ||
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 | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | * | ||
25 | *****************************************************************************/ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <linux/dma-mapping.h> | ||
33 | #include <linux/delay.h> | ||
34 | #include <linux/sched.h> | ||
35 | #include <linux/skbuff.h> | ||
36 | #include <linux/netdevice.h> | ||
37 | #include <linux/wireless.h> | ||
38 | #include <linux/firmware.h> | ||
39 | #include <linux/etherdevice.h> | ||
40 | #include <asm/unaligned.h> | ||
41 | #include <net/mac80211.h> | ||
42 | |||
43 | #include "iwl-fh.h" | ||
44 | #include "iwl-3945-fh.h" | ||
45 | #include "iwl-commands.h" | ||
46 | #include "iwl-sta.h" | ||
47 | #include "iwl-3945.h" | ||
48 | #include "iwl-eeprom.h" | ||
49 | #include "iwl-core.h" | ||
50 | #include "iwl-helpers.h" | ||
51 | #include "iwl-led.h" | ||
52 | #include "iwl-3945-led.h" | ||
53 | #include "iwl-3945-debugfs.h" | ||
54 | #include "iwl-legacy.h" | ||
55 | |||
56 | #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ | ||
57 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ | ||
58 | IWL_RATE_##r##M_IEEE, \ | ||
59 | IWL_RATE_##ip##M_INDEX, \ | ||
60 | IWL_RATE_##in##M_INDEX, \ | ||
61 | IWL_RATE_##rp##M_INDEX, \ | ||
62 | IWL_RATE_##rn##M_INDEX, \ | ||
63 | IWL_RATE_##pp##M_INDEX, \ | ||
64 | IWL_RATE_##np##M_INDEX, \ | ||
65 | IWL_RATE_##r##M_INDEX_TABLE, \ | ||
66 | IWL_RATE_##ip##M_INDEX_TABLE } | ||
67 | |||
68 | /* | ||
69 | * Parameter order: | ||
70 | * rate, prev rate, next rate, prev tgg rate, next tgg rate | ||
71 | * | ||
72 | * If there isn't a valid next or previous rate then INV is used which | ||
73 | * maps to IWL_RATE_INVALID | ||
74 | * | ||
75 | */ | ||
76 | const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945] = { | ||
77 | IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2), /* 1mbps */ | ||
78 | IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5), /* 2mbps */ | ||
79 | IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11), /*5.5mbps */ | ||
80 | IWL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18), /* 11mbps */ | ||
81 | IWL_DECLARE_RATE_INFO(6, 5, 9, 5, 11, 5, 11), /* 6mbps */ | ||
82 | IWL_DECLARE_RATE_INFO(9, 6, 11, 5, 11, 5, 11), /* 9mbps */ | ||
83 | IWL_DECLARE_RATE_INFO(12, 11, 18, 11, 18, 11, 18), /* 12mbps */ | ||
84 | IWL_DECLARE_RATE_INFO(18, 12, 24, 12, 24, 11, 24), /* 18mbps */ | ||
85 | IWL_DECLARE_RATE_INFO(24, 18, 36, 18, 36, 18, 36), /* 24mbps */ | ||
86 | IWL_DECLARE_RATE_INFO(36, 24, 48, 24, 48, 24, 48), /* 36mbps */ | ||
87 | IWL_DECLARE_RATE_INFO(48, 36, 54, 36, 54, 36, 54), /* 48mbps */ | ||
88 | IWL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),/* 54mbps */ | ||
89 | }; | ||
90 | |||
91 | static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index) | ||
92 | { | ||
93 | u8 rate = iwl3945_rates[rate_index].prev_ieee; | ||
94 | |||
95 | if (rate == IWL_RATE_INVALID) | ||
96 | rate = rate_index; | ||
97 | return rate; | ||
98 | } | ||
99 | |||
100 | /* 1 = enable the iwl3945_disable_events() function */ | ||
101 | #define IWL_EVT_DISABLE (0) | ||
102 | #define IWL_EVT_DISABLE_SIZE (1532/32) | ||
103 | |||
104 | /** | ||
105 | * iwl3945_disable_events - Disable selected events in uCode event log | ||
106 | * | ||
107 | * Disable an event by writing "1"s into "disable" | ||
108 | * bitmap in SRAM. Bit position corresponds to Event # (id/type). | ||
109 | * Default values of 0 enable uCode events to be logged. | ||
110 | * Use for only special debugging. This function is just a placeholder as-is, | ||
111 | * you'll need to provide the special bits! ... | ||
112 | * ... and set IWL_EVT_DISABLE to 1. */ | ||
113 | void iwl3945_disable_events(struct iwl_priv *priv) | ||
114 | { | ||
115 | int i; | ||
116 | u32 base; /* SRAM address of event log header */ | ||
117 | u32 disable_ptr; /* SRAM address of event-disable bitmap array */ | ||
118 | u32 array_size; /* # of u32 entries in array */ | ||
119 | static const u32 evt_disable[IWL_EVT_DISABLE_SIZE] = { | ||
120 | 0x00000000, /* 31 - 0 Event id numbers */ | ||
121 | 0x00000000, /* 63 - 32 */ | ||
122 | 0x00000000, /* 95 - 64 */ | ||
123 | 0x00000000, /* 127 - 96 */ | ||
124 | 0x00000000, /* 159 - 128 */ | ||
125 | 0x00000000, /* 191 - 160 */ | ||
126 | 0x00000000, /* 223 - 192 */ | ||
127 | 0x00000000, /* 255 - 224 */ | ||
128 | 0x00000000, /* 287 - 256 */ | ||
129 | 0x00000000, /* 319 - 288 */ | ||
130 | 0x00000000, /* 351 - 320 */ | ||
131 | 0x00000000, /* 383 - 352 */ | ||
132 | 0x00000000, /* 415 - 384 */ | ||
133 | 0x00000000, /* 447 - 416 */ | ||
134 | 0x00000000, /* 479 - 448 */ | ||
135 | 0x00000000, /* 511 - 480 */ | ||
136 | 0x00000000, /* 543 - 512 */ | ||
137 | 0x00000000, /* 575 - 544 */ | ||
138 | 0x00000000, /* 607 - 576 */ | ||
139 | 0x00000000, /* 639 - 608 */ | ||
140 | 0x00000000, /* 671 - 640 */ | ||
141 | 0x00000000, /* 703 - 672 */ | ||
142 | 0x00000000, /* 735 - 704 */ | ||
143 | 0x00000000, /* 767 - 736 */ | ||
144 | 0x00000000, /* 799 - 768 */ | ||
145 | 0x00000000, /* 831 - 800 */ | ||
146 | 0x00000000, /* 863 - 832 */ | ||
147 | 0x00000000, /* 895 - 864 */ | ||
148 | 0x00000000, /* 927 - 896 */ | ||
149 | 0x00000000, /* 959 - 928 */ | ||
150 | 0x00000000, /* 991 - 960 */ | ||
151 | 0x00000000, /* 1023 - 992 */ | ||
152 | 0x00000000, /* 1055 - 1024 */ | ||
153 | 0x00000000, /* 1087 - 1056 */ | ||
154 | 0x00000000, /* 1119 - 1088 */ | ||
155 | 0x00000000, /* 1151 - 1120 */ | ||
156 | 0x00000000, /* 1183 - 1152 */ | ||
157 | 0x00000000, /* 1215 - 1184 */ | ||
158 | 0x00000000, /* 1247 - 1216 */ | ||
159 | 0x00000000, /* 1279 - 1248 */ | ||
160 | 0x00000000, /* 1311 - 1280 */ | ||
161 | 0x00000000, /* 1343 - 1312 */ | ||
162 | 0x00000000, /* 1375 - 1344 */ | ||
163 | 0x00000000, /* 1407 - 1376 */ | ||
164 | 0x00000000, /* 1439 - 1408 */ | ||
165 | 0x00000000, /* 1471 - 1440 */ | ||
166 | 0x00000000, /* 1503 - 1472 */ | ||
167 | }; | ||
168 | |||
169 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | ||
170 | if (!iwl3945_hw_valid_rtc_data_addr(base)) { | ||
171 | IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); | ||
172 | return; | ||
173 | } | ||
174 | |||
175 | disable_ptr = iwl_read_targ_mem(priv, base + (4 * sizeof(u32))); | ||
176 | array_size = iwl_read_targ_mem(priv, base + (5 * sizeof(u32))); | ||
177 | |||
178 | if (IWL_EVT_DISABLE && (array_size == IWL_EVT_DISABLE_SIZE)) { | ||
179 | IWL_DEBUG_INFO(priv, "Disabling selected uCode log events at 0x%x\n", | ||
180 | disable_ptr); | ||
181 | for (i = 0; i < IWL_EVT_DISABLE_SIZE; i++) | ||
182 | iwl_write_targ_mem(priv, | ||
183 | disable_ptr + (i * sizeof(u32)), | ||
184 | evt_disable[i]); | ||
185 | |||
186 | } else { | ||
187 | IWL_DEBUG_INFO(priv, "Selected uCode log events may be disabled\n"); | ||
188 | IWL_DEBUG_INFO(priv, " by writing \"1\"s into disable bitmap\n"); | ||
189 | IWL_DEBUG_INFO(priv, " in SRAM at 0x%x, size %d u32s\n", | ||
190 | disable_ptr, array_size); | ||
191 | } | ||
192 | |||
193 | } | ||
194 | |||
195 | static int iwl3945_hwrate_to_plcp_idx(u8 plcp) | ||
196 | { | ||
197 | int idx; | ||
198 | |||
199 | for (idx = 0; idx < IWL_RATE_COUNT_3945; idx++) | ||
200 | if (iwl3945_rates[idx].plcp == plcp) | ||
201 | return idx; | ||
202 | return -1; | ||
203 | } | ||
204 | |||
205 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
206 | #define TX_STATUS_ENTRY(x) case TX_3945_STATUS_FAIL_ ## x: return #x | ||
207 | |||
208 | static const char *iwl3945_get_tx_fail_reason(u32 status) | ||
209 | { | ||
210 | switch (status & TX_STATUS_MSK) { | ||
211 | case TX_3945_STATUS_SUCCESS: | ||
212 | return "SUCCESS"; | ||
213 | TX_STATUS_ENTRY(SHORT_LIMIT); | ||
214 | TX_STATUS_ENTRY(LONG_LIMIT); | ||
215 | TX_STATUS_ENTRY(FIFO_UNDERRUN); | ||
216 | TX_STATUS_ENTRY(MGMNT_ABORT); | ||
217 | TX_STATUS_ENTRY(NEXT_FRAG); | ||
218 | TX_STATUS_ENTRY(LIFE_EXPIRE); | ||
219 | TX_STATUS_ENTRY(DEST_PS); | ||
220 | TX_STATUS_ENTRY(ABORTED); | ||
221 | TX_STATUS_ENTRY(BT_RETRY); | ||
222 | TX_STATUS_ENTRY(STA_INVALID); | ||
223 | TX_STATUS_ENTRY(FRAG_DROPPED); | ||
224 | TX_STATUS_ENTRY(TID_DISABLE); | ||
225 | TX_STATUS_ENTRY(FRAME_FLUSHED); | ||
226 | TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL); | ||
227 | TX_STATUS_ENTRY(TX_LOCKED); | ||
228 | TX_STATUS_ENTRY(NO_BEACON_ON_RADAR); | ||
229 | } | ||
230 | |||
231 | return "UNKNOWN"; | ||
232 | } | ||
233 | #else | ||
234 | static inline const char *iwl3945_get_tx_fail_reason(u32 status) | ||
235 | { | ||
236 | return ""; | ||
237 | } | ||
238 | #endif | ||
239 | |||
240 | /* | ||
241 | * get ieee prev rate from rate scale table. | ||
242 | * for A and B mode we need to overright prev | ||
243 | * value | ||
244 | */ | ||
245 | int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate) | ||
246 | { | ||
247 | int next_rate = iwl3945_get_prev_ieee_rate(rate); | ||
248 | |||
249 | switch (priv->band) { | ||
250 | case IEEE80211_BAND_5GHZ: | ||
251 | if (rate == IWL_RATE_12M_INDEX) | ||
252 | next_rate = IWL_RATE_9M_INDEX; | ||
253 | else if (rate == IWL_RATE_6M_INDEX) | ||
254 | next_rate = IWL_RATE_6M_INDEX; | ||
255 | break; | ||
256 | case IEEE80211_BAND_2GHZ: | ||
257 | if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) && | ||
258 | iwl_is_associated(priv, IWL_RXON_CTX_BSS)) { | ||
259 | if (rate == IWL_RATE_11M_INDEX) | ||
260 | next_rate = IWL_RATE_5M_INDEX; | ||
261 | } | ||
262 | break; | ||
263 | |||
264 | default: | ||
265 | break; | ||
266 | } | ||
267 | |||
268 | return next_rate; | ||
269 | } | ||
270 | |||
271 | |||
272 | /** | ||
273 | * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd | ||
274 | * | ||
275 | * When FW advances 'R' index, all entries between old and new 'R' index | ||
276 | * need to be reclaimed. As result, some free space forms. If there is | ||
277 | * enough free space (> low mark), wake the stack that feeds us. | ||
278 | */ | ||
279 | static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, | ||
280 | int txq_id, int index) | ||
281 | { | ||
282 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
283 | struct iwl_queue *q = &txq->q; | ||
284 | struct iwl_tx_info *tx_info; | ||
285 | |||
286 | BUG_ON(txq_id == IWL39_CMD_QUEUE_NUM); | ||
287 | |||
288 | for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index; | ||
289 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | ||
290 | |||
291 | tx_info = &txq->txb[txq->q.read_ptr]; | ||
292 | ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb); | ||
293 | tx_info->skb = NULL; | ||
294 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | ||
295 | } | ||
296 | |||
297 | if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) && | ||
298 | (txq_id != IWL39_CMD_QUEUE_NUM) && | ||
299 | priv->mac80211_registered) | ||
300 | iwl_wake_queue(priv, txq); | ||
301 | } | ||
302 | |||
303 | /** | ||
304 | * iwl3945_rx_reply_tx - Handle Tx response | ||
305 | */ | ||
306 | static void iwl3945_rx_reply_tx(struct iwl_priv *priv, | ||
307 | struct iwl_rx_mem_buffer *rxb) | ||
308 | { | ||
309 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
310 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | ||
311 | int txq_id = SEQ_TO_QUEUE(sequence); | ||
312 | int index = SEQ_TO_INDEX(sequence); | ||
313 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
314 | struct ieee80211_tx_info *info; | ||
315 | struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; | ||
316 | u32 status = le32_to_cpu(tx_resp->status); | ||
317 | int rate_idx; | ||
318 | int fail; | ||
319 | |||
320 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { | ||
321 | IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " | ||
322 | "is out of range [0-%d] %d %d\n", txq_id, | ||
323 | index, txq->q.n_bd, txq->q.write_ptr, | ||
324 | txq->q.read_ptr); | ||
325 | return; | ||
326 | } | ||
327 | |||
328 | txq->time_stamp = jiffies; | ||
329 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); | ||
330 | ieee80211_tx_info_clear_status(info); | ||
331 | |||
332 | /* Fill the MRR chain with some info about on-chip retransmissions */ | ||
333 | rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate); | ||
334 | if (info->band == IEEE80211_BAND_5GHZ) | ||
335 | rate_idx -= IWL_FIRST_OFDM_RATE; | ||
336 | |||
337 | fail = tx_resp->failure_frame; | ||
338 | |||
339 | info->status.rates[0].idx = rate_idx; | ||
340 | info->status.rates[0].count = fail + 1; /* add final attempt */ | ||
341 | |||
342 | /* tx_status->rts_retry_count = tx_resp->failure_rts; */ | ||
343 | info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ? | ||
344 | IEEE80211_TX_STAT_ACK : 0; | ||
345 | |||
346 | IWL_DEBUG_TX(priv, "Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n", | ||
347 | txq_id, iwl3945_get_tx_fail_reason(status), status, | ||
348 | tx_resp->rate, tx_resp->failure_frame); | ||
349 | |||
350 | IWL_DEBUG_TX_REPLY(priv, "Tx queue reclaim %d\n", index); | ||
351 | iwl3945_tx_queue_reclaim(priv, txq_id, index); | ||
352 | |||
353 | if (status & TX_ABORT_REQUIRED_MSK) | ||
354 | IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); | ||
355 | } | ||
356 | |||
357 | |||
358 | |||
359 | /***************************************************************************** | ||
360 | * | ||
361 | * Intel PRO/Wireless 3945ABG/BG Network Connection | ||
362 | * | ||
363 | * RX handler implementations | ||
364 | * | ||
365 | *****************************************************************************/ | ||
366 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
367 | /* | ||
368 | * based on the assumption of all statistics counter are in DWORD | ||
369 | * FIXME: This function is for debugging, do not deal with | ||
370 | * the case of counters roll-over. | ||
371 | */ | ||
372 | static void iwl3945_accumulative_statistics(struct iwl_priv *priv, | ||
373 | __le32 *stats) | ||
374 | { | ||
375 | int i; | ||
376 | __le32 *prev_stats; | ||
377 | u32 *accum_stats; | ||
378 | u32 *delta, *max_delta; | ||
379 | |||
380 | prev_stats = (__le32 *)&priv->_3945.statistics; | ||
381 | accum_stats = (u32 *)&priv->_3945.accum_statistics; | ||
382 | delta = (u32 *)&priv->_3945.delta_statistics; | ||
383 | max_delta = (u32 *)&priv->_3945.max_delta; | ||
384 | |||
385 | for (i = sizeof(__le32); i < sizeof(struct iwl3945_notif_statistics); | ||
386 | i += sizeof(__le32), stats++, prev_stats++, delta++, | ||
387 | max_delta++, accum_stats++) { | ||
388 | if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) { | ||
389 | *delta = (le32_to_cpu(*stats) - | ||
390 | le32_to_cpu(*prev_stats)); | ||
391 | *accum_stats += *delta; | ||
392 | if (*delta > *max_delta) | ||
393 | *max_delta = *delta; | ||
394 | } | ||
395 | } | ||
396 | |||
397 | /* reset accumulative statistics for "no-counter" type statistics */ | ||
398 | priv->_3945.accum_statistics.general.temperature = | ||
399 | priv->_3945.statistics.general.temperature; | ||
400 | priv->_3945.accum_statistics.general.ttl_timestamp = | ||
401 | priv->_3945.statistics.general.ttl_timestamp; | ||
402 | } | ||
403 | #endif | ||
404 | |||
405 | /** | ||
406 | * iwl3945_good_plcp_health - checks for plcp error. | ||
407 | * | ||
408 | * When the plcp error is exceeding the thresholds, reset the radio | ||
409 | * to improve the throughput. | ||
410 | */ | ||
411 | static bool iwl3945_good_plcp_health(struct iwl_priv *priv, | ||
412 | struct iwl_rx_packet *pkt) | ||
413 | { | ||
414 | bool rc = true; | ||
415 | struct iwl3945_notif_statistics current_stat; | ||
416 | int combined_plcp_delta; | ||
417 | unsigned int plcp_msec; | ||
418 | unsigned long plcp_received_jiffies; | ||
419 | |||
420 | if (priv->cfg->base_params->plcp_delta_threshold == | ||
421 | IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) { | ||
422 | IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n"); | ||
423 | return rc; | ||
424 | } | ||
425 | memcpy(¤t_stat, pkt->u.raw, sizeof(struct | ||
426 | iwl3945_notif_statistics)); | ||
427 | /* | ||
428 | * check for plcp_err and trigger radio reset if it exceeds | ||
429 | * the plcp error threshold plcp_delta. | ||
430 | */ | ||
431 | plcp_received_jiffies = jiffies; | ||
432 | plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies - | ||
433 | (long) priv->plcp_jiffies); | ||
434 | priv->plcp_jiffies = plcp_received_jiffies; | ||
435 | /* | ||
436 | * check to make sure plcp_msec is not 0 to prevent division | ||
437 | * by zero. | ||
438 | */ | ||
439 | if (plcp_msec) { | ||
440 | combined_plcp_delta = | ||
441 | (le32_to_cpu(current_stat.rx.ofdm.plcp_err) - | ||
442 | le32_to_cpu(priv->_3945.statistics.rx.ofdm.plcp_err)); | ||
443 | |||
444 | if ((combined_plcp_delta > 0) && | ||
445 | ((combined_plcp_delta * 100) / plcp_msec) > | ||
446 | priv->cfg->base_params->plcp_delta_threshold) { | ||
447 | /* | ||
448 | * if plcp_err exceed the threshold, the following | ||
449 | * data is printed in csv format: | ||
450 | * Text: plcp_err exceeded %d, | ||
451 | * Received ofdm.plcp_err, | ||
452 | * Current ofdm.plcp_err, | ||
453 | * combined_plcp_delta, | ||
454 | * plcp_msec | ||
455 | */ | ||
456 | IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " | ||
457 | "%u, %d, %u mSecs\n", | ||
458 | priv->cfg->base_params->plcp_delta_threshold, | ||
459 | le32_to_cpu(current_stat.rx.ofdm.plcp_err), | ||
460 | combined_plcp_delta, plcp_msec); | ||
461 | /* | ||
462 | * Reset the RF radio due to the high plcp | ||
463 | * error rate | ||
464 | */ | ||
465 | rc = false; | ||
466 | } | ||
467 | } | ||
468 | return rc; | ||
469 | } | ||
470 | |||
471 | void iwl3945_hw_rx_statistics(struct iwl_priv *priv, | ||
472 | struct iwl_rx_mem_buffer *rxb) | ||
473 | { | ||
474 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
475 | |||
476 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | ||
477 | (int)sizeof(struct iwl3945_notif_statistics), | ||
478 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | ||
479 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
480 | iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw); | ||
481 | #endif | ||
482 | iwl_recover_from_statistics(priv, pkt); | ||
483 | |||
484 | memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics)); | ||
485 | } | ||
486 | |||
487 | void iwl3945_reply_statistics(struct iwl_priv *priv, | ||
488 | struct iwl_rx_mem_buffer *rxb) | ||
489 | { | ||
490 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
491 | __le32 *flag = (__le32 *)&pkt->u.raw; | ||
492 | |||
493 | if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) { | ||
494 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
495 | memset(&priv->_3945.accum_statistics, 0, | ||
496 | sizeof(struct iwl3945_notif_statistics)); | ||
497 | memset(&priv->_3945.delta_statistics, 0, | ||
498 | sizeof(struct iwl3945_notif_statistics)); | ||
499 | memset(&priv->_3945.max_delta, 0, | ||
500 | sizeof(struct iwl3945_notif_statistics)); | ||
501 | #endif | ||
502 | IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); | ||
503 | } | ||
504 | iwl3945_hw_rx_statistics(priv, rxb); | ||
505 | } | ||
506 | |||
507 | |||
508 | /****************************************************************************** | ||
509 | * | ||
510 | * Misc. internal state and helper functions | ||
511 | * | ||
512 | ******************************************************************************/ | ||
513 | |||
514 | /* This is necessary only for a number of statistics, see the caller. */ | ||
515 | static int iwl3945_is_network_packet(struct iwl_priv *priv, | ||
516 | struct ieee80211_hdr *header) | ||
517 | { | ||
518 | /* Filter incoming packets to determine if they are targeted toward | ||
519 | * this network, discarding packets coming from ourselves */ | ||
520 | switch (priv->iw_mode) { | ||
521 | case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */ | ||
522 | /* packets to our IBSS update information */ | ||
523 | return !compare_ether_addr(header->addr3, priv->bssid); | ||
524 | case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */ | ||
525 | /* packets to our IBSS update information */ | ||
526 | return !compare_ether_addr(header->addr2, priv->bssid); | ||
527 | default: | ||
528 | return 1; | ||
529 | } | ||
530 | } | ||
531 | |||
532 | static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | ||
533 | struct iwl_rx_mem_buffer *rxb, | ||
534 | struct ieee80211_rx_status *stats) | ||
535 | { | ||
536 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
537 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); | ||
538 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | ||
539 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | ||
540 | u16 len = le16_to_cpu(rx_hdr->len); | ||
541 | struct sk_buff *skb; | ||
542 | __le16 fc = hdr->frame_control; | ||
543 | |||
544 | /* We received data from the HW, so stop the watchdog */ | ||
545 | if (unlikely(len + IWL39_RX_FRAME_SIZE > | ||
546 | PAGE_SIZE << priv->hw_params.rx_page_order)) { | ||
547 | IWL_DEBUG_DROP(priv, "Corruption detected!\n"); | ||
548 | return; | ||
549 | } | ||
550 | |||
551 | /* We only process data packets if the interface is open */ | ||
552 | if (unlikely(!priv->is_open)) { | ||
553 | IWL_DEBUG_DROP_LIMIT(priv, | ||
554 | "Dropping packet while interface is not open.\n"); | ||
555 | return; | ||
556 | } | ||
557 | |||
558 | skb = dev_alloc_skb(128); | ||
559 | if (!skb) { | ||
560 | IWL_ERR(priv, "dev_alloc_skb failed\n"); | ||
561 | return; | ||
562 | } | ||
563 | |||
564 | if (!iwl3945_mod_params.sw_crypto) | ||
565 | iwl_set_decrypted_flag(priv, | ||
566 | (struct ieee80211_hdr *)rxb_addr(rxb), | ||
567 | le32_to_cpu(rx_end->status), stats); | ||
568 | |||
569 | skb_add_rx_frag(skb, 0, rxb->page, | ||
570 | (void *)rx_hdr->payload - (void *)pkt, len); | ||
571 | |||
572 | iwl_update_stats(priv, false, fc, len); | ||
573 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | ||
574 | |||
575 | ieee80211_rx(priv->hw, skb); | ||
576 | priv->alloc_rxb_page--; | ||
577 | rxb->page = NULL; | ||
578 | } | ||
579 | |||
580 | #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) | ||
581 | |||
582 | static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | ||
583 | struct iwl_rx_mem_buffer *rxb) | ||
584 | { | ||
585 | struct ieee80211_hdr *header; | ||
586 | struct ieee80211_rx_status rx_status; | ||
587 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
588 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | ||
589 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | ||
590 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | ||
591 | u16 rx_stats_sig_avg __maybe_unused = le16_to_cpu(rx_stats->sig_avg); | ||
592 | u16 rx_stats_noise_diff __maybe_unused = le16_to_cpu(rx_stats->noise_diff); | ||
593 | u8 network_packet; | ||
594 | |||
595 | rx_status.flag = 0; | ||
596 | rx_status.mactime = le64_to_cpu(rx_end->timestamp); | ||
597 | rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
598 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
599 | rx_status.freq = | ||
600 | ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel), | ||
601 | rx_status.band); | ||
602 | |||
603 | rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate); | ||
604 | if (rx_status.band == IEEE80211_BAND_5GHZ) | ||
605 | rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; | ||
606 | |||
607 | rx_status.antenna = (le16_to_cpu(rx_hdr->phy_flags) & | ||
608 | RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4; | ||
609 | |||
610 | /* set the preamble flag if appropriate */ | ||
611 | if (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | ||
612 | rx_status.flag |= RX_FLAG_SHORTPRE; | ||
613 | |||
614 | if ((unlikely(rx_stats->phy_count > 20))) { | ||
615 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | ||
616 | rx_stats->phy_count); | ||
617 | return; | ||
618 | } | ||
619 | |||
620 | if (!(rx_end->status & RX_RES_STATUS_NO_CRC32_ERROR) | ||
621 | || !(rx_end->status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
622 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", rx_end->status); | ||
623 | return; | ||
624 | } | ||
625 | |||
626 | |||
627 | |||
628 | /* Convert 3945's rssi indicator to dBm */ | ||
629 | rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET; | ||
630 | |||
631 | IWL_DEBUG_STATS(priv, "Rssi %d sig_avg %d noise_diff %d\n", | ||
632 | rx_status.signal, rx_stats_sig_avg, | ||
633 | rx_stats_noise_diff); | ||
634 | |||
635 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); | ||
636 | |||
637 | network_packet = iwl3945_is_network_packet(priv, header); | ||
638 | |||
639 | IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Rate:%u\n", | ||
640 | network_packet ? '*' : ' ', | ||
641 | le16_to_cpu(rx_hdr->channel), | ||
642 | rx_status.signal, rx_status.signal, | ||
643 | rx_status.rate_idx); | ||
644 | |||
645 | iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header); | ||
646 | |||
647 | if (network_packet) { | ||
648 | priv->_3945.last_beacon_time = | ||
649 | le32_to_cpu(rx_end->beacon_timestamp); | ||
650 | priv->_3945.last_tsf = le64_to_cpu(rx_end->timestamp); | ||
651 | priv->_3945.last_rx_rssi = rx_status.signal; | ||
652 | } | ||
653 | |||
654 | iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); | ||
655 | } | ||
656 | |||
657 | int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | ||
658 | struct iwl_tx_queue *txq, | ||
659 | dma_addr_t addr, u16 len, u8 reset, u8 pad) | ||
660 | { | ||
661 | int count; | ||
662 | struct iwl_queue *q; | ||
663 | struct iwl3945_tfd *tfd, *tfd_tmp; | ||
664 | |||
665 | q = &txq->q; | ||
666 | tfd_tmp = (struct iwl3945_tfd *)txq->tfds; | ||
667 | tfd = &tfd_tmp[q->write_ptr]; | ||
668 | |||
669 | if (reset) | ||
670 | memset(tfd, 0, sizeof(*tfd)); | ||
671 | |||
672 | count = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags)); | ||
673 | |||
674 | if ((count >= NUM_TFD_CHUNKS) || (count < 0)) { | ||
675 | IWL_ERR(priv, "Error can not send more than %d chunks\n", | ||
676 | NUM_TFD_CHUNKS); | ||
677 | return -EINVAL; | ||
678 | } | ||
679 | |||
680 | tfd->tbs[count].addr = cpu_to_le32(addr); | ||
681 | tfd->tbs[count].len = cpu_to_le32(len); | ||
682 | |||
683 | count++; | ||
684 | |||
685 | tfd->control_flags = cpu_to_le32(TFD_CTL_COUNT_SET(count) | | ||
686 | TFD_CTL_PAD_SET(pad)); | ||
687 | |||
688 | return 0; | ||
689 | } | ||
690 | |||
691 | /** | ||
692 | * iwl3945_hw_txq_free_tfd - Free one TFD, those at index [txq->q.read_ptr] | ||
693 | * | ||
694 | * Does NOT advance any indexes | ||
695 | */ | ||
696 | void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) | ||
697 | { | ||
698 | struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)txq->tfds; | ||
699 | int index = txq->q.read_ptr; | ||
700 | struct iwl3945_tfd *tfd = &tfd_tmp[index]; | ||
701 | struct pci_dev *dev = priv->pci_dev; | ||
702 | int i; | ||
703 | int counter; | ||
704 | |||
705 | /* sanity check */ | ||
706 | counter = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags)); | ||
707 | if (counter > NUM_TFD_CHUNKS) { | ||
708 | IWL_ERR(priv, "Too many chunks: %i\n", counter); | ||
709 | /* @todo issue fatal error, it is quite serious situation */ | ||
710 | return; | ||
711 | } | ||
712 | |||
713 | /* Unmap tx_cmd */ | ||
714 | if (counter) | ||
715 | pci_unmap_single(dev, | ||
716 | dma_unmap_addr(&txq->meta[index], mapping), | ||
717 | dma_unmap_len(&txq->meta[index], len), | ||
718 | PCI_DMA_TODEVICE); | ||
719 | |||
720 | /* unmap chunks if any */ | ||
721 | |||
722 | for (i = 1; i < counter; i++) | ||
723 | pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr), | ||
724 | le32_to_cpu(tfd->tbs[i].len), PCI_DMA_TODEVICE); | ||
725 | |||
726 | /* free SKB */ | ||
727 | if (txq->txb) { | ||
728 | struct sk_buff *skb; | ||
729 | |||
730 | skb = txq->txb[txq->q.read_ptr].skb; | ||
731 | |||
732 | /* can be called from irqs-disabled context */ | ||
733 | if (skb) { | ||
734 | dev_kfree_skb_any(skb); | ||
735 | txq->txb[txq->q.read_ptr].skb = NULL; | ||
736 | } | ||
737 | } | ||
738 | } | ||
739 | |||
740 | /** | ||
741 | * iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD: | ||
742 | * | ||
743 | */ | ||
744 | void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, | ||
745 | struct iwl_device_cmd *cmd, | ||
746 | struct ieee80211_tx_info *info, | ||
747 | struct ieee80211_hdr *hdr, | ||
748 | int sta_id, int tx_id) | ||
749 | { | ||
750 | u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value; | ||
751 | u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT_3945); | ||
752 | u16 rate_mask; | ||
753 | int rate; | ||
754 | u8 rts_retry_limit; | ||
755 | u8 data_retry_limit; | ||
756 | __le32 tx_flags; | ||
757 | __le16 fc = hdr->frame_control; | ||
758 | struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload; | ||
759 | |||
760 | rate = iwl3945_rates[rate_index].plcp; | ||
761 | tx_flags = tx_cmd->tx_flags; | ||
762 | |||
763 | /* We need to figure out how to get the sta->supp_rates while | ||
764 | * in this running context */ | ||
765 | rate_mask = IWL_RATES_MASK_3945; | ||
766 | |||
767 | /* Set retry limit on DATA packets and Probe Responses*/ | ||
768 | if (ieee80211_is_probe_resp(fc)) | ||
769 | data_retry_limit = 3; | ||
770 | else | ||
771 | data_retry_limit = IWL_DEFAULT_TX_RETRY; | ||
772 | tx_cmd->data_retry_limit = data_retry_limit; | ||
773 | |||
774 | if (tx_id >= IWL39_CMD_QUEUE_NUM) | ||
775 | rts_retry_limit = 3; | ||
776 | else | ||
777 | rts_retry_limit = 7; | ||
778 | |||
779 | if (data_retry_limit < rts_retry_limit) | ||
780 | rts_retry_limit = data_retry_limit; | ||
781 | tx_cmd->rts_retry_limit = rts_retry_limit; | ||
782 | |||
783 | tx_cmd->rate = rate; | ||
784 | tx_cmd->tx_flags = tx_flags; | ||
785 | |||
786 | /* OFDM */ | ||
787 | tx_cmd->supp_rates[0] = | ||
788 | ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF; | ||
789 | |||
790 | /* CCK */ | ||
791 | tx_cmd->supp_rates[1] = (rate_mask & 0xF); | ||
792 | |||
793 | IWL_DEBUG_RATE(priv, "Tx sta id: %d, rate: %d (plcp), flags: 0x%4X " | ||
794 | "cck/ofdm mask: 0x%x/0x%x\n", sta_id, | ||
795 | tx_cmd->rate, le32_to_cpu(tx_cmd->tx_flags), | ||
796 | tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]); | ||
797 | } | ||
798 | |||
799 | static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate) | ||
800 | { | ||
801 | unsigned long flags_spin; | ||
802 | struct iwl_station_entry *station; | ||
803 | |||
804 | if (sta_id == IWL_INVALID_STATION) | ||
805 | return IWL_INVALID_STATION; | ||
806 | |||
807 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | ||
808 | station = &priv->stations[sta_id]; | ||
809 | |||
810 | station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK; | ||
811 | station->sta.rate_n_flags = cpu_to_le16(tx_rate); | ||
812 | station->sta.mode = STA_CONTROL_MODIFY_MSK; | ||
813 | iwl_send_add_sta(priv, &station->sta, CMD_ASYNC); | ||
814 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
815 | |||
816 | IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n", | ||
817 | sta_id, tx_rate); | ||
818 | return sta_id; | ||
819 | } | ||
820 | |||
821 | static void iwl3945_set_pwr_vmain(struct iwl_priv *priv) | ||
822 | { | ||
823 | /* | ||
824 | * (for documentation purposes) | ||
825 | * to set power to V_AUX, do | ||
826 | |||
827 | if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) { | ||
828 | iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, | ||
829 | APMG_PS_CTRL_VAL_PWR_SRC_VAUX, | ||
830 | ~APMG_PS_CTRL_MSK_PWR_SRC); | ||
831 | |||
832 | iwl_poll_bit(priv, CSR_GPIO_IN, | ||
833 | CSR_GPIO_IN_VAL_VAUX_PWR_SRC, | ||
834 | CSR_GPIO_IN_BIT_AUX_POWER, 5000); | ||
835 | } | ||
836 | */ | ||
837 | |||
838 | iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, | ||
839 | APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, | ||
840 | ~APMG_PS_CTRL_MSK_PWR_SRC); | ||
841 | |||
842 | iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC, | ||
843 | CSR_GPIO_IN_BIT_AUX_POWER, 5000); /* uS */ | ||
844 | } | ||
845 | |||
846 | static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
847 | { | ||
848 | iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->bd_dma); | ||
849 | iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma); | ||
850 | iwl_write_direct32(priv, FH39_RCSR_WPTR(0), 0); | ||
851 | iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), | ||
852 | FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE | | ||
853 | FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE | | ||
854 | FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN | | ||
855 | FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 | | ||
856 | (RX_QUEUE_SIZE_LOG << FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE) | | ||
857 | FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST | | ||
858 | (1 << FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH) | | ||
859 | FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH); | ||
860 | |||
861 | /* fake read to flush all prev I/O */ | ||
862 | iwl_read_direct32(priv, FH39_RSSR_CTRL); | ||
863 | |||
864 | return 0; | ||
865 | } | ||
866 | |||
867 | static int iwl3945_tx_reset(struct iwl_priv *priv) | ||
868 | { | ||
869 | |||
870 | /* bypass mode */ | ||
871 | iwl_write_prph(priv, ALM_SCD_MODE_REG, 0x2); | ||
872 | |||
873 | /* RA 0 is active */ | ||
874 | iwl_write_prph(priv, ALM_SCD_ARASTAT_REG, 0x01); | ||
875 | |||
876 | /* all 6 fifo are active */ | ||
877 | iwl_write_prph(priv, ALM_SCD_TXFACT_REG, 0x3f); | ||
878 | |||
879 | iwl_write_prph(priv, ALM_SCD_SBYP_MODE_1_REG, 0x010000); | ||
880 | iwl_write_prph(priv, ALM_SCD_SBYP_MODE_2_REG, 0x030002); | ||
881 | iwl_write_prph(priv, ALM_SCD_TXF4MF_REG, 0x000004); | ||
882 | iwl_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005); | ||
883 | |||
884 | iwl_write_direct32(priv, FH39_TSSR_CBB_BASE, | ||
885 | priv->_3945.shared_phys); | ||
886 | |||
887 | iwl_write_direct32(priv, FH39_TSSR_MSG_CONFIG, | ||
888 | FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON | | ||
889 | FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON | | ||
890 | FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B | | ||
891 | FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON | | ||
892 | FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON | | ||
893 | FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH | | ||
894 | FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH); | ||
895 | |||
896 | |||
897 | return 0; | ||
898 | } | ||
899 | |||
900 | /** | ||
901 | * iwl3945_txq_ctx_reset - Reset TX queue context | ||
902 | * | ||
903 | * Destroys all DMA structures and initialize them again | ||
904 | */ | ||
905 | static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) | ||
906 | { | ||
907 | int rc; | ||
908 | int txq_id, slots_num; | ||
909 | |||
910 | iwl3945_hw_txq_ctx_free(priv); | ||
911 | |||
912 | /* allocate tx queue structure */ | ||
913 | rc = iwl_alloc_txq_mem(priv); | ||
914 | if (rc) | ||
915 | return rc; | ||
916 | |||
917 | /* Tx CMD queue */ | ||
918 | rc = iwl3945_tx_reset(priv); | ||
919 | if (rc) | ||
920 | goto error; | ||
921 | |||
922 | /* Tx queue(s) */ | ||
923 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
924 | slots_num = (txq_id == IWL39_CMD_QUEUE_NUM) ? | ||
925 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
926 | rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, | ||
927 | txq_id); | ||
928 | if (rc) { | ||
929 | IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); | ||
930 | goto error; | ||
931 | } | ||
932 | } | ||
933 | |||
934 | return rc; | ||
935 | |||
936 | error: | ||
937 | iwl3945_hw_txq_ctx_free(priv); | ||
938 | return rc; | ||
939 | } | ||
940 | |||
941 | |||
942 | /* | ||
943 | * Start up 3945's basic functionality after it has been reset | ||
944 | * (e.g. after platform boot, or shutdown via iwl_apm_stop()) | ||
945 | * NOTE: This does not load uCode nor start the embedded processor | ||
946 | */ | ||
947 | static int iwl3945_apm_init(struct iwl_priv *priv) | ||
948 | { | ||
949 | int ret = iwl_apm_init(priv); | ||
950 | |||
951 | /* Clear APMG (NIC's internal power management) interrupts */ | ||
952 | iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0); | ||
953 | iwl_write_prph(priv, APMG_RTC_INT_STT_REG, 0xFFFFFFFF); | ||
954 | |||
955 | /* Reset radio chip */ | ||
956 | iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); | ||
957 | udelay(5); | ||
958 | iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); | ||
959 | |||
960 | return ret; | ||
961 | } | ||
962 | |||
963 | static void iwl3945_nic_config(struct iwl_priv *priv) | ||
964 | { | ||
965 | struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; | ||
966 | unsigned long flags; | ||
967 | u8 rev_id = 0; | ||
968 | |||
969 | spin_lock_irqsave(&priv->lock, flags); | ||
970 | |||
971 | /* Determine HW type */ | ||
972 | pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id); | ||
973 | |||
974 | IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); | ||
975 | |||
976 | if (rev_id & PCI_CFG_REV_ID_BIT_RTP) | ||
977 | IWL_DEBUG_INFO(priv, "RTP type\n"); | ||
978 | else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { | ||
979 | IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n"); | ||
980 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
981 | CSR39_HW_IF_CONFIG_REG_BIT_3945_MB); | ||
982 | } else { | ||
983 | IWL_DEBUG_INFO(priv, "3945 RADIO-MM type\n"); | ||
984 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
985 | CSR39_HW_IF_CONFIG_REG_BIT_3945_MM); | ||
986 | } | ||
987 | |||
988 | if (EEPROM_SKU_CAP_OP_MODE_MRC == eeprom->sku_cap) { | ||
989 | IWL_DEBUG_INFO(priv, "SKU OP mode is mrc\n"); | ||
990 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
991 | CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC); | ||
992 | } else | ||
993 | IWL_DEBUG_INFO(priv, "SKU OP mode is basic\n"); | ||
994 | |||
995 | if ((eeprom->board_revision & 0xF0) == 0xD0) { | ||
996 | IWL_DEBUG_INFO(priv, "3945ABG revision is 0x%X\n", | ||
997 | eeprom->board_revision); | ||
998 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
999 | CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); | ||
1000 | } else { | ||
1001 | IWL_DEBUG_INFO(priv, "3945ABG revision is 0x%X\n", | ||
1002 | eeprom->board_revision); | ||
1003 | iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
1004 | CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); | ||
1005 | } | ||
1006 | |||
1007 | if (eeprom->almgor_m_version <= 1) { | ||
1008 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
1009 | CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A); | ||
1010 | IWL_DEBUG_INFO(priv, "Card M type A version is 0x%X\n", | ||
1011 | eeprom->almgor_m_version); | ||
1012 | } else { | ||
1013 | IWL_DEBUG_INFO(priv, "Card M type B version is 0x%X\n", | ||
1014 | eeprom->almgor_m_version); | ||
1015 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
1016 | CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B); | ||
1017 | } | ||
1018 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1019 | |||
1020 | if (eeprom->sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE) | ||
1021 | IWL_DEBUG_RF_KILL(priv, "SW RF KILL supported in EEPROM.\n"); | ||
1022 | |||
1023 | if (eeprom->sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE) | ||
1024 | IWL_DEBUG_RF_KILL(priv, "HW RF KILL supported in EEPROM.\n"); | ||
1025 | } | ||
1026 | |||
1027 | int iwl3945_hw_nic_init(struct iwl_priv *priv) | ||
1028 | { | ||
1029 | int rc; | ||
1030 | unsigned long flags; | ||
1031 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
1032 | |||
1033 | spin_lock_irqsave(&priv->lock, flags); | ||
1034 | priv->cfg->ops->lib->apm_ops.init(priv); | ||
1035 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1036 | |||
1037 | iwl3945_set_pwr_vmain(priv); | ||
1038 | |||
1039 | priv->cfg->ops->lib->apm_ops.config(priv); | ||
1040 | |||
1041 | /* Allocate the RX queue, or reset if it is already allocated */ | ||
1042 | if (!rxq->bd) { | ||
1043 | rc = iwl_rx_queue_alloc(priv); | ||
1044 | if (rc) { | ||
1045 | IWL_ERR(priv, "Unable to initialize Rx queue\n"); | ||
1046 | return -ENOMEM; | ||
1047 | } | ||
1048 | } else | ||
1049 | iwl3945_rx_queue_reset(priv, rxq); | ||
1050 | |||
1051 | iwl3945_rx_replenish(priv); | ||
1052 | |||
1053 | iwl3945_rx_init(priv, rxq); | ||
1054 | |||
1055 | |||
1056 | /* Look at using this instead: | ||
1057 | rxq->need_update = 1; | ||
1058 | iwl_rx_queue_update_write_ptr(priv, rxq); | ||
1059 | */ | ||
1060 | |||
1061 | iwl_write_direct32(priv, FH39_RCSR_WPTR(0), rxq->write & ~7); | ||
1062 | |||
1063 | rc = iwl3945_txq_ctx_reset(priv); | ||
1064 | if (rc) | ||
1065 | return rc; | ||
1066 | |||
1067 | set_bit(STATUS_INIT, &priv->status); | ||
1068 | |||
1069 | return 0; | ||
1070 | } | ||
1071 | |||
1072 | /** | ||
1073 | * iwl3945_hw_txq_ctx_free - Free TXQ Context | ||
1074 | * | ||
1075 | * Destroy all TX DMA queues and structures | ||
1076 | */ | ||
1077 | void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv) | ||
1078 | { | ||
1079 | int txq_id; | ||
1080 | |||
1081 | /* Tx queues */ | ||
1082 | if (priv->txq) | ||
1083 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; | ||
1084 | txq_id++) | ||
1085 | if (txq_id == IWL39_CMD_QUEUE_NUM) | ||
1086 | iwl_cmd_queue_free(priv); | ||
1087 | else | ||
1088 | iwl_tx_queue_free(priv, txq_id); | ||
1089 | |||
1090 | /* free tx queue structure */ | ||
1091 | iwl_free_txq_mem(priv); | ||
1092 | } | ||
1093 | |||
1094 | void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) | ||
1095 | { | ||
1096 | int txq_id; | ||
1097 | |||
1098 | /* stop SCD */ | ||
1099 | iwl_write_prph(priv, ALM_SCD_MODE_REG, 0); | ||
1100 | iwl_write_prph(priv, ALM_SCD_TXFACT_REG, 0); | ||
1101 | |||
1102 | /* reset TFD queues */ | ||
1103 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
1104 | iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), 0x0); | ||
1105 | iwl_poll_direct_bit(priv, FH39_TSSR_TX_STATUS, | ||
1106 | FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id), | ||
1107 | 1000); | ||
1108 | } | ||
1109 | |||
1110 | iwl3945_hw_txq_ctx_free(priv); | ||
1111 | } | ||
1112 | |||
1113 | /** | ||
1114 | * iwl3945_hw_reg_adjust_power_by_temp | ||
1115 | * return index delta into power gain settings table | ||
1116 | */ | ||
1117 | static int iwl3945_hw_reg_adjust_power_by_temp(int new_reading, int old_reading) | ||
1118 | { | ||
1119 | return (new_reading - old_reading) * (-11) / 100; | ||
1120 | } | ||
1121 | |||
1122 | /** | ||
1123 | * iwl3945_hw_reg_temp_out_of_range - Keep temperature in sane range | ||
1124 | */ | ||
1125 | static inline int iwl3945_hw_reg_temp_out_of_range(int temperature) | ||
1126 | { | ||
1127 | return ((temperature < -260) || (temperature > 25)) ? 1 : 0; | ||
1128 | } | ||
1129 | |||
1130 | int iwl3945_hw_get_temperature(struct iwl_priv *priv) | ||
1131 | { | ||
1132 | return iwl_read32(priv, CSR_UCODE_DRV_GP2); | ||
1133 | } | ||
1134 | |||
1135 | /** | ||
1136 | * iwl3945_hw_reg_txpower_get_temperature | ||
1137 | * get the current temperature by reading from NIC | ||
1138 | */ | ||
1139 | static int iwl3945_hw_reg_txpower_get_temperature(struct iwl_priv *priv) | ||
1140 | { | ||
1141 | struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; | ||
1142 | int temperature; | ||
1143 | |||
1144 | temperature = iwl3945_hw_get_temperature(priv); | ||
1145 | |||
1146 | /* driver's okay range is -260 to +25. | ||
1147 | * human readable okay range is 0 to +285 */ | ||
1148 | IWL_DEBUG_INFO(priv, "Temperature: %d\n", temperature + IWL_TEMP_CONVERT); | ||
1149 | |||
1150 | /* handle insane temp reading */ | ||
1151 | if (iwl3945_hw_reg_temp_out_of_range(temperature)) { | ||
1152 | IWL_ERR(priv, "Error bad temperature value %d\n", temperature); | ||
1153 | |||
1154 | /* if really really hot(?), | ||
1155 | * substitute the 3rd band/group's temp measured at factory */ | ||
1156 | if (priv->last_temperature > 100) | ||
1157 | temperature = eeprom->groups[2].temperature; | ||
1158 | else /* else use most recent "sane" value from driver */ | ||
1159 | temperature = priv->last_temperature; | ||
1160 | } | ||
1161 | |||
1162 | return temperature; /* raw, not "human readable" */ | ||
1163 | } | ||
1164 | |||
1165 | /* Adjust Txpower only if temperature variance is greater than threshold. | ||
1166 | * | ||
1167 | * Both are lower than older versions' 9 degrees */ | ||
1168 | #define IWL_TEMPERATURE_LIMIT_TIMER 6 | ||
1169 | |||
1170 | /** | ||
1171 | * is_temp_calib_needed - determines if new calibration is needed | ||
1172 | * | ||
1173 | * records new temperature in tx_mgr->temperature. | ||
1174 | * replaces tx_mgr->last_temperature *only* if calib needed | ||
1175 | * (assumes caller will actually do the calibration!). */ | ||
1176 | static int is_temp_calib_needed(struct iwl_priv *priv) | ||
1177 | { | ||
1178 | int temp_diff; | ||
1179 | |||
1180 | priv->temperature = iwl3945_hw_reg_txpower_get_temperature(priv); | ||
1181 | temp_diff = priv->temperature - priv->last_temperature; | ||
1182 | |||
1183 | /* get absolute value */ | ||
1184 | if (temp_diff < 0) { | ||
1185 | IWL_DEBUG_POWER(priv, "Getting cooler, delta %d,\n", temp_diff); | ||
1186 | temp_diff = -temp_diff; | ||
1187 | } else if (temp_diff == 0) | ||
1188 | IWL_DEBUG_POWER(priv, "Same temp,\n"); | ||
1189 | else | ||
1190 | IWL_DEBUG_POWER(priv, "Getting warmer, delta %d,\n", temp_diff); | ||
1191 | |||
1192 | /* if we don't need calibration, *don't* update last_temperature */ | ||
1193 | if (temp_diff < IWL_TEMPERATURE_LIMIT_TIMER) { | ||
1194 | IWL_DEBUG_POWER(priv, "Timed thermal calib not needed\n"); | ||
1195 | return 0; | ||
1196 | } | ||
1197 | |||
1198 | IWL_DEBUG_POWER(priv, "Timed thermal calib needed\n"); | ||
1199 | |||
1200 | /* assume that caller will actually do calib ... | ||
1201 | * update the "last temperature" value */ | ||
1202 | priv->last_temperature = priv->temperature; | ||
1203 | return 1; | ||
1204 | } | ||
1205 | |||
1206 | #define IWL_MAX_GAIN_ENTRIES 78 | ||
1207 | #define IWL_CCK_FROM_OFDM_POWER_DIFF -5 | ||
1208 | #define IWL_CCK_FROM_OFDM_INDEX_DIFF (10) | ||
1209 | |||
1210 | /* radio and DSP power table, each step is 1/2 dB. | ||
1211 | * 1st number is for RF analog gain, 2nd number is for DSP pre-DAC gain. */ | ||
1212 | static struct iwl3945_tx_power power_gain_table[2][IWL_MAX_GAIN_ENTRIES] = { | ||
1213 | { | ||
1214 | {251, 127}, /* 2.4 GHz, highest power */ | ||
1215 | {251, 127}, | ||
1216 | {251, 127}, | ||
1217 | {251, 127}, | ||
1218 | {251, 125}, | ||
1219 | {251, 110}, | ||
1220 | {251, 105}, | ||
1221 | {251, 98}, | ||
1222 | {187, 125}, | ||
1223 | {187, 115}, | ||
1224 | {187, 108}, | ||
1225 | {187, 99}, | ||
1226 | {243, 119}, | ||
1227 | {243, 111}, | ||
1228 | {243, 105}, | ||
1229 | {243, 97}, | ||
1230 | {243, 92}, | ||
1231 | {211, 106}, | ||
1232 | {211, 100}, | ||
1233 | {179, 120}, | ||
1234 | {179, 113}, | ||
1235 | {179, 107}, | ||
1236 | {147, 125}, | ||
1237 | {147, 119}, | ||
1238 | {147, 112}, | ||
1239 | {147, 106}, | ||
1240 | {147, 101}, | ||
1241 | {147, 97}, | ||
1242 | {147, 91}, | ||
1243 | {115, 107}, | ||
1244 | {235, 121}, | ||
1245 | {235, 115}, | ||
1246 | {235, 109}, | ||
1247 | {203, 127}, | ||
1248 | {203, 121}, | ||
1249 | {203, 115}, | ||
1250 | {203, 108}, | ||
1251 | {203, 102}, | ||
1252 | {203, 96}, | ||
1253 | {203, 92}, | ||
1254 | {171, 110}, | ||
1255 | {171, 104}, | ||
1256 | {171, 98}, | ||
1257 | {139, 116}, | ||
1258 | {227, 125}, | ||
1259 | {227, 119}, | ||
1260 | {227, 113}, | ||
1261 | {227, 107}, | ||
1262 | {227, 101}, | ||
1263 | {227, 96}, | ||
1264 | {195, 113}, | ||
1265 | {195, 106}, | ||
1266 | {195, 102}, | ||
1267 | {195, 95}, | ||
1268 | {163, 113}, | ||
1269 | {163, 106}, | ||
1270 | {163, 102}, | ||
1271 | {163, 95}, | ||
1272 | {131, 113}, | ||
1273 | {131, 106}, | ||
1274 | {131, 102}, | ||
1275 | {131, 95}, | ||
1276 | {99, 113}, | ||
1277 | {99, 106}, | ||
1278 | {99, 102}, | ||
1279 | {99, 95}, | ||
1280 | {67, 113}, | ||
1281 | {67, 106}, | ||
1282 | {67, 102}, | ||
1283 | {67, 95}, | ||
1284 | {35, 113}, | ||
1285 | {35, 106}, | ||
1286 | {35, 102}, | ||
1287 | {35, 95}, | ||
1288 | {3, 113}, | ||
1289 | {3, 106}, | ||
1290 | {3, 102}, | ||
1291 | {3, 95} }, /* 2.4 GHz, lowest power */ | ||
1292 | { | ||
1293 | {251, 127}, /* 5.x GHz, highest power */ | ||
1294 | {251, 120}, | ||
1295 | {251, 114}, | ||
1296 | {219, 119}, | ||
1297 | {219, 101}, | ||
1298 | {187, 113}, | ||
1299 | {187, 102}, | ||
1300 | {155, 114}, | ||
1301 | {155, 103}, | ||
1302 | {123, 117}, | ||
1303 | {123, 107}, | ||
1304 | {123, 99}, | ||
1305 | {123, 92}, | ||
1306 | {91, 108}, | ||
1307 | {59, 125}, | ||
1308 | {59, 118}, | ||
1309 | {59, 109}, | ||
1310 | {59, 102}, | ||
1311 | {59, 96}, | ||
1312 | {59, 90}, | ||
1313 | {27, 104}, | ||
1314 | {27, 98}, | ||
1315 | {27, 92}, | ||
1316 | {115, 118}, | ||
1317 | {115, 111}, | ||
1318 | {115, 104}, | ||
1319 | {83, 126}, | ||
1320 | {83, 121}, | ||
1321 | {83, 113}, | ||
1322 | {83, 105}, | ||
1323 | {83, 99}, | ||
1324 | {51, 118}, | ||
1325 | {51, 111}, | ||
1326 | {51, 104}, | ||
1327 | {51, 98}, | ||
1328 | {19, 116}, | ||
1329 | {19, 109}, | ||
1330 | {19, 102}, | ||
1331 | {19, 98}, | ||
1332 | {19, 93}, | ||
1333 | {171, 113}, | ||
1334 | {171, 107}, | ||
1335 | {171, 99}, | ||
1336 | {139, 120}, | ||
1337 | {139, 113}, | ||
1338 | {139, 107}, | ||
1339 | {139, 99}, | ||
1340 | {107, 120}, | ||
1341 | {107, 113}, | ||
1342 | {107, 107}, | ||
1343 | {107, 99}, | ||
1344 | {75, 120}, | ||
1345 | {75, 113}, | ||
1346 | {75, 107}, | ||
1347 | {75, 99}, | ||
1348 | {43, 120}, | ||
1349 | {43, 113}, | ||
1350 | {43, 107}, | ||
1351 | {43, 99}, | ||
1352 | {11, 120}, | ||
1353 | {11, 113}, | ||
1354 | {11, 107}, | ||
1355 | {11, 99}, | ||
1356 | {131, 107}, | ||
1357 | {131, 99}, | ||
1358 | {99, 120}, | ||
1359 | {99, 113}, | ||
1360 | {99, 107}, | ||
1361 | {99, 99}, | ||
1362 | {67, 120}, | ||
1363 | {67, 113}, | ||
1364 | {67, 107}, | ||
1365 | {67, 99}, | ||
1366 | {35, 120}, | ||
1367 | {35, 113}, | ||
1368 | {35, 107}, | ||
1369 | {35, 99}, | ||
1370 | {3, 120} } /* 5.x GHz, lowest power */ | ||
1371 | }; | ||
1372 | |||
1373 | static inline u8 iwl3945_hw_reg_fix_power_index(int index) | ||
1374 | { | ||
1375 | if (index < 0) | ||
1376 | return 0; | ||
1377 | if (index >= IWL_MAX_GAIN_ENTRIES) | ||
1378 | return IWL_MAX_GAIN_ENTRIES - 1; | ||
1379 | return (u8) index; | ||
1380 | } | ||
1381 | |||
1382 | /* Kick off thermal recalibration check every 60 seconds */ | ||
1383 | #define REG_RECALIB_PERIOD (60) | ||
1384 | |||
1385 | /** | ||
1386 | * iwl3945_hw_reg_set_scan_power - Set Tx power for scan probe requests | ||
1387 | * | ||
1388 | * Set (in our channel info database) the direct scan Tx power for 1 Mbit (CCK) | ||
1389 | * or 6 Mbit (OFDM) rates. | ||
1390 | */ | ||
1391 | static void iwl3945_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index, | ||
1392 | s32 rate_index, const s8 *clip_pwrs, | ||
1393 | struct iwl_channel_info *ch_info, | ||
1394 | int band_index) | ||
1395 | { | ||
1396 | struct iwl3945_scan_power_info *scan_power_info; | ||
1397 | s8 power; | ||
1398 | u8 power_index; | ||
1399 | |||
1400 | scan_power_info = &ch_info->scan_pwr_info[scan_tbl_index]; | ||
1401 | |||
1402 | /* use this channel group's 6Mbit clipping/saturation pwr, | ||
1403 | * but cap at regulatory scan power restriction (set during init | ||
1404 | * based on eeprom channel data) for this channel. */ | ||
1405 | power = min(ch_info->scan_power, clip_pwrs[IWL_RATE_6M_INDEX_TABLE]); | ||
1406 | |||
1407 | /* further limit to user's max power preference. | ||
1408 | * FIXME: Other spectrum management power limitations do not | ||
1409 | * seem to apply?? */ | ||
1410 | power = min(power, priv->tx_power_user_lmt); | ||
1411 | scan_power_info->requested_power = power; | ||
1412 | |||
1413 | /* find difference between new scan *power* and current "normal" | ||
1414 | * Tx *power* for 6Mb. Use this difference (x2) to adjust the | ||
1415 | * current "normal" temperature-compensated Tx power *index* for | ||
1416 | * this rate (1Mb or 6Mb) to yield new temp-compensated scan power | ||
1417 | * *index*. */ | ||
1418 | power_index = ch_info->power_info[rate_index].power_table_index | ||
1419 | - (power - ch_info->power_info | ||
1420 | [IWL_RATE_6M_INDEX_TABLE].requested_power) * 2; | ||
1421 | |||
1422 | /* store reference index that we use when adjusting *all* scan | ||
1423 | * powers. So we can accommodate user (all channel) or spectrum | ||
1424 | * management (single channel) power changes "between" temperature | ||
1425 | * feedback compensation procedures. | ||
1426 | * don't force fit this reference index into gain table; it may be a | ||
1427 | * negative number. This will help avoid errors when we're at | ||
1428 | * the lower bounds (highest gains, for warmest temperatures) | ||
1429 | * of the table. */ | ||
1430 | |||
1431 | /* don't exceed table bounds for "real" setting */ | ||
1432 | power_index = iwl3945_hw_reg_fix_power_index(power_index); | ||
1433 | |||
1434 | scan_power_info->power_table_index = power_index; | ||
1435 | scan_power_info->tpc.tx_gain = | ||
1436 | power_gain_table[band_index][power_index].tx_gain; | ||
1437 | scan_power_info->tpc.dsp_atten = | ||
1438 | power_gain_table[band_index][power_index].dsp_atten; | ||
1439 | } | ||
1440 | |||
1441 | /** | ||
1442 | * iwl3945_send_tx_power - fill in Tx Power command with gain settings | ||
1443 | * | ||
1444 | * Configures power settings for all rates for the current channel, | ||
1445 | * using values from channel info struct, and send to NIC | ||
1446 | */ | ||
1447 | static int iwl3945_send_tx_power(struct iwl_priv *priv) | ||
1448 | { | ||
1449 | int rate_idx, i; | ||
1450 | const struct iwl_channel_info *ch_info = NULL; | ||
1451 | struct iwl3945_txpowertable_cmd txpower = { | ||
1452 | .channel = priv->contexts[IWL_RXON_CTX_BSS].active.channel, | ||
1453 | }; | ||
1454 | u16 chan; | ||
1455 | |||
1456 | if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status), | ||
1457 | "TX Power requested while scanning!\n")) | ||
1458 | return -EAGAIN; | ||
1459 | |||
1460 | chan = le16_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.channel); | ||
1461 | |||
1462 | txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1; | ||
1463 | ch_info = iwl_get_channel_info(priv, priv->band, chan); | ||
1464 | if (!ch_info) { | ||
1465 | IWL_ERR(priv, | ||
1466 | "Failed to get channel info for channel %d [%d]\n", | ||
1467 | chan, priv->band); | ||
1468 | return -EINVAL; | ||
1469 | } | ||
1470 | |||
1471 | if (!is_channel_valid(ch_info)) { | ||
1472 | IWL_DEBUG_POWER(priv, "Not calling TX_PWR_TABLE_CMD on " | ||
1473 | "non-Tx channel.\n"); | ||
1474 | return 0; | ||
1475 | } | ||
1476 | |||
1477 | /* fill cmd with power settings for all rates for current channel */ | ||
1478 | /* Fill OFDM rate */ | ||
1479 | for (rate_idx = IWL_FIRST_OFDM_RATE, i = 0; | ||
1480 | rate_idx <= IWL39_LAST_OFDM_RATE; rate_idx++, i++) { | ||
1481 | |||
1482 | txpower.power[i].tpc = ch_info->power_info[i].tpc; | ||
1483 | txpower.power[i].rate = iwl3945_rates[rate_idx].plcp; | ||
1484 | |||
1485 | IWL_DEBUG_POWER(priv, "ch %d:%d rf %d dsp %3d rate code 0x%02x\n", | ||
1486 | le16_to_cpu(txpower.channel), | ||
1487 | txpower.band, | ||
1488 | txpower.power[i].tpc.tx_gain, | ||
1489 | txpower.power[i].tpc.dsp_atten, | ||
1490 | txpower.power[i].rate); | ||
1491 | } | ||
1492 | /* Fill CCK rates */ | ||
1493 | for (rate_idx = IWL_FIRST_CCK_RATE; | ||
1494 | rate_idx <= IWL_LAST_CCK_RATE; rate_idx++, i++) { | ||
1495 | txpower.power[i].tpc = ch_info->power_info[i].tpc; | ||
1496 | txpower.power[i].rate = iwl3945_rates[rate_idx].plcp; | ||
1497 | |||
1498 | IWL_DEBUG_POWER(priv, "ch %d:%d rf %d dsp %3d rate code 0x%02x\n", | ||
1499 | le16_to_cpu(txpower.channel), | ||
1500 | txpower.band, | ||
1501 | txpower.power[i].tpc.tx_gain, | ||
1502 | txpower.power[i].tpc.dsp_atten, | ||
1503 | txpower.power[i].rate); | ||
1504 | } | ||
1505 | |||
1506 | return iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, | ||
1507 | sizeof(struct iwl3945_txpowertable_cmd), | ||
1508 | &txpower); | ||
1509 | |||
1510 | } | ||
1511 | |||
1512 | /** | ||
1513 | * iwl3945_hw_reg_set_new_power - Configures power tables at new levels | ||
1514 | * @ch_info: Channel to update. Uses power_info.requested_power. | ||
1515 | * | ||
1516 | * Replace requested_power and base_power_index ch_info fields for | ||
1517 | * one channel. | ||
1518 | * | ||
1519 | * Called if user or spectrum management changes power preferences. | ||
1520 | * Takes into account h/w and modulation limitations (clip power). | ||
1521 | * | ||
1522 | * This does *not* send anything to NIC, just sets up ch_info for one channel. | ||
1523 | * | ||
1524 | * NOTE: reg_compensate_for_temperature_dif() *must* be run after this to | ||
1525 | * properly fill out the scan powers, and actual h/w gain settings, | ||
1526 | * and send changes to NIC | ||
1527 | */ | ||
1528 | static int iwl3945_hw_reg_set_new_power(struct iwl_priv *priv, | ||
1529 | struct iwl_channel_info *ch_info) | ||
1530 | { | ||
1531 | struct iwl3945_channel_power_info *power_info; | ||
1532 | int power_changed = 0; | ||
1533 | int i; | ||
1534 | const s8 *clip_pwrs; | ||
1535 | int power; | ||
1536 | |||
1537 | /* Get this chnlgrp's rate-to-max/clip-powers table */ | ||
1538 | clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers; | ||
1539 | |||
1540 | /* Get this channel's rate-to-current-power settings table */ | ||
1541 | power_info = ch_info->power_info; | ||
1542 | |||
1543 | /* update OFDM Txpower settings */ | ||
1544 | for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; | ||
1545 | i++, ++power_info) { | ||
1546 | int delta_idx; | ||
1547 | |||
1548 | /* limit new power to be no more than h/w capability */ | ||
1549 | power = min(ch_info->curr_txpow, clip_pwrs[i]); | ||
1550 | if (power == power_info->requested_power) | ||
1551 | continue; | ||
1552 | |||
1553 | /* find difference between old and new requested powers, | ||
1554 | * update base (non-temp-compensated) power index */ | ||
1555 | delta_idx = (power - power_info->requested_power) * 2; | ||
1556 | power_info->base_power_index -= delta_idx; | ||
1557 | |||
1558 | /* save new requested power value */ | ||
1559 | power_info->requested_power = power; | ||
1560 | |||
1561 | power_changed = 1; | ||
1562 | } | ||
1563 | |||
1564 | /* update CCK Txpower settings, based on OFDM 12M setting ... | ||
1565 | * ... all CCK power settings for a given channel are the *same*. */ | ||
1566 | if (power_changed) { | ||
1567 | power = | ||
1568 | ch_info->power_info[IWL_RATE_12M_INDEX_TABLE]. | ||
1569 | requested_power + IWL_CCK_FROM_OFDM_POWER_DIFF; | ||
1570 | |||
1571 | /* do all CCK rates' iwl3945_channel_power_info structures */ | ||
1572 | for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++) { | ||
1573 | power_info->requested_power = power; | ||
1574 | power_info->base_power_index = | ||
1575 | ch_info->power_info[IWL_RATE_12M_INDEX_TABLE]. | ||
1576 | base_power_index + IWL_CCK_FROM_OFDM_INDEX_DIFF; | ||
1577 | ++power_info; | ||
1578 | } | ||
1579 | } | ||
1580 | |||
1581 | return 0; | ||
1582 | } | ||
1583 | |||
1584 | /** | ||
1585 | * iwl3945_hw_reg_get_ch_txpower_limit - returns new power limit for channel | ||
1586 | * | ||
1587 | * NOTE: Returned power limit may be less (but not more) than requested, | ||
1588 | * based strictly on regulatory (eeprom and spectrum mgt) limitations | ||
1589 | * (no consideration for h/w clipping limitations). | ||
1590 | */ | ||
1591 | static int iwl3945_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info) | ||
1592 | { | ||
1593 | s8 max_power; | ||
1594 | |||
1595 | #if 0 | ||
1596 | /* if we're using TGd limits, use lower of TGd or EEPROM */ | ||
1597 | if (ch_info->tgd_data.max_power != 0) | ||
1598 | max_power = min(ch_info->tgd_data.max_power, | ||
1599 | ch_info->eeprom.max_power_avg); | ||
1600 | |||
1601 | /* else just use EEPROM limits */ | ||
1602 | else | ||
1603 | #endif | ||
1604 | max_power = ch_info->eeprom.max_power_avg; | ||
1605 | |||
1606 | return min(max_power, ch_info->max_power_avg); | ||
1607 | } | ||
1608 | |||
1609 | /** | ||
1610 | * iwl3945_hw_reg_comp_txpower_temp - Compensate for temperature | ||
1611 | * | ||
1612 | * Compensate txpower settings of *all* channels for temperature. | ||
1613 | * This only accounts for the difference between current temperature | ||
1614 | * and the factory calibration temperatures, and bases the new settings | ||
1615 | * on the channel's base_power_index. | ||
1616 | * | ||
1617 | * If RxOn is "associated", this sends the new Txpower to NIC! | ||
1618 | */ | ||
1619 | static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv) | ||
1620 | { | ||
1621 | struct iwl_channel_info *ch_info = NULL; | ||
1622 | struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; | ||
1623 | int delta_index; | ||
1624 | const s8 *clip_pwrs; /* array of h/w max power levels for each rate */ | ||
1625 | u8 a_band; | ||
1626 | u8 rate_index; | ||
1627 | u8 scan_tbl_index; | ||
1628 | u8 i; | ||
1629 | int ref_temp; | ||
1630 | int temperature = priv->temperature; | ||
1631 | |||
1632 | if (priv->disable_tx_power_cal || | ||
1633 | test_bit(STATUS_SCANNING, &priv->status)) { | ||
1634 | /* do not perform tx power calibration */ | ||
1635 | return 0; | ||
1636 | } | ||
1637 | /* set up new Tx power info for each and every channel, 2.4 and 5.x */ | ||
1638 | for (i = 0; i < priv->channel_count; i++) { | ||
1639 | ch_info = &priv->channel_info[i]; | ||
1640 | a_band = is_channel_a_band(ch_info); | ||
1641 | |||
1642 | /* Get this chnlgrp's factory calibration temperature */ | ||
1643 | ref_temp = (s16)eeprom->groups[ch_info->group_index]. | ||
1644 | temperature; | ||
1645 | |||
1646 | /* get power index adjustment based on current and factory | ||
1647 | * temps */ | ||
1648 | delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature, | ||
1649 | ref_temp); | ||
1650 | |||
1651 | /* set tx power value for all rates, OFDM and CCK */ | ||
1652 | for (rate_index = 0; rate_index < IWL_RATE_COUNT_3945; | ||
1653 | rate_index++) { | ||
1654 | int power_idx = | ||
1655 | ch_info->power_info[rate_index].base_power_index; | ||
1656 | |||
1657 | /* temperature compensate */ | ||
1658 | power_idx += delta_index; | ||
1659 | |||
1660 | /* stay within table range */ | ||
1661 | power_idx = iwl3945_hw_reg_fix_power_index(power_idx); | ||
1662 | ch_info->power_info[rate_index]. | ||
1663 | power_table_index = (u8) power_idx; | ||
1664 | ch_info->power_info[rate_index].tpc = | ||
1665 | power_gain_table[a_band][power_idx]; | ||
1666 | } | ||
1667 | |||
1668 | /* Get this chnlgrp's rate-to-max/clip-powers table */ | ||
1669 | clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers; | ||
1670 | |||
1671 | /* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */ | ||
1672 | for (scan_tbl_index = 0; | ||
1673 | scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) { | ||
1674 | s32 actual_index = (scan_tbl_index == 0) ? | ||
1675 | IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE; | ||
1676 | iwl3945_hw_reg_set_scan_power(priv, scan_tbl_index, | ||
1677 | actual_index, clip_pwrs, | ||
1678 | ch_info, a_band); | ||
1679 | } | ||
1680 | } | ||
1681 | |||
1682 | /* send Txpower command for current channel to ucode */ | ||
1683 | return priv->cfg->ops->lib->send_tx_power(priv); | ||
1684 | } | ||
1685 | |||
1686 | int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power) | ||
1687 | { | ||
1688 | struct iwl_channel_info *ch_info; | ||
1689 | s8 max_power; | ||
1690 | u8 a_band; | ||
1691 | u8 i; | ||
1692 | |||
1693 | if (priv->tx_power_user_lmt == power) { | ||
1694 | IWL_DEBUG_POWER(priv, "Requested Tx power same as current " | ||
1695 | "limit: %ddBm.\n", power); | ||
1696 | return 0; | ||
1697 | } | ||
1698 | |||
1699 | IWL_DEBUG_POWER(priv, "Setting upper limit clamp to %ddBm.\n", power); | ||
1700 | priv->tx_power_user_lmt = power; | ||
1701 | |||
1702 | /* set up new Tx powers for each and every channel, 2.4 and 5.x */ | ||
1703 | |||
1704 | for (i = 0; i < priv->channel_count; i++) { | ||
1705 | ch_info = &priv->channel_info[i]; | ||
1706 | a_band = is_channel_a_band(ch_info); | ||
1707 | |||
1708 | /* find minimum power of all user and regulatory constraints | ||
1709 | * (does not consider h/w clipping limitations) */ | ||
1710 | max_power = iwl3945_hw_reg_get_ch_txpower_limit(ch_info); | ||
1711 | max_power = min(power, max_power); | ||
1712 | if (max_power != ch_info->curr_txpow) { | ||
1713 | ch_info->curr_txpow = max_power; | ||
1714 | |||
1715 | /* this considers the h/w clipping limitations */ | ||
1716 | iwl3945_hw_reg_set_new_power(priv, ch_info); | ||
1717 | } | ||
1718 | } | ||
1719 | |||
1720 | /* update txpower settings for all channels, | ||
1721 | * send to NIC if associated. */ | ||
1722 | is_temp_calib_needed(priv); | ||
1723 | iwl3945_hw_reg_comp_txpower_temp(priv); | ||
1724 | |||
1725 | return 0; | ||
1726 | } | ||
1727 | |||
1728 | static int iwl3945_send_rxon_assoc(struct iwl_priv *priv, | ||
1729 | struct iwl_rxon_context *ctx) | ||
1730 | { | ||
1731 | int rc = 0; | ||
1732 | struct iwl_rx_packet *pkt; | ||
1733 | struct iwl3945_rxon_assoc_cmd rxon_assoc; | ||
1734 | struct iwl_host_cmd cmd = { | ||
1735 | .id = REPLY_RXON_ASSOC, | ||
1736 | .len = sizeof(rxon_assoc), | ||
1737 | .flags = CMD_WANT_SKB, | ||
1738 | .data = &rxon_assoc, | ||
1739 | }; | ||
1740 | const struct iwl_rxon_cmd *rxon1 = &ctx->staging; | ||
1741 | const struct iwl_rxon_cmd *rxon2 = &ctx->active; | ||
1742 | |||
1743 | if ((rxon1->flags == rxon2->flags) && | ||
1744 | (rxon1->filter_flags == rxon2->filter_flags) && | ||
1745 | (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && | ||
1746 | (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { | ||
1747 | IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); | ||
1748 | return 0; | ||
1749 | } | ||
1750 | |||
1751 | rxon_assoc.flags = ctx->staging.flags; | ||
1752 | rxon_assoc.filter_flags = ctx->staging.filter_flags; | ||
1753 | rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates; | ||
1754 | rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates; | ||
1755 | rxon_assoc.reserved = 0; | ||
1756 | |||
1757 | rc = iwl_send_cmd_sync(priv, &cmd); | ||
1758 | if (rc) | ||
1759 | return rc; | ||
1760 | |||
1761 | pkt = (struct iwl_rx_packet *)cmd.reply_page; | ||
1762 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
1763 | IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n"); | ||
1764 | rc = -EIO; | ||
1765 | } | ||
1766 | |||
1767 | iwl_free_pages(priv, cmd.reply_page); | ||
1768 | |||
1769 | return rc; | ||
1770 | } | ||
1771 | |||
1772 | /** | ||
1773 | * iwl3945_commit_rxon - commit staging_rxon to hardware | ||
1774 | * | ||
1775 | * The RXON command in staging_rxon is committed to the hardware and | ||
1776 | * the active_rxon structure is updated with the new data. This | ||
1777 | * function correctly transitions out of the RXON_ASSOC_MSK state if | ||
1778 | * a HW tune is required based on the RXON structure changes. | ||
1779 | */ | ||
1780 | int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | ||
1781 | { | ||
1782 | /* cast away the const for active_rxon in this function */ | ||
1783 | struct iwl3945_rxon_cmd *active_rxon = (void *)&ctx->active; | ||
1784 | struct iwl3945_rxon_cmd *staging_rxon = (void *)&ctx->staging; | ||
1785 | int rc = 0; | ||
1786 | bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK); | ||
1787 | |||
1788 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
1789 | return -EINVAL; | ||
1790 | |||
1791 | if (!iwl_is_alive(priv)) | ||
1792 | return -1; | ||
1793 | |||
1794 | /* always get timestamp with Rx frame */ | ||
1795 | staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK; | ||
1796 | |||
1797 | /* select antenna */ | ||
1798 | staging_rxon->flags &= | ||
1799 | ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK); | ||
1800 | staging_rxon->flags |= iwl3945_get_antenna_flags(priv); | ||
1801 | |||
1802 | rc = iwl_check_rxon_cmd(priv, ctx); | ||
1803 | if (rc) { | ||
1804 | IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); | ||
1805 | return -EINVAL; | ||
1806 | } | ||
1807 | |||
1808 | /* If we don't need to send a full RXON, we can use | ||
1809 | * iwl3945_rxon_assoc_cmd which is used to reconfigure filter | ||
1810 | * and other flags for the current radio configuration. */ | ||
1811 | if (!iwl_full_rxon_required(priv, &priv->contexts[IWL_RXON_CTX_BSS])) { | ||
1812 | rc = iwl_send_rxon_assoc(priv, | ||
1813 | &priv->contexts[IWL_RXON_CTX_BSS]); | ||
1814 | if (rc) { | ||
1815 | IWL_ERR(priv, "Error setting RXON_ASSOC " | ||
1816 | "configuration (%d).\n", rc); | ||
1817 | return rc; | ||
1818 | } | ||
1819 | |||
1820 | memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); | ||
1821 | |||
1822 | return 0; | ||
1823 | } | ||
1824 | |||
1825 | /* If we are currently associated and the new config requires | ||
1826 | * an RXON_ASSOC and the new config wants the associated mask enabled, | ||
1827 | * we must clear the associated from the active configuration | ||
1828 | * before we apply the new config */ | ||
1829 | if (iwl_is_associated(priv, IWL_RXON_CTX_BSS) && new_assoc) { | ||
1830 | IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); | ||
1831 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
1832 | |||
1833 | /* | ||
1834 | * reserved4 and 5 could have been filled by the iwlcore code. | ||
1835 | * Let's clear them before pushing to the 3945. | ||
1836 | */ | ||
1837 | active_rxon->reserved4 = 0; | ||
1838 | active_rxon->reserved5 = 0; | ||
1839 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON, | ||
1840 | sizeof(struct iwl3945_rxon_cmd), | ||
1841 | &priv->contexts[IWL_RXON_CTX_BSS].active); | ||
1842 | |||
1843 | /* If the mask clearing failed then we set | ||
1844 | * active_rxon back to what it was previously */ | ||
1845 | if (rc) { | ||
1846 | active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; | ||
1847 | IWL_ERR(priv, "Error clearing ASSOC_MSK on current " | ||
1848 | "configuration (%d).\n", rc); | ||
1849 | return rc; | ||
1850 | } | ||
1851 | iwl_clear_ucode_stations(priv, | ||
1852 | &priv->contexts[IWL_RXON_CTX_BSS]); | ||
1853 | iwl_restore_stations(priv, &priv->contexts[IWL_RXON_CTX_BSS]); | ||
1854 | } | ||
1855 | |||
1856 | IWL_DEBUG_INFO(priv, "Sending RXON\n" | ||
1857 | "* with%s RXON_FILTER_ASSOC_MSK\n" | ||
1858 | "* channel = %d\n" | ||
1859 | "* bssid = %pM\n", | ||
1860 | (new_assoc ? "" : "out"), | ||
1861 | le16_to_cpu(staging_rxon->channel), | ||
1862 | staging_rxon->bssid_addr); | ||
1863 | |||
1864 | /* | ||
1865 | * reserved4 and 5 could have been filled by the iwlcore code. | ||
1866 | * Let's clear them before pushing to the 3945. | ||
1867 | */ | ||
1868 | staging_rxon->reserved4 = 0; | ||
1869 | staging_rxon->reserved5 = 0; | ||
1870 | |||
1871 | iwl_set_rxon_hwcrypto(priv, ctx, !iwl3945_mod_params.sw_crypto); | ||
1872 | |||
1873 | /* Apply the new configuration */ | ||
1874 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON, | ||
1875 | sizeof(struct iwl3945_rxon_cmd), | ||
1876 | staging_rxon); | ||
1877 | if (rc) { | ||
1878 | IWL_ERR(priv, "Error setting new configuration (%d).\n", rc); | ||
1879 | return rc; | ||
1880 | } | ||
1881 | |||
1882 | memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); | ||
1883 | |||
1884 | if (!new_assoc) { | ||
1885 | iwl_clear_ucode_stations(priv, | ||
1886 | &priv->contexts[IWL_RXON_CTX_BSS]); | ||
1887 | iwl_restore_stations(priv, &priv->contexts[IWL_RXON_CTX_BSS]); | ||
1888 | } | ||
1889 | |||
1890 | /* If we issue a new RXON command which required a tune then we must | ||
1891 | * send a new TXPOWER command or we won't be able to Tx any frames */ | ||
1892 | rc = iwl_set_tx_power(priv, priv->tx_power_next, true); | ||
1893 | if (rc) { | ||
1894 | IWL_ERR(priv, "Error setting Tx power (%d).\n", rc); | ||
1895 | return rc; | ||
1896 | } | ||
1897 | |||
1898 | /* Init the hardware's rate fallback order based on the band */ | ||
1899 | rc = iwl3945_init_hw_rate_table(priv); | ||
1900 | if (rc) { | ||
1901 | IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc); | ||
1902 | return -EIO; | ||
1903 | } | ||
1904 | |||
1905 | return 0; | ||
1906 | } | ||
1907 | |||
1908 | /** | ||
1909 | * iwl3945_reg_txpower_periodic - called when time to check our temperature. | ||
1910 | * | ||
1911 | * -- reset periodic timer | ||
1912 | * -- see if temp has changed enough to warrant re-calibration ... if so: | ||
1913 | * -- correct coeffs for temp (can reset temp timer) | ||
1914 | * -- save this temp as "last", | ||
1915 | * -- send new set of gain settings to NIC | ||
1916 | * NOTE: This should continue working, even when we're not associated, | ||
1917 | * so we can keep our internal table of scan powers current. */ | ||
1918 | void iwl3945_reg_txpower_periodic(struct iwl_priv *priv) | ||
1919 | { | ||
1920 | /* This will kick in the "brute force" | ||
1921 | * iwl3945_hw_reg_comp_txpower_temp() below */ | ||
1922 | if (!is_temp_calib_needed(priv)) | ||
1923 | goto reschedule; | ||
1924 | |||
1925 | /* Set up a new set of temp-adjusted TxPowers, send to NIC. | ||
1926 | * This is based *only* on current temperature, | ||
1927 | * ignoring any previous power measurements */ | ||
1928 | iwl3945_hw_reg_comp_txpower_temp(priv); | ||
1929 | |||
1930 | reschedule: | ||
1931 | queue_delayed_work(priv->workqueue, | ||
1932 | &priv->_3945.thermal_periodic, REG_RECALIB_PERIOD * HZ); | ||
1933 | } | ||
1934 | |||
1935 | static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work) | ||
1936 | { | ||
1937 | struct iwl_priv *priv = container_of(work, struct iwl_priv, | ||
1938 | _3945.thermal_periodic.work); | ||
1939 | |||
1940 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
1941 | return; | ||
1942 | |||
1943 | mutex_lock(&priv->mutex); | ||
1944 | iwl3945_reg_txpower_periodic(priv); | ||
1945 | mutex_unlock(&priv->mutex); | ||
1946 | } | ||
1947 | |||
1948 | /** | ||
1949 | * iwl3945_hw_reg_get_ch_grp_index - find the channel-group index (0-4) | ||
1950 | * for the channel. | ||
1951 | * | ||
1952 | * This function is used when initializing channel-info structs. | ||
1953 | * | ||
1954 | * NOTE: These channel groups do *NOT* match the bands above! | ||
1955 | * These channel groups are based on factory-tested channels; | ||
1956 | * on A-band, EEPROM's "group frequency" entries represent the top | ||
1957 | * channel in each group 1-4. Group 5 All B/G channels are in group 0. | ||
1958 | */ | ||
1959 | static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl_priv *priv, | ||
1960 | const struct iwl_channel_info *ch_info) | ||
1961 | { | ||
1962 | struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; | ||
1963 | struct iwl3945_eeprom_txpower_group *ch_grp = &eeprom->groups[0]; | ||
1964 | u8 group; | ||
1965 | u16 group_index = 0; /* based on factory calib frequencies */ | ||
1966 | u8 grp_channel; | ||
1967 | |||
1968 | /* Find the group index for the channel ... don't use index 1(?) */ | ||
1969 | if (is_channel_a_band(ch_info)) { | ||
1970 | for (group = 1; group < 5; group++) { | ||
1971 | grp_channel = ch_grp[group].group_channel; | ||
1972 | if (ch_info->channel <= grp_channel) { | ||
1973 | group_index = group; | ||
1974 | break; | ||
1975 | } | ||
1976 | } | ||
1977 | /* group 4 has a few channels *above* its factory cal freq */ | ||
1978 | if (group == 5) | ||
1979 | group_index = 4; | ||
1980 | } else | ||
1981 | group_index = 0; /* 2.4 GHz, group 0 */ | ||
1982 | |||
1983 | IWL_DEBUG_POWER(priv, "Chnl %d mapped to grp %d\n", ch_info->channel, | ||
1984 | group_index); | ||
1985 | return group_index; | ||
1986 | } | ||
1987 | |||
1988 | /** | ||
1989 | * iwl3945_hw_reg_get_matched_power_index - Interpolate to get nominal index | ||
1990 | * | ||
1991 | * Interpolate to get nominal (i.e. at factory calibration temperature) index | ||
1992 | * into radio/DSP gain settings table for requested power. | ||
1993 | */ | ||
1994 | static int iwl3945_hw_reg_get_matched_power_index(struct iwl_priv *priv, | ||
1995 | s8 requested_power, | ||
1996 | s32 setting_index, s32 *new_index) | ||
1997 | { | ||
1998 | const struct iwl3945_eeprom_txpower_group *chnl_grp = NULL; | ||
1999 | struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; | ||
2000 | s32 index0, index1; | ||
2001 | s32 power = 2 * requested_power; | ||
2002 | s32 i; | ||
2003 | const struct iwl3945_eeprom_txpower_sample *samples; | ||
2004 | s32 gains0, gains1; | ||
2005 | s32 res; | ||
2006 | s32 denominator; | ||
2007 | |||
2008 | chnl_grp = &eeprom->groups[setting_index]; | ||
2009 | samples = chnl_grp->samples; | ||
2010 | for (i = 0; i < 5; i++) { | ||
2011 | if (power == samples[i].power) { | ||
2012 | *new_index = samples[i].gain_index; | ||
2013 | return 0; | ||
2014 | } | ||
2015 | } | ||
2016 | |||
2017 | if (power > samples[1].power) { | ||
2018 | index0 = 0; | ||
2019 | index1 = 1; | ||
2020 | } else if (power > samples[2].power) { | ||
2021 | index0 = 1; | ||
2022 | index1 = 2; | ||
2023 | } else if (power > samples[3].power) { | ||
2024 | index0 = 2; | ||
2025 | index1 = 3; | ||
2026 | } else { | ||
2027 | index0 = 3; | ||
2028 | index1 = 4; | ||
2029 | } | ||
2030 | |||
2031 | denominator = (s32) samples[index1].power - (s32) samples[index0].power; | ||
2032 | if (denominator == 0) | ||
2033 | return -EINVAL; | ||
2034 | gains0 = (s32) samples[index0].gain_index * (1 << 19); | ||
2035 | gains1 = (s32) samples[index1].gain_index * (1 << 19); | ||
2036 | res = gains0 + (gains1 - gains0) * | ||
2037 | ((s32) power - (s32) samples[index0].power) / denominator + | ||
2038 | (1 << 18); | ||
2039 | *new_index = res >> 19; | ||
2040 | return 0; | ||
2041 | } | ||
2042 | |||
2043 | static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv) | ||
2044 | { | ||
2045 | u32 i; | ||
2046 | s32 rate_index; | ||
2047 | struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; | ||
2048 | const struct iwl3945_eeprom_txpower_group *group; | ||
2049 | |||
2050 | IWL_DEBUG_POWER(priv, "Initializing factory calib info from EEPROM\n"); | ||
2051 | |||
2052 | for (i = 0; i < IWL_NUM_TX_CALIB_GROUPS; i++) { | ||
2053 | s8 *clip_pwrs; /* table of power levels for each rate */ | ||
2054 | s8 satur_pwr; /* saturation power for each chnl group */ | ||
2055 | group = &eeprom->groups[i]; | ||
2056 | |||
2057 | /* sanity check on factory saturation power value */ | ||
2058 | if (group->saturation_power < 40) { | ||
2059 | IWL_WARN(priv, "Error: saturation power is %d, " | ||
2060 | "less than minimum expected 40\n", | ||
2061 | group->saturation_power); | ||
2062 | return; | ||
2063 | } | ||
2064 | |||
2065 | /* | ||
2066 | * Derive requested power levels for each rate, based on | ||
2067 | * hardware capabilities (saturation power for band). | ||
2068 | * Basic value is 3dB down from saturation, with further | ||
2069 | * power reductions for highest 3 data rates. These | ||
2070 | * backoffs provide headroom for high rate modulation | ||
2071 | * power peaks, without too much distortion (clipping). | ||
2072 | */ | ||
2073 | /* we'll fill in this array with h/w max power levels */ | ||
2074 | clip_pwrs = (s8 *) priv->_3945.clip_groups[i].clip_powers; | ||
2075 | |||
2076 | /* divide factory saturation power by 2 to find -3dB level */ | ||
2077 | satur_pwr = (s8) (group->saturation_power >> 1); | ||
2078 | |||
2079 | /* fill in channel group's nominal powers for each rate */ | ||
2080 | for (rate_index = 0; | ||
2081 | rate_index < IWL_RATE_COUNT_3945; rate_index++, clip_pwrs++) { | ||
2082 | switch (rate_index) { | ||
2083 | case IWL_RATE_36M_INDEX_TABLE: | ||
2084 | if (i == 0) /* B/G */ | ||
2085 | *clip_pwrs = satur_pwr; | ||
2086 | else /* A */ | ||
2087 | *clip_pwrs = satur_pwr - 5; | ||
2088 | break; | ||
2089 | case IWL_RATE_48M_INDEX_TABLE: | ||
2090 | if (i == 0) | ||
2091 | *clip_pwrs = satur_pwr - 7; | ||
2092 | else | ||
2093 | *clip_pwrs = satur_pwr - 10; | ||
2094 | break; | ||
2095 | case IWL_RATE_54M_INDEX_TABLE: | ||
2096 | if (i == 0) | ||
2097 | *clip_pwrs = satur_pwr - 9; | ||
2098 | else | ||
2099 | *clip_pwrs = satur_pwr - 12; | ||
2100 | break; | ||
2101 | default: | ||
2102 | *clip_pwrs = satur_pwr; | ||
2103 | break; | ||
2104 | } | ||
2105 | } | ||
2106 | } | ||
2107 | } | ||
2108 | |||
2109 | /** | ||
2110 | * iwl3945_txpower_set_from_eeprom - Set channel power info based on EEPROM | ||
2111 | * | ||
2112 | * Second pass (during init) to set up priv->channel_info | ||
2113 | * | ||
2114 | * Set up Tx-power settings in our channel info database for each VALID | ||
2115 | * (for this geo/SKU) channel, at all Tx data rates, based on eeprom values | ||
2116 | * and current temperature. | ||
2117 | * | ||
2118 | * Since this is based on current temperature (at init time), these values may | ||
2119 | * not be valid for very long, but it gives us a starting/default point, | ||
2120 | * and allows us to active (i.e. using Tx) scan. | ||
2121 | * | ||
2122 | * This does *not* write values to NIC, just sets up our internal table. | ||
2123 | */ | ||
2124 | int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) | ||
2125 | { | ||
2126 | struct iwl_channel_info *ch_info = NULL; | ||
2127 | struct iwl3945_channel_power_info *pwr_info; | ||
2128 | struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; | ||
2129 | int delta_index; | ||
2130 | u8 rate_index; | ||
2131 | u8 scan_tbl_index; | ||
2132 | const s8 *clip_pwrs; /* array of power levels for each rate */ | ||
2133 | u8 gain, dsp_atten; | ||
2134 | s8 power; | ||
2135 | u8 pwr_index, base_pwr_index, a_band; | ||
2136 | u8 i; | ||
2137 | int temperature; | ||
2138 | |||
2139 | /* save temperature reference, | ||
2140 | * so we can determine next time to calibrate */ | ||
2141 | temperature = iwl3945_hw_reg_txpower_get_temperature(priv); | ||
2142 | priv->last_temperature = temperature; | ||
2143 | |||
2144 | iwl3945_hw_reg_init_channel_groups(priv); | ||
2145 | |||
2146 | /* initialize Tx power info for each and every channel, 2.4 and 5.x */ | ||
2147 | for (i = 0, ch_info = priv->channel_info; i < priv->channel_count; | ||
2148 | i++, ch_info++) { | ||
2149 | a_band = is_channel_a_band(ch_info); | ||
2150 | if (!is_channel_valid(ch_info)) | ||
2151 | continue; | ||
2152 | |||
2153 | /* find this channel's channel group (*not* "band") index */ | ||
2154 | ch_info->group_index = | ||
2155 | iwl3945_hw_reg_get_ch_grp_index(priv, ch_info); | ||
2156 | |||
2157 | /* Get this chnlgrp's rate->max/clip-powers table */ | ||
2158 | clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers; | ||
2159 | |||
2160 | /* calculate power index *adjustment* value according to | ||
2161 | * diff between current temperature and factory temperature */ | ||
2162 | delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature, | ||
2163 | eeprom->groups[ch_info->group_index]. | ||
2164 | temperature); | ||
2165 | |||
2166 | IWL_DEBUG_POWER(priv, "Delta index for channel %d: %d [%d]\n", | ||
2167 | ch_info->channel, delta_index, temperature + | ||
2168 | IWL_TEMP_CONVERT); | ||
2169 | |||
2170 | /* set tx power value for all OFDM rates */ | ||
2171 | for (rate_index = 0; rate_index < IWL_OFDM_RATES; | ||
2172 | rate_index++) { | ||
2173 | s32 uninitialized_var(power_idx); | ||
2174 | int rc; | ||
2175 | |||
2176 | /* use channel group's clip-power table, | ||
2177 | * but don't exceed channel's max power */ | ||
2178 | s8 pwr = min(ch_info->max_power_avg, | ||
2179 | clip_pwrs[rate_index]); | ||
2180 | |||
2181 | pwr_info = &ch_info->power_info[rate_index]; | ||
2182 | |||
2183 | /* get base (i.e. at factory-measured temperature) | ||
2184 | * power table index for this rate's power */ | ||
2185 | rc = iwl3945_hw_reg_get_matched_power_index(priv, pwr, | ||
2186 | ch_info->group_index, | ||
2187 | &power_idx); | ||
2188 | if (rc) { | ||
2189 | IWL_ERR(priv, "Invalid power index\n"); | ||
2190 | return rc; | ||
2191 | } | ||
2192 | pwr_info->base_power_index = (u8) power_idx; | ||
2193 | |||
2194 | /* temperature compensate */ | ||
2195 | power_idx += delta_index; | ||
2196 | |||
2197 | /* stay within range of gain table */ | ||
2198 | power_idx = iwl3945_hw_reg_fix_power_index(power_idx); | ||
2199 | |||
2200 | /* fill 1 OFDM rate's iwl3945_channel_power_info struct */ | ||
2201 | pwr_info->requested_power = pwr; | ||
2202 | pwr_info->power_table_index = (u8) power_idx; | ||
2203 | pwr_info->tpc.tx_gain = | ||
2204 | power_gain_table[a_band][power_idx].tx_gain; | ||
2205 | pwr_info->tpc.dsp_atten = | ||
2206 | power_gain_table[a_band][power_idx].dsp_atten; | ||
2207 | } | ||
2208 | |||
2209 | /* set tx power for CCK rates, based on OFDM 12 Mbit settings*/ | ||
2210 | pwr_info = &ch_info->power_info[IWL_RATE_12M_INDEX_TABLE]; | ||
2211 | power = pwr_info->requested_power + | ||
2212 | IWL_CCK_FROM_OFDM_POWER_DIFF; | ||
2213 | pwr_index = pwr_info->power_table_index + | ||
2214 | IWL_CCK_FROM_OFDM_INDEX_DIFF; | ||
2215 | base_pwr_index = pwr_info->base_power_index + | ||
2216 | IWL_CCK_FROM_OFDM_INDEX_DIFF; | ||
2217 | |||
2218 | /* stay within table range */ | ||
2219 | pwr_index = iwl3945_hw_reg_fix_power_index(pwr_index); | ||
2220 | gain = power_gain_table[a_band][pwr_index].tx_gain; | ||
2221 | dsp_atten = power_gain_table[a_band][pwr_index].dsp_atten; | ||
2222 | |||
2223 | /* fill each CCK rate's iwl3945_channel_power_info structure | ||
2224 | * NOTE: All CCK-rate Txpwrs are the same for a given chnl! | ||
2225 | * NOTE: CCK rates start at end of OFDM rates! */ | ||
2226 | for (rate_index = 0; | ||
2227 | rate_index < IWL_CCK_RATES; rate_index++) { | ||
2228 | pwr_info = &ch_info->power_info[rate_index+IWL_OFDM_RATES]; | ||
2229 | pwr_info->requested_power = power; | ||
2230 | pwr_info->power_table_index = pwr_index; | ||
2231 | pwr_info->base_power_index = base_pwr_index; | ||
2232 | pwr_info->tpc.tx_gain = gain; | ||
2233 | pwr_info->tpc.dsp_atten = dsp_atten; | ||
2234 | } | ||
2235 | |||
2236 | /* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */ | ||
2237 | for (scan_tbl_index = 0; | ||
2238 | scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) { | ||
2239 | s32 actual_index = (scan_tbl_index == 0) ? | ||
2240 | IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE; | ||
2241 | iwl3945_hw_reg_set_scan_power(priv, scan_tbl_index, | ||
2242 | actual_index, clip_pwrs, ch_info, a_band); | ||
2243 | } | ||
2244 | } | ||
2245 | |||
2246 | return 0; | ||
2247 | } | ||
2248 | |||
2249 | int iwl3945_hw_rxq_stop(struct iwl_priv *priv) | ||
2250 | { | ||
2251 | int rc; | ||
2252 | |||
2253 | iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), 0); | ||
2254 | rc = iwl_poll_direct_bit(priv, FH39_RSSR_STATUS, | ||
2255 | FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); | ||
2256 | if (rc < 0) | ||
2257 | IWL_ERR(priv, "Can't stop Rx DMA.\n"); | ||
2258 | |||
2259 | return 0; | ||
2260 | } | ||
2261 | |||
2262 | int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq) | ||
2263 | { | ||
2264 | int txq_id = txq->q.id; | ||
2265 | |||
2266 | struct iwl3945_shared *shared_data = priv->_3945.shared_virt; | ||
2267 | |||
2268 | shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr); | ||
2269 | |||
2270 | iwl_write_direct32(priv, FH39_CBCC_CTRL(txq_id), 0); | ||
2271 | iwl_write_direct32(priv, FH39_CBCC_BASE(txq_id), 0); | ||
2272 | |||
2273 | iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), | ||
2274 | FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT | | ||
2275 | FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF | | ||
2276 | FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD | | ||
2277 | FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL | | ||
2278 | FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE); | ||
2279 | |||
2280 | /* fake read to flush all prev. writes */ | ||
2281 | iwl_read32(priv, FH39_TSSR_CBB_BASE); | ||
2282 | |||
2283 | return 0; | ||
2284 | } | ||
2285 | |||
2286 | /* | ||
2287 | * HCMD utils | ||
2288 | */ | ||
2289 | static u16 iwl3945_get_hcmd_size(u8 cmd_id, u16 len) | ||
2290 | { | ||
2291 | switch (cmd_id) { | ||
2292 | case REPLY_RXON: | ||
2293 | return sizeof(struct iwl3945_rxon_cmd); | ||
2294 | case POWER_TABLE_CMD: | ||
2295 | return sizeof(struct iwl3945_powertable_cmd); | ||
2296 | default: | ||
2297 | return len; | ||
2298 | } | ||
2299 | } | ||
2300 | |||
2301 | |||
2302 | static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | ||
2303 | { | ||
2304 | struct iwl3945_addsta_cmd *addsta = (struct iwl3945_addsta_cmd *)data; | ||
2305 | addsta->mode = cmd->mode; | ||
2306 | memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify)); | ||
2307 | memcpy(&addsta->key, &cmd->key, sizeof(struct iwl4965_keyinfo)); | ||
2308 | addsta->station_flags = cmd->station_flags; | ||
2309 | addsta->station_flags_msk = cmd->station_flags_msk; | ||
2310 | addsta->tid_disable_tx = cpu_to_le16(0); | ||
2311 | addsta->rate_n_flags = cmd->rate_n_flags; | ||
2312 | addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid; | ||
2313 | addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid; | ||
2314 | addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn; | ||
2315 | |||
2316 | return (u16)sizeof(struct iwl3945_addsta_cmd); | ||
2317 | } | ||
2318 | |||
2319 | static int iwl3945_add_bssid_station(struct iwl_priv *priv, | ||
2320 | const u8 *addr, u8 *sta_id_r) | ||
2321 | { | ||
2322 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
2323 | int ret; | ||
2324 | u8 sta_id; | ||
2325 | unsigned long flags; | ||
2326 | |||
2327 | if (sta_id_r) | ||
2328 | *sta_id_r = IWL_INVALID_STATION; | ||
2329 | |||
2330 | ret = iwl_add_station_common(priv, ctx, addr, 0, NULL, &sta_id); | ||
2331 | if (ret) { | ||
2332 | IWL_ERR(priv, "Unable to add station %pM\n", addr); | ||
2333 | return ret; | ||
2334 | } | ||
2335 | |||
2336 | if (sta_id_r) | ||
2337 | *sta_id_r = sta_id; | ||
2338 | |||
2339 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
2340 | priv->stations[sta_id].used |= IWL_STA_LOCAL; | ||
2341 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
2342 | |||
2343 | return 0; | ||
2344 | } | ||
2345 | static int iwl3945_manage_ibss_station(struct iwl_priv *priv, | ||
2346 | struct ieee80211_vif *vif, bool add) | ||
2347 | { | ||
2348 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
2349 | int ret; | ||
2350 | |||
2351 | if (add) { | ||
2352 | ret = iwl3945_add_bssid_station(priv, vif->bss_conf.bssid, | ||
2353 | &vif_priv->ibss_bssid_sta_id); | ||
2354 | if (ret) | ||
2355 | return ret; | ||
2356 | |||
2357 | iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id, | ||
2358 | (priv->band == IEEE80211_BAND_5GHZ) ? | ||
2359 | IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP); | ||
2360 | iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id); | ||
2361 | |||
2362 | return 0; | ||
2363 | } | ||
2364 | |||
2365 | return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, | ||
2366 | vif->bss_conf.bssid); | ||
2367 | } | ||
2368 | |||
2369 | /** | ||
2370 | * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table | ||
2371 | */ | ||
2372 | int iwl3945_init_hw_rate_table(struct iwl_priv *priv) | ||
2373 | { | ||
2374 | int rc, i, index, prev_index; | ||
2375 | struct iwl3945_rate_scaling_cmd rate_cmd = { | ||
2376 | .reserved = {0, 0, 0}, | ||
2377 | }; | ||
2378 | struct iwl3945_rate_scaling_info *table = rate_cmd.table; | ||
2379 | |||
2380 | for (i = 0; i < ARRAY_SIZE(iwl3945_rates); i++) { | ||
2381 | index = iwl3945_rates[i].table_rs_index; | ||
2382 | |||
2383 | table[index].rate_n_flags = | ||
2384 | iwl3945_hw_set_rate_n_flags(iwl3945_rates[i].plcp, 0); | ||
2385 | table[index].try_cnt = priv->retry_rate; | ||
2386 | prev_index = iwl3945_get_prev_ieee_rate(i); | ||
2387 | table[index].next_rate_index = | ||
2388 | iwl3945_rates[prev_index].table_rs_index; | ||
2389 | } | ||
2390 | |||
2391 | switch (priv->band) { | ||
2392 | case IEEE80211_BAND_5GHZ: | ||
2393 | IWL_DEBUG_RATE(priv, "Select A mode rate scale\n"); | ||
2394 | /* If one of the following CCK rates is used, | ||
2395 | * have it fall back to the 6M OFDM rate */ | ||
2396 | for (i = IWL_RATE_1M_INDEX_TABLE; | ||
2397 | i <= IWL_RATE_11M_INDEX_TABLE; i++) | ||
2398 | table[i].next_rate_index = | ||
2399 | iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index; | ||
2400 | |||
2401 | /* Don't fall back to CCK rates */ | ||
2402 | table[IWL_RATE_12M_INDEX_TABLE].next_rate_index = | ||
2403 | IWL_RATE_9M_INDEX_TABLE; | ||
2404 | |||
2405 | /* Don't drop out of OFDM rates */ | ||
2406 | table[IWL_RATE_6M_INDEX_TABLE].next_rate_index = | ||
2407 | iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index; | ||
2408 | break; | ||
2409 | |||
2410 | case IEEE80211_BAND_2GHZ: | ||
2411 | IWL_DEBUG_RATE(priv, "Select B/G mode rate scale\n"); | ||
2412 | /* If an OFDM rate is used, have it fall back to the | ||
2413 | * 1M CCK rates */ | ||
2414 | |||
2415 | if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) && | ||
2416 | iwl_is_associated(priv, IWL_RXON_CTX_BSS)) { | ||
2417 | |||
2418 | index = IWL_FIRST_CCK_RATE; | ||
2419 | for (i = IWL_RATE_6M_INDEX_TABLE; | ||
2420 | i <= IWL_RATE_54M_INDEX_TABLE; i++) | ||
2421 | table[i].next_rate_index = | ||
2422 | iwl3945_rates[index].table_rs_index; | ||
2423 | |||
2424 | index = IWL_RATE_11M_INDEX_TABLE; | ||
2425 | /* CCK shouldn't fall back to OFDM... */ | ||
2426 | table[index].next_rate_index = IWL_RATE_5M_INDEX_TABLE; | ||
2427 | } | ||
2428 | break; | ||
2429 | |||
2430 | default: | ||
2431 | WARN_ON(1); | ||
2432 | break; | ||
2433 | } | ||
2434 | |||
2435 | /* Update the rate scaling for control frame Tx */ | ||
2436 | rate_cmd.table_id = 0; | ||
2437 | rc = iwl_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd), | ||
2438 | &rate_cmd); | ||
2439 | if (rc) | ||
2440 | return rc; | ||
2441 | |||
2442 | /* Update the rate scaling for data frame Tx */ | ||
2443 | rate_cmd.table_id = 1; | ||
2444 | return iwl_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd), | ||
2445 | &rate_cmd); | ||
2446 | } | ||
2447 | |||
2448 | /* Called when initializing driver */ | ||
2449 | int iwl3945_hw_set_hw_params(struct iwl_priv *priv) | ||
2450 | { | ||
2451 | memset((void *)&priv->hw_params, 0, | ||
2452 | sizeof(struct iwl_hw_params)); | ||
2453 | |||
2454 | priv->_3945.shared_virt = | ||
2455 | dma_alloc_coherent(&priv->pci_dev->dev, | ||
2456 | sizeof(struct iwl3945_shared), | ||
2457 | &priv->_3945.shared_phys, GFP_KERNEL); | ||
2458 | if (!priv->_3945.shared_virt) { | ||
2459 | IWL_ERR(priv, "failed to allocate pci memory\n"); | ||
2460 | return -ENOMEM; | ||
2461 | } | ||
2462 | |||
2463 | /* Assign number of Usable TX queues */ | ||
2464 | priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; | ||
2465 | |||
2466 | priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); | ||
2467 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K); | ||
2468 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; | ||
2469 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | ||
2470 | priv->hw_params.max_stations = IWL3945_STATION_COUNT; | ||
2471 | priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL3945_BROADCAST_ID; | ||
2472 | |||
2473 | priv->sta_key_max_num = STA_KEY_MAX_NUM; | ||
2474 | |||
2475 | priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR; | ||
2476 | priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL; | ||
2477 | priv->hw_params.beacon_time_tsf_bits = IWL3945_EXT_BEACON_TIME_POS; | ||
2478 | |||
2479 | return 0; | ||
2480 | } | ||
2481 | |||
2482 | unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv, | ||
2483 | struct iwl3945_frame *frame, u8 rate) | ||
2484 | { | ||
2485 | struct iwl3945_tx_beacon_cmd *tx_beacon_cmd; | ||
2486 | unsigned int frame_size; | ||
2487 | |||
2488 | tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u; | ||
2489 | memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); | ||
2490 | |||
2491 | tx_beacon_cmd->tx.sta_id = | ||
2492 | priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id; | ||
2493 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
2494 | |||
2495 | frame_size = iwl3945_fill_beacon_frame(priv, | ||
2496 | tx_beacon_cmd->frame, | ||
2497 | sizeof(frame->u) - sizeof(*tx_beacon_cmd)); | ||
2498 | |||
2499 | BUG_ON(frame_size > MAX_MPDU_SIZE); | ||
2500 | tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); | ||
2501 | |||
2502 | tx_beacon_cmd->tx.rate = rate; | ||
2503 | tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK | | ||
2504 | TX_CMD_FLG_TSF_MSK); | ||
2505 | |||
2506 | /* supp_rates[0] == OFDM start at IWL_FIRST_OFDM_RATE*/ | ||
2507 | tx_beacon_cmd->tx.supp_rates[0] = | ||
2508 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | ||
2509 | |||
2510 | tx_beacon_cmd->tx.supp_rates[1] = | ||
2511 | (IWL_CCK_BASIC_RATES_MASK & 0xF); | ||
2512 | |||
2513 | return sizeof(struct iwl3945_tx_beacon_cmd) + frame_size; | ||
2514 | } | ||
2515 | |||
2516 | void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv) | ||
2517 | { | ||
2518 | priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx; | ||
2519 | priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx; | ||
2520 | } | ||
2521 | |||
2522 | void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv) | ||
2523 | { | ||
2524 | INIT_DELAYED_WORK(&priv->_3945.thermal_periodic, | ||
2525 | iwl3945_bg_reg_txpower_periodic); | ||
2526 | } | ||
2527 | |||
2528 | void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv) | ||
2529 | { | ||
2530 | cancel_delayed_work(&priv->_3945.thermal_periodic); | ||
2531 | } | ||
2532 | |||
2533 | /* check contents of special bootstrap uCode SRAM */ | ||
2534 | static int iwl3945_verify_bsm(struct iwl_priv *priv) | ||
2535 | { | ||
2536 | __le32 *image = priv->ucode_boot.v_addr; | ||
2537 | u32 len = priv->ucode_boot.len; | ||
2538 | u32 reg; | ||
2539 | u32 val; | ||
2540 | |||
2541 | IWL_DEBUG_INFO(priv, "Begin verify bsm\n"); | ||
2542 | |||
2543 | /* verify BSM SRAM contents */ | ||
2544 | val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG); | ||
2545 | for (reg = BSM_SRAM_LOWER_BOUND; | ||
2546 | reg < BSM_SRAM_LOWER_BOUND + len; | ||
2547 | reg += sizeof(u32), image++) { | ||
2548 | val = iwl_read_prph(priv, reg); | ||
2549 | if (val != le32_to_cpu(*image)) { | ||
2550 | IWL_ERR(priv, "BSM uCode verification failed at " | ||
2551 | "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n", | ||
2552 | BSM_SRAM_LOWER_BOUND, | ||
2553 | reg - BSM_SRAM_LOWER_BOUND, len, | ||
2554 | val, le32_to_cpu(*image)); | ||
2555 | return -EIO; | ||
2556 | } | ||
2557 | } | ||
2558 | |||
2559 | IWL_DEBUG_INFO(priv, "BSM bootstrap uCode image OK\n"); | ||
2560 | |||
2561 | return 0; | ||
2562 | } | ||
2563 | |||
2564 | |||
2565 | /****************************************************************************** | ||
2566 | * | ||
2567 | * EEPROM related functions | ||
2568 | * | ||
2569 | ******************************************************************************/ | ||
2570 | |||
2571 | /* | ||
2572 | * Clear the OWNER_MSK, to establish driver (instead of uCode running on | ||
2573 | * embedded controller) as EEPROM reader; each read is a series of pulses | ||
2574 | * to/from the EEPROM chip, not a single event, so even reads could conflict | ||
2575 | * if they weren't arbitrated by some ownership mechanism. Here, the driver | ||
2576 | * simply claims ownership, which should be safe when this function is called | ||
2577 | * (i.e. before loading uCode!). | ||
2578 | */ | ||
2579 | static int iwl3945_eeprom_acquire_semaphore(struct iwl_priv *priv) | ||
2580 | { | ||
2581 | _iwl_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK); | ||
2582 | return 0; | ||
2583 | } | ||
2584 | |||
2585 | |||
2586 | static void iwl3945_eeprom_release_semaphore(struct iwl_priv *priv) | ||
2587 | { | ||
2588 | return; | ||
2589 | } | ||
2590 | |||
2591 | /** | ||
2592 | * iwl3945_load_bsm - Load bootstrap instructions | ||
2593 | * | ||
2594 | * BSM operation: | ||
2595 | * | ||
2596 | * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program | ||
2597 | * in special SRAM that does not power down during RFKILL. When powering back | ||
2598 | * up after power-saving sleeps (or during initial uCode load), the BSM loads | ||
2599 | * the bootstrap program into the on-board processor, and starts it. | ||
2600 | * | ||
2601 | * The bootstrap program loads (via DMA) instructions and data for a new | ||
2602 | * program from host DRAM locations indicated by the host driver in the | ||
2603 | * BSM_DRAM_* registers. Once the new program is loaded, it starts | ||
2604 | * automatically. | ||
2605 | * | ||
2606 | * When initializing the NIC, the host driver points the BSM to the | ||
2607 | * "initialize" uCode image. This uCode sets up some internal data, then | ||
2608 | * notifies host via "initialize alive" that it is complete. | ||
2609 | * | ||
2610 | * The host then replaces the BSM_DRAM_* pointer values to point to the | ||
2611 | * normal runtime uCode instructions and a backup uCode data cache buffer | ||
2612 | * (filled initially with starting data values for the on-board processor), | ||
2613 | * then triggers the "initialize" uCode to load and launch the runtime uCode, | ||
2614 | * which begins normal operation. | ||
2615 | * | ||
2616 | * When doing a power-save shutdown, runtime uCode saves data SRAM into | ||
2617 | * the backup data cache in DRAM before SRAM is powered down. | ||
2618 | * | ||
2619 | * When powering back up, the BSM loads the bootstrap program. This reloads | ||
2620 | * the runtime uCode instructions and the backup data cache into SRAM, | ||
2621 | * and re-launches the runtime uCode from where it left off. | ||
2622 | */ | ||
2623 | static int iwl3945_load_bsm(struct iwl_priv *priv) | ||
2624 | { | ||
2625 | __le32 *image = priv->ucode_boot.v_addr; | ||
2626 | u32 len = priv->ucode_boot.len; | ||
2627 | dma_addr_t pinst; | ||
2628 | dma_addr_t pdata; | ||
2629 | u32 inst_len; | ||
2630 | u32 data_len; | ||
2631 | int rc; | ||
2632 | int i; | ||
2633 | u32 done; | ||
2634 | u32 reg_offset; | ||
2635 | |||
2636 | IWL_DEBUG_INFO(priv, "Begin load bsm\n"); | ||
2637 | |||
2638 | /* make sure bootstrap program is no larger than BSM's SRAM size */ | ||
2639 | if (len > IWL39_MAX_BSM_SIZE) | ||
2640 | return -EINVAL; | ||
2641 | |||
2642 | /* Tell bootstrap uCode where to find the "Initialize" uCode | ||
2643 | * in host DRAM ... host DRAM physical address bits 31:0 for 3945. | ||
2644 | * NOTE: iwl3945_initialize_alive_start() will replace these values, | ||
2645 | * after the "initialize" uCode has run, to point to | ||
2646 | * runtime/protocol instructions and backup data cache. */ | ||
2647 | pinst = priv->ucode_init.p_addr; | ||
2648 | pdata = priv->ucode_init_data.p_addr; | ||
2649 | inst_len = priv->ucode_init.len; | ||
2650 | data_len = priv->ucode_init_data.len; | ||
2651 | |||
2652 | iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); | ||
2653 | iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); | ||
2654 | iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); | ||
2655 | iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len); | ||
2656 | |||
2657 | /* Fill BSM memory with bootstrap instructions */ | ||
2658 | for (reg_offset = BSM_SRAM_LOWER_BOUND; | ||
2659 | reg_offset < BSM_SRAM_LOWER_BOUND + len; | ||
2660 | reg_offset += sizeof(u32), image++) | ||
2661 | _iwl_write_prph(priv, reg_offset, | ||
2662 | le32_to_cpu(*image)); | ||
2663 | |||
2664 | rc = iwl3945_verify_bsm(priv); | ||
2665 | if (rc) | ||
2666 | return rc; | ||
2667 | |||
2668 | /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ | ||
2669 | iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); | ||
2670 | iwl_write_prph(priv, BSM_WR_MEM_DST_REG, | ||
2671 | IWL39_RTC_INST_LOWER_BOUND); | ||
2672 | iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); | ||
2673 | |||
2674 | /* Load bootstrap code into instruction SRAM now, | ||
2675 | * to prepare to load "initialize" uCode */ | ||
2676 | iwl_write_prph(priv, BSM_WR_CTRL_REG, | ||
2677 | BSM_WR_CTRL_REG_BIT_START); | ||
2678 | |||
2679 | /* Wait for load of bootstrap uCode to finish */ | ||
2680 | for (i = 0; i < 100; i++) { | ||
2681 | done = iwl_read_prph(priv, BSM_WR_CTRL_REG); | ||
2682 | if (!(done & BSM_WR_CTRL_REG_BIT_START)) | ||
2683 | break; | ||
2684 | udelay(10); | ||
2685 | } | ||
2686 | if (i < 100) | ||
2687 | IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i); | ||
2688 | else { | ||
2689 | IWL_ERR(priv, "BSM write did not complete!\n"); | ||
2690 | return -EIO; | ||
2691 | } | ||
2692 | |||
2693 | /* Enable future boot loads whenever power management unit triggers it | ||
2694 | * (e.g. when powering back up after power-save shutdown) */ | ||
2695 | iwl_write_prph(priv, BSM_WR_CTRL_REG, | ||
2696 | BSM_WR_CTRL_REG_BIT_START_EN); | ||
2697 | |||
2698 | return 0; | ||
2699 | } | ||
2700 | |||
2701 | static struct iwl_hcmd_ops iwl3945_hcmd = { | ||
2702 | .rxon_assoc = iwl3945_send_rxon_assoc, | ||
2703 | .commit_rxon = iwl3945_commit_rxon, | ||
2704 | .send_bt_config = iwl_send_bt_config, | ||
2705 | }; | ||
2706 | |||
2707 | static struct iwl_lib_ops iwl3945_lib = { | ||
2708 | .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd, | ||
2709 | .txq_free_tfd = iwl3945_hw_txq_free_tfd, | ||
2710 | .txq_init = iwl3945_hw_tx_queue_init, | ||
2711 | .load_ucode = iwl3945_load_bsm, | ||
2712 | .dump_nic_event_log = iwl3945_dump_nic_event_log, | ||
2713 | .dump_nic_error_log = iwl3945_dump_nic_error_log, | ||
2714 | .apm_ops = { | ||
2715 | .init = iwl3945_apm_init, | ||
2716 | .config = iwl3945_nic_config, | ||
2717 | }, | ||
2718 | .eeprom_ops = { | ||
2719 | .regulatory_bands = { | ||
2720 | EEPROM_REGULATORY_BAND_1_CHANNELS, | ||
2721 | EEPROM_REGULATORY_BAND_2_CHANNELS, | ||
2722 | EEPROM_REGULATORY_BAND_3_CHANNELS, | ||
2723 | EEPROM_REGULATORY_BAND_4_CHANNELS, | ||
2724 | EEPROM_REGULATORY_BAND_5_CHANNELS, | ||
2725 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
2726 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
2727 | }, | ||
2728 | .acquire_semaphore = iwl3945_eeprom_acquire_semaphore, | ||
2729 | .release_semaphore = iwl3945_eeprom_release_semaphore, | ||
2730 | .query_addr = iwlcore_eeprom_query_addr, | ||
2731 | }, | ||
2732 | .send_tx_power = iwl3945_send_tx_power, | ||
2733 | .is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr, | ||
2734 | .isr_ops = { | ||
2735 | .isr = iwl_isr_legacy, | ||
2736 | }, | ||
2737 | |||
2738 | .debugfs_ops = { | ||
2739 | .rx_stats_read = iwl3945_ucode_rx_stats_read, | ||
2740 | .tx_stats_read = iwl3945_ucode_tx_stats_read, | ||
2741 | .general_stats_read = iwl3945_ucode_general_stats_read, | ||
2742 | }, | ||
2743 | }; | ||
2744 | |||
2745 | static const struct iwl_legacy_ops iwl3945_legacy_ops = { | ||
2746 | .post_associate = iwl3945_post_associate, | ||
2747 | .config_ap = iwl3945_config_ap, | ||
2748 | .manage_ibss_station = iwl3945_manage_ibss_station, | ||
2749 | }; | ||
2750 | |||
2751 | static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { | ||
2752 | .get_hcmd_size = iwl3945_get_hcmd_size, | ||
2753 | .build_addsta_hcmd = iwl3945_build_addsta_hcmd, | ||
2754 | .tx_cmd_protection = iwl_legacy_tx_cmd_protection, | ||
2755 | .request_scan = iwl3945_request_scan, | ||
2756 | .post_scan = iwl3945_post_scan, | ||
2757 | }; | ||
2758 | |||
2759 | static const struct iwl_ops iwl3945_ops = { | ||
2760 | .lib = &iwl3945_lib, | ||
2761 | .hcmd = &iwl3945_hcmd, | ||
2762 | .utils = &iwl3945_hcmd_utils, | ||
2763 | .led = &iwl3945_led_ops, | ||
2764 | .legacy = &iwl3945_legacy_ops, | ||
2765 | .ieee80211_ops = &iwl3945_hw_ops, | ||
2766 | }; | ||
2767 | |||
2768 | static struct iwl_base_params iwl3945_base_params = { | ||
2769 | .eeprom_size = IWL3945_EEPROM_IMG_SIZE, | ||
2770 | .num_of_queues = IWL39_NUM_QUEUES, | ||
2771 | .pll_cfg_val = CSR39_ANA_PLL_CFG_VAL, | ||
2772 | .set_l0s = false, | ||
2773 | .use_bsm = true, | ||
2774 | .use_isr_legacy = true, | ||
2775 | .led_compensation = 64, | ||
2776 | .broken_powersave = true, | ||
2777 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
2778 | .wd_timeout = IWL_DEF_WD_TIMEOUT, | ||
2779 | .max_event_log_size = 512, | ||
2780 | .tx_power_by_driver = true, | ||
2781 | }; | ||
2782 | |||
2783 | static struct iwl_cfg iwl3945_bg_cfg = { | ||
2784 | .name = "3945BG", | ||
2785 | .fw_name_pre = IWL3945_FW_PRE, | ||
2786 | .ucode_api_max = IWL3945_UCODE_API_MAX, | ||
2787 | .ucode_api_min = IWL3945_UCODE_API_MIN, | ||
2788 | .sku = IWL_SKU_G, | ||
2789 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, | ||
2790 | .ops = &iwl3945_ops, | ||
2791 | .mod_params = &iwl3945_mod_params, | ||
2792 | .base_params = &iwl3945_base_params, | ||
2793 | .led_mode = IWL_LED_BLINK, | ||
2794 | }; | ||
2795 | |||
2796 | static struct iwl_cfg iwl3945_abg_cfg = { | ||
2797 | .name = "3945ABG", | ||
2798 | .fw_name_pre = IWL3945_FW_PRE, | ||
2799 | .ucode_api_max = IWL3945_UCODE_API_MAX, | ||
2800 | .ucode_api_min = IWL3945_UCODE_API_MIN, | ||
2801 | .sku = IWL_SKU_A|IWL_SKU_G, | ||
2802 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, | ||
2803 | .ops = &iwl3945_ops, | ||
2804 | .mod_params = &iwl3945_mod_params, | ||
2805 | .base_params = &iwl3945_base_params, | ||
2806 | .led_mode = IWL_LED_BLINK, | ||
2807 | }; | ||
2808 | |||
2809 | DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { | ||
2810 | {IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)}, | ||
2811 | {IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)}, | ||
2812 | {IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)}, | ||
2813 | {IWL_PCI_DEVICE(0x4227, 0x1014, iwl3945_bg_cfg)}, | ||
2814 | {IWL_PCI_DEVICE(0x4222, PCI_ANY_ID, iwl3945_abg_cfg)}, | ||
2815 | {IWL_PCI_DEVICE(0x4227, PCI_ANY_ID, iwl3945_abg_cfg)}, | ||
2816 | {0} | ||
2817 | }; | ||
2818 | |||
2819 | MODULE_DEVICE_TABLE(pci, iwl3945_hw_card_ids); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h deleted file mode 100644 index 3eef1eb74a7..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ /dev/null | |||
@@ -1,308 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. | ||
4 | * | ||
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 | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | * | ||
25 | *****************************************************************************/ | ||
26 | /* | ||
27 | * Please use this file (iwl-3945.h) for driver implementation definitions. | ||
28 | * Please use iwl-3945-commands.h for uCode API definitions. | ||
29 | * Please use iwl-3945-hw.h for hardware-related definitions. | ||
30 | */ | ||
31 | |||
32 | #ifndef __iwl_3945_h__ | ||
33 | #define __iwl_3945_h__ | ||
34 | |||
35 | #include <linux/pci.h> /* for struct pci_device_id */ | ||
36 | #include <linux/kernel.h> | ||
37 | #include <net/ieee80211_radiotap.h> | ||
38 | |||
39 | /* Hardware specific file defines the PCI IDs table for that hardware module */ | ||
40 | extern const struct pci_device_id iwl3945_hw_card_ids[]; | ||
41 | |||
42 | #include "iwl-csr.h" | ||
43 | #include "iwl-prph.h" | ||
44 | #include "iwl-fh.h" | ||
45 | #include "iwl-3945-hw.h" | ||
46 | #include "iwl-debug.h" | ||
47 | #include "iwl-power.h" | ||
48 | #include "iwl-dev.h" | ||
49 | #include "iwl-led.h" | ||
50 | |||
51 | /* Highest firmware API version supported */ | ||
52 | #define IWL3945_UCODE_API_MAX 2 | ||
53 | |||
54 | /* Lowest firmware API version supported */ | ||
55 | #define IWL3945_UCODE_API_MIN 1 | ||
56 | |||
57 | #define IWL3945_FW_PRE "iwlwifi-3945-" | ||
58 | #define _IWL3945_MODULE_FIRMWARE(api) IWL3945_FW_PRE #api ".ucode" | ||
59 | #define IWL3945_MODULE_FIRMWARE(api) _IWL3945_MODULE_FIRMWARE(api) | ||
60 | |||
61 | /* Default noise level to report when noise measurement is not available. | ||
62 | * This may be because we're: | ||
63 | * 1) Not associated (4965, no beacon statistics being sent to driver) | ||
64 | * 2) Scanning (noise measurement does not apply to associated channel) | ||
65 | * 3) Receiving CCK (3945 delivers noise info only for OFDM frames) | ||
66 | * Use default noise value of -127 ... this is below the range of measurable | ||
67 | * Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user. | ||
68 | * Also, -127 works better than 0 when averaging frames with/without | ||
69 | * noise info (e.g. averaging might be done in app); measured dBm values are | ||
70 | * always negative ... using a negative value as the default keeps all | ||
71 | * averages within an s8's (used in some apps) range of negative values. */ | ||
72 | #define IWL_NOISE_MEAS_NOT_AVAILABLE (-127) | ||
73 | |||
74 | /* Module parameters accessible from iwl-*.c */ | ||
75 | extern struct iwl_mod_params iwl3945_mod_params; | ||
76 | |||
77 | struct iwl3945_rate_scale_data { | ||
78 | u64 data; | ||
79 | s32 success_counter; | ||
80 | s32 success_ratio; | ||
81 | s32 counter; | ||
82 | s32 average_tpt; | ||
83 | unsigned long stamp; | ||
84 | }; | ||
85 | |||
86 | struct iwl3945_rs_sta { | ||
87 | spinlock_t lock; | ||
88 | struct iwl_priv *priv; | ||
89 | s32 *expected_tpt; | ||
90 | unsigned long last_partial_flush; | ||
91 | unsigned long last_flush; | ||
92 | u32 flush_time; | ||
93 | u32 last_tx_packets; | ||
94 | u32 tx_packets; | ||
95 | u8 tgg; | ||
96 | u8 flush_pending; | ||
97 | u8 start_rate; | ||
98 | struct timer_list rate_scale_flush; | ||
99 | struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945]; | ||
100 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
101 | struct dentry *rs_sta_dbgfs_stats_table_file; | ||
102 | #endif | ||
103 | |||
104 | /* used to be in sta_info */ | ||
105 | int last_txrate_idx; | ||
106 | }; | ||
107 | |||
108 | |||
109 | /* | ||
110 | * The common struct MUST be first because it is shared between | ||
111 | * 3945 and agn! | ||
112 | */ | ||
113 | struct iwl3945_sta_priv { | ||
114 | struct iwl_station_priv_common common; | ||
115 | struct iwl3945_rs_sta rs_sta; | ||
116 | }; | ||
117 | |||
118 | enum iwl3945_antenna { | ||
119 | IWL_ANTENNA_DIVERSITY, | ||
120 | IWL_ANTENNA_MAIN, | ||
121 | IWL_ANTENNA_AUX | ||
122 | }; | ||
123 | |||
124 | /* | ||
125 | * RTS threshold here is total size [2347] minus 4 FCS bytes | ||
126 | * Per spec: | ||
127 | * a value of 0 means RTS on all data/management packets | ||
128 | * a value > max MSDU size means no RTS | ||
129 | * else RTS for data/management frames where MPDU is larger | ||
130 | * than RTS value. | ||
131 | */ | ||
132 | #define DEFAULT_RTS_THRESHOLD 2347U | ||
133 | #define MIN_RTS_THRESHOLD 0U | ||
134 | #define MAX_RTS_THRESHOLD 2347U | ||
135 | #define MAX_MSDU_SIZE 2304U | ||
136 | #define MAX_MPDU_SIZE 2346U | ||
137 | #define DEFAULT_BEACON_INTERVAL 100U | ||
138 | #define DEFAULT_SHORT_RETRY_LIMIT 7U | ||
139 | #define DEFAULT_LONG_RETRY_LIMIT 4U | ||
140 | |||
141 | #define IWL_TX_FIFO_AC0 0 | ||
142 | #define IWL_TX_FIFO_AC1 1 | ||
143 | #define IWL_TX_FIFO_AC2 2 | ||
144 | #define IWL_TX_FIFO_AC3 3 | ||
145 | #define IWL_TX_FIFO_HCCA_1 5 | ||
146 | #define IWL_TX_FIFO_HCCA_2 6 | ||
147 | #define IWL_TX_FIFO_NONE 7 | ||
148 | |||
149 | #define IEEE80211_DATA_LEN 2304 | ||
150 | #define IEEE80211_4ADDR_LEN 30 | ||
151 | #define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) | ||
152 | #define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) | ||
153 | |||
154 | struct iwl3945_frame { | ||
155 | union { | ||
156 | struct ieee80211_hdr frame; | ||
157 | struct iwl3945_tx_beacon_cmd beacon; | ||
158 | u8 raw[IEEE80211_FRAME_LEN]; | ||
159 | u8 cmd[360]; | ||
160 | } u; | ||
161 | struct list_head list; | ||
162 | }; | ||
163 | |||
164 | #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) | ||
165 | #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) | ||
166 | #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) | ||
167 | |||
168 | #define SUP_RATE_11A_MAX_NUM_CHANNELS 8 | ||
169 | #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 | ||
170 | #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 | ||
171 | |||
172 | #define IWL_SUPPORTED_RATES_IE_LEN 8 | ||
173 | |||
174 | #define SCAN_INTERVAL 100 | ||
175 | |||
176 | #define MAX_TID_COUNT 9 | ||
177 | |||
178 | #define IWL_INVALID_RATE 0xFF | ||
179 | #define IWL_INVALID_VALUE -1 | ||
180 | |||
181 | #define STA_PS_STATUS_WAKE 0 | ||
182 | #define STA_PS_STATUS_SLEEP 1 | ||
183 | |||
184 | struct iwl3945_ibss_seq { | ||
185 | u8 mac[ETH_ALEN]; | ||
186 | u16 seq_num; | ||
187 | u16 frag_num; | ||
188 | unsigned long packet_time; | ||
189 | struct list_head list; | ||
190 | }; | ||
191 | |||
192 | #define IWL_RX_HDR(x) ((struct iwl3945_rx_frame_hdr *)(\ | ||
193 | x->u.rx_frame.stats.payload + \ | ||
194 | x->u.rx_frame.stats.phy_count)) | ||
195 | #define IWL_RX_END(x) ((struct iwl3945_rx_frame_end *)(\ | ||
196 | IWL_RX_HDR(x)->payload + \ | ||
197 | le16_to_cpu(IWL_RX_HDR(x)->len))) | ||
198 | #define IWL_RX_STATS(x) (&x->u.rx_frame.stats) | ||
199 | #define IWL_RX_DATA(x) (IWL_RX_HDR(x)->payload) | ||
200 | |||
201 | |||
202 | /****************************************************************************** | ||
203 | * | ||
204 | * Functions implemented in iwl-base.c which are forward declared here | ||
205 | * for use by iwl-*.c | ||
206 | * | ||
207 | *****************************************************************************/ | ||
208 | extern int iwl3945_calc_db_from_ratio(int sig_ratio); | ||
209 | extern void iwl3945_rx_replenish(void *data); | ||
210 | extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
211 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, | ||
212 | struct ieee80211_hdr *hdr,int left); | ||
213 | extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | ||
214 | char **buf, bool display); | ||
215 | extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); | ||
216 | |||
217 | /****************************************************************************** | ||
218 | * | ||
219 | * Functions implemented in iwl-[34]*.c which are forward declared here | ||
220 | * for use by iwl-base.c | ||
221 | * | ||
222 | * NOTE: The implementation of these functions are hardware specific | ||
223 | * which is why they are in the hardware specific files (vs. iwl-base.c) | ||
224 | * | ||
225 | * Naming convention -- | ||
226 | * iwl3945_ <-- Its part of iwlwifi (should be changed to iwl3945_) | ||
227 | * iwl3945_hw_ <-- Hardware specific (implemented in iwl-XXXX.c by all HW) | ||
228 | * iwlXXXX_ <-- Hardware specific (implemented in iwl-XXXX.c for XXXX) | ||
229 | * iwl3945_bg_ <-- Called from work queue context | ||
230 | * iwl3945_mac_ <-- mac80211 callback | ||
231 | * | ||
232 | ****************************************************************************/ | ||
233 | extern void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv); | ||
234 | extern void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv); | ||
235 | extern void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv); | ||
236 | extern int iwl3945_hw_rxq_stop(struct iwl_priv *priv); | ||
237 | extern int iwl3945_hw_set_hw_params(struct iwl_priv *priv); | ||
238 | extern int iwl3945_hw_nic_init(struct iwl_priv *priv); | ||
239 | extern int iwl3945_hw_nic_stop_master(struct iwl_priv *priv); | ||
240 | extern void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv); | ||
241 | extern void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv); | ||
242 | extern int iwl3945_hw_nic_reset(struct iwl_priv *priv); | ||
243 | extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | ||
244 | struct iwl_tx_queue *txq, | ||
245 | dma_addr_t addr, u16 len, | ||
246 | u8 reset, u8 pad); | ||
247 | extern void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, | ||
248 | struct iwl_tx_queue *txq); | ||
249 | extern int iwl3945_hw_get_temperature(struct iwl_priv *priv); | ||
250 | extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, | ||
251 | struct iwl_tx_queue *txq); | ||
252 | extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv, | ||
253 | struct iwl3945_frame *frame, u8 rate); | ||
254 | void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, | ||
255 | struct iwl_device_cmd *cmd, | ||
256 | struct ieee80211_tx_info *info, | ||
257 | struct ieee80211_hdr *hdr, | ||
258 | int sta_id, int tx_id); | ||
259 | extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv); | ||
260 | extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power); | ||
261 | extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv, | ||
262 | struct iwl_rx_mem_buffer *rxb); | ||
263 | void iwl3945_reply_statistics(struct iwl_priv *priv, | ||
264 | struct iwl_rx_mem_buffer *rxb); | ||
265 | extern void iwl3945_disable_events(struct iwl_priv *priv); | ||
266 | extern int iwl4965_get_temperature(const struct iwl_priv *priv); | ||
267 | extern void iwl3945_post_associate(struct iwl_priv *priv); | ||
268 | extern void iwl3945_config_ap(struct iwl_priv *priv); | ||
269 | |||
270 | extern int iwl3945_commit_rxon(struct iwl_priv *priv, | ||
271 | struct iwl_rxon_context *ctx); | ||
272 | |||
273 | /** | ||
274 | * iwl3945_hw_find_station - Find station id for a given BSSID | ||
275 | * @bssid: MAC address of station ID to find | ||
276 | * | ||
277 | * NOTE: This should not be hardware specific but the code has | ||
278 | * not yet been merged into a single common layer for managing the | ||
279 | * station tables. | ||
280 | */ | ||
281 | extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid); | ||
282 | |||
283 | extern struct ieee80211_ops iwl3945_hw_ops; | ||
284 | |||
285 | /* | ||
286 | * Forward declare iwl-3945.c functions for iwl-base.c | ||
287 | */ | ||
288 | extern __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv); | ||
289 | extern int iwl3945_init_hw_rate_table(struct iwl_priv *priv); | ||
290 | extern void iwl3945_reg_txpower_periodic(struct iwl_priv *priv); | ||
291 | extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv); | ||
292 | |||
293 | extern const struct iwl_channel_info *iwl3945_get_channel_info( | ||
294 | const struct iwl_priv *priv, enum ieee80211_band band, u16 channel); | ||
295 | |||
296 | extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate); | ||
297 | |||
298 | /* scanning */ | ||
299 | int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); | ||
300 | void iwl3945_post_scan(struct iwl_priv *priv); | ||
301 | |||
302 | /* rates */ | ||
303 | extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945]; | ||
304 | |||
305 | /* Requires full declaration of iwl_priv before including */ | ||
306 | #include "iwl-io.h" | ||
307 | |||
308 | #endif | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h deleted file mode 100644 index 9166794eda0..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ /dev/null | |||
@@ -1,792 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | /* | ||
64 | * Please use this file (iwl-4965-hw.h) only for hardware-related definitions. | ||
65 | * Use iwl-commands.h for uCode API definitions. | ||
66 | * Use iwl-dev.h for driver implementation definitions. | ||
67 | */ | ||
68 | |||
69 | #ifndef __iwl_4965_hw_h__ | ||
70 | #define __iwl_4965_hw_h__ | ||
71 | |||
72 | #include "iwl-fh.h" | ||
73 | |||
74 | /* EEPROM */ | ||
75 | #define IWL4965_EEPROM_IMG_SIZE 1024 | ||
76 | |||
77 | /* | ||
78 | * uCode queue management definitions ... | ||
79 | * The first queue used for block-ack aggregation is #7 (4965 only). | ||
80 | * All block-ack aggregation queues should map to Tx DMA/FIFO channel 7. | ||
81 | */ | ||
82 | #define IWL49_FIRST_AMPDU_QUEUE 7 | ||
83 | |||
84 | /* Sizes and addresses for instruction and data memory (SRAM) in | ||
85 | * 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ | ||
86 | #define IWL49_RTC_INST_LOWER_BOUND (0x000000) | ||
87 | #define IWL49_RTC_INST_UPPER_BOUND (0x018000) | ||
88 | |||
89 | #define IWL49_RTC_DATA_LOWER_BOUND (0x800000) | ||
90 | #define IWL49_RTC_DATA_UPPER_BOUND (0x80A000) | ||
91 | |||
92 | #define IWL49_RTC_INST_SIZE (IWL49_RTC_INST_UPPER_BOUND - \ | ||
93 | IWL49_RTC_INST_LOWER_BOUND) | ||
94 | #define IWL49_RTC_DATA_SIZE (IWL49_RTC_DATA_UPPER_BOUND - \ | ||
95 | IWL49_RTC_DATA_LOWER_BOUND) | ||
96 | |||
97 | #define IWL49_MAX_INST_SIZE IWL49_RTC_INST_SIZE | ||
98 | #define IWL49_MAX_DATA_SIZE IWL49_RTC_DATA_SIZE | ||
99 | |||
100 | /* Size of uCode instruction memory in bootstrap state machine */ | ||
101 | #define IWL49_MAX_BSM_SIZE BSM_SRAM_SIZE | ||
102 | |||
103 | static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr) | ||
104 | { | ||
105 | return (addr >= IWL49_RTC_DATA_LOWER_BOUND) && | ||
106 | (addr < IWL49_RTC_DATA_UPPER_BOUND); | ||
107 | } | ||
108 | |||
109 | /********************* START TEMPERATURE *************************************/ | ||
110 | |||
111 | /** | ||
112 | * 4965 temperature calculation. | ||
113 | * | ||
114 | * The driver must calculate the device temperature before calculating | ||
115 | * a txpower setting (amplifier gain is temperature dependent). The | ||
116 | * calculation uses 4 measurements, 3 of which (R1, R2, R3) are calibration | ||
117 | * values used for the life of the driver, and one of which (R4) is the | ||
118 | * real-time temperature indicator. | ||
119 | * | ||
120 | * uCode provides all 4 values to the driver via the "initialize alive" | ||
121 | * notification (see struct iwl4965_init_alive_resp). After the runtime uCode | ||
122 | * image loads, uCode updates the R4 value via statistics notifications | ||
123 | * (see STATISTICS_NOTIFICATION), which occur after each received beacon | ||
124 | * when associated, or can be requested via REPLY_STATISTICS_CMD. | ||
125 | * | ||
126 | * NOTE: uCode provides the R4 value as a 23-bit signed value. Driver | ||
127 | * must sign-extend to 32 bits before applying formula below. | ||
128 | * | ||
129 | * Formula: | ||
130 | * | ||
131 | * degrees Kelvin = ((97 * 259 * (R4 - R2) / (R3 - R1)) / 100) + 8 | ||
132 | * | ||
133 | * NOTE: The basic formula is 259 * (R4-R2) / (R3-R1). The 97/100 is | ||
134 | * an additional correction, which should be centered around 0 degrees | ||
135 | * Celsius (273 degrees Kelvin). The 8 (3 percent of 273) compensates for | ||
136 | * centering the 97/100 correction around 0 degrees K. | ||
137 | * | ||
138 | * Add 273 to Kelvin value to find degrees Celsius, for comparing current | ||
139 | * temperature with factory-measured temperatures when calculating txpower | ||
140 | * settings. | ||
141 | */ | ||
142 | #define TEMPERATURE_CALIB_KELVIN_OFFSET 8 | ||
143 | #define TEMPERATURE_CALIB_A_VAL 259 | ||
144 | |||
145 | /* Limit range of calculated temperature to be between these Kelvin values */ | ||
146 | #define IWL_TX_POWER_TEMPERATURE_MIN (263) | ||
147 | #define IWL_TX_POWER_TEMPERATURE_MAX (410) | ||
148 | |||
149 | #define IWL_TX_POWER_TEMPERATURE_OUT_OF_RANGE(t) \ | ||
150 | (((t) < IWL_TX_POWER_TEMPERATURE_MIN) || \ | ||
151 | ((t) > IWL_TX_POWER_TEMPERATURE_MAX)) | ||
152 | |||
153 | /********************* END TEMPERATURE ***************************************/ | ||
154 | |||
155 | /********************* START TXPOWER *****************************************/ | ||
156 | |||
157 | /** | ||
158 | * 4965 txpower calculations rely on information from three sources: | ||
159 | * | ||
160 | * 1) EEPROM | ||
161 | * 2) "initialize" alive notification | ||
162 | * 3) statistics notifications | ||
163 | * | ||
164 | * EEPROM data consists of: | ||
165 | * | ||
166 | * 1) Regulatory information (max txpower and channel usage flags) is provided | ||
167 | * separately for each channel that can possibly supported by 4965. | ||
168 | * 40 MHz wide (.11n HT40) channels are listed separately from 20 MHz | ||
169 | * (legacy) channels. | ||
170 | * | ||
171 | * See struct iwl4965_eeprom_channel for format, and struct iwl4965_eeprom | ||
172 | * for locations in EEPROM. | ||
173 | * | ||
174 | * 2) Factory txpower calibration information is provided separately for | ||
175 | * sub-bands of contiguous channels. 2.4GHz has just one sub-band, | ||
176 | * but 5 GHz has several sub-bands. | ||
177 | * | ||
178 | * In addition, per-band (2.4 and 5 Ghz) saturation txpowers are provided. | ||
179 | * | ||
180 | * See struct iwl4965_eeprom_calib_info (and the tree of structures | ||
181 | * contained within it) for format, and struct iwl4965_eeprom for | ||
182 | * locations in EEPROM. | ||
183 | * | ||
184 | * "Initialization alive" notification (see struct iwl4965_init_alive_resp) | ||
185 | * consists of: | ||
186 | * | ||
187 | * 1) Temperature calculation parameters. | ||
188 | * | ||
189 | * 2) Power supply voltage measurement. | ||
190 | * | ||
191 | * 3) Tx gain compensation to balance 2 transmitters for MIMO use. | ||
192 | * | ||
193 | * Statistics notifications deliver: | ||
194 | * | ||
195 | * 1) Current values for temperature param R4. | ||
196 | */ | ||
197 | |||
198 | /** | ||
199 | * To calculate a txpower setting for a given desired target txpower, channel, | ||
200 | * modulation bit rate, and transmitter chain (4965 has 2 transmitters to | ||
201 | * support MIMO and transmit diversity), driver must do the following: | ||
202 | * | ||
203 | * 1) Compare desired txpower vs. (EEPROM) regulatory limit for this channel. | ||
204 | * Do not exceed regulatory limit; reduce target txpower if necessary. | ||
205 | * | ||
206 | * If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31), | ||
207 | * 2 transmitters will be used simultaneously; driver must reduce the | ||
208 | * regulatory limit by 3 dB (half-power) for each transmitter, so the | ||
209 | * combined total output of the 2 transmitters is within regulatory limits. | ||
210 | * | ||
211 | * | ||
212 | * 2) Compare target txpower vs. (EEPROM) saturation txpower *reduced by | ||
213 | * backoff for this bit rate*. Do not exceed (saturation - backoff[rate]); | ||
214 | * reduce target txpower if necessary. | ||
215 | * | ||
216 | * Backoff values below are in 1/2 dB units (equivalent to steps in | ||
217 | * txpower gain tables): | ||
218 | * | ||
219 | * OFDM 6 - 36 MBit: 10 steps (5 dB) | ||
220 | * OFDM 48 MBit: 15 steps (7.5 dB) | ||
221 | * OFDM 54 MBit: 17 steps (8.5 dB) | ||
222 | * OFDM 60 MBit: 20 steps (10 dB) | ||
223 | * CCK all rates: 10 steps (5 dB) | ||
224 | * | ||
225 | * Backoff values apply to saturation txpower on a per-transmitter basis; | ||
226 | * when using MIMO (2 transmitters), each transmitter uses the same | ||
227 | * saturation level provided in EEPROM, and the same backoff values; | ||
228 | * no reduction (such as with regulatory txpower limits) is required. | ||
229 | * | ||
230 | * Saturation and Backoff values apply equally to 20 Mhz (legacy) channel | ||
231 | * widths and 40 Mhz (.11n HT40) channel widths; there is no separate | ||
232 | * factory measurement for ht40 channels. | ||
233 | * | ||
234 | * The result of this step is the final target txpower. The rest of | ||
235 | * the steps figure out the proper settings for the device to achieve | ||
236 | * that target txpower. | ||
237 | * | ||
238 | * | ||
239 | * 3) Determine (EEPROM) calibration sub band for the target channel, by | ||
240 | * comparing against first and last channels in each sub band | ||
241 | * (see struct iwl4965_eeprom_calib_subband_info). | ||
242 | * | ||
243 | * | ||
244 | * 4) Linearly interpolate (EEPROM) factory calibration measurement sets, | ||
245 | * referencing the 2 factory-measured (sample) channels within the sub band. | ||
246 | * | ||
247 | * Interpolation is based on difference between target channel's frequency | ||
248 | * and the sample channels' frequencies. Since channel numbers are based | ||
249 | * on frequency (5 MHz between each channel number), this is equivalent | ||
250 | * to interpolating based on channel number differences. | ||
251 | * | ||
252 | * Note that the sample channels may or may not be the channels at the | ||
253 | * edges of the sub band. The target channel may be "outside" of the | ||
254 | * span of the sampled channels. | ||
255 | * | ||
256 | * Driver may choose the pair (for 2 Tx chains) of measurements (see | ||
257 | * struct iwl4965_eeprom_calib_ch_info) for which the actual measured | ||
258 | * txpower comes closest to the desired txpower. Usually, though, | ||
259 | * the middle set of measurements is closest to the regulatory limits, | ||
260 | * and is therefore a good choice for all txpower calculations (this | ||
261 | * assumes that high accuracy is needed for maximizing legal txpower, | ||
262 | * while lower txpower configurations do not need as much accuracy). | ||
263 | * | ||
264 | * Driver should interpolate both members of the chosen measurement pair, | ||
265 | * i.e. for both Tx chains (radio transmitters), unless the driver knows | ||
266 | * that only one of the chains will be used (e.g. only one tx antenna | ||
267 | * connected, but this should be unusual). The rate scaling algorithm | ||
268 | * switches antennas to find best performance, so both Tx chains will | ||
269 | * be used (although only one at a time) even for non-MIMO transmissions. | ||
270 | * | ||
271 | * Driver should interpolate factory values for temperature, gain table | ||
272 | * index, and actual power. The power amplifier detector values are | ||
273 | * not used by the driver. | ||
274 | * | ||
275 | * Sanity check: If the target channel happens to be one of the sample | ||
276 | * channels, the results should agree with the sample channel's | ||
277 | * measurements! | ||
278 | * | ||
279 | * | ||
280 | * 5) Find difference between desired txpower and (interpolated) | ||
281 | * factory-measured txpower. Using (interpolated) factory gain table index | ||
282 | * (shown elsewhere) as a starting point, adjust this index lower to | ||
283 | * increase txpower, or higher to decrease txpower, until the target | ||
284 | * txpower is reached. Each step in the gain table is 1/2 dB. | ||
285 | * | ||
286 | * For example, if factory measured txpower is 16 dBm, and target txpower | ||
287 | * is 13 dBm, add 6 steps to the factory gain index to reduce txpower | ||
288 | * by 3 dB. | ||
289 | * | ||
290 | * | ||
291 | * 6) Find difference between current device temperature and (interpolated) | ||
292 | * factory-measured temperature for sub-band. Factory values are in | ||
293 | * degrees Celsius. To calculate current temperature, see comments for | ||
294 | * "4965 temperature calculation". | ||
295 | * | ||
296 | * If current temperature is higher than factory temperature, driver must | ||
297 | * increase gain (lower gain table index), and vice verse. | ||
298 | * | ||
299 | * Temperature affects gain differently for different channels: | ||
300 | * | ||
301 | * 2.4 GHz all channels: 3.5 degrees per half-dB step | ||
302 | * 5 GHz channels 34-43: 4.5 degrees per half-dB step | ||
303 | * 5 GHz channels >= 44: 4.0 degrees per half-dB step | ||
304 | * | ||
305 | * NOTE: Temperature can increase rapidly when transmitting, especially | ||
306 | * with heavy traffic at high txpowers. Driver should update | ||
307 | * temperature calculations often under these conditions to | ||
308 | * maintain strong txpower in the face of rising temperature. | ||
309 | * | ||
310 | * | ||
311 | * 7) Find difference between current power supply voltage indicator | ||
312 | * (from "initialize alive") and factory-measured power supply voltage | ||
313 | * indicator (EEPROM). | ||
314 | * | ||
315 | * If the current voltage is higher (indicator is lower) than factory | ||
316 | * voltage, gain should be reduced (gain table index increased) by: | ||
317 | * | ||
318 | * (eeprom - current) / 7 | ||
319 | * | ||
320 | * If the current voltage is lower (indicator is higher) than factory | ||
321 | * voltage, gain should be increased (gain table index decreased) by: | ||
322 | * | ||
323 | * 2 * (current - eeprom) / 7 | ||
324 | * | ||
325 | * If number of index steps in either direction turns out to be > 2, | ||
326 | * something is wrong ... just use 0. | ||
327 | * | ||
328 | * NOTE: Voltage compensation is independent of band/channel. | ||
329 | * | ||
330 | * NOTE: "Initialize" uCode measures current voltage, which is assumed | ||
331 | * to be constant after this initial measurement. Voltage | ||
332 | * compensation for txpower (number of steps in gain table) | ||
333 | * may be calculated once and used until the next uCode bootload. | ||
334 | * | ||
335 | * | ||
336 | * 8) If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31), | ||
337 | * adjust txpower for each transmitter chain, so txpower is balanced | ||
338 | * between the two chains. There are 5 pairs of tx_atten[group][chain] | ||
339 | * values in "initialize alive", one pair for each of 5 channel ranges: | ||
340 | * | ||
341 | * Group 0: 5 GHz channel 34-43 | ||
342 | * Group 1: 5 GHz channel 44-70 | ||
343 | * Group 2: 5 GHz channel 71-124 | ||
344 | * Group 3: 5 GHz channel 125-200 | ||
345 | * Group 4: 2.4 GHz all channels | ||
346 | * | ||
347 | * Add the tx_atten[group][chain] value to the index for the target chain. | ||
348 | * The values are signed, but are in pairs of 0 and a non-negative number, | ||
349 | * so as to reduce gain (if necessary) of the "hotter" channel. This | ||
350 | * avoids any need to double-check for regulatory compliance after | ||
351 | * this step. | ||
352 | * | ||
353 | * | ||
354 | * 9) If setting up for a CCK rate, lower the gain by adding a CCK compensation | ||
355 | * value to the index: | ||
356 | * | ||
357 | * Hardware rev B: 9 steps (4.5 dB) | ||
358 | * Hardware rev C: 5 steps (2.5 dB) | ||
359 | * | ||
360 | * Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG, | ||
361 | * bits [3:2], 1 = B, 2 = C. | ||
362 | * | ||
363 | * NOTE: This compensation is in addition to any saturation backoff that | ||
364 | * might have been applied in an earlier step. | ||
365 | * | ||
366 | * | ||
367 | * 10) Select the gain table, based on band (2.4 vs 5 GHz). | ||
368 | * | ||
369 | * Limit the adjusted index to stay within the table! | ||
370 | * | ||
371 | * | ||
372 | * 11) Read gain table entries for DSP and radio gain, place into appropriate | ||
373 | * location(s) in command (struct iwl4965_txpowertable_cmd). | ||
374 | */ | ||
375 | |||
376 | /** | ||
377 | * When MIMO is used (2 transmitters operating simultaneously), driver should | ||
378 | * limit each transmitter to deliver a max of 3 dB below the regulatory limit | ||
379 | * for the device. That is, use half power for each transmitter, so total | ||
380 | * txpower is within regulatory limits. | ||
381 | * | ||
382 | * The value "6" represents number of steps in gain table to reduce power 3 dB. | ||
383 | * Each step is 1/2 dB. | ||
384 | */ | ||
385 | #define IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION (6) | ||
386 | |||
387 | /** | ||
388 | * CCK gain compensation. | ||
389 | * | ||
390 | * When calculating txpowers for CCK, after making sure that the target power | ||
391 | * is within regulatory and saturation limits, driver must additionally | ||
392 | * back off gain by adding these values to the gain table index. | ||
393 | * | ||
394 | * Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG, | ||
395 | * bits [3:2], 1 = B, 2 = C. | ||
396 | */ | ||
397 | #define IWL_TX_POWER_CCK_COMPENSATION_B_STEP (9) | ||
398 | #define IWL_TX_POWER_CCK_COMPENSATION_C_STEP (5) | ||
399 | |||
400 | /* | ||
401 | * 4965 power supply voltage compensation for txpower | ||
402 | */ | ||
403 | #define TX_POWER_IWL_VOLTAGE_CODES_PER_03V (7) | ||
404 | |||
405 | /** | ||
406 | * Gain tables. | ||
407 | * | ||
408 | * The following tables contain pair of values for setting txpower, i.e. | ||
409 | * gain settings for the output of the device's digital signal processor (DSP), | ||
410 | * and for the analog gain structure of the transmitter. | ||
411 | * | ||
412 | * Each entry in the gain tables represents a step of 1/2 dB. Note that these | ||
413 | * are *relative* steps, not indications of absolute output power. Output | ||
414 | * power varies with temperature, voltage, and channel frequency, and also | ||
415 | * requires consideration of average power (to satisfy regulatory constraints), | ||
416 | * and peak power (to avoid distortion of the output signal). | ||
417 | * | ||
418 | * Each entry contains two values: | ||
419 | * 1) DSP gain (or sometimes called DSP attenuation). This is a fine-grained | ||
420 | * linear value that multiplies the output of the digital signal processor, | ||
421 | * before being sent to the analog radio. | ||
422 | * 2) Radio gain. This sets the analog gain of the radio Tx path. | ||
423 | * It is a coarser setting, and behaves in a logarithmic (dB) fashion. | ||
424 | * | ||
425 | * EEPROM contains factory calibration data for txpower. This maps actual | ||
426 | * measured txpower levels to gain settings in the "well known" tables | ||
427 | * below ("well-known" means here that both factory calibration *and* the | ||
428 | * driver work with the same table). | ||
429 | * | ||
430 | * There are separate tables for 2.4 GHz and 5 GHz bands. The 5 GHz table | ||
431 | * has an extension (into negative indexes), in case the driver needs to | ||
432 | * boost power setting for high device temperatures (higher than would be | ||
433 | * present during factory calibration). A 5 Ghz EEPROM index of "40" | ||
434 | * corresponds to the 49th entry in the table used by the driver. | ||
435 | */ | ||
436 | #define MIN_TX_GAIN_INDEX (0) /* highest gain, lowest idx, 2.4 */ | ||
437 | #define MIN_TX_GAIN_INDEX_52GHZ_EXT (-9) /* highest gain, lowest idx, 5 */ | ||
438 | |||
439 | /** | ||
440 | * 2.4 GHz gain table | ||
441 | * | ||
442 | * Index Dsp gain Radio gain | ||
443 | * 0 110 0x3f (highest gain) | ||
444 | * 1 104 0x3f | ||
445 | * 2 98 0x3f | ||
446 | * 3 110 0x3e | ||
447 | * 4 104 0x3e | ||
448 | * 5 98 0x3e | ||
449 | * 6 110 0x3d | ||
450 | * 7 104 0x3d | ||
451 | * 8 98 0x3d | ||
452 | * 9 110 0x3c | ||
453 | * 10 104 0x3c | ||
454 | * 11 98 0x3c | ||
455 | * 12 110 0x3b | ||
456 | * 13 104 0x3b | ||
457 | * 14 98 0x3b | ||
458 | * 15 110 0x3a | ||
459 | * 16 104 0x3a | ||
460 | * 17 98 0x3a | ||
461 | * 18 110 0x39 | ||
462 | * 19 104 0x39 | ||
463 | * 20 98 0x39 | ||
464 | * 21 110 0x38 | ||
465 | * 22 104 0x38 | ||
466 | * 23 98 0x38 | ||
467 | * 24 110 0x37 | ||
468 | * 25 104 0x37 | ||
469 | * 26 98 0x37 | ||
470 | * 27 110 0x36 | ||
471 | * 28 104 0x36 | ||
472 | * 29 98 0x36 | ||
473 | * 30 110 0x35 | ||
474 | * 31 104 0x35 | ||
475 | * 32 98 0x35 | ||
476 | * 33 110 0x34 | ||
477 | * 34 104 0x34 | ||
478 | * 35 98 0x34 | ||
479 | * 36 110 0x33 | ||
480 | * 37 104 0x33 | ||
481 | * 38 98 0x33 | ||
482 | * 39 110 0x32 | ||
483 | * 40 104 0x32 | ||
484 | * 41 98 0x32 | ||
485 | * 42 110 0x31 | ||
486 | * 43 104 0x31 | ||
487 | * 44 98 0x31 | ||
488 | * 45 110 0x30 | ||
489 | * 46 104 0x30 | ||
490 | * 47 98 0x30 | ||
491 | * 48 110 0x6 | ||
492 | * 49 104 0x6 | ||
493 | * 50 98 0x6 | ||
494 | * 51 110 0x5 | ||
495 | * 52 104 0x5 | ||
496 | * 53 98 0x5 | ||
497 | * 54 110 0x4 | ||
498 | * 55 104 0x4 | ||
499 | * 56 98 0x4 | ||
500 | * 57 110 0x3 | ||
501 | * 58 104 0x3 | ||
502 | * 59 98 0x3 | ||
503 | * 60 110 0x2 | ||
504 | * 61 104 0x2 | ||
505 | * 62 98 0x2 | ||
506 | * 63 110 0x1 | ||
507 | * 64 104 0x1 | ||
508 | * 65 98 0x1 | ||
509 | * 66 110 0x0 | ||
510 | * 67 104 0x0 | ||
511 | * 68 98 0x0 | ||
512 | * 69 97 0 | ||
513 | * 70 96 0 | ||
514 | * 71 95 0 | ||
515 | * 72 94 0 | ||
516 | * 73 93 0 | ||
517 | * 74 92 0 | ||
518 | * 75 91 0 | ||
519 | * 76 90 0 | ||
520 | * 77 89 0 | ||
521 | * 78 88 0 | ||
522 | * 79 87 0 | ||
523 | * 80 86 0 | ||
524 | * 81 85 0 | ||
525 | * 82 84 0 | ||
526 | * 83 83 0 | ||
527 | * 84 82 0 | ||
528 | * 85 81 0 | ||
529 | * 86 80 0 | ||
530 | * 87 79 0 | ||
531 | * 88 78 0 | ||
532 | * 89 77 0 | ||
533 | * 90 76 0 | ||
534 | * 91 75 0 | ||
535 | * 92 74 0 | ||
536 | * 93 73 0 | ||
537 | * 94 72 0 | ||
538 | * 95 71 0 | ||
539 | * 96 70 0 | ||
540 | * 97 69 0 | ||
541 | * 98 68 0 | ||
542 | */ | ||
543 | |||
544 | /** | ||
545 | * 5 GHz gain table | ||
546 | * | ||
547 | * Index Dsp gain Radio gain | ||
548 | * -9 123 0x3F (highest gain) | ||
549 | * -8 117 0x3F | ||
550 | * -7 110 0x3F | ||
551 | * -6 104 0x3F | ||
552 | * -5 98 0x3F | ||
553 | * -4 110 0x3E | ||
554 | * -3 104 0x3E | ||
555 | * -2 98 0x3E | ||
556 | * -1 110 0x3D | ||
557 | * 0 104 0x3D | ||
558 | * 1 98 0x3D | ||
559 | * 2 110 0x3C | ||
560 | * 3 104 0x3C | ||
561 | * 4 98 0x3C | ||
562 | * 5 110 0x3B | ||
563 | * 6 104 0x3B | ||
564 | * 7 98 0x3B | ||
565 | * 8 110 0x3A | ||
566 | * 9 104 0x3A | ||
567 | * 10 98 0x3A | ||
568 | * 11 110 0x39 | ||
569 | * 12 104 0x39 | ||
570 | * 13 98 0x39 | ||
571 | * 14 110 0x38 | ||
572 | * 15 104 0x38 | ||
573 | * 16 98 0x38 | ||
574 | * 17 110 0x37 | ||
575 | * 18 104 0x37 | ||
576 | * 19 98 0x37 | ||
577 | * 20 110 0x36 | ||
578 | * 21 104 0x36 | ||
579 | * 22 98 0x36 | ||
580 | * 23 110 0x35 | ||
581 | * 24 104 0x35 | ||
582 | * 25 98 0x35 | ||
583 | * 26 110 0x34 | ||
584 | * 27 104 0x34 | ||
585 | * 28 98 0x34 | ||
586 | * 29 110 0x33 | ||
587 | * 30 104 0x33 | ||
588 | * 31 98 0x33 | ||
589 | * 32 110 0x32 | ||
590 | * 33 104 0x32 | ||
591 | * 34 98 0x32 | ||
592 | * 35 110 0x31 | ||
593 | * 36 104 0x31 | ||
594 | * 37 98 0x31 | ||
595 | * 38 110 0x30 | ||
596 | * 39 104 0x30 | ||
597 | * 40 98 0x30 | ||
598 | * 41 110 0x25 | ||
599 | * 42 104 0x25 | ||
600 | * 43 98 0x25 | ||
601 | * 44 110 0x24 | ||
602 | * 45 104 0x24 | ||
603 | * 46 98 0x24 | ||
604 | * 47 110 0x23 | ||
605 | * 48 104 0x23 | ||
606 | * 49 98 0x23 | ||
607 | * 50 110 0x22 | ||
608 | * 51 104 0x18 | ||
609 | * 52 98 0x18 | ||
610 | * 53 110 0x17 | ||
611 | * 54 104 0x17 | ||
612 | * 55 98 0x17 | ||
613 | * 56 110 0x16 | ||
614 | * 57 104 0x16 | ||
615 | * 58 98 0x16 | ||
616 | * 59 110 0x15 | ||
617 | * 60 104 0x15 | ||
618 | * 61 98 0x15 | ||
619 | * 62 110 0x14 | ||
620 | * 63 104 0x14 | ||
621 | * 64 98 0x14 | ||
622 | * 65 110 0x13 | ||
623 | * 66 104 0x13 | ||
624 | * 67 98 0x13 | ||
625 | * 68 110 0x12 | ||
626 | * 69 104 0x08 | ||
627 | * 70 98 0x08 | ||
628 | * 71 110 0x07 | ||
629 | * 72 104 0x07 | ||
630 | * 73 98 0x07 | ||
631 | * 74 110 0x06 | ||
632 | * 75 104 0x06 | ||
633 | * 76 98 0x06 | ||
634 | * 77 110 0x05 | ||
635 | * 78 104 0x05 | ||
636 | * 79 98 0x05 | ||
637 | * 80 110 0x04 | ||
638 | * 81 104 0x04 | ||
639 | * 82 98 0x04 | ||
640 | * 83 110 0x03 | ||
641 | * 84 104 0x03 | ||
642 | * 85 98 0x03 | ||
643 | * 86 110 0x02 | ||
644 | * 87 104 0x02 | ||
645 | * 88 98 0x02 | ||
646 | * 89 110 0x01 | ||
647 | * 90 104 0x01 | ||
648 | * 91 98 0x01 | ||
649 | * 92 110 0x00 | ||
650 | * 93 104 0x00 | ||
651 | * 94 98 0x00 | ||
652 | * 95 93 0x00 | ||
653 | * 96 88 0x00 | ||
654 | * 97 83 0x00 | ||
655 | * 98 78 0x00 | ||
656 | */ | ||
657 | |||
658 | |||
659 | /** | ||
660 | * Sanity checks and default values for EEPROM regulatory levels. | ||
661 | * If EEPROM values fall outside MIN/MAX range, use default values. | ||
662 | * | ||
663 | * Regulatory limits refer to the maximum average txpower allowed by | ||
664 | * regulatory agencies in the geographies in which the device is meant | ||
665 | * to be operated. These limits are SKU-specific (i.e. geography-specific), | ||
666 | * and channel-specific; each channel has an individual regulatory limit | ||
667 | * listed in the EEPROM. | ||
668 | * | ||
669 | * Units are in half-dBm (i.e. "34" means 17 dBm). | ||
670 | */ | ||
671 | #define IWL_TX_POWER_DEFAULT_REGULATORY_24 (34) | ||
672 | #define IWL_TX_POWER_DEFAULT_REGULATORY_52 (34) | ||
673 | #define IWL_TX_POWER_REGULATORY_MIN (0) | ||
674 | #define IWL_TX_POWER_REGULATORY_MAX (34) | ||
675 | |||
676 | /** | ||
677 | * Sanity checks and default values for EEPROM saturation levels. | ||
678 | * If EEPROM values fall outside MIN/MAX range, use default values. | ||
679 | * | ||
680 | * Saturation is the highest level that the output power amplifier can produce | ||
681 | * without significant clipping distortion. This is a "peak" power level. | ||
682 | * Different types of modulation (i.e. various "rates", and OFDM vs. CCK) | ||
683 | * require differing amounts of backoff, relative to their average power output, | ||
684 | * in order to avoid clipping distortion. | ||
685 | * | ||
686 | * Driver must make sure that it is violating neither the saturation limit, | ||
687 | * nor the regulatory limit, when calculating Tx power settings for various | ||
688 | * rates. | ||
689 | * | ||
690 | * Units are in half-dBm (i.e. "38" means 19 dBm). | ||
691 | */ | ||
692 | #define IWL_TX_POWER_DEFAULT_SATURATION_24 (38) | ||
693 | #define IWL_TX_POWER_DEFAULT_SATURATION_52 (38) | ||
694 | #define IWL_TX_POWER_SATURATION_MIN (20) | ||
695 | #define IWL_TX_POWER_SATURATION_MAX (50) | ||
696 | |||
697 | /** | ||
698 | * Channel groups used for Tx Attenuation calibration (MIMO tx channel balance) | ||
699 | * and thermal Txpower calibration. | ||
700 | * | ||
701 | * When calculating txpower, driver must compensate for current device | ||
702 | * temperature; higher temperature requires higher gain. Driver must calculate | ||
703 | * current temperature (see "4965 temperature calculation"), then compare vs. | ||
704 | * factory calibration temperature in EEPROM; if current temperature is higher | ||
705 | * than factory temperature, driver must *increase* gain by proportions shown | ||
706 | * in table below. If current temperature is lower than factory, driver must | ||
707 | * *decrease* gain. | ||
708 | * | ||
709 | * Different frequency ranges require different compensation, as shown below. | ||
710 | */ | ||
711 | /* Group 0, 5.2 GHz ch 34-43: 4.5 degrees per 1/2 dB. */ | ||
712 | #define CALIB_IWL_TX_ATTEN_GR1_FCH 34 | ||
713 | #define CALIB_IWL_TX_ATTEN_GR1_LCH 43 | ||
714 | |||
715 | /* Group 1, 5.3 GHz ch 44-70: 4.0 degrees per 1/2 dB. */ | ||
716 | #define CALIB_IWL_TX_ATTEN_GR2_FCH 44 | ||
717 | #define CALIB_IWL_TX_ATTEN_GR2_LCH 70 | ||
718 | |||
719 | /* Group 2, 5.5 GHz ch 71-124: 4.0 degrees per 1/2 dB. */ | ||
720 | #define CALIB_IWL_TX_ATTEN_GR3_FCH 71 | ||
721 | #define CALIB_IWL_TX_ATTEN_GR3_LCH 124 | ||
722 | |||
723 | /* Group 3, 5.7 GHz ch 125-200: 4.0 degrees per 1/2 dB. */ | ||
724 | #define CALIB_IWL_TX_ATTEN_GR4_FCH 125 | ||
725 | #define CALIB_IWL_TX_ATTEN_GR4_LCH 200 | ||
726 | |||
727 | /* Group 4, 2.4 GHz all channels: 3.5 degrees per 1/2 dB. */ | ||
728 | #define CALIB_IWL_TX_ATTEN_GR5_FCH 1 | ||
729 | #define CALIB_IWL_TX_ATTEN_GR5_LCH 20 | ||
730 | |||
731 | enum { | ||
732 | CALIB_CH_GROUP_1 = 0, | ||
733 | CALIB_CH_GROUP_2 = 1, | ||
734 | CALIB_CH_GROUP_3 = 2, | ||
735 | CALIB_CH_GROUP_4 = 3, | ||
736 | CALIB_CH_GROUP_5 = 4, | ||
737 | CALIB_CH_GROUP_MAX | ||
738 | }; | ||
739 | |||
740 | /********************* END TXPOWER *****************************************/ | ||
741 | |||
742 | |||
743 | /** | ||
744 | * Tx/Rx Queues | ||
745 | * | ||
746 | * Most communication between driver and 4965 is via queues of data buffers. | ||
747 | * For example, all commands that the driver issues to device's embedded | ||
748 | * controller (uCode) are via the command queue (one of the Tx queues). All | ||
749 | * uCode command responses/replies/notifications, including Rx frames, are | ||
750 | * conveyed from uCode to driver via the Rx queue. | ||
751 | * | ||
752 | * Most support for these queues, including handshake support, resides in | ||
753 | * structures in host DRAM, shared between the driver and the device. When | ||
754 | * allocating this memory, the driver must make sure that data written by | ||
755 | * the host CPU updates DRAM immediately (and does not get "stuck" in CPU's | ||
756 | * cache memory), so DRAM and cache are consistent, and the device can | ||
757 | * immediately see changes made by the driver. | ||
758 | * | ||
759 | * 4965 supports up to 16 DRAM-based Tx queues, and services these queues via | ||
760 | * up to 7 DMA channels (FIFOs). Each Tx queue is supported by a circular array | ||
761 | * in DRAM containing 256 Transmit Frame Descriptors (TFDs). | ||
762 | */ | ||
763 | #define IWL49_NUM_FIFOS 7 | ||
764 | #define IWL49_CMD_FIFO_NUM 4 | ||
765 | #define IWL49_NUM_QUEUES 16 | ||
766 | #define IWL49_NUM_AMPDU_QUEUES 8 | ||
767 | |||
768 | |||
769 | /** | ||
770 | * struct iwl4965_schedq_bc_tbl | ||
771 | * | ||
772 | * Byte Count table | ||
773 | * | ||
774 | * Each Tx queue uses a byte-count table containing 320 entries: | ||
775 | * one 16-bit entry for each of 256 TFDs, plus an additional 64 entries that | ||
776 | * duplicate the first 64 entries (to avoid wrap-around within a Tx window; | ||
777 | * max Tx window is 64 TFDs). | ||
778 | * | ||
779 | * When driver sets up a new TFD, it must also enter the total byte count | ||
780 | * of the frame to be transmitted into the corresponding entry in the byte | ||
781 | * count table for the chosen Tx queue. If the TFD index is 0-63, the driver | ||
782 | * must duplicate the byte count entry in corresponding index 256-319. | ||
783 | * | ||
784 | * padding puts each byte count table on a 1024-byte boundary; | ||
785 | * 4965 assumes tables are separated by 1024 bytes. | ||
786 | */ | ||
787 | struct iwl4965_scd_bc_tbl { | ||
788 | __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; | ||
789 | u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)]; | ||
790 | } __packed; | ||
791 | |||
792 | #endif /* !__iwl_4965_hw_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c deleted file mode 100644 index 8998ed134d1..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ /dev/null | |||
@@ -1,2666 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. | ||
4 | * | ||
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 | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | * | ||
25 | *****************************************************************************/ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/pci.h> | ||
31 | #include <linux/dma-mapping.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/sched.h> | ||
34 | #include <linux/skbuff.h> | ||
35 | #include <linux/netdevice.h> | ||
36 | #include <linux/wireless.h> | ||
37 | #include <net/mac80211.h> | ||
38 | #include <linux/etherdevice.h> | ||
39 | #include <asm/unaligned.h> | ||
40 | |||
41 | #include "iwl-eeprom.h" | ||
42 | #include "iwl-dev.h" | ||
43 | #include "iwl-core.h" | ||
44 | #include "iwl-io.h" | ||
45 | #include "iwl-helpers.h" | ||
46 | #include "iwl-agn-calib.h" | ||
47 | #include "iwl-sta.h" | ||
48 | #include "iwl-agn-led.h" | ||
49 | #include "iwl-agn.h" | ||
50 | #include "iwl-agn-debugfs.h" | ||
51 | #include "iwl-legacy.h" | ||
52 | |||
53 | static int iwl4965_send_tx_power(struct iwl_priv *priv); | ||
54 | static int iwl4965_hw_get_temperature(struct iwl_priv *priv); | ||
55 | |||
56 | /* Highest firmware API version supported */ | ||
57 | #define IWL4965_UCODE_API_MAX 2 | ||
58 | |||
59 | /* Lowest firmware API version supported */ | ||
60 | #define IWL4965_UCODE_API_MIN 2 | ||
61 | |||
62 | #define IWL4965_FW_PRE "iwlwifi-4965-" | ||
63 | #define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode" | ||
64 | #define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api) | ||
65 | |||
66 | /* check contents of special bootstrap uCode SRAM */ | ||
67 | static int iwl4965_verify_bsm(struct iwl_priv *priv) | ||
68 | { | ||
69 | __le32 *image = priv->ucode_boot.v_addr; | ||
70 | u32 len = priv->ucode_boot.len; | ||
71 | u32 reg; | ||
72 | u32 val; | ||
73 | |||
74 | IWL_DEBUG_INFO(priv, "Begin verify bsm\n"); | ||
75 | |||
76 | /* verify BSM SRAM contents */ | ||
77 | val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG); | ||
78 | for (reg = BSM_SRAM_LOWER_BOUND; | ||
79 | reg < BSM_SRAM_LOWER_BOUND + len; | ||
80 | reg += sizeof(u32), image++) { | ||
81 | val = iwl_read_prph(priv, reg); | ||
82 | if (val != le32_to_cpu(*image)) { | ||
83 | IWL_ERR(priv, "BSM uCode verification failed at " | ||
84 | "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n", | ||
85 | BSM_SRAM_LOWER_BOUND, | ||
86 | reg - BSM_SRAM_LOWER_BOUND, len, | ||
87 | val, le32_to_cpu(*image)); | ||
88 | return -EIO; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | IWL_DEBUG_INFO(priv, "BSM bootstrap uCode image OK\n"); | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * iwl4965_load_bsm - Load bootstrap instructions | ||
99 | * | ||
100 | * BSM operation: | ||
101 | * | ||
102 | * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program | ||
103 | * in special SRAM that does not power down during RFKILL. When powering back | ||
104 | * up after power-saving sleeps (or during initial uCode load), the BSM loads | ||
105 | * the bootstrap program into the on-board processor, and starts it. | ||
106 | * | ||
107 | * The bootstrap program loads (via DMA) instructions and data for a new | ||
108 | * program from host DRAM locations indicated by the host driver in the | ||
109 | * BSM_DRAM_* registers. Once the new program is loaded, it starts | ||
110 | * automatically. | ||
111 | * | ||
112 | * When initializing the NIC, the host driver points the BSM to the | ||
113 | * "initialize" uCode image. This uCode sets up some internal data, then | ||
114 | * notifies host via "initialize alive" that it is complete. | ||
115 | * | ||
116 | * The host then replaces the BSM_DRAM_* pointer values to point to the | ||
117 | * normal runtime uCode instructions and a backup uCode data cache buffer | ||
118 | * (filled initially with starting data values for the on-board processor), | ||
119 | * then triggers the "initialize" uCode to load and launch the runtime uCode, | ||
120 | * which begins normal operation. | ||
121 | * | ||
122 | * When doing a power-save shutdown, runtime uCode saves data SRAM into | ||
123 | * the backup data cache in DRAM before SRAM is powered down. | ||
124 | * | ||
125 | * When powering back up, the BSM loads the bootstrap program. This reloads | ||
126 | * the runtime uCode instructions and the backup data cache into SRAM, | ||
127 | * and re-launches the runtime uCode from where it left off. | ||
128 | */ | ||
129 | static int iwl4965_load_bsm(struct iwl_priv *priv) | ||
130 | { | ||
131 | __le32 *image = priv->ucode_boot.v_addr; | ||
132 | u32 len = priv->ucode_boot.len; | ||
133 | dma_addr_t pinst; | ||
134 | dma_addr_t pdata; | ||
135 | u32 inst_len; | ||
136 | u32 data_len; | ||
137 | int i; | ||
138 | u32 done; | ||
139 | u32 reg_offset; | ||
140 | int ret; | ||
141 | |||
142 | IWL_DEBUG_INFO(priv, "Begin load bsm\n"); | ||
143 | |||
144 | priv->ucode_type = UCODE_RT; | ||
145 | |||
146 | /* make sure bootstrap program is no larger than BSM's SRAM size */ | ||
147 | if (len > IWL49_MAX_BSM_SIZE) | ||
148 | return -EINVAL; | ||
149 | |||
150 | /* Tell bootstrap uCode where to find the "Initialize" uCode | ||
151 | * in host DRAM ... host DRAM physical address bits 35:4 for 4965. | ||
152 | * NOTE: iwl_init_alive_start() will replace these values, | ||
153 | * after the "initialize" uCode has run, to point to | ||
154 | * runtime/protocol instructions and backup data cache. | ||
155 | */ | ||
156 | pinst = priv->ucode_init.p_addr >> 4; | ||
157 | pdata = priv->ucode_init_data.p_addr >> 4; | ||
158 | inst_len = priv->ucode_init.len; | ||
159 | data_len = priv->ucode_init_data.len; | ||
160 | |||
161 | iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); | ||
162 | iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); | ||
163 | iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); | ||
164 | iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len); | ||
165 | |||
166 | /* Fill BSM memory with bootstrap instructions */ | ||
167 | for (reg_offset = BSM_SRAM_LOWER_BOUND; | ||
168 | reg_offset < BSM_SRAM_LOWER_BOUND + len; | ||
169 | reg_offset += sizeof(u32), image++) | ||
170 | _iwl_write_prph(priv, reg_offset, le32_to_cpu(*image)); | ||
171 | |||
172 | ret = iwl4965_verify_bsm(priv); | ||
173 | if (ret) | ||
174 | return ret; | ||
175 | |||
176 | /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ | ||
177 | iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); | ||
178 | iwl_write_prph(priv, BSM_WR_MEM_DST_REG, IWL49_RTC_INST_LOWER_BOUND); | ||
179 | iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); | ||
180 | |||
181 | /* Load bootstrap code into instruction SRAM now, | ||
182 | * to prepare to load "initialize" uCode */ | ||
183 | iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START); | ||
184 | |||
185 | /* Wait for load of bootstrap uCode to finish */ | ||
186 | for (i = 0; i < 100; i++) { | ||
187 | done = iwl_read_prph(priv, BSM_WR_CTRL_REG); | ||
188 | if (!(done & BSM_WR_CTRL_REG_BIT_START)) | ||
189 | break; | ||
190 | udelay(10); | ||
191 | } | ||
192 | if (i < 100) | ||
193 | IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i); | ||
194 | else { | ||
195 | IWL_ERR(priv, "BSM write did not complete!\n"); | ||
196 | return -EIO; | ||
197 | } | ||
198 | |||
199 | /* Enable future boot loads whenever power management unit triggers it | ||
200 | * (e.g. when powering back up after power-save shutdown) */ | ||
201 | iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN); | ||
202 | |||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | /** | ||
208 | * iwl4965_set_ucode_ptrs - Set uCode address location | ||
209 | * | ||
210 | * Tell initialization uCode where to find runtime uCode. | ||
211 | * | ||
212 | * BSM registers initially contain pointers to initialization uCode. | ||
213 | * We need to replace them to load runtime uCode inst and data, | ||
214 | * and to save runtime data when powering down. | ||
215 | */ | ||
216 | static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv) | ||
217 | { | ||
218 | dma_addr_t pinst; | ||
219 | dma_addr_t pdata; | ||
220 | int ret = 0; | ||
221 | |||
222 | /* bits 35:4 for 4965 */ | ||
223 | pinst = priv->ucode_code.p_addr >> 4; | ||
224 | pdata = priv->ucode_data_backup.p_addr >> 4; | ||
225 | |||
226 | /* Tell bootstrap uCode where to find image to load */ | ||
227 | iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); | ||
228 | iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); | ||
229 | iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, | ||
230 | priv->ucode_data.len); | ||
231 | |||
232 | /* Inst byte count must be last to set up, bit 31 signals uCode | ||
233 | * that all new ptr/size info is in place */ | ||
234 | iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, | ||
235 | priv->ucode_code.len | BSM_DRAM_INST_LOAD); | ||
236 | IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n"); | ||
237 | |||
238 | return ret; | ||
239 | } | ||
240 | |||
241 | /** | ||
242 | * iwl4965_init_alive_start - Called after REPLY_ALIVE notification received | ||
243 | * | ||
244 | * Called after REPLY_ALIVE notification received from "initialize" uCode. | ||
245 | * | ||
246 | * The 4965 "initialize" ALIVE reply contains calibration data for: | ||
247 | * Voltage, temperature, and MIMO tx gain correction, now stored in priv | ||
248 | * (3945 does not contain this data). | ||
249 | * | ||
250 | * Tell "initialize" uCode to go ahead and load the runtime uCode. | ||
251 | */ | ||
252 | static void iwl4965_init_alive_start(struct iwl_priv *priv) | ||
253 | { | ||
254 | /* Bootstrap uCode has loaded initialize uCode ... verify inst image. | ||
255 | * This is a paranoid check, because we would not have gotten the | ||
256 | * "initialize" alive if code weren't properly loaded. */ | ||
257 | if (iwl_verify_ucode(priv)) { | ||
258 | /* Runtime instruction load was bad; | ||
259 | * take it all the way back down so we can try again */ | ||
260 | IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); | ||
261 | goto restart; | ||
262 | } | ||
263 | |||
264 | /* Calculate temperature */ | ||
265 | priv->temperature = iwl4965_hw_get_temperature(priv); | ||
266 | |||
267 | /* Send pointers to protocol/runtime uCode image ... init code will | ||
268 | * load and launch runtime uCode, which will send us another "Alive" | ||
269 | * notification. */ | ||
270 | IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); | ||
271 | if (iwl4965_set_ucode_ptrs(priv)) { | ||
272 | /* Runtime instruction load won't happen; | ||
273 | * take it all the way back down so we can try again */ | ||
274 | IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n"); | ||
275 | goto restart; | ||
276 | } | ||
277 | return; | ||
278 | |||
279 | restart: | ||
280 | queue_work(priv->workqueue, &priv->restart); | ||
281 | } | ||
282 | |||
283 | static bool is_ht40_channel(__le32 rxon_flags) | ||
284 | { | ||
285 | int chan_mod = le32_to_cpu(rxon_flags & RXON_FLG_CHANNEL_MODE_MSK) | ||
286 | >> RXON_FLG_CHANNEL_MODE_POS; | ||
287 | return ((chan_mod == CHANNEL_MODE_PURE_40) || | ||
288 | (chan_mod == CHANNEL_MODE_MIXED)); | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * EEPROM handlers | ||
293 | */ | ||
294 | static u16 iwl4965_eeprom_calib_version(struct iwl_priv *priv) | ||
295 | { | ||
296 | return iwl_eeprom_query16(priv, EEPROM_4965_CALIB_VERSION_OFFSET); | ||
297 | } | ||
298 | |||
299 | /* | ||
300 | * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask | ||
301 | * must be called under priv->lock and mac access | ||
302 | */ | ||
303 | static void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask) | ||
304 | { | ||
305 | iwl_write_prph(priv, IWL49_SCD_TXFACT, mask); | ||
306 | } | ||
307 | |||
308 | static void iwl4965_nic_config(struct iwl_priv *priv) | ||
309 | { | ||
310 | unsigned long flags; | ||
311 | u16 radio_cfg; | ||
312 | |||
313 | spin_lock_irqsave(&priv->lock, flags); | ||
314 | |||
315 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | ||
316 | |||
317 | /* write radio config values to register */ | ||
318 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) == EEPROM_4965_RF_CFG_TYPE_MAX) | ||
319 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
320 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | | ||
321 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | | ||
322 | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); | ||
323 | |||
324 | /* set CSR_HW_CONFIG_REG for uCode use */ | ||
325 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
326 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||
327 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||
328 | |||
329 | priv->calib_info = (struct iwl_eeprom_calib_info *) | ||
330 | iwl_eeprom_query_addr(priv, EEPROM_4965_CALIB_TXPOWER_OFFSET); | ||
331 | |||
332 | spin_unlock_irqrestore(&priv->lock, flags); | ||
333 | } | ||
334 | |||
335 | /* Reset differential Rx gains in NIC to prepare for chain noise calibration. | ||
336 | * Called after every association, but this runs only once! | ||
337 | * ... once chain noise is calibrated the first time, it's good forever. */ | ||
338 | static void iwl4965_chain_noise_reset(struct iwl_priv *priv) | ||
339 | { | ||
340 | struct iwl_chain_noise_data *data = &(priv->chain_noise_data); | ||
341 | |||
342 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && | ||
343 | iwl_is_any_associated(priv)) { | ||
344 | struct iwl_calib_diff_gain_cmd cmd; | ||
345 | |||
346 | /* clear data for chain noise calibration algorithm */ | ||
347 | data->chain_noise_a = 0; | ||
348 | data->chain_noise_b = 0; | ||
349 | data->chain_noise_c = 0; | ||
350 | data->chain_signal_a = 0; | ||
351 | data->chain_signal_b = 0; | ||
352 | data->chain_signal_c = 0; | ||
353 | data->beacon_count = 0; | ||
354 | |||
355 | memset(&cmd, 0, sizeof(cmd)); | ||
356 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD; | ||
357 | cmd.diff_gain_a = 0; | ||
358 | cmd.diff_gain_b = 0; | ||
359 | cmd.diff_gain_c = 0; | ||
360 | if (iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, | ||
361 | sizeof(cmd), &cmd)) | ||
362 | IWL_ERR(priv, | ||
363 | "Could not send REPLY_PHY_CALIBRATION_CMD\n"); | ||
364 | data->state = IWL_CHAIN_NOISE_ACCUMULATE; | ||
365 | IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); | ||
366 | } | ||
367 | } | ||
368 | |||
369 | static void iwl4965_gain_computation(struct iwl_priv *priv, | ||
370 | u32 *average_noise, | ||
371 | u16 min_average_noise_antenna_i, | ||
372 | u32 min_average_noise, | ||
373 | u8 default_chain) | ||
374 | { | ||
375 | int i, ret; | ||
376 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | ||
377 | |||
378 | data->delta_gain_code[min_average_noise_antenna_i] = 0; | ||
379 | |||
380 | for (i = default_chain; i < NUM_RX_CHAINS; i++) { | ||
381 | s32 delta_g = 0; | ||
382 | |||
383 | if (!(data->disconn_array[i]) && | ||
384 | (data->delta_gain_code[i] == | ||
385 | CHAIN_NOISE_DELTA_GAIN_INIT_VAL)) { | ||
386 | delta_g = average_noise[i] - min_average_noise; | ||
387 | data->delta_gain_code[i] = (u8)((delta_g * 10) / 15); | ||
388 | data->delta_gain_code[i] = | ||
389 | min(data->delta_gain_code[i], | ||
390 | (u8) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); | ||
391 | |||
392 | data->delta_gain_code[i] = | ||
393 | (data->delta_gain_code[i] | (1 << 2)); | ||
394 | } else { | ||
395 | data->delta_gain_code[i] = 0; | ||
396 | } | ||
397 | } | ||
398 | IWL_DEBUG_CALIB(priv, "delta_gain_codes: a %d b %d c %d\n", | ||
399 | data->delta_gain_code[0], | ||
400 | data->delta_gain_code[1], | ||
401 | data->delta_gain_code[2]); | ||
402 | |||
403 | /* Differential gain gets sent to uCode only once */ | ||
404 | if (!data->radio_write) { | ||
405 | struct iwl_calib_diff_gain_cmd cmd; | ||
406 | data->radio_write = 1; | ||
407 | |||
408 | memset(&cmd, 0, sizeof(cmd)); | ||
409 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD; | ||
410 | cmd.diff_gain_a = data->delta_gain_code[0]; | ||
411 | cmd.diff_gain_b = data->delta_gain_code[1]; | ||
412 | cmd.diff_gain_c = data->delta_gain_code[2]; | ||
413 | ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, | ||
414 | sizeof(cmd), &cmd); | ||
415 | if (ret) | ||
416 | IWL_DEBUG_CALIB(priv, "fail sending cmd " | ||
417 | "REPLY_PHY_CALIBRATION_CMD\n"); | ||
418 | |||
419 | /* TODO we might want recalculate | ||
420 | * rx_chain in rxon cmd */ | ||
421 | |||
422 | /* Mark so we run this algo only once! */ | ||
423 | data->state = IWL_CHAIN_NOISE_CALIBRATED; | ||
424 | } | ||
425 | } | ||
426 | |||
427 | static void iwl4965_bg_txpower_work(struct work_struct *work) | ||
428 | { | ||
429 | struct iwl_priv *priv = container_of(work, struct iwl_priv, | ||
430 | txpower_work); | ||
431 | |||
432 | /* If a scan happened to start before we got here | ||
433 | * then just return; the statistics notification will | ||
434 | * kick off another scheduled work to compensate for | ||
435 | * any temperature delta we missed here. */ | ||
436 | if (test_bit(STATUS_EXIT_PENDING, &priv->status) || | ||
437 | test_bit(STATUS_SCANNING, &priv->status)) | ||
438 | return; | ||
439 | |||
440 | mutex_lock(&priv->mutex); | ||
441 | |||
442 | /* Regardless of if we are associated, we must reconfigure the | ||
443 | * TX power since frames can be sent on non-radar channels while | ||
444 | * not associated */ | ||
445 | iwl4965_send_tx_power(priv); | ||
446 | |||
447 | /* Update last_temperature to keep is_calib_needed from running | ||
448 | * when it isn't needed... */ | ||
449 | priv->last_temperature = priv->temperature; | ||
450 | |||
451 | mutex_unlock(&priv->mutex); | ||
452 | } | ||
453 | |||
454 | /* | ||
455 | * Acquire priv->lock before calling this function ! | ||
456 | */ | ||
457 | static void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index) | ||
458 | { | ||
459 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, | ||
460 | (index & 0xff) | (txq_id << 8)); | ||
461 | iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(txq_id), index); | ||
462 | } | ||
463 | |||
464 | /** | ||
465 | * iwl4965_tx_queue_set_status - (optionally) start Tx/Cmd queue | ||
466 | * @tx_fifo_id: Tx DMA/FIFO channel (range 0-7) that the queue will feed | ||
467 | * @scd_retry: (1) Indicates queue will be used in aggregation mode | ||
468 | * | ||
469 | * NOTE: Acquire priv->lock before calling this function ! | ||
470 | */ | ||
471 | static void iwl4965_tx_queue_set_status(struct iwl_priv *priv, | ||
472 | struct iwl_tx_queue *txq, | ||
473 | int tx_fifo_id, int scd_retry) | ||
474 | { | ||
475 | int txq_id = txq->q.id; | ||
476 | |||
477 | /* Find out whether to activate Tx queue */ | ||
478 | int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; | ||
479 | |||
480 | /* Set up and activate */ | ||
481 | iwl_write_prph(priv, IWL49_SCD_QUEUE_STATUS_BITS(txq_id), | ||
482 | (active << IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE) | | ||
483 | (tx_fifo_id << IWL49_SCD_QUEUE_STTS_REG_POS_TXF) | | ||
484 | (scd_retry << IWL49_SCD_QUEUE_STTS_REG_POS_WSL) | | ||
485 | (scd_retry << IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK) | | ||
486 | IWL49_SCD_QUEUE_STTS_REG_MSK); | ||
487 | |||
488 | txq->sched_retry = scd_retry; | ||
489 | |||
490 | IWL_DEBUG_INFO(priv, "%s %s Queue %d on AC %d\n", | ||
491 | active ? "Activate" : "Deactivate", | ||
492 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); | ||
493 | } | ||
494 | |||
495 | static const s8 default_queue_to_tx_fifo[] = { | ||
496 | IWL_TX_FIFO_VO, | ||
497 | IWL_TX_FIFO_VI, | ||
498 | IWL_TX_FIFO_BE, | ||
499 | IWL_TX_FIFO_BK, | ||
500 | IWL49_CMD_FIFO_NUM, | ||
501 | IWL_TX_FIFO_UNUSED, | ||
502 | IWL_TX_FIFO_UNUSED, | ||
503 | }; | ||
504 | |||
505 | static int iwl4965_alive_notify(struct iwl_priv *priv) | ||
506 | { | ||
507 | u32 a; | ||
508 | unsigned long flags; | ||
509 | int i, chan; | ||
510 | u32 reg_val; | ||
511 | |||
512 | spin_lock_irqsave(&priv->lock, flags); | ||
513 | |||
514 | /* Clear 4965's internal Tx Scheduler data base */ | ||
515 | priv->scd_base_addr = iwl_read_prph(priv, IWL49_SCD_SRAM_BASE_ADDR); | ||
516 | a = priv->scd_base_addr + IWL49_SCD_CONTEXT_DATA_OFFSET; | ||
517 | for (; a < priv->scd_base_addr + IWL49_SCD_TX_STTS_BITMAP_OFFSET; a += 4) | ||
518 | iwl_write_targ_mem(priv, a, 0); | ||
519 | for (; a < priv->scd_base_addr + IWL49_SCD_TRANSLATE_TBL_OFFSET; a += 4) | ||
520 | iwl_write_targ_mem(priv, a, 0); | ||
521 | for (; a < priv->scd_base_addr + | ||
522 | IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) | ||
523 | iwl_write_targ_mem(priv, a, 0); | ||
524 | |||
525 | /* Tel 4965 where to find Tx byte count tables */ | ||
526 | iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR, | ||
527 | priv->scd_bc_tbls.dma >> 10); | ||
528 | |||
529 | /* Enable DMA channel */ | ||
530 | for (chan = 0; chan < FH49_TCSR_CHNL_NUM ; chan++) | ||
531 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), | ||
532 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
533 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); | ||
534 | |||
535 | /* Update FH chicken bits */ | ||
536 | reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); | ||
537 | iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, | ||
538 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | ||
539 | |||
540 | /* Disable chain mode for all queues */ | ||
541 | iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0); | ||
542 | |||
543 | /* Initialize each Tx queue (including the command queue) */ | ||
544 | for (i = 0; i < priv->hw_params.max_txq_num; i++) { | ||
545 | |||
546 | /* TFD circular buffer read/write indexes */ | ||
547 | iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(i), 0); | ||
548 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); | ||
549 | |||
550 | /* Max Tx Window size for Scheduler-ACK mode */ | ||
551 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
552 | IWL49_SCD_CONTEXT_QUEUE_OFFSET(i), | ||
553 | (SCD_WIN_SIZE << | ||
554 | IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) & | ||
555 | IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK); | ||
556 | |||
557 | /* Frame limit */ | ||
558 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
559 | IWL49_SCD_CONTEXT_QUEUE_OFFSET(i) + | ||
560 | sizeof(u32), | ||
561 | (SCD_FRAME_LIMIT << | ||
562 | IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
563 | IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK); | ||
564 | |||
565 | } | ||
566 | iwl_write_prph(priv, IWL49_SCD_INTERRUPT_MASK, | ||
567 | (1 << priv->hw_params.max_txq_num) - 1); | ||
568 | |||
569 | /* Activate all Tx DMA/FIFO channels */ | ||
570 | priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 6)); | ||
571 | |||
572 | iwl4965_set_wr_ptrs(priv, IWL_DEFAULT_CMD_QUEUE_NUM, 0); | ||
573 | |||
574 | /* make sure all queue are not stopped */ | ||
575 | memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); | ||
576 | for (i = 0; i < 4; i++) | ||
577 | atomic_set(&priv->queue_stop_count[i], 0); | ||
578 | |||
579 | /* reset to 0 to enable all the queue first */ | ||
580 | priv->txq_ctx_active_msk = 0; | ||
581 | /* Map each Tx/cmd queue to its corresponding fifo */ | ||
582 | BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7); | ||
583 | |||
584 | for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { | ||
585 | int ac = default_queue_to_tx_fifo[i]; | ||
586 | |||
587 | iwl_txq_ctx_activate(priv, i); | ||
588 | |||
589 | if (ac == IWL_TX_FIFO_UNUSED) | ||
590 | continue; | ||
591 | |||
592 | iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0); | ||
593 | } | ||
594 | |||
595 | spin_unlock_irqrestore(&priv->lock, flags); | ||
596 | |||
597 | return 0; | ||
598 | } | ||
599 | |||
600 | static struct iwl_sensitivity_ranges iwl4965_sensitivity = { | ||
601 | .min_nrg_cck = 97, | ||
602 | .max_nrg_cck = 0, /* not used, set to 0 */ | ||
603 | |||
604 | .auto_corr_min_ofdm = 85, | ||
605 | .auto_corr_min_ofdm_mrc = 170, | ||
606 | .auto_corr_min_ofdm_x1 = 105, | ||
607 | .auto_corr_min_ofdm_mrc_x1 = 220, | ||
608 | |||
609 | .auto_corr_max_ofdm = 120, | ||
610 | .auto_corr_max_ofdm_mrc = 210, | ||
611 | .auto_corr_max_ofdm_x1 = 140, | ||
612 | .auto_corr_max_ofdm_mrc_x1 = 270, | ||
613 | |||
614 | .auto_corr_min_cck = 125, | ||
615 | .auto_corr_max_cck = 200, | ||
616 | .auto_corr_min_cck_mrc = 200, | ||
617 | .auto_corr_max_cck_mrc = 400, | ||
618 | |||
619 | .nrg_th_cck = 100, | ||
620 | .nrg_th_ofdm = 100, | ||
621 | |||
622 | .barker_corr_th_min = 190, | ||
623 | .barker_corr_th_min_mrc = 390, | ||
624 | .nrg_th_cca = 62, | ||
625 | }; | ||
626 | |||
627 | static void iwl4965_set_ct_threshold(struct iwl_priv *priv) | ||
628 | { | ||
629 | /* want Kelvin */ | ||
630 | priv->hw_params.ct_kill_threshold = | ||
631 | CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY); | ||
632 | } | ||
633 | |||
634 | /** | ||
635 | * iwl4965_hw_set_hw_params | ||
636 | * | ||
637 | * Called when initializing driver | ||
638 | */ | ||
639 | static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) | ||
640 | { | ||
641 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | ||
642 | priv->cfg->mod_params->num_of_queues <= IWL49_NUM_QUEUES) | ||
643 | priv->cfg->base_params->num_of_queues = | ||
644 | priv->cfg->mod_params->num_of_queues; | ||
645 | |||
646 | priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; | ||
647 | priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; | ||
648 | priv->hw_params.scd_bc_tbls_size = | ||
649 | priv->cfg->base_params->num_of_queues * | ||
650 | sizeof(struct iwl4965_scd_bc_tbl); | ||
651 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | ||
652 | priv->hw_params.max_stations = IWL4965_STATION_COUNT; | ||
653 | priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL4965_BROADCAST_ID; | ||
654 | priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE; | ||
655 | priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE; | ||
656 | priv->hw_params.max_bsm_size = BSM_SRAM_SIZE; | ||
657 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ); | ||
658 | |||
659 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; | ||
660 | |||
661 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); | ||
662 | priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); | ||
663 | priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; | ||
664 | priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; | ||
665 | |||
666 | iwl4965_set_ct_threshold(priv); | ||
667 | |||
668 | priv->hw_params.sens = &iwl4965_sensitivity; | ||
669 | priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
670 | |||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res) | ||
675 | { | ||
676 | s32 sign = 1; | ||
677 | |||
678 | if (num < 0) { | ||
679 | sign = -sign; | ||
680 | num = -num; | ||
681 | } | ||
682 | if (denom < 0) { | ||
683 | sign = -sign; | ||
684 | denom = -denom; | ||
685 | } | ||
686 | *res = 1; | ||
687 | *res = ((num * 2 + denom) / (denom * 2)) * sign; | ||
688 | |||
689 | return 1; | ||
690 | } | ||
691 | |||
692 | /** | ||
693 | * iwl4965_get_voltage_compensation - Power supply voltage comp for txpower | ||
694 | * | ||
695 | * Determines power supply voltage compensation for txpower calculations. | ||
696 | * Returns number of 1/2-dB steps to subtract from gain table index, | ||
697 | * to compensate for difference between power supply voltage during | ||
698 | * factory measurements, vs. current power supply voltage. | ||
699 | * | ||
700 | * Voltage indication is higher for lower voltage. | ||
701 | * Lower voltage requires more gain (lower gain table index). | ||
702 | */ | ||
703 | static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage, | ||
704 | s32 current_voltage) | ||
705 | { | ||
706 | s32 comp = 0; | ||
707 | |||
708 | if ((TX_POWER_IWL_ILLEGAL_VOLTAGE == eeprom_voltage) || | ||
709 | (TX_POWER_IWL_ILLEGAL_VOLTAGE == current_voltage)) | ||
710 | return 0; | ||
711 | |||
712 | iwl4965_math_div_round(current_voltage - eeprom_voltage, | ||
713 | TX_POWER_IWL_VOLTAGE_CODES_PER_03V, &comp); | ||
714 | |||
715 | if (current_voltage > eeprom_voltage) | ||
716 | comp *= 2; | ||
717 | if ((comp < -2) || (comp > 2)) | ||
718 | comp = 0; | ||
719 | |||
720 | return comp; | ||
721 | } | ||
722 | |||
723 | static s32 iwl4965_get_tx_atten_grp(u16 channel) | ||
724 | { | ||
725 | if (channel >= CALIB_IWL_TX_ATTEN_GR5_FCH && | ||
726 | channel <= CALIB_IWL_TX_ATTEN_GR5_LCH) | ||
727 | return CALIB_CH_GROUP_5; | ||
728 | |||
729 | if (channel >= CALIB_IWL_TX_ATTEN_GR1_FCH && | ||
730 | channel <= CALIB_IWL_TX_ATTEN_GR1_LCH) | ||
731 | return CALIB_CH_GROUP_1; | ||
732 | |||
733 | if (channel >= CALIB_IWL_TX_ATTEN_GR2_FCH && | ||
734 | channel <= CALIB_IWL_TX_ATTEN_GR2_LCH) | ||
735 | return CALIB_CH_GROUP_2; | ||
736 | |||
737 | if (channel >= CALIB_IWL_TX_ATTEN_GR3_FCH && | ||
738 | channel <= CALIB_IWL_TX_ATTEN_GR3_LCH) | ||
739 | return CALIB_CH_GROUP_3; | ||
740 | |||
741 | if (channel >= CALIB_IWL_TX_ATTEN_GR4_FCH && | ||
742 | channel <= CALIB_IWL_TX_ATTEN_GR4_LCH) | ||
743 | return CALIB_CH_GROUP_4; | ||
744 | |||
745 | return -1; | ||
746 | } | ||
747 | |||
748 | static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel) | ||
749 | { | ||
750 | s32 b = -1; | ||
751 | |||
752 | for (b = 0; b < EEPROM_TX_POWER_BANDS; b++) { | ||
753 | if (priv->calib_info->band_info[b].ch_from == 0) | ||
754 | continue; | ||
755 | |||
756 | if ((channel >= priv->calib_info->band_info[b].ch_from) | ||
757 | && (channel <= priv->calib_info->band_info[b].ch_to)) | ||
758 | break; | ||
759 | } | ||
760 | |||
761 | return b; | ||
762 | } | ||
763 | |||
764 | static s32 iwl4965_interpolate_value(s32 x, s32 x1, s32 y1, s32 x2, s32 y2) | ||
765 | { | ||
766 | s32 val; | ||
767 | |||
768 | if (x2 == x1) | ||
769 | return y1; | ||
770 | else { | ||
771 | iwl4965_math_div_round((x2 - x) * (y1 - y2), (x2 - x1), &val); | ||
772 | return val + y2; | ||
773 | } | ||
774 | } | ||
775 | |||
776 | /** | ||
777 | * iwl4965_interpolate_chan - Interpolate factory measurements for one channel | ||
778 | * | ||
779 | * Interpolates factory measurements from the two sample channels within a | ||
780 | * sub-band, to apply to channel of interest. Interpolation is proportional to | ||
781 | * differences in channel frequencies, which is proportional to differences | ||
782 | * in channel number. | ||
783 | */ | ||
784 | static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel, | ||
785 | struct iwl_eeprom_calib_ch_info *chan_info) | ||
786 | { | ||
787 | s32 s = -1; | ||
788 | u32 c; | ||
789 | u32 m; | ||
790 | const struct iwl_eeprom_calib_measure *m1; | ||
791 | const struct iwl_eeprom_calib_measure *m2; | ||
792 | struct iwl_eeprom_calib_measure *omeas; | ||
793 | u32 ch_i1; | ||
794 | u32 ch_i2; | ||
795 | |||
796 | s = iwl4965_get_sub_band(priv, channel); | ||
797 | if (s >= EEPROM_TX_POWER_BANDS) { | ||
798 | IWL_ERR(priv, "Tx Power can not find channel %d\n", channel); | ||
799 | return -1; | ||
800 | } | ||
801 | |||
802 | ch_i1 = priv->calib_info->band_info[s].ch1.ch_num; | ||
803 | ch_i2 = priv->calib_info->band_info[s].ch2.ch_num; | ||
804 | chan_info->ch_num = (u8) channel; | ||
805 | |||
806 | IWL_DEBUG_TXPOWER(priv, "channel %d subband %d factory cal ch %d & %d\n", | ||
807 | channel, s, ch_i1, ch_i2); | ||
808 | |||
809 | for (c = 0; c < EEPROM_TX_POWER_TX_CHAINS; c++) { | ||
810 | for (m = 0; m < EEPROM_TX_POWER_MEASUREMENTS; m++) { | ||
811 | m1 = &(priv->calib_info->band_info[s].ch1. | ||
812 | measurements[c][m]); | ||
813 | m2 = &(priv->calib_info->band_info[s].ch2. | ||
814 | measurements[c][m]); | ||
815 | omeas = &(chan_info->measurements[c][m]); | ||
816 | |||
817 | omeas->actual_pow = | ||
818 | (u8) iwl4965_interpolate_value(channel, ch_i1, | ||
819 | m1->actual_pow, | ||
820 | ch_i2, | ||
821 | m2->actual_pow); | ||
822 | omeas->gain_idx = | ||
823 | (u8) iwl4965_interpolate_value(channel, ch_i1, | ||
824 | m1->gain_idx, ch_i2, | ||
825 | m2->gain_idx); | ||
826 | omeas->temperature = | ||
827 | (u8) iwl4965_interpolate_value(channel, ch_i1, | ||
828 | m1->temperature, | ||
829 | ch_i2, | ||
830 | m2->temperature); | ||
831 | omeas->pa_det = | ||
832 | (s8) iwl4965_interpolate_value(channel, ch_i1, | ||
833 | m1->pa_det, ch_i2, | ||
834 | m2->pa_det); | ||
835 | |||
836 | IWL_DEBUG_TXPOWER(priv, | ||
837 | "chain %d meas %d AP1=%d AP2=%d AP=%d\n", c, m, | ||
838 | m1->actual_pow, m2->actual_pow, omeas->actual_pow); | ||
839 | IWL_DEBUG_TXPOWER(priv, | ||
840 | "chain %d meas %d NI1=%d NI2=%d NI=%d\n", c, m, | ||
841 | m1->gain_idx, m2->gain_idx, omeas->gain_idx); | ||
842 | IWL_DEBUG_TXPOWER(priv, | ||
843 | "chain %d meas %d PA1=%d PA2=%d PA=%d\n", c, m, | ||
844 | m1->pa_det, m2->pa_det, omeas->pa_det); | ||
845 | IWL_DEBUG_TXPOWER(priv, | ||
846 | "chain %d meas %d T1=%d T2=%d T=%d\n", c, m, | ||
847 | m1->temperature, m2->temperature, | ||
848 | omeas->temperature); | ||
849 | } | ||
850 | } | ||
851 | |||
852 | return 0; | ||
853 | } | ||
854 | |||
855 | /* bit-rate-dependent table to prevent Tx distortion, in half-dB units, | ||
856 | * for OFDM 6, 12, 18, 24, 36, 48, 54, 60 MBit, and CCK all rates. */ | ||
857 | static s32 back_off_table[] = { | ||
858 | 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 20 MHz */ | ||
859 | 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 20 MHz */ | ||
860 | 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 40 MHz */ | ||
861 | 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 40 MHz */ | ||
862 | 10 /* CCK */ | ||
863 | }; | ||
864 | |||
865 | /* Thermal compensation values for txpower for various frequency ranges ... | ||
866 | * ratios from 3:1 to 4.5:1 of degrees (Celsius) per half-dB gain adjust */ | ||
867 | static struct iwl4965_txpower_comp_entry { | ||
868 | s32 degrees_per_05db_a; | ||
869 | s32 degrees_per_05db_a_denom; | ||
870 | } tx_power_cmp_tble[CALIB_CH_GROUP_MAX] = { | ||
871 | {9, 2}, /* group 0 5.2, ch 34-43 */ | ||
872 | {4, 1}, /* group 1 5.2, ch 44-70 */ | ||
873 | {4, 1}, /* group 2 5.2, ch 71-124 */ | ||
874 | {4, 1}, /* group 3 5.2, ch 125-200 */ | ||
875 | {3, 1} /* group 4 2.4, ch all */ | ||
876 | }; | ||
877 | |||
878 | static s32 get_min_power_index(s32 rate_power_index, u32 band) | ||
879 | { | ||
880 | if (!band) { | ||
881 | if ((rate_power_index & 7) <= 4) | ||
882 | return MIN_TX_GAIN_INDEX_52GHZ_EXT; | ||
883 | } | ||
884 | return MIN_TX_GAIN_INDEX; | ||
885 | } | ||
886 | |||
887 | struct gain_entry { | ||
888 | u8 dsp; | ||
889 | u8 radio; | ||
890 | }; | ||
891 | |||
892 | static const struct gain_entry gain_table[2][108] = { | ||
893 | /* 5.2GHz power gain index table */ | ||
894 | { | ||
895 | {123, 0x3F}, /* highest txpower */ | ||
896 | {117, 0x3F}, | ||
897 | {110, 0x3F}, | ||
898 | {104, 0x3F}, | ||
899 | {98, 0x3F}, | ||
900 | {110, 0x3E}, | ||
901 | {104, 0x3E}, | ||
902 | {98, 0x3E}, | ||
903 | {110, 0x3D}, | ||
904 | {104, 0x3D}, | ||
905 | {98, 0x3D}, | ||
906 | {110, 0x3C}, | ||
907 | {104, 0x3C}, | ||
908 | {98, 0x3C}, | ||
909 | {110, 0x3B}, | ||
910 | {104, 0x3B}, | ||
911 | {98, 0x3B}, | ||
912 | {110, 0x3A}, | ||
913 | {104, 0x3A}, | ||
914 | {98, 0x3A}, | ||
915 | {110, 0x39}, | ||
916 | {104, 0x39}, | ||
917 | {98, 0x39}, | ||
918 | {110, 0x38}, | ||
919 | {104, 0x38}, | ||
920 | {98, 0x38}, | ||
921 | {110, 0x37}, | ||
922 | {104, 0x37}, | ||
923 | {98, 0x37}, | ||
924 | {110, 0x36}, | ||
925 | {104, 0x36}, | ||
926 | {98, 0x36}, | ||
927 | {110, 0x35}, | ||
928 | {104, 0x35}, | ||
929 | {98, 0x35}, | ||
930 | {110, 0x34}, | ||
931 | {104, 0x34}, | ||
932 | {98, 0x34}, | ||
933 | {110, 0x33}, | ||
934 | {104, 0x33}, | ||
935 | {98, 0x33}, | ||
936 | {110, 0x32}, | ||
937 | {104, 0x32}, | ||
938 | {98, 0x32}, | ||
939 | {110, 0x31}, | ||
940 | {104, 0x31}, | ||
941 | {98, 0x31}, | ||
942 | {110, 0x30}, | ||
943 | {104, 0x30}, | ||
944 | {98, 0x30}, | ||
945 | {110, 0x25}, | ||
946 | {104, 0x25}, | ||
947 | {98, 0x25}, | ||
948 | {110, 0x24}, | ||
949 | {104, 0x24}, | ||
950 | {98, 0x24}, | ||
951 | {110, 0x23}, | ||
952 | {104, 0x23}, | ||
953 | {98, 0x23}, | ||
954 | {110, 0x22}, | ||
955 | {104, 0x18}, | ||
956 | {98, 0x18}, | ||
957 | {110, 0x17}, | ||
958 | {104, 0x17}, | ||
959 | {98, 0x17}, | ||
960 | {110, 0x16}, | ||
961 | {104, 0x16}, | ||
962 | {98, 0x16}, | ||
963 | {110, 0x15}, | ||
964 | {104, 0x15}, | ||
965 | {98, 0x15}, | ||
966 | {110, 0x14}, | ||
967 | {104, 0x14}, | ||
968 | {98, 0x14}, | ||
969 | {110, 0x13}, | ||
970 | {104, 0x13}, | ||
971 | {98, 0x13}, | ||
972 | {110, 0x12}, | ||
973 | {104, 0x08}, | ||
974 | {98, 0x08}, | ||
975 | {110, 0x07}, | ||
976 | {104, 0x07}, | ||
977 | {98, 0x07}, | ||
978 | {110, 0x06}, | ||
979 | {104, 0x06}, | ||
980 | {98, 0x06}, | ||
981 | {110, 0x05}, | ||
982 | {104, 0x05}, | ||
983 | {98, 0x05}, | ||
984 | {110, 0x04}, | ||
985 | {104, 0x04}, | ||
986 | {98, 0x04}, | ||
987 | {110, 0x03}, | ||
988 | {104, 0x03}, | ||
989 | {98, 0x03}, | ||
990 | {110, 0x02}, | ||
991 | {104, 0x02}, | ||
992 | {98, 0x02}, | ||
993 | {110, 0x01}, | ||
994 | {104, 0x01}, | ||
995 | {98, 0x01}, | ||
996 | {110, 0x00}, | ||
997 | {104, 0x00}, | ||
998 | {98, 0x00}, | ||
999 | {93, 0x00}, | ||
1000 | {88, 0x00}, | ||
1001 | {83, 0x00}, | ||
1002 | {78, 0x00}, | ||
1003 | }, | ||
1004 | /* 2.4GHz power gain index table */ | ||
1005 | { | ||
1006 | {110, 0x3f}, /* highest txpower */ | ||
1007 | {104, 0x3f}, | ||
1008 | {98, 0x3f}, | ||
1009 | {110, 0x3e}, | ||
1010 | {104, 0x3e}, | ||
1011 | {98, 0x3e}, | ||
1012 | {110, 0x3d}, | ||
1013 | {104, 0x3d}, | ||
1014 | {98, 0x3d}, | ||
1015 | {110, 0x3c}, | ||
1016 | {104, 0x3c}, | ||
1017 | {98, 0x3c}, | ||
1018 | {110, 0x3b}, | ||
1019 | {104, 0x3b}, | ||
1020 | {98, 0x3b}, | ||
1021 | {110, 0x3a}, | ||
1022 | {104, 0x3a}, | ||
1023 | {98, 0x3a}, | ||
1024 | {110, 0x39}, | ||
1025 | {104, 0x39}, | ||
1026 | {98, 0x39}, | ||
1027 | {110, 0x38}, | ||
1028 | {104, 0x38}, | ||
1029 | {98, 0x38}, | ||
1030 | {110, 0x37}, | ||
1031 | {104, 0x37}, | ||
1032 | {98, 0x37}, | ||
1033 | {110, 0x36}, | ||
1034 | {104, 0x36}, | ||
1035 | {98, 0x36}, | ||
1036 | {110, 0x35}, | ||
1037 | {104, 0x35}, | ||
1038 | {98, 0x35}, | ||
1039 | {110, 0x34}, | ||
1040 | {104, 0x34}, | ||
1041 | {98, 0x34}, | ||
1042 | {110, 0x33}, | ||
1043 | {104, 0x33}, | ||
1044 | {98, 0x33}, | ||
1045 | {110, 0x32}, | ||
1046 | {104, 0x32}, | ||
1047 | {98, 0x32}, | ||
1048 | {110, 0x31}, | ||
1049 | {104, 0x31}, | ||
1050 | {98, 0x31}, | ||
1051 | {110, 0x30}, | ||
1052 | {104, 0x30}, | ||
1053 | {98, 0x30}, | ||
1054 | {110, 0x6}, | ||
1055 | {104, 0x6}, | ||
1056 | {98, 0x6}, | ||
1057 | {110, 0x5}, | ||
1058 | {104, 0x5}, | ||
1059 | {98, 0x5}, | ||
1060 | {110, 0x4}, | ||
1061 | {104, 0x4}, | ||
1062 | {98, 0x4}, | ||
1063 | {110, 0x3}, | ||
1064 | {104, 0x3}, | ||
1065 | {98, 0x3}, | ||
1066 | {110, 0x2}, | ||
1067 | {104, 0x2}, | ||
1068 | {98, 0x2}, | ||
1069 | {110, 0x1}, | ||
1070 | {104, 0x1}, | ||
1071 | {98, 0x1}, | ||
1072 | {110, 0x0}, | ||
1073 | {104, 0x0}, | ||
1074 | {98, 0x0}, | ||
1075 | {97, 0}, | ||
1076 | {96, 0}, | ||
1077 | {95, 0}, | ||
1078 | {94, 0}, | ||
1079 | {93, 0}, | ||
1080 | {92, 0}, | ||
1081 | {91, 0}, | ||
1082 | {90, 0}, | ||
1083 | {89, 0}, | ||
1084 | {88, 0}, | ||
1085 | {87, 0}, | ||
1086 | {86, 0}, | ||
1087 | {85, 0}, | ||
1088 | {84, 0}, | ||
1089 | {83, 0}, | ||
1090 | {82, 0}, | ||
1091 | {81, 0}, | ||
1092 | {80, 0}, | ||
1093 | {79, 0}, | ||
1094 | {78, 0}, | ||
1095 | {77, 0}, | ||
1096 | {76, 0}, | ||
1097 | {75, 0}, | ||
1098 | {74, 0}, | ||
1099 | {73, 0}, | ||
1100 | {72, 0}, | ||
1101 | {71, 0}, | ||
1102 | {70, 0}, | ||
1103 | {69, 0}, | ||
1104 | {68, 0}, | ||
1105 | {67, 0}, | ||
1106 | {66, 0}, | ||
1107 | {65, 0}, | ||
1108 | {64, 0}, | ||
1109 | {63, 0}, | ||
1110 | {62, 0}, | ||
1111 | {61, 0}, | ||
1112 | {60, 0}, | ||
1113 | {59, 0}, | ||
1114 | } | ||
1115 | }; | ||
1116 | |||
1117 | static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, | ||
1118 | u8 is_ht40, u8 ctrl_chan_high, | ||
1119 | struct iwl4965_tx_power_db *tx_power_tbl) | ||
1120 | { | ||
1121 | u8 saturation_power; | ||
1122 | s32 target_power; | ||
1123 | s32 user_target_power; | ||
1124 | s32 power_limit; | ||
1125 | s32 current_temp; | ||
1126 | s32 reg_limit; | ||
1127 | s32 current_regulatory; | ||
1128 | s32 txatten_grp = CALIB_CH_GROUP_MAX; | ||
1129 | int i; | ||
1130 | int c; | ||
1131 | const struct iwl_channel_info *ch_info = NULL; | ||
1132 | struct iwl_eeprom_calib_ch_info ch_eeprom_info; | ||
1133 | const struct iwl_eeprom_calib_measure *measurement; | ||
1134 | s16 voltage; | ||
1135 | s32 init_voltage; | ||
1136 | s32 voltage_compensation; | ||
1137 | s32 degrees_per_05db_num; | ||
1138 | s32 degrees_per_05db_denom; | ||
1139 | s32 factory_temp; | ||
1140 | s32 temperature_comp[2]; | ||
1141 | s32 factory_gain_index[2]; | ||
1142 | s32 factory_actual_pwr[2]; | ||
1143 | s32 power_index; | ||
1144 | |||
1145 | /* tx_power_user_lmt is in dBm, convert to half-dBm (half-dB units | ||
1146 | * are used for indexing into txpower table) */ | ||
1147 | user_target_power = 2 * priv->tx_power_user_lmt; | ||
1148 | |||
1149 | /* Get current (RXON) channel, band, width */ | ||
1150 | IWL_DEBUG_TXPOWER(priv, "chan %d band %d is_ht40 %d\n", channel, band, | ||
1151 | is_ht40); | ||
1152 | |||
1153 | ch_info = iwl_get_channel_info(priv, priv->band, channel); | ||
1154 | |||
1155 | if (!is_channel_valid(ch_info)) | ||
1156 | return -EINVAL; | ||
1157 | |||
1158 | /* get txatten group, used to select 1) thermal txpower adjustment | ||
1159 | * and 2) mimo txpower balance between Tx chains. */ | ||
1160 | txatten_grp = iwl4965_get_tx_atten_grp(channel); | ||
1161 | if (txatten_grp < 0) { | ||
1162 | IWL_ERR(priv, "Can't find txatten group for channel %d.\n", | ||
1163 | channel); | ||
1164 | return -EINVAL; | ||
1165 | } | ||
1166 | |||
1167 | IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n", | ||
1168 | channel, txatten_grp); | ||
1169 | |||
1170 | if (is_ht40) { | ||
1171 | if (ctrl_chan_high) | ||
1172 | channel -= 2; | ||
1173 | else | ||
1174 | channel += 2; | ||
1175 | } | ||
1176 | |||
1177 | /* hardware txpower limits ... | ||
1178 | * saturation (clipping distortion) txpowers are in half-dBm */ | ||
1179 | if (band) | ||
1180 | saturation_power = priv->calib_info->saturation_power24; | ||
1181 | else | ||
1182 | saturation_power = priv->calib_info->saturation_power52; | ||
1183 | |||
1184 | if (saturation_power < IWL_TX_POWER_SATURATION_MIN || | ||
1185 | saturation_power > IWL_TX_POWER_SATURATION_MAX) { | ||
1186 | if (band) | ||
1187 | saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_24; | ||
1188 | else | ||
1189 | saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_52; | ||
1190 | } | ||
1191 | |||
1192 | /* regulatory txpower limits ... reg_limit values are in half-dBm, | ||
1193 | * max_power_avg values are in dBm, convert * 2 */ | ||
1194 | if (is_ht40) | ||
1195 | reg_limit = ch_info->ht40_max_power_avg * 2; | ||
1196 | else | ||
1197 | reg_limit = ch_info->max_power_avg * 2; | ||
1198 | |||
1199 | if ((reg_limit < IWL_TX_POWER_REGULATORY_MIN) || | ||
1200 | (reg_limit > IWL_TX_POWER_REGULATORY_MAX)) { | ||
1201 | if (band) | ||
1202 | reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_24; | ||
1203 | else | ||
1204 | reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_52; | ||
1205 | } | ||
1206 | |||
1207 | /* Interpolate txpower calibration values for this channel, | ||
1208 | * based on factory calibration tests on spaced channels. */ | ||
1209 | iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info); | ||
1210 | |||
1211 | /* calculate tx gain adjustment based on power supply voltage */ | ||
1212 | voltage = le16_to_cpu(priv->calib_info->voltage); | ||
1213 | init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage); | ||
1214 | voltage_compensation = | ||
1215 | iwl4965_get_voltage_compensation(voltage, init_voltage); | ||
1216 | |||
1217 | IWL_DEBUG_TXPOWER(priv, "curr volt %d eeprom volt %d volt comp %d\n", | ||
1218 | init_voltage, | ||
1219 | voltage, voltage_compensation); | ||
1220 | |||
1221 | /* get current temperature (Celsius) */ | ||
1222 | current_temp = max(priv->temperature, IWL_TX_POWER_TEMPERATURE_MIN); | ||
1223 | current_temp = min(priv->temperature, IWL_TX_POWER_TEMPERATURE_MAX); | ||
1224 | current_temp = KELVIN_TO_CELSIUS(current_temp); | ||
1225 | |||
1226 | /* select thermal txpower adjustment params, based on channel group | ||
1227 | * (same frequency group used for mimo txatten adjustment) */ | ||
1228 | degrees_per_05db_num = | ||
1229 | tx_power_cmp_tble[txatten_grp].degrees_per_05db_a; | ||
1230 | degrees_per_05db_denom = | ||
1231 | tx_power_cmp_tble[txatten_grp].degrees_per_05db_a_denom; | ||
1232 | |||
1233 | /* get per-chain txpower values from factory measurements */ | ||
1234 | for (c = 0; c < 2; c++) { | ||
1235 | measurement = &ch_eeprom_info.measurements[c][1]; | ||
1236 | |||
1237 | /* txgain adjustment (in half-dB steps) based on difference | ||
1238 | * between factory and current temperature */ | ||
1239 | factory_temp = measurement->temperature; | ||
1240 | iwl4965_math_div_round((current_temp - factory_temp) * | ||
1241 | degrees_per_05db_denom, | ||
1242 | degrees_per_05db_num, | ||
1243 | &temperature_comp[c]); | ||
1244 | |||
1245 | factory_gain_index[c] = measurement->gain_idx; | ||
1246 | factory_actual_pwr[c] = measurement->actual_pow; | ||
1247 | |||
1248 | IWL_DEBUG_TXPOWER(priv, "chain = %d\n", c); | ||
1249 | IWL_DEBUG_TXPOWER(priv, "fctry tmp %d, " | ||
1250 | "curr tmp %d, comp %d steps\n", | ||
1251 | factory_temp, current_temp, | ||
1252 | temperature_comp[c]); | ||
1253 | |||
1254 | IWL_DEBUG_TXPOWER(priv, "fctry idx %d, fctry pwr %d\n", | ||
1255 | factory_gain_index[c], | ||
1256 | factory_actual_pwr[c]); | ||
1257 | } | ||
1258 | |||
1259 | /* for each of 33 bit-rates (including 1 for CCK) */ | ||
1260 | for (i = 0; i < POWER_TABLE_NUM_ENTRIES; i++) { | ||
1261 | u8 is_mimo_rate; | ||
1262 | union iwl4965_tx_power_dual_stream tx_power; | ||
1263 | |||
1264 | /* for mimo, reduce each chain's txpower by half | ||
1265 | * (3dB, 6 steps), so total output power is regulatory | ||
1266 | * compliant. */ | ||
1267 | if (i & 0x8) { | ||
1268 | current_regulatory = reg_limit - | ||
1269 | IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION; | ||
1270 | is_mimo_rate = 1; | ||
1271 | } else { | ||
1272 | current_regulatory = reg_limit; | ||
1273 | is_mimo_rate = 0; | ||
1274 | } | ||
1275 | |||
1276 | /* find txpower limit, either hardware or regulatory */ | ||
1277 | power_limit = saturation_power - back_off_table[i]; | ||
1278 | if (power_limit > current_regulatory) | ||
1279 | power_limit = current_regulatory; | ||
1280 | |||
1281 | /* reduce user's txpower request if necessary | ||
1282 | * for this rate on this channel */ | ||
1283 | target_power = user_target_power; | ||
1284 | if (target_power > power_limit) | ||
1285 | target_power = power_limit; | ||
1286 | |||
1287 | IWL_DEBUG_TXPOWER(priv, "rate %d sat %d reg %d usr %d tgt %d\n", | ||
1288 | i, saturation_power - back_off_table[i], | ||
1289 | current_regulatory, user_target_power, | ||
1290 | target_power); | ||
1291 | |||
1292 | /* for each of 2 Tx chains (radio transmitters) */ | ||
1293 | for (c = 0; c < 2; c++) { | ||
1294 | s32 atten_value; | ||
1295 | |||
1296 | if (is_mimo_rate) | ||
1297 | atten_value = | ||
1298 | (s32)le32_to_cpu(priv->card_alive_init. | ||
1299 | tx_atten[txatten_grp][c]); | ||
1300 | else | ||
1301 | atten_value = 0; | ||
1302 | |||
1303 | /* calculate index; higher index means lower txpower */ | ||
1304 | power_index = (u8) (factory_gain_index[c] - | ||
1305 | (target_power - | ||
1306 | factory_actual_pwr[c]) - | ||
1307 | temperature_comp[c] - | ||
1308 | voltage_compensation + | ||
1309 | atten_value); | ||
1310 | |||
1311 | /* IWL_DEBUG_TXPOWER(priv, "calculated txpower index %d\n", | ||
1312 | power_index); */ | ||
1313 | |||
1314 | if (power_index < get_min_power_index(i, band)) | ||
1315 | power_index = get_min_power_index(i, band); | ||
1316 | |||
1317 | /* adjust 5 GHz index to support negative indexes */ | ||
1318 | if (!band) | ||
1319 | power_index += 9; | ||
1320 | |||
1321 | /* CCK, rate 32, reduce txpower for CCK */ | ||
1322 | if (i == POWER_TABLE_CCK_ENTRY) | ||
1323 | power_index += | ||
1324 | IWL_TX_POWER_CCK_COMPENSATION_C_STEP; | ||
1325 | |||
1326 | /* stay within the table! */ | ||
1327 | if (power_index > 107) { | ||
1328 | IWL_WARN(priv, "txpower index %d > 107\n", | ||
1329 | power_index); | ||
1330 | power_index = 107; | ||
1331 | } | ||
1332 | if (power_index < 0) { | ||
1333 | IWL_WARN(priv, "txpower index %d < 0\n", | ||
1334 | power_index); | ||
1335 | power_index = 0; | ||
1336 | } | ||
1337 | |||
1338 | /* fill txpower command for this rate/chain */ | ||
1339 | tx_power.s.radio_tx_gain[c] = | ||
1340 | gain_table[band][power_index].radio; | ||
1341 | tx_power.s.dsp_predis_atten[c] = | ||
1342 | gain_table[band][power_index].dsp; | ||
1343 | |||
1344 | IWL_DEBUG_TXPOWER(priv, "chain %d mimo %d index %d " | ||
1345 | "gain 0x%02x dsp %d\n", | ||
1346 | c, atten_value, power_index, | ||
1347 | tx_power.s.radio_tx_gain[c], | ||
1348 | tx_power.s.dsp_predis_atten[c]); | ||
1349 | } /* for each chain */ | ||
1350 | |||
1351 | tx_power_tbl->power_tbl[i].dw = cpu_to_le32(tx_power.dw); | ||
1352 | |||
1353 | } /* for each rate */ | ||
1354 | |||
1355 | return 0; | ||
1356 | } | ||
1357 | |||
1358 | /** | ||
1359 | * iwl4965_send_tx_power - Configure the TXPOWER level user limit | ||
1360 | * | ||
1361 | * Uses the active RXON for channel, band, and characteristics (ht40, high) | ||
1362 | * The power limit is taken from priv->tx_power_user_lmt. | ||
1363 | */ | ||
1364 | static int iwl4965_send_tx_power(struct iwl_priv *priv) | ||
1365 | { | ||
1366 | struct iwl4965_txpowertable_cmd cmd = { 0 }; | ||
1367 | int ret; | ||
1368 | u8 band = 0; | ||
1369 | bool is_ht40 = false; | ||
1370 | u8 ctrl_chan_high = 0; | ||
1371 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
1372 | |||
1373 | if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status), | ||
1374 | "TX Power requested while scanning!\n")) | ||
1375 | return -EAGAIN; | ||
1376 | |||
1377 | band = priv->band == IEEE80211_BAND_2GHZ; | ||
1378 | |||
1379 | is_ht40 = is_ht40_channel(ctx->active.flags); | ||
1380 | |||
1381 | if (is_ht40 && (ctx->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) | ||
1382 | ctrl_chan_high = 1; | ||
1383 | |||
1384 | cmd.band = band; | ||
1385 | cmd.channel = ctx->active.channel; | ||
1386 | |||
1387 | ret = iwl4965_fill_txpower_tbl(priv, band, | ||
1388 | le16_to_cpu(ctx->active.channel), | ||
1389 | is_ht40, ctrl_chan_high, &cmd.tx_power); | ||
1390 | if (ret) | ||
1391 | goto out; | ||
1392 | |||
1393 | ret = iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd); | ||
1394 | |||
1395 | out: | ||
1396 | return ret; | ||
1397 | } | ||
1398 | |||
1399 | static int iwl4965_send_rxon_assoc(struct iwl_priv *priv, | ||
1400 | struct iwl_rxon_context *ctx) | ||
1401 | { | ||
1402 | int ret = 0; | ||
1403 | struct iwl4965_rxon_assoc_cmd rxon_assoc; | ||
1404 | const struct iwl_rxon_cmd *rxon1 = &ctx->staging; | ||
1405 | const struct iwl_rxon_cmd *rxon2 = &ctx->active; | ||
1406 | |||
1407 | if ((rxon1->flags == rxon2->flags) && | ||
1408 | (rxon1->filter_flags == rxon2->filter_flags) && | ||
1409 | (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && | ||
1410 | (rxon1->ofdm_ht_single_stream_basic_rates == | ||
1411 | rxon2->ofdm_ht_single_stream_basic_rates) && | ||
1412 | (rxon1->ofdm_ht_dual_stream_basic_rates == | ||
1413 | rxon2->ofdm_ht_dual_stream_basic_rates) && | ||
1414 | (rxon1->rx_chain == rxon2->rx_chain) && | ||
1415 | (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { | ||
1416 | IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); | ||
1417 | return 0; | ||
1418 | } | ||
1419 | |||
1420 | rxon_assoc.flags = ctx->staging.flags; | ||
1421 | rxon_assoc.filter_flags = ctx->staging.filter_flags; | ||
1422 | rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates; | ||
1423 | rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates; | ||
1424 | rxon_assoc.reserved = 0; | ||
1425 | rxon_assoc.ofdm_ht_single_stream_basic_rates = | ||
1426 | ctx->staging.ofdm_ht_single_stream_basic_rates; | ||
1427 | rxon_assoc.ofdm_ht_dual_stream_basic_rates = | ||
1428 | ctx->staging.ofdm_ht_dual_stream_basic_rates; | ||
1429 | rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain; | ||
1430 | |||
1431 | ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, | ||
1432 | sizeof(rxon_assoc), &rxon_assoc, NULL); | ||
1433 | if (ret) | ||
1434 | return ret; | ||
1435 | |||
1436 | return ret; | ||
1437 | } | ||
1438 | |||
1439 | static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | ||
1440 | { | ||
1441 | /* cast away the const for active_rxon in this function */ | ||
1442 | struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active; | ||
1443 | int ret; | ||
1444 | bool new_assoc = | ||
1445 | !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); | ||
1446 | |||
1447 | if (!iwl_is_alive(priv)) | ||
1448 | return -EBUSY; | ||
1449 | |||
1450 | if (!ctx->is_active) | ||
1451 | return 0; | ||
1452 | |||
1453 | /* always get timestamp with Rx frame */ | ||
1454 | ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; | ||
1455 | |||
1456 | ret = iwl_check_rxon_cmd(priv, ctx); | ||
1457 | if (ret) { | ||
1458 | IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); | ||
1459 | return -EINVAL; | ||
1460 | } | ||
1461 | |||
1462 | /* | ||
1463 | * receive commit_rxon request | ||
1464 | * abort any previous channel switch if still in process | ||
1465 | */ | ||
1466 | if (priv->switch_rxon.switch_in_progress && | ||
1467 | (priv->switch_rxon.channel != ctx->staging.channel)) { | ||
1468 | IWL_DEBUG_11H(priv, "abort channel switch on %d\n", | ||
1469 | le16_to_cpu(priv->switch_rxon.channel)); | ||
1470 | iwl_chswitch_done(priv, false); | ||
1471 | } | ||
1472 | |||
1473 | /* If we don't need to send a full RXON, we can use | ||
1474 | * iwl_rxon_assoc_cmd which is used to reconfigure filter | ||
1475 | * and other flags for the current radio configuration. */ | ||
1476 | if (!iwl_full_rxon_required(priv, ctx)) { | ||
1477 | ret = iwl_send_rxon_assoc(priv, ctx); | ||
1478 | if (ret) { | ||
1479 | IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret); | ||
1480 | return ret; | ||
1481 | } | ||
1482 | |||
1483 | memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); | ||
1484 | iwl_print_rx_config_cmd(priv, ctx); | ||
1485 | return 0; | ||
1486 | } | ||
1487 | |||
1488 | /* If we are currently associated and the new config requires | ||
1489 | * an RXON_ASSOC and the new config wants the associated mask enabled, | ||
1490 | * we must clear the associated from the active configuration | ||
1491 | * before we apply the new config */ | ||
1492 | if (iwl_is_associated_ctx(ctx) && new_assoc) { | ||
1493 | IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); | ||
1494 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
1495 | |||
1496 | ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, | ||
1497 | sizeof(struct iwl_rxon_cmd), | ||
1498 | active_rxon); | ||
1499 | |||
1500 | /* If the mask clearing failed then we set | ||
1501 | * active_rxon back to what it was previously */ | ||
1502 | if (ret) { | ||
1503 | active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; | ||
1504 | IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); | ||
1505 | return ret; | ||
1506 | } | ||
1507 | iwl_clear_ucode_stations(priv, ctx); | ||
1508 | iwl_restore_stations(priv, ctx); | ||
1509 | ret = iwl_restore_default_wep_keys(priv, ctx); | ||
1510 | if (ret) { | ||
1511 | IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); | ||
1512 | return ret; | ||
1513 | } | ||
1514 | } | ||
1515 | |||
1516 | IWL_DEBUG_INFO(priv, "Sending RXON\n" | ||
1517 | "* with%s RXON_FILTER_ASSOC_MSK\n" | ||
1518 | "* channel = %d\n" | ||
1519 | "* bssid = %pM\n", | ||
1520 | (new_assoc ? "" : "out"), | ||
1521 | le16_to_cpu(ctx->staging.channel), | ||
1522 | ctx->staging.bssid_addr); | ||
1523 | |||
1524 | iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto); | ||
1525 | |||
1526 | /* Apply the new configuration | ||
1527 | * RXON unassoc clears the station table in uCode so restoration of | ||
1528 | * stations is needed after it (the RXON command) completes | ||
1529 | */ | ||
1530 | if (!new_assoc) { | ||
1531 | ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, | ||
1532 | sizeof(struct iwl_rxon_cmd), &ctx->staging); | ||
1533 | if (ret) { | ||
1534 | IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); | ||
1535 | return ret; | ||
1536 | } | ||
1537 | IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); | ||
1538 | memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); | ||
1539 | iwl_clear_ucode_stations(priv, ctx); | ||
1540 | iwl_restore_stations(priv, ctx); | ||
1541 | ret = iwl_restore_default_wep_keys(priv, ctx); | ||
1542 | if (ret) { | ||
1543 | IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); | ||
1544 | return ret; | ||
1545 | } | ||
1546 | } | ||
1547 | if (new_assoc) { | ||
1548 | priv->start_calib = 0; | ||
1549 | /* Apply the new configuration | ||
1550 | * RXON assoc doesn't clear the station table in uCode, | ||
1551 | */ | ||
1552 | ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, | ||
1553 | sizeof(struct iwl_rxon_cmd), &ctx->staging); | ||
1554 | if (ret) { | ||
1555 | IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); | ||
1556 | return ret; | ||
1557 | } | ||
1558 | memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); | ||
1559 | } | ||
1560 | iwl_print_rx_config_cmd(priv, ctx); | ||
1561 | |||
1562 | iwl_init_sensitivity(priv); | ||
1563 | |||
1564 | /* If we issue a new RXON command which required a tune then we must | ||
1565 | * send a new TXPOWER command or we won't be able to Tx any frames */ | ||
1566 | ret = iwl_set_tx_power(priv, priv->tx_power_next, true); | ||
1567 | if (ret) { | ||
1568 | IWL_ERR(priv, "Error sending TX power (%d)\n", ret); | ||
1569 | return ret; | ||
1570 | } | ||
1571 | |||
1572 | return 0; | ||
1573 | } | ||
1574 | |||
1575 | static int iwl4965_hw_channel_switch(struct iwl_priv *priv, | ||
1576 | struct ieee80211_channel_switch *ch_switch) | ||
1577 | { | ||
1578 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
1579 | int rc; | ||
1580 | u8 band = 0; | ||
1581 | bool is_ht40 = false; | ||
1582 | u8 ctrl_chan_high = 0; | ||
1583 | struct iwl4965_channel_switch_cmd cmd; | ||
1584 | const struct iwl_channel_info *ch_info; | ||
1585 | u32 switch_time_in_usec, ucode_switch_time; | ||
1586 | u16 ch; | ||
1587 | u32 tsf_low; | ||
1588 | u8 switch_count; | ||
1589 | u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); | ||
1590 | struct ieee80211_vif *vif = ctx->vif; | ||
1591 | band = priv->band == IEEE80211_BAND_2GHZ; | ||
1592 | |||
1593 | is_ht40 = is_ht40_channel(ctx->staging.flags); | ||
1594 | |||
1595 | if (is_ht40 && | ||
1596 | (ctx->staging.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) | ||
1597 | ctrl_chan_high = 1; | ||
1598 | |||
1599 | cmd.band = band; | ||
1600 | cmd.expect_beacon = 0; | ||
1601 | ch = ch_switch->channel->hw_value; | ||
1602 | cmd.channel = cpu_to_le16(ch); | ||
1603 | cmd.rxon_flags = ctx->staging.flags; | ||
1604 | cmd.rxon_filter_flags = ctx->staging.filter_flags; | ||
1605 | switch_count = ch_switch->count; | ||
1606 | tsf_low = ch_switch->timestamp & 0x0ffffffff; | ||
1607 | /* | ||
1608 | * calculate the ucode channel switch time | ||
1609 | * adding TSF as one of the factor for when to switch | ||
1610 | */ | ||
1611 | if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { | ||
1612 | if (switch_count > ((priv->ucode_beacon_time - tsf_low) / | ||
1613 | beacon_interval)) { | ||
1614 | switch_count -= (priv->ucode_beacon_time - | ||
1615 | tsf_low) / beacon_interval; | ||
1616 | } else | ||
1617 | switch_count = 0; | ||
1618 | } | ||
1619 | if (switch_count <= 1) | ||
1620 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | ||
1621 | else { | ||
1622 | switch_time_in_usec = | ||
1623 | vif->bss_conf.beacon_int * switch_count * TIME_UNIT; | ||
1624 | ucode_switch_time = iwl_usecs_to_beacons(priv, | ||
1625 | switch_time_in_usec, | ||
1626 | beacon_interval); | ||
1627 | cmd.switch_time = iwl_add_beacon_time(priv, | ||
1628 | priv->ucode_beacon_time, | ||
1629 | ucode_switch_time, | ||
1630 | beacon_interval); | ||
1631 | } | ||
1632 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | ||
1633 | cmd.switch_time); | ||
1634 | ch_info = iwl_get_channel_info(priv, priv->band, ch); | ||
1635 | if (ch_info) | ||
1636 | cmd.expect_beacon = is_channel_radar(ch_info); | ||
1637 | else { | ||
1638 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | ||
1639 | ctx->active.channel, ch); | ||
1640 | return -EFAULT; | ||
1641 | } | ||
1642 | |||
1643 | rc = iwl4965_fill_txpower_tbl(priv, band, ch, is_ht40, | ||
1644 | ctrl_chan_high, &cmd.tx_power); | ||
1645 | if (rc) { | ||
1646 | IWL_DEBUG_11H(priv, "error:%d fill txpower_tbl\n", rc); | ||
1647 | return rc; | ||
1648 | } | ||
1649 | |||
1650 | priv->switch_rxon.channel = cmd.channel; | ||
1651 | priv->switch_rxon.switch_in_progress = true; | ||
1652 | |||
1653 | return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); | ||
1654 | } | ||
1655 | |||
1656 | /** | ||
1657 | * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array | ||
1658 | */ | ||
1659 | static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | ||
1660 | struct iwl_tx_queue *txq, | ||
1661 | u16 byte_cnt) | ||
1662 | { | ||
1663 | struct iwl4965_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; | ||
1664 | int txq_id = txq->q.id; | ||
1665 | int write_ptr = txq->q.write_ptr; | ||
1666 | int len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; | ||
1667 | __le16 bc_ent; | ||
1668 | |||
1669 | WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); | ||
1670 | |||
1671 | bc_ent = cpu_to_le16(len & 0xFFF); | ||
1672 | /* Set up byte count within first 256 entries */ | ||
1673 | scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; | ||
1674 | |||
1675 | /* If within first 64 entries, duplicate at end */ | ||
1676 | if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) | ||
1677 | scd_bc_tbl[txq_id]. | ||
1678 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; | ||
1679 | } | ||
1680 | |||
1681 | /** | ||
1682 | * iwl4965_hw_get_temperature - return the calibrated temperature (in Kelvin) | ||
1683 | * @statistics: Provides the temperature reading from the uCode | ||
1684 | * | ||
1685 | * A return of <0 indicates bogus data in the statistics | ||
1686 | */ | ||
1687 | static int iwl4965_hw_get_temperature(struct iwl_priv *priv) | ||
1688 | { | ||
1689 | s32 temperature; | ||
1690 | s32 vt; | ||
1691 | s32 R1, R2, R3; | ||
1692 | u32 R4; | ||
1693 | |||
1694 | if (test_bit(STATUS_TEMPERATURE, &priv->status) && | ||
1695 | (priv->_agn.statistics.flag & | ||
1696 | STATISTICS_REPLY_FLG_HT40_MODE_MSK)) { | ||
1697 | IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n"); | ||
1698 | R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]); | ||
1699 | R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]); | ||
1700 | R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[1]); | ||
1701 | R4 = le32_to_cpu(priv->card_alive_init.therm_r4[1]); | ||
1702 | } else { | ||
1703 | IWL_DEBUG_TEMP(priv, "Running temperature calibration\n"); | ||
1704 | R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[0]); | ||
1705 | R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[0]); | ||
1706 | R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[0]); | ||
1707 | R4 = le32_to_cpu(priv->card_alive_init.therm_r4[0]); | ||
1708 | } | ||
1709 | |||
1710 | /* | ||
1711 | * Temperature is only 23 bits, so sign extend out to 32. | ||
1712 | * | ||
1713 | * NOTE If we haven't received a statistics notification yet | ||
1714 | * with an updated temperature, use R4 provided to us in the | ||
1715 | * "initialize" ALIVE response. | ||
1716 | */ | ||
1717 | if (!test_bit(STATUS_TEMPERATURE, &priv->status)) | ||
1718 | vt = sign_extend32(R4, 23); | ||
1719 | else | ||
1720 | vt = sign_extend32(le32_to_cpu(priv->_agn.statistics. | ||
1721 | general.common.temperature), 23); | ||
1722 | |||
1723 | IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt); | ||
1724 | |||
1725 | if (R3 == R1) { | ||
1726 | IWL_ERR(priv, "Calibration conflict R1 == R3\n"); | ||
1727 | return -1; | ||
1728 | } | ||
1729 | |||
1730 | /* Calculate temperature in degrees Kelvin, adjust by 97%. | ||
1731 | * Add offset to center the adjustment around 0 degrees Centigrade. */ | ||
1732 | temperature = TEMPERATURE_CALIB_A_VAL * (vt - R2); | ||
1733 | temperature /= (R3 - R1); | ||
1734 | temperature = (temperature * 97) / 100 + TEMPERATURE_CALIB_KELVIN_OFFSET; | ||
1735 | |||
1736 | IWL_DEBUG_TEMP(priv, "Calibrated temperature: %dK, %dC\n", | ||
1737 | temperature, KELVIN_TO_CELSIUS(temperature)); | ||
1738 | |||
1739 | return temperature; | ||
1740 | } | ||
1741 | |||
1742 | /* Adjust Txpower only if temperature variance is greater than threshold. */ | ||
1743 | #define IWL_TEMPERATURE_THRESHOLD 3 | ||
1744 | |||
1745 | /** | ||
1746 | * iwl4965_is_temp_calib_needed - determines if new calibration is needed | ||
1747 | * | ||
1748 | * If the temperature changed has changed sufficiently, then a recalibration | ||
1749 | * is needed. | ||
1750 | * | ||
1751 | * Assumes caller will replace priv->last_temperature once calibration | ||
1752 | * executed. | ||
1753 | */ | ||
1754 | static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv) | ||
1755 | { | ||
1756 | int temp_diff; | ||
1757 | |||
1758 | if (!test_bit(STATUS_STATISTICS, &priv->status)) { | ||
1759 | IWL_DEBUG_TEMP(priv, "Temperature not updated -- no statistics.\n"); | ||
1760 | return 0; | ||
1761 | } | ||
1762 | |||
1763 | temp_diff = priv->temperature - priv->last_temperature; | ||
1764 | |||
1765 | /* get absolute value */ | ||
1766 | if (temp_diff < 0) { | ||
1767 | IWL_DEBUG_POWER(priv, "Getting cooler, delta %d\n", temp_diff); | ||
1768 | temp_diff = -temp_diff; | ||
1769 | } else if (temp_diff == 0) | ||
1770 | IWL_DEBUG_POWER(priv, "Temperature unchanged\n"); | ||
1771 | else | ||
1772 | IWL_DEBUG_POWER(priv, "Getting warmer, delta %d\n", temp_diff); | ||
1773 | |||
1774 | if (temp_diff < IWL_TEMPERATURE_THRESHOLD) { | ||
1775 | IWL_DEBUG_POWER(priv, " => thermal txpower calib not needed\n"); | ||
1776 | return 0; | ||
1777 | } | ||
1778 | |||
1779 | IWL_DEBUG_POWER(priv, " => thermal txpower calib needed\n"); | ||
1780 | |||
1781 | return 1; | ||
1782 | } | ||
1783 | |||
1784 | static void iwl4965_temperature_calib(struct iwl_priv *priv) | ||
1785 | { | ||
1786 | s32 temp; | ||
1787 | |||
1788 | temp = iwl4965_hw_get_temperature(priv); | ||
1789 | if (temp < 0) | ||
1790 | return; | ||
1791 | |||
1792 | if (priv->temperature != temp) { | ||
1793 | if (priv->temperature) | ||
1794 | IWL_DEBUG_TEMP(priv, "Temperature changed " | ||
1795 | "from %dC to %dC\n", | ||
1796 | KELVIN_TO_CELSIUS(priv->temperature), | ||
1797 | KELVIN_TO_CELSIUS(temp)); | ||
1798 | else | ||
1799 | IWL_DEBUG_TEMP(priv, "Temperature " | ||
1800 | "initialized to %dC\n", | ||
1801 | KELVIN_TO_CELSIUS(temp)); | ||
1802 | } | ||
1803 | |||
1804 | priv->temperature = temp; | ||
1805 | iwl_tt_handler(priv); | ||
1806 | set_bit(STATUS_TEMPERATURE, &priv->status); | ||
1807 | |||
1808 | if (!priv->disable_tx_power_cal && | ||
1809 | unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && | ||
1810 | iwl4965_is_temp_calib_needed(priv)) | ||
1811 | queue_work(priv->workqueue, &priv->txpower_work); | ||
1812 | } | ||
1813 | |||
1814 | /** | ||
1815 | * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration | ||
1816 | */ | ||
1817 | static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv, | ||
1818 | u16 txq_id) | ||
1819 | { | ||
1820 | /* Simply stop the queue, but don't change any configuration; | ||
1821 | * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ | ||
1822 | iwl_write_prph(priv, | ||
1823 | IWL49_SCD_QUEUE_STATUS_BITS(txq_id), | ||
1824 | (0 << IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE)| | ||
1825 | (1 << IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); | ||
1826 | } | ||
1827 | |||
1828 | /** | ||
1829 | * txq_id must be greater than IWL49_FIRST_AMPDU_QUEUE | ||
1830 | * priv->lock must be held by the caller | ||
1831 | */ | ||
1832 | static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | ||
1833 | u16 ssn_idx, u8 tx_fifo) | ||
1834 | { | ||
1835 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || | ||
1836 | (IWL49_FIRST_AMPDU_QUEUE + | ||
1837 | priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { | ||
1838 | IWL_WARN(priv, | ||
1839 | "queue number out of range: %d, must be %d to %d\n", | ||
1840 | txq_id, IWL49_FIRST_AMPDU_QUEUE, | ||
1841 | IWL49_FIRST_AMPDU_QUEUE + | ||
1842 | priv->cfg->base_params->num_of_ampdu_queues - 1); | ||
1843 | return -EINVAL; | ||
1844 | } | ||
1845 | |||
1846 | iwl4965_tx_queue_stop_scheduler(priv, txq_id); | ||
1847 | |||
1848 | iwl_clear_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id)); | ||
1849 | |||
1850 | priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); | ||
1851 | priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); | ||
1852 | /* supposes that ssn_idx is valid (!= 0xFFF) */ | ||
1853 | iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx); | ||
1854 | |||
1855 | iwl_clear_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id)); | ||
1856 | iwl_txq_ctx_deactivate(priv, txq_id); | ||
1857 | iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); | ||
1858 | |||
1859 | return 0; | ||
1860 | } | ||
1861 | |||
1862 | /** | ||
1863 | * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue | ||
1864 | */ | ||
1865 | static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, | ||
1866 | u16 txq_id) | ||
1867 | { | ||
1868 | u32 tbl_dw_addr; | ||
1869 | u32 tbl_dw; | ||
1870 | u16 scd_q2ratid; | ||
1871 | |||
1872 | scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK; | ||
1873 | |||
1874 | tbl_dw_addr = priv->scd_base_addr + | ||
1875 | IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); | ||
1876 | |||
1877 | tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); | ||
1878 | |||
1879 | if (txq_id & 0x1) | ||
1880 | tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); | ||
1881 | else | ||
1882 | tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); | ||
1883 | |||
1884 | iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); | ||
1885 | |||
1886 | return 0; | ||
1887 | } | ||
1888 | |||
1889 | |||
1890 | /** | ||
1891 | * iwl4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue | ||
1892 | * | ||
1893 | * NOTE: txq_id must be greater than IWL49_FIRST_AMPDU_QUEUE, | ||
1894 | * i.e. it must be one of the higher queues used for aggregation | ||
1895 | */ | ||
1896 | static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, | ||
1897 | int tx_fifo, int sta_id, int tid, u16 ssn_idx) | ||
1898 | { | ||
1899 | unsigned long flags; | ||
1900 | u16 ra_tid; | ||
1901 | int ret; | ||
1902 | |||
1903 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || | ||
1904 | (IWL49_FIRST_AMPDU_QUEUE + | ||
1905 | priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { | ||
1906 | IWL_WARN(priv, | ||
1907 | "queue number out of range: %d, must be %d to %d\n", | ||
1908 | txq_id, IWL49_FIRST_AMPDU_QUEUE, | ||
1909 | IWL49_FIRST_AMPDU_QUEUE + | ||
1910 | priv->cfg->base_params->num_of_ampdu_queues - 1); | ||
1911 | return -EINVAL; | ||
1912 | } | ||
1913 | |||
1914 | ra_tid = BUILD_RAxTID(sta_id, tid); | ||
1915 | |||
1916 | /* Modify device's station table to Tx this TID */ | ||
1917 | ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); | ||
1918 | if (ret) | ||
1919 | return ret; | ||
1920 | |||
1921 | spin_lock_irqsave(&priv->lock, flags); | ||
1922 | |||
1923 | /* Stop this Tx queue before configuring it */ | ||
1924 | iwl4965_tx_queue_stop_scheduler(priv, txq_id); | ||
1925 | |||
1926 | /* Map receiver-address / traffic-ID to this queue */ | ||
1927 | iwl4965_tx_queue_set_q2ratid(priv, ra_tid, txq_id); | ||
1928 | |||
1929 | /* Set this queue as a chain-building queue */ | ||
1930 | iwl_set_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id)); | ||
1931 | |||
1932 | /* Place first TFD at index corresponding to start sequence number. | ||
1933 | * Assumes that ssn_idx is valid (!= 0xFFF) */ | ||
1934 | priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); | ||
1935 | priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); | ||
1936 | iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx); | ||
1937 | |||
1938 | /* Set up Tx window size and frame limit for this queue */ | ||
1939 | iwl_write_targ_mem(priv, | ||
1940 | priv->scd_base_addr + IWL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id), | ||
1941 | (SCD_WIN_SIZE << IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) & | ||
1942 | IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK); | ||
1943 | |||
1944 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
1945 | IWL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), | ||
1946 | (SCD_FRAME_LIMIT << IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) | ||
1947 | & IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK); | ||
1948 | |||
1949 | iwl_set_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id)); | ||
1950 | |||
1951 | /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ | ||
1952 | iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); | ||
1953 | |||
1954 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1955 | |||
1956 | return 0; | ||
1957 | } | ||
1958 | |||
1959 | |||
1960 | static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len) | ||
1961 | { | ||
1962 | switch (cmd_id) { | ||
1963 | case REPLY_RXON: | ||
1964 | return (u16) sizeof(struct iwl4965_rxon_cmd); | ||
1965 | default: | ||
1966 | return len; | ||
1967 | } | ||
1968 | } | ||
1969 | |||
1970 | static u16 iwl4965_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | ||
1971 | { | ||
1972 | struct iwl4965_addsta_cmd *addsta = (struct iwl4965_addsta_cmd *)data; | ||
1973 | addsta->mode = cmd->mode; | ||
1974 | memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify)); | ||
1975 | memcpy(&addsta->key, &cmd->key, sizeof(struct iwl4965_keyinfo)); | ||
1976 | addsta->station_flags = cmd->station_flags; | ||
1977 | addsta->station_flags_msk = cmd->station_flags_msk; | ||
1978 | addsta->tid_disable_tx = cmd->tid_disable_tx; | ||
1979 | addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid; | ||
1980 | addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid; | ||
1981 | addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn; | ||
1982 | addsta->sleep_tx_count = cmd->sleep_tx_count; | ||
1983 | addsta->reserved1 = cpu_to_le16(0); | ||
1984 | addsta->reserved2 = cpu_to_le16(0); | ||
1985 | |||
1986 | return (u16)sizeof(struct iwl4965_addsta_cmd); | ||
1987 | } | ||
1988 | |||
1989 | static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp) | ||
1990 | { | ||
1991 | return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN; | ||
1992 | } | ||
1993 | |||
1994 | /** | ||
1995 | * iwl4965_tx_status_reply_tx - Handle Tx response for frames in aggregation queue | ||
1996 | */ | ||
1997 | static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | ||
1998 | struct iwl_ht_agg *agg, | ||
1999 | struct iwl4965_tx_resp *tx_resp, | ||
2000 | int txq_id, u16 start_idx) | ||
2001 | { | ||
2002 | u16 status; | ||
2003 | struct agg_tx_status *frame_status = tx_resp->u.agg_status; | ||
2004 | struct ieee80211_tx_info *info = NULL; | ||
2005 | struct ieee80211_hdr *hdr = NULL; | ||
2006 | u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); | ||
2007 | int i, sh, idx; | ||
2008 | u16 seq; | ||
2009 | if (agg->wait_for_ba) | ||
2010 | IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); | ||
2011 | |||
2012 | agg->frame_count = tx_resp->frame_count; | ||
2013 | agg->start_idx = start_idx; | ||
2014 | agg->rate_n_flags = rate_n_flags; | ||
2015 | agg->bitmap = 0; | ||
2016 | |||
2017 | /* num frames attempted by Tx command */ | ||
2018 | if (agg->frame_count == 1) { | ||
2019 | /* Only one frame was attempted; no block-ack will arrive */ | ||
2020 | status = le16_to_cpu(frame_status[0].status); | ||
2021 | idx = start_idx; | ||
2022 | |||
2023 | /* FIXME: code repetition */ | ||
2024 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", | ||
2025 | agg->frame_count, agg->start_idx, idx); | ||
2026 | |||
2027 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb); | ||
2028 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
2029 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
2030 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
2031 | iwlagn_hwrate_to_tx_control(priv, rate_n_flags, info); | ||
2032 | /* FIXME: code repetition end */ | ||
2033 | |||
2034 | IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", | ||
2035 | status & 0xff, tx_resp->failure_frame); | ||
2036 | IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags); | ||
2037 | |||
2038 | agg->wait_for_ba = 0; | ||
2039 | } else { | ||
2040 | /* Two or more frames were attempted; expect block-ack */ | ||
2041 | u64 bitmap = 0; | ||
2042 | int start = agg->start_idx; | ||
2043 | |||
2044 | /* Construct bit-map of pending frames within Tx window */ | ||
2045 | for (i = 0; i < agg->frame_count; i++) { | ||
2046 | u16 sc; | ||
2047 | status = le16_to_cpu(frame_status[i].status); | ||
2048 | seq = le16_to_cpu(frame_status[i].sequence); | ||
2049 | idx = SEQ_TO_INDEX(seq); | ||
2050 | txq_id = SEQ_TO_QUEUE(seq); | ||
2051 | |||
2052 | if (status & (AGG_TX_STATE_FEW_BYTES_MSK | | ||
2053 | AGG_TX_STATE_ABORT_MSK)) | ||
2054 | continue; | ||
2055 | |||
2056 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", | ||
2057 | agg->frame_count, txq_id, idx); | ||
2058 | |||
2059 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); | ||
2060 | if (!hdr) { | ||
2061 | IWL_ERR(priv, | ||
2062 | "BUG_ON idx doesn't point to valid skb" | ||
2063 | " idx=%d, txq_id=%d\n", idx, txq_id); | ||
2064 | return -1; | ||
2065 | } | ||
2066 | |||
2067 | sc = le16_to_cpu(hdr->seq_ctrl); | ||
2068 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { | ||
2069 | IWL_ERR(priv, | ||
2070 | "BUG_ON idx doesn't match seq control" | ||
2071 | " idx=%d, seq_idx=%d, seq=%d\n", | ||
2072 | idx, SEQ_TO_SN(sc), hdr->seq_ctrl); | ||
2073 | return -1; | ||
2074 | } | ||
2075 | |||
2076 | IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", | ||
2077 | i, idx, SEQ_TO_SN(sc)); | ||
2078 | |||
2079 | sh = idx - start; | ||
2080 | if (sh > 64) { | ||
2081 | sh = (start - idx) + 0xff; | ||
2082 | bitmap = bitmap << sh; | ||
2083 | sh = 0; | ||
2084 | start = idx; | ||
2085 | } else if (sh < -64) | ||
2086 | sh = 0xff - (start - idx); | ||
2087 | else if (sh < 0) { | ||
2088 | sh = start - idx; | ||
2089 | start = idx; | ||
2090 | bitmap = bitmap << sh; | ||
2091 | sh = 0; | ||
2092 | } | ||
2093 | bitmap |= 1ULL << sh; | ||
2094 | IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", | ||
2095 | start, (unsigned long long)bitmap); | ||
2096 | } | ||
2097 | |||
2098 | agg->bitmap = bitmap; | ||
2099 | agg->start_idx = start; | ||
2100 | IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", | ||
2101 | agg->frame_count, agg->start_idx, | ||
2102 | (unsigned long long)agg->bitmap); | ||
2103 | |||
2104 | if (bitmap) | ||
2105 | agg->wait_for_ba = 1; | ||
2106 | } | ||
2107 | return 0; | ||
2108 | } | ||
2109 | |||
2110 | static u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) | ||
2111 | { | ||
2112 | int i; | ||
2113 | int start = 0; | ||
2114 | int ret = IWL_INVALID_STATION; | ||
2115 | unsigned long flags; | ||
2116 | |||
2117 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) || | ||
2118 | (priv->iw_mode == NL80211_IFTYPE_AP)) | ||
2119 | start = IWL_STA_ID; | ||
2120 | |||
2121 | if (is_broadcast_ether_addr(addr)) | ||
2122 | return priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id; | ||
2123 | |||
2124 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
2125 | for (i = start; i < priv->hw_params.max_stations; i++) | ||
2126 | if (priv->stations[i].used && | ||
2127 | (!compare_ether_addr(priv->stations[i].sta.sta.addr, | ||
2128 | addr))) { | ||
2129 | ret = i; | ||
2130 | goto out; | ||
2131 | } | ||
2132 | |||
2133 | IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n", | ||
2134 | addr, priv->num_stations); | ||
2135 | |||
2136 | out: | ||
2137 | /* | ||
2138 | * It may be possible that more commands interacting with stations | ||
2139 | * arrive before we completed processing the adding of | ||
2140 | * station | ||
2141 | */ | ||
2142 | if (ret != IWL_INVALID_STATION && | ||
2143 | (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) || | ||
2144 | ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) && | ||
2145 | (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) { | ||
2146 | IWL_ERR(priv, "Requested station info for sta %d before ready.\n", | ||
2147 | ret); | ||
2148 | ret = IWL_INVALID_STATION; | ||
2149 | } | ||
2150 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
2151 | return ret; | ||
2152 | } | ||
2153 | |||
2154 | static int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) | ||
2155 | { | ||
2156 | if (priv->iw_mode == NL80211_IFTYPE_STATION) { | ||
2157 | return IWL_AP_ID; | ||
2158 | } else { | ||
2159 | u8 *da = ieee80211_get_DA(hdr); | ||
2160 | return iwl_find_station(priv, da); | ||
2161 | } | ||
2162 | } | ||
2163 | |||
2164 | /** | ||
2165 | * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response | ||
2166 | */ | ||
2167 | static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | ||
2168 | struct iwl_rx_mem_buffer *rxb) | ||
2169 | { | ||
2170 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
2171 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | ||
2172 | int txq_id = SEQ_TO_QUEUE(sequence); | ||
2173 | int index = SEQ_TO_INDEX(sequence); | ||
2174 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
2175 | struct ieee80211_hdr *hdr; | ||
2176 | struct ieee80211_tx_info *info; | ||
2177 | struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; | ||
2178 | u32 status = le32_to_cpu(tx_resp->u.status); | ||
2179 | int uninitialized_var(tid); | ||
2180 | int sta_id; | ||
2181 | int freed; | ||
2182 | u8 *qc = NULL; | ||
2183 | unsigned long flags; | ||
2184 | |||
2185 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { | ||
2186 | IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " | ||
2187 | "is out of range [0-%d] %d %d\n", txq_id, | ||
2188 | index, txq->q.n_bd, txq->q.write_ptr, | ||
2189 | txq->q.read_ptr); | ||
2190 | return; | ||
2191 | } | ||
2192 | |||
2193 | txq->time_stamp = jiffies; | ||
2194 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); | ||
2195 | memset(&info->status, 0, sizeof(info->status)); | ||
2196 | |||
2197 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, index); | ||
2198 | if (ieee80211_is_data_qos(hdr->frame_control)) { | ||
2199 | qc = ieee80211_get_qos_ctl(hdr); | ||
2200 | tid = qc[0] & 0xf; | ||
2201 | } | ||
2202 | |||
2203 | sta_id = iwl_get_ra_sta_id(priv, hdr); | ||
2204 | if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) { | ||
2205 | IWL_ERR(priv, "Station not known\n"); | ||
2206 | return; | ||
2207 | } | ||
2208 | |||
2209 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
2210 | if (txq->sched_retry) { | ||
2211 | const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp); | ||
2212 | struct iwl_ht_agg *agg = NULL; | ||
2213 | WARN_ON(!qc); | ||
2214 | |||
2215 | agg = &priv->stations[sta_id].tid[tid].agg; | ||
2216 | |||
2217 | iwl4965_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); | ||
2218 | |||
2219 | /* check if BAR is needed */ | ||
2220 | if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) | ||
2221 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | ||
2222 | |||
2223 | if (txq->q.read_ptr != (scd_ssn & 0xff)) { | ||
2224 | index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); | ||
2225 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " | ||
2226 | "%d index %d\n", scd_ssn , index); | ||
2227 | freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); | ||
2228 | if (qc) | ||
2229 | iwl_free_tfds_in_queue(priv, sta_id, | ||
2230 | tid, freed); | ||
2231 | |||
2232 | if (priv->mac80211_registered && | ||
2233 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && | ||
2234 | (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) | ||
2235 | iwl_wake_queue(priv, txq); | ||
2236 | } | ||
2237 | } else { | ||
2238 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
2239 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
2240 | iwlagn_hwrate_to_tx_control(priv, | ||
2241 | le32_to_cpu(tx_resp->rate_n_flags), | ||
2242 | info); | ||
2243 | |||
2244 | IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) " | ||
2245 | "rate_n_flags 0x%x retries %d\n", | ||
2246 | txq_id, | ||
2247 | iwl_get_tx_fail_reason(status), status, | ||
2248 | le32_to_cpu(tx_resp->rate_n_flags), | ||
2249 | tx_resp->failure_frame); | ||
2250 | |||
2251 | freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); | ||
2252 | if (qc && likely(sta_id != IWL_INVALID_STATION)) | ||
2253 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
2254 | else if (sta_id == IWL_INVALID_STATION) | ||
2255 | IWL_DEBUG_TX_REPLY(priv, "Station not known\n"); | ||
2256 | |||
2257 | if (priv->mac80211_registered && | ||
2258 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) | ||
2259 | iwl_wake_queue(priv, txq); | ||
2260 | } | ||
2261 | if (qc && likely(sta_id != IWL_INVALID_STATION)) | ||
2262 | iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); | ||
2263 | |||
2264 | iwl_check_abort_status(priv, tx_resp->frame_count, status); | ||
2265 | |||
2266 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
2267 | } | ||
2268 | |||
2269 | static void iwl4965_rx_beacon_notif(struct iwl_priv *priv, | ||
2270 | struct iwl_rx_mem_buffer *rxb) | ||
2271 | { | ||
2272 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
2273 | struct iwl4965_beacon_notif *beacon = (void *)pkt->u.raw; | ||
2274 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
2275 | u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); | ||
2276 | |||
2277 | IWL_DEBUG_RX(priv, "beacon status %#x, retries:%d ibssmgr:%d " | ||
2278 | "tsf:0x%.8x%.8x rate:%d\n", | ||
2279 | le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK, | ||
2280 | beacon->beacon_notify_hdr.failure_frame, | ||
2281 | le32_to_cpu(beacon->ibss_mgr_status), | ||
2282 | le32_to_cpu(beacon->high_tsf), | ||
2283 | le32_to_cpu(beacon->low_tsf), rate); | ||
2284 | #endif | ||
2285 | |||
2286 | priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); | ||
2287 | |||
2288 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
2289 | queue_work(priv->workqueue, &priv->beacon_update); | ||
2290 | } | ||
2291 | |||
2292 | static int iwl4965_calc_rssi(struct iwl_priv *priv, | ||
2293 | struct iwl_rx_phy_res *rx_resp) | ||
2294 | { | ||
2295 | /* data from PHY/DSP regarding signal strength, etc., | ||
2296 | * contents are always there, not configurable by host. */ | ||
2297 | struct iwl4965_rx_non_cfg_phy *ncphy = | ||
2298 | (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy_buf; | ||
2299 | u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL49_AGC_DB_MASK) | ||
2300 | >> IWL49_AGC_DB_POS; | ||
2301 | |||
2302 | u32 valid_antennae = | ||
2303 | (le16_to_cpu(rx_resp->phy_flags) & IWL49_RX_PHY_FLAGS_ANTENNAE_MASK) | ||
2304 | >> IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET; | ||
2305 | u8 max_rssi = 0; | ||
2306 | u32 i; | ||
2307 | |||
2308 | /* Find max rssi among 3 possible receivers. | ||
2309 | * These values are measured by the digital signal processor (DSP). | ||
2310 | * They should stay fairly constant even as the signal strength varies, | ||
2311 | * if the radio's automatic gain control (AGC) is working right. | ||
2312 | * AGC value (see below) will provide the "interesting" info. */ | ||
2313 | for (i = 0; i < 3; i++) | ||
2314 | if (valid_antennae & (1 << i)) | ||
2315 | max_rssi = max(ncphy->rssi_info[i << 1], max_rssi); | ||
2316 | |||
2317 | IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", | ||
2318 | ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4], | ||
2319 | max_rssi, agc); | ||
2320 | |||
2321 | /* dBm = max_rssi dB - agc dB - constant. | ||
2322 | * Higher AGC (higher radio gain) means lower signal. */ | ||
2323 | return max_rssi - agc - IWLAGN_RSSI_OFFSET; | ||
2324 | } | ||
2325 | |||
2326 | |||
2327 | /* Set up 4965-specific Rx frame reply handlers */ | ||
2328 | static void iwl4965_rx_handler_setup(struct iwl_priv *priv) | ||
2329 | { | ||
2330 | /* Legacy Rx frames */ | ||
2331 | priv->rx_handlers[REPLY_RX] = iwlagn_rx_reply_rx; | ||
2332 | /* Tx response */ | ||
2333 | priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; | ||
2334 | priv->rx_handlers[BEACON_NOTIFICATION] = iwl4965_rx_beacon_notif; | ||
2335 | |||
2336 | /* set up notification wait support */ | ||
2337 | spin_lock_init(&priv->_agn.notif_wait_lock); | ||
2338 | INIT_LIST_HEAD(&priv->_agn.notif_waits); | ||
2339 | init_waitqueue_head(&priv->_agn.notif_waitq); | ||
2340 | } | ||
2341 | |||
2342 | static void iwl4965_setup_deferred_work(struct iwl_priv *priv) | ||
2343 | { | ||
2344 | INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work); | ||
2345 | } | ||
2346 | |||
2347 | static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) | ||
2348 | { | ||
2349 | cancel_work_sync(&priv->txpower_work); | ||
2350 | } | ||
2351 | |||
2352 | static struct iwl_hcmd_ops iwl4965_hcmd = { | ||
2353 | .rxon_assoc = iwl4965_send_rxon_assoc, | ||
2354 | .commit_rxon = iwl4965_commit_rxon, | ||
2355 | .set_rxon_chain = iwlagn_set_rxon_chain, | ||
2356 | .send_bt_config = iwl_send_bt_config, | ||
2357 | }; | ||
2358 | |||
2359 | static void iwl4965_post_scan(struct iwl_priv *priv) | ||
2360 | { | ||
2361 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
2362 | |||
2363 | /* | ||
2364 | * Since setting the RXON may have been deferred while | ||
2365 | * performing the scan, fire one off if needed | ||
2366 | */ | ||
2367 | if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) | ||
2368 | iwlcore_commit_rxon(priv, ctx); | ||
2369 | } | ||
2370 | |||
2371 | static void iwl4965_post_associate(struct iwl_priv *priv) | ||
2372 | { | ||
2373 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
2374 | struct ieee80211_vif *vif = ctx->vif; | ||
2375 | struct ieee80211_conf *conf = NULL; | ||
2376 | int ret = 0; | ||
2377 | |||
2378 | if (!vif || !priv->is_open) | ||
2379 | return; | ||
2380 | |||
2381 | if (vif->type == NL80211_IFTYPE_AP) { | ||
2382 | IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); | ||
2383 | return; | ||
2384 | } | ||
2385 | |||
2386 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
2387 | return; | ||
2388 | |||
2389 | iwl_scan_cancel_timeout(priv, 200); | ||
2390 | |||
2391 | conf = ieee80211_get_hw_conf(priv->hw); | ||
2392 | |||
2393 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
2394 | iwlcore_commit_rxon(priv, ctx); | ||
2395 | |||
2396 | ret = iwl_send_rxon_timing(priv, ctx); | ||
2397 | if (ret) | ||
2398 | IWL_WARN(priv, "RXON timing - " | ||
2399 | "Attempting to continue.\n"); | ||
2400 | |||
2401 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; | ||
2402 | |||
2403 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | ||
2404 | |||
2405 | if (priv->cfg->ops->hcmd->set_rxon_chain) | ||
2406 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); | ||
2407 | |||
2408 | ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); | ||
2409 | |||
2410 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", | ||
2411 | vif->bss_conf.aid, vif->bss_conf.beacon_int); | ||
2412 | |||
2413 | if (vif->bss_conf.use_short_preamble) | ||
2414 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | ||
2415 | else | ||
2416 | ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | ||
2417 | |||
2418 | if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { | ||
2419 | if (vif->bss_conf.use_short_slot) | ||
2420 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; | ||
2421 | else | ||
2422 | ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | ||
2423 | } | ||
2424 | |||
2425 | iwlcore_commit_rxon(priv, ctx); | ||
2426 | |||
2427 | IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", | ||
2428 | vif->bss_conf.aid, ctx->active.bssid_addr); | ||
2429 | |||
2430 | switch (vif->type) { | ||
2431 | case NL80211_IFTYPE_STATION: | ||
2432 | break; | ||
2433 | case NL80211_IFTYPE_ADHOC: | ||
2434 | iwlagn_send_beacon_cmd(priv); | ||
2435 | break; | ||
2436 | default: | ||
2437 | IWL_ERR(priv, "%s Should not be called in %d mode\n", | ||
2438 | __func__, vif->type); | ||
2439 | break; | ||
2440 | } | ||
2441 | |||
2442 | /* the chain noise calibration will enabled PM upon completion | ||
2443 | * If chain noise has already been run, then we need to enable | ||
2444 | * power management here */ | ||
2445 | if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE) | ||
2446 | iwl_power_update_mode(priv, false); | ||
2447 | |||
2448 | /* Enable Rx differential gain and sensitivity calibrations */ | ||
2449 | iwl_chain_noise_reset(priv); | ||
2450 | priv->start_calib = 1; | ||
2451 | } | ||
2452 | |||
2453 | static void iwl4965_config_ap(struct iwl_priv *priv) | ||
2454 | { | ||
2455 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
2456 | struct ieee80211_vif *vif = ctx->vif; | ||
2457 | int ret = 0; | ||
2458 | |||
2459 | lockdep_assert_held(&priv->mutex); | ||
2460 | |||
2461 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
2462 | return; | ||
2463 | |||
2464 | /* The following should be done only at AP bring up */ | ||
2465 | if (!iwl_is_associated_ctx(ctx)) { | ||
2466 | |||
2467 | /* RXON - unassoc (to set timing command) */ | ||
2468 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
2469 | iwlcore_commit_rxon(priv, ctx); | ||
2470 | |||
2471 | /* RXON Timing */ | ||
2472 | ret = iwl_send_rxon_timing(priv, ctx); | ||
2473 | if (ret) | ||
2474 | IWL_WARN(priv, "RXON timing failed - " | ||
2475 | "Attempting to continue.\n"); | ||
2476 | |||
2477 | /* AP has all antennas */ | ||
2478 | priv->chain_noise_data.active_chains = | ||
2479 | priv->hw_params.valid_rx_ant; | ||
2480 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | ||
2481 | if (priv->cfg->ops->hcmd->set_rxon_chain) | ||
2482 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); | ||
2483 | |||
2484 | ctx->staging.assoc_id = 0; | ||
2485 | |||
2486 | if (vif->bss_conf.use_short_preamble) | ||
2487 | ctx->staging.flags |= | ||
2488 | RXON_FLG_SHORT_PREAMBLE_MSK; | ||
2489 | else | ||
2490 | ctx->staging.flags &= | ||
2491 | ~RXON_FLG_SHORT_PREAMBLE_MSK; | ||
2492 | |||
2493 | if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { | ||
2494 | if (vif->bss_conf.use_short_slot) | ||
2495 | ctx->staging.flags |= | ||
2496 | RXON_FLG_SHORT_SLOT_MSK; | ||
2497 | else | ||
2498 | ctx->staging.flags &= | ||
2499 | ~RXON_FLG_SHORT_SLOT_MSK; | ||
2500 | } | ||
2501 | /* need to send beacon cmd before committing assoc RXON! */ | ||
2502 | iwlagn_send_beacon_cmd(priv); | ||
2503 | /* restore RXON assoc */ | ||
2504 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; | ||
2505 | iwlcore_commit_rxon(priv, ctx); | ||
2506 | } | ||
2507 | iwlagn_send_beacon_cmd(priv); | ||
2508 | |||
2509 | /* FIXME - we need to add code here to detect a totally new | ||
2510 | * configuration, reset the AP, unassoc, rxon timing, assoc, | ||
2511 | * clear sta table, add BCAST sta... */ | ||
2512 | } | ||
2513 | |||
2514 | static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { | ||
2515 | .get_hcmd_size = iwl4965_get_hcmd_size, | ||
2516 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, | ||
2517 | .chain_noise_reset = iwl4965_chain_noise_reset, | ||
2518 | .gain_computation = iwl4965_gain_computation, | ||
2519 | .tx_cmd_protection = iwl_legacy_tx_cmd_protection, | ||
2520 | .calc_rssi = iwl4965_calc_rssi, | ||
2521 | .request_scan = iwlagn_request_scan, | ||
2522 | .post_scan = iwl4965_post_scan, | ||
2523 | }; | ||
2524 | |||
2525 | static struct iwl_lib_ops iwl4965_lib = { | ||
2526 | .set_hw_params = iwl4965_hw_set_hw_params, | ||
2527 | .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl, | ||
2528 | .txq_set_sched = iwl4965_txq_set_sched, | ||
2529 | .txq_agg_enable = iwl4965_txq_agg_enable, | ||
2530 | .txq_agg_disable = iwl4965_txq_agg_disable, | ||
2531 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | ||
2532 | .txq_free_tfd = iwl_hw_txq_free_tfd, | ||
2533 | .txq_init = iwl_hw_tx_queue_init, | ||
2534 | .rx_handler_setup = iwl4965_rx_handler_setup, | ||
2535 | .setup_deferred_work = iwl4965_setup_deferred_work, | ||
2536 | .cancel_deferred_work = iwl4965_cancel_deferred_work, | ||
2537 | .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr, | ||
2538 | .alive_notify = iwl4965_alive_notify, | ||
2539 | .init_alive_start = iwl4965_init_alive_start, | ||
2540 | .load_ucode = iwl4965_load_bsm, | ||
2541 | .dump_nic_event_log = iwl_dump_nic_event_log, | ||
2542 | .dump_nic_error_log = iwl_dump_nic_error_log, | ||
2543 | .dump_fh = iwl_dump_fh, | ||
2544 | .set_channel_switch = iwl4965_hw_channel_switch, | ||
2545 | .apm_ops = { | ||
2546 | .init = iwl_apm_init, | ||
2547 | .config = iwl4965_nic_config, | ||
2548 | }, | ||
2549 | .eeprom_ops = { | ||
2550 | .regulatory_bands = { | ||
2551 | EEPROM_REGULATORY_BAND_1_CHANNELS, | ||
2552 | EEPROM_REGULATORY_BAND_2_CHANNELS, | ||
2553 | EEPROM_REGULATORY_BAND_3_CHANNELS, | ||
2554 | EEPROM_REGULATORY_BAND_4_CHANNELS, | ||
2555 | EEPROM_REGULATORY_BAND_5_CHANNELS, | ||
2556 | EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS, | ||
2557 | EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS | ||
2558 | }, | ||
2559 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | ||
2560 | .release_semaphore = iwlcore_eeprom_release_semaphore, | ||
2561 | .calib_version = iwl4965_eeprom_calib_version, | ||
2562 | .query_addr = iwlcore_eeprom_query_addr, | ||
2563 | }, | ||
2564 | .send_tx_power = iwl4965_send_tx_power, | ||
2565 | .update_chain_flags = iwl_update_chain_flags, | ||
2566 | .isr_ops = { | ||
2567 | .isr = iwl_isr_legacy, | ||
2568 | }, | ||
2569 | .temp_ops = { | ||
2570 | .temperature = iwl4965_temperature_calib, | ||
2571 | }, | ||
2572 | .debugfs_ops = { | ||
2573 | .rx_stats_read = iwl_ucode_rx_stats_read, | ||
2574 | .tx_stats_read = iwl_ucode_tx_stats_read, | ||
2575 | .general_stats_read = iwl_ucode_general_stats_read, | ||
2576 | .bt_stats_read = iwl_ucode_bt_stats_read, | ||
2577 | .reply_tx_error = iwl_reply_tx_error_read, | ||
2578 | }, | ||
2579 | .check_plcp_health = iwl_good_plcp_health, | ||
2580 | }; | ||
2581 | |||
2582 | static const struct iwl_legacy_ops iwl4965_legacy_ops = { | ||
2583 | .post_associate = iwl4965_post_associate, | ||
2584 | .config_ap = iwl4965_config_ap, | ||
2585 | .manage_ibss_station = iwlagn_manage_ibss_station, | ||
2586 | .update_bcast_stations = iwl_update_bcast_stations, | ||
2587 | }; | ||
2588 | |||
2589 | struct ieee80211_ops iwl4965_hw_ops = { | ||
2590 | .tx = iwlagn_mac_tx, | ||
2591 | .start = iwlagn_mac_start, | ||
2592 | .stop = iwlagn_mac_stop, | ||
2593 | .add_interface = iwl_mac_add_interface, | ||
2594 | .remove_interface = iwl_mac_remove_interface, | ||
2595 | .change_interface = iwl_mac_change_interface, | ||
2596 | .config = iwl_legacy_mac_config, | ||
2597 | .configure_filter = iwlagn_configure_filter, | ||
2598 | .set_key = iwlagn_mac_set_key, | ||
2599 | .update_tkip_key = iwlagn_mac_update_tkip_key, | ||
2600 | .conf_tx = iwl_mac_conf_tx, | ||
2601 | .reset_tsf = iwl_legacy_mac_reset_tsf, | ||
2602 | .bss_info_changed = iwl_legacy_mac_bss_info_changed, | ||
2603 | .ampdu_action = iwlagn_mac_ampdu_action, | ||
2604 | .hw_scan = iwl_mac_hw_scan, | ||
2605 | .sta_add = iwlagn_mac_sta_add, | ||
2606 | .sta_remove = iwl_mac_sta_remove, | ||
2607 | .channel_switch = iwlagn_mac_channel_switch, | ||
2608 | .flush = iwlagn_mac_flush, | ||
2609 | .tx_last_beacon = iwl_mac_tx_last_beacon, | ||
2610 | }; | ||
2611 | |||
2612 | static const struct iwl_ops iwl4965_ops = { | ||
2613 | .lib = &iwl4965_lib, | ||
2614 | .hcmd = &iwl4965_hcmd, | ||
2615 | .utils = &iwl4965_hcmd_utils, | ||
2616 | .led = &iwlagn_led_ops, | ||
2617 | .legacy = &iwl4965_legacy_ops, | ||
2618 | .ieee80211_ops = &iwl4965_hw_ops, | ||
2619 | }; | ||
2620 | |||
2621 | static struct iwl_base_params iwl4965_base_params = { | ||
2622 | .eeprom_size = IWL4965_EEPROM_IMG_SIZE, | ||
2623 | .num_of_queues = IWL49_NUM_QUEUES, | ||
2624 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, | ||
2625 | .pll_cfg_val = 0, | ||
2626 | .set_l0s = true, | ||
2627 | .use_bsm = true, | ||
2628 | .use_isr_legacy = true, | ||
2629 | .broken_powersave = true, | ||
2630 | .led_compensation = 61, | ||
2631 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, | ||
2632 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
2633 | .wd_timeout = IWL_DEF_WD_TIMEOUT, | ||
2634 | .temperature_kelvin = true, | ||
2635 | .max_event_log_size = 512, | ||
2636 | .tx_power_by_driver = true, | ||
2637 | .ucode_tracing = true, | ||
2638 | .sensitivity_calib_by_driver = true, | ||
2639 | .chain_noise_calib_by_driver = true, | ||
2640 | .no_agg_framecnt_info = true, | ||
2641 | }; | ||
2642 | |||
2643 | struct iwl_cfg iwl4965_agn_cfg = { | ||
2644 | .name = "Intel(R) Wireless WiFi Link 4965AGN", | ||
2645 | .fw_name_pre = IWL4965_FW_PRE, | ||
2646 | .ucode_api_max = IWL4965_UCODE_API_MAX, | ||
2647 | .ucode_api_min = IWL4965_UCODE_API_MIN, | ||
2648 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | ||
2649 | .valid_tx_ant = ANT_AB, | ||
2650 | .valid_rx_ant = ANT_ABC, | ||
2651 | .eeprom_ver = EEPROM_4965_EEPROM_VERSION, | ||
2652 | .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, | ||
2653 | .ops = &iwl4965_ops, | ||
2654 | .mod_params = &iwlagn_mod_params, | ||
2655 | .base_params = &iwl4965_base_params, | ||
2656 | .led_mode = IWL_LED_BLINK, | ||
2657 | /* | ||
2658 | * Force use of chains B and C for scan RX on 5 GHz band | ||
2659 | * because the device has off-channel reception on chain A. | ||
2660 | */ | ||
2661 | .scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC, | ||
2662 | }; | ||
2663 | |||
2664 | /* Module firmware */ | ||
2665 | MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); | ||
2666 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 9965215697b..d08fa938501 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -86,7 +86,6 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); | |||
86 | MODULE_VERSION(DRV_VERSION); | 86 | MODULE_VERSION(DRV_VERSION); |
87 | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | 87 | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); |
88 | MODULE_LICENSE("GPL"); | 88 | MODULE_LICENSE("GPL"); |
89 | MODULE_ALIAS("iwl4965"); | ||
90 | 89 | ||
91 | static int iwlagn_ant_coupling; | 90 | static int iwlagn_ant_coupling; |
92 | static bool iwlagn_bt_ch_announce = 1; | 91 | static bool iwlagn_bt_ch_announce = 1; |
@@ -3810,7 +3809,6 @@ static void iwlagn_bg_roc_done(struct work_struct *work) | |||
3810 | mutex_unlock(&priv->mutex); | 3809 | mutex_unlock(&priv->mutex); |
3811 | } | 3810 | } |
3812 | 3811 | ||
3813 | #ifdef CONFIG_IWL5000 | ||
3814 | static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, | 3812 | static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, |
3815 | struct ieee80211_channel *channel, | 3813 | struct ieee80211_channel *channel, |
3816 | enum nl80211_channel_type channel_type, | 3814 | enum nl80211_channel_type channel_type, |
@@ -3866,7 +3864,6 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | |||
3866 | 3864 | ||
3867 | return 0; | 3865 | return 0; |
3868 | } | 3866 | } |
3869 | #endif | ||
3870 | 3867 | ||
3871 | /***************************************************************************** | 3868 | /***************************************************************************** |
3872 | * | 3869 | * |
@@ -4036,7 +4033,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv) | |||
4036 | kfree(priv->scan_cmd); | 4033 | kfree(priv->scan_cmd); |
4037 | } | 4034 | } |
4038 | 4035 | ||
4039 | #ifdef CONFIG_IWL5000 | ||
4040 | struct ieee80211_ops iwlagn_hw_ops = { | 4036 | struct ieee80211_ops iwlagn_hw_ops = { |
4041 | .tx = iwlagn_mac_tx, | 4037 | .tx = iwlagn_mac_tx, |
4042 | .start = iwlagn_mac_start, | 4038 | .start = iwlagn_mac_start, |
@@ -4061,7 +4057,6 @@ struct ieee80211_ops iwlagn_hw_ops = { | |||
4061 | .remain_on_channel = iwl_mac_remain_on_channel, | 4057 | .remain_on_channel = iwl_mac_remain_on_channel, |
4062 | .cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel, | 4058 | .cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel, |
4063 | }; | 4059 | }; |
4064 | #endif | ||
4065 | 4060 | ||
4066 | static void iwl_hw_detect(struct iwl_priv *priv) | 4061 | static void iwl_hw_detect(struct iwl_priv *priv) |
4067 | { | 4062 | { |
@@ -4129,12 +4124,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
4129 | if (cfg->mod_params->disable_hw_scan) { | 4124 | if (cfg->mod_params->disable_hw_scan) { |
4130 | dev_printk(KERN_DEBUG, &(pdev->dev), | 4125 | dev_printk(KERN_DEBUG, &(pdev->dev), |
4131 | "sw scan support is deprecated\n"); | 4126 | "sw scan support is deprecated\n"); |
4132 | #ifdef CONFIG_IWL5000 | ||
4133 | iwlagn_hw_ops.hw_scan = NULL; | 4127 | iwlagn_hw_ops.hw_scan = NULL; |
4134 | #endif | ||
4135 | #ifdef CONFIG_IWL4965 | ||
4136 | iwl4965_hw_ops.hw_scan = NULL; | ||
4137 | #endif | ||
4138 | } | 4128 | } |
4139 | 4129 | ||
4140 | hw = iwl_alloc_all(cfg); | 4130 | hw = iwl_alloc_all(cfg); |
@@ -4513,12 +4503,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) | |||
4513 | 4503 | ||
4514 | /* Hardware specific file defines the PCI IDs table for that hardware module */ | 4504 | /* Hardware specific file defines the PCI IDs table for that hardware module */ |
4515 | static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | 4505 | static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { |
4516 | #ifdef CONFIG_IWL4965 | ||
4517 | {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, | ||
4518 | {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, | ||
4519 | #endif /* CONFIG_IWL4965 */ | ||
4520 | #ifdef CONFIG_IWL5000 | ||
4521 | /* 5100 Series WiFi */ | ||
4522 | {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */ | 4506 | {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */ |
4523 | {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */ | 4507 | {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */ |
4524 | {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */ | 4508 | {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */ |
@@ -4704,8 +4688,6 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
4704 | {IWL_PCI_DEVICE(0x0893, 0x0266, iwl230_bg_cfg)}, | 4688 | {IWL_PCI_DEVICE(0x0893, 0x0266, iwl230_bg_cfg)}, |
4705 | {IWL_PCI_DEVICE(0x0892, 0x0466, iwl230_bg_cfg)}, | 4689 | {IWL_PCI_DEVICE(0x0892, 0x0466, iwl230_bg_cfg)}, |
4706 | 4690 | ||
4707 | #endif /* CONFIG_IWL5000 */ | ||
4708 | |||
4709 | {0} | 4691 | {0} |
4710 | }; | 4692 | }; |
4711 | MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); | 4693 | MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 977ddfb8c24..4bd34206025 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -43,11 +43,6 @@ | |||
43 | #include "iwl-helpers.h" | 43 | #include "iwl-helpers.h" |
44 | 44 | ||
45 | 45 | ||
46 | MODULE_DESCRIPTION("iwl core"); | ||
47 | MODULE_VERSION(IWLWIFI_VERSION); | ||
48 | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | ||
49 | MODULE_LICENSE("GPL"); | ||
50 | |||
51 | /* | 46 | /* |
52 | * set bt_coex_active to true, uCode will do kill/defer | 47 | * set bt_coex_active to true, uCode will do kill/defer |
53 | * every time the priority line is asserted (BT is sending signals on the | 48 | * every time the priority line is asserted (BT is sending signals on the |
@@ -65,15 +60,12 @@ MODULE_LICENSE("GPL"); | |||
65 | * default: bt_coex_active = true (BT_COEX_ENABLE) | 60 | * default: bt_coex_active = true (BT_COEX_ENABLE) |
66 | */ | 61 | */ |
67 | bool bt_coex_active = true; | 62 | bool bt_coex_active = true; |
68 | EXPORT_SYMBOL_GPL(bt_coex_active); | ||
69 | module_param(bt_coex_active, bool, S_IRUGO); | 63 | module_param(bt_coex_active, bool, S_IRUGO); |
70 | MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist"); | 64 | MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist"); |
71 | 65 | ||
72 | u32 iwl_debug_level; | 66 | u32 iwl_debug_level; |
73 | EXPORT_SYMBOL(iwl_debug_level); | ||
74 | 67 | ||
75 | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 68 | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
76 | EXPORT_SYMBOL(iwl_bcast_addr); | ||
77 | 69 | ||
78 | 70 | ||
79 | /* This function both allocates and initializes hw and priv. */ | 71 | /* This function both allocates and initializes hw and priv. */ |
@@ -98,7 +90,6 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg) | |||
98 | out: | 90 | out: |
99 | return hw; | 91 | return hw; |
100 | } | 92 | } |
101 | EXPORT_SYMBOL(iwl_alloc_all); | ||
102 | 93 | ||
103 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ | 94 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ |
104 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ | 95 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ |
@@ -272,7 +263,6 @@ int iwlcore_init_geos(struct iwl_priv *priv) | |||
272 | 263 | ||
273 | return 0; | 264 | return 0; |
274 | } | 265 | } |
275 | EXPORT_SYMBOL(iwlcore_init_geos); | ||
276 | 266 | ||
277 | /* | 267 | /* |
278 | * iwlcore_free_geos - undo allocations in iwlcore_init_geos | 268 | * iwlcore_free_geos - undo allocations in iwlcore_init_geos |
@@ -283,7 +273,6 @@ void iwlcore_free_geos(struct iwl_priv *priv) | |||
283 | kfree(priv->ieee_rates); | 273 | kfree(priv->ieee_rates); |
284 | clear_bit(STATUS_GEO_CONFIGURED, &priv->status); | 274 | clear_bit(STATUS_GEO_CONFIGURED, &priv->status); |
285 | } | 275 | } |
286 | EXPORT_SYMBOL(iwlcore_free_geos); | ||
287 | 276 | ||
288 | static bool iwl_is_channel_extension(struct iwl_priv *priv, | 277 | static bool iwl_is_channel_extension(struct iwl_priv *priv, |
289 | enum ieee80211_band band, | 278 | enum ieee80211_band band, |
@@ -328,7 +317,6 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | |||
328 | le16_to_cpu(ctx->staging.channel), | 317 | le16_to_cpu(ctx->staging.channel), |
329 | ctx->ht.extension_chan_offset); | 318 | ctx->ht.extension_chan_offset); |
330 | } | 319 | } |
331 | EXPORT_SYMBOL(iwl_is_ht40_tx_allowed); | ||
332 | 320 | ||
333 | static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) | 321 | static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) |
334 | { | 322 | { |
@@ -429,7 +417,6 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
429 | return iwl_send_cmd_pdu(priv, ctx->rxon_timing_cmd, | 417 | return iwl_send_cmd_pdu(priv, ctx->rxon_timing_cmd, |
430 | sizeof(ctx->timing), &ctx->timing); | 418 | sizeof(ctx->timing), &ctx->timing); |
431 | } | 419 | } |
432 | EXPORT_SYMBOL(iwl_send_rxon_timing); | ||
433 | 420 | ||
434 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | 421 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, |
435 | int hw_decrypt) | 422 | int hw_decrypt) |
@@ -442,7 +429,6 @@ void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | |||
442 | rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK; | 429 | rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK; |
443 | 430 | ||
444 | } | 431 | } |
445 | EXPORT_SYMBOL(iwl_set_rxon_hwcrypto); | ||
446 | 432 | ||
447 | /* validate RXON structure is valid */ | 433 | /* validate RXON structure is valid */ |
448 | int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | 434 | int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx) |
@@ -515,7 +501,6 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
515 | } | 501 | } |
516 | return 0; | 502 | return 0; |
517 | } | 503 | } |
518 | EXPORT_SYMBOL(iwl_check_rxon_cmd); | ||
519 | 504 | ||
520 | /** | 505 | /** |
521 | * iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed | 506 | * iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed |
@@ -579,7 +564,6 @@ int iwl_full_rxon_required(struct iwl_priv *priv, | |||
579 | 564 | ||
580 | return 0; | 565 | return 0; |
581 | } | 566 | } |
582 | EXPORT_SYMBOL(iwl_full_rxon_required); | ||
583 | 567 | ||
584 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv, | 568 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv, |
585 | struct iwl_rxon_context *ctx) | 569 | struct iwl_rxon_context *ctx) |
@@ -593,7 +577,6 @@ u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv, | |||
593 | else | 577 | else |
594 | return IWL_RATE_6M_PLCP; | 578 | return IWL_RATE_6M_PLCP; |
595 | } | 579 | } |
596 | EXPORT_SYMBOL(iwl_rate_get_lowest_plcp); | ||
597 | 580 | ||
598 | static void _iwl_set_rxon_ht(struct iwl_priv *priv, | 581 | static void _iwl_set_rxon_ht(struct iwl_priv *priv, |
599 | struct iwl_ht_config *ht_conf, | 582 | struct iwl_ht_config *ht_conf, |
@@ -670,7 +653,6 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) | |||
670 | for_each_context(priv, ctx) | 653 | for_each_context(priv, ctx) |
671 | _iwl_set_rxon_ht(priv, ht_conf, ctx); | 654 | _iwl_set_rxon_ht(priv, ht_conf, ctx); |
672 | } | 655 | } |
673 | EXPORT_SYMBOL(iwl_set_rxon_ht); | ||
674 | 656 | ||
675 | /* Return valid, unused, channel for a passive scan to reset the RF */ | 657 | /* Return valid, unused, channel for a passive scan to reset the RF */ |
676 | u8 iwl_get_single_channel_number(struct iwl_priv *priv, | 658 | u8 iwl_get_single_channel_number(struct iwl_priv *priv, |
@@ -711,7 +693,6 @@ u8 iwl_get_single_channel_number(struct iwl_priv *priv, | |||
711 | 693 | ||
712 | return channel; | 694 | return channel; |
713 | } | 695 | } |
714 | EXPORT_SYMBOL(iwl_get_single_channel_number); | ||
715 | 696 | ||
716 | /** | 697 | /** |
717 | * iwl_set_rxon_channel - Set the band and channel values in staging RXON | 698 | * iwl_set_rxon_channel - Set the band and channel values in staging RXON |
@@ -742,7 +723,6 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch, | |||
742 | 723 | ||
743 | return 0; | 724 | return 0; |
744 | } | 725 | } |
745 | EXPORT_SYMBOL(iwl_set_rxon_channel); | ||
746 | 726 | ||
747 | void iwl_set_flags_for_band(struct iwl_priv *priv, | 727 | void iwl_set_flags_for_band(struct iwl_priv *priv, |
748 | struct iwl_rxon_context *ctx, | 728 | struct iwl_rxon_context *ctx, |
@@ -766,7 +746,6 @@ void iwl_set_flags_for_band(struct iwl_priv *priv, | |||
766 | ctx->staging.flags &= ~RXON_FLG_CCK_MSK; | 746 | ctx->staging.flags &= ~RXON_FLG_CCK_MSK; |
767 | } | 747 | } |
768 | } | 748 | } |
769 | EXPORT_SYMBOL(iwl_set_flags_for_band); | ||
770 | 749 | ||
771 | /* | 750 | /* |
772 | * initialize rxon structure with default values from eeprom | 751 | * initialize rxon structure with default values from eeprom |
@@ -838,7 +817,6 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, | |||
838 | ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff; | 817 | ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff; |
839 | ctx->staging.ofdm_ht_triple_stream_basic_rates = 0xff; | 818 | ctx->staging.ofdm_ht_triple_stream_basic_rates = 0xff; |
840 | } | 819 | } |
841 | EXPORT_SYMBOL(iwl_connection_init_rx_config); | ||
842 | 820 | ||
843 | void iwl_set_rate(struct iwl_priv *priv) | 821 | void iwl_set_rate(struct iwl_priv *priv) |
844 | { | 822 | { |
@@ -871,7 +849,6 @@ void iwl_set_rate(struct iwl_priv *priv) | |||
871 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | 849 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; |
872 | } | 850 | } |
873 | } | 851 | } |
874 | EXPORT_SYMBOL(iwl_set_rate); | ||
875 | 852 | ||
876 | void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) | 853 | void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) |
877 | { | 854 | { |
@@ -891,7 +868,6 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) | |||
891 | mutex_unlock(&priv->mutex); | 868 | mutex_unlock(&priv->mutex); |
892 | } | 869 | } |
893 | } | 870 | } |
894 | EXPORT_SYMBOL(iwl_chswitch_done); | ||
895 | 871 | ||
896 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 872 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) |
897 | { | 873 | { |
@@ -919,7 +895,6 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
919 | } | 895 | } |
920 | } | 896 | } |
921 | } | 897 | } |
922 | EXPORT_SYMBOL(iwl_rx_csa); | ||
923 | 898 | ||
924 | #ifdef CONFIG_IWLWIFI_DEBUG | 899 | #ifdef CONFIG_IWLWIFI_DEBUG |
925 | void iwl_print_rx_config_cmd(struct iwl_priv *priv, | 900 | void iwl_print_rx_config_cmd(struct iwl_priv *priv, |
@@ -941,7 +916,6 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv, | |||
941 | IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr); | 916 | IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr); |
942 | IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); | 917 | IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); |
943 | } | 918 | } |
944 | EXPORT_SYMBOL(iwl_print_rx_config_cmd); | ||
945 | #endif | 919 | #endif |
946 | /** | 920 | /** |
947 | * iwl_irq_handle_error - called for HW or SW error interrupt from card | 921 | * iwl_irq_handle_error - called for HW or SW error interrupt from card |
@@ -1021,7 +995,6 @@ void iwl_irq_handle_error(struct iwl_priv *priv) | |||
1021 | queue_work(priv->workqueue, &priv->restart); | 995 | queue_work(priv->workqueue, &priv->restart); |
1022 | } | 996 | } |
1023 | } | 997 | } |
1024 | EXPORT_SYMBOL(iwl_irq_handle_error); | ||
1025 | 998 | ||
1026 | static int iwl_apm_stop_master(struct iwl_priv *priv) | 999 | static int iwl_apm_stop_master(struct iwl_priv *priv) |
1027 | { | 1000 | { |
@@ -1058,7 +1031,6 @@ void iwl_apm_stop(struct iwl_priv *priv) | |||
1058 | */ | 1031 | */ |
1059 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | 1032 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); |
1060 | } | 1033 | } |
1061 | EXPORT_SYMBOL(iwl_apm_stop); | ||
1062 | 1034 | ||
1063 | 1035 | ||
1064 | /* | 1036 | /* |
@@ -1173,7 +1145,6 @@ int iwl_apm_init(struct iwl_priv *priv) | |||
1173 | out: | 1145 | out: |
1174 | return ret; | 1146 | return ret; |
1175 | } | 1147 | } |
1176 | EXPORT_SYMBOL(iwl_apm_init); | ||
1177 | 1148 | ||
1178 | 1149 | ||
1179 | int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | 1150 | int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) |
@@ -1233,7 +1204,6 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | |||
1233 | } | 1204 | } |
1234 | return ret; | 1205 | return ret; |
1235 | } | 1206 | } |
1236 | EXPORT_SYMBOL(iwl_set_tx_power); | ||
1237 | 1207 | ||
1238 | void iwl_send_bt_config(struct iwl_priv *priv) | 1208 | void iwl_send_bt_config(struct iwl_priv *priv) |
1239 | { | 1209 | { |
@@ -1257,7 +1227,6 @@ void iwl_send_bt_config(struct iwl_priv *priv) | |||
1257 | sizeof(struct iwl_bt_cmd), &bt_cmd)) | 1227 | sizeof(struct iwl_bt_cmd), &bt_cmd)) |
1258 | IWL_ERR(priv, "failed to send BT Coex Config\n"); | 1228 | IWL_ERR(priv, "failed to send BT Coex Config\n"); |
1259 | } | 1229 | } |
1260 | EXPORT_SYMBOL(iwl_send_bt_config); | ||
1261 | 1230 | ||
1262 | int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) | 1231 | int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) |
1263 | { | 1232 | { |
@@ -1275,7 +1244,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) | |||
1275 | sizeof(struct iwl_statistics_cmd), | 1244 | sizeof(struct iwl_statistics_cmd), |
1276 | &statistics_cmd); | 1245 | &statistics_cmd); |
1277 | } | 1246 | } |
1278 | EXPORT_SYMBOL(iwl_send_statistics_request); | ||
1279 | 1247 | ||
1280 | void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, | 1248 | void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, |
1281 | struct iwl_rx_mem_buffer *rxb) | 1249 | struct iwl_rx_mem_buffer *rxb) |
@@ -1287,7 +1255,6 @@ void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, | |||
1287 | sleep->pm_sleep_mode, sleep->pm_wakeup_src); | 1255 | sleep->pm_sleep_mode, sleep->pm_wakeup_src); |
1288 | #endif | 1256 | #endif |
1289 | } | 1257 | } |
1290 | EXPORT_SYMBOL(iwl_rx_pm_sleep_notif); | ||
1291 | 1258 | ||
1292 | void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, | 1259 | void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, |
1293 | struct iwl_rx_mem_buffer *rxb) | 1260 | struct iwl_rx_mem_buffer *rxb) |
@@ -1299,7 +1266,6 @@ void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, | |||
1299 | get_cmd_string(pkt->hdr.cmd)); | 1266 | get_cmd_string(pkt->hdr.cmd)); |
1300 | iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len); | 1267 | iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len); |
1301 | } | 1268 | } |
1302 | EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif); | ||
1303 | 1269 | ||
1304 | void iwl_rx_reply_error(struct iwl_priv *priv, | 1270 | void iwl_rx_reply_error(struct iwl_priv *priv, |
1305 | struct iwl_rx_mem_buffer *rxb) | 1271 | struct iwl_rx_mem_buffer *rxb) |
@@ -1314,7 +1280,6 @@ void iwl_rx_reply_error(struct iwl_priv *priv, | |||
1314 | le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num), | 1280 | le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num), |
1315 | le32_to_cpu(pkt->u.err_resp.error_info)); | 1281 | le32_to_cpu(pkt->u.err_resp.error_info)); |
1316 | } | 1282 | } |
1317 | EXPORT_SYMBOL(iwl_rx_reply_error); | ||
1318 | 1283 | ||
1319 | void iwl_clear_isr_stats(struct iwl_priv *priv) | 1284 | void iwl_clear_isr_stats(struct iwl_priv *priv) |
1320 | { | 1285 | { |
@@ -1366,7 +1331,6 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1366 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1331 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
1367 | return 0; | 1332 | return 0; |
1368 | } | 1333 | } |
1369 | EXPORT_SYMBOL(iwl_mac_conf_tx); | ||
1370 | 1334 | ||
1371 | int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw) | 1335 | int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw) |
1372 | { | 1336 | { |
@@ -1374,7 +1338,6 @@ int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw) | |||
1374 | 1338 | ||
1375 | return priv->ibss_manager == IWL_IBSS_MANAGER; | 1339 | return priv->ibss_manager == IWL_IBSS_MANAGER; |
1376 | } | 1340 | } |
1377 | EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon); | ||
1378 | 1341 | ||
1379 | static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | 1342 | static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx) |
1380 | { | 1343 | { |
@@ -1484,7 +1447,6 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
1484 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1447 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
1485 | return err; | 1448 | return err; |
1486 | } | 1449 | } |
1487 | EXPORT_SYMBOL(iwl_mac_add_interface); | ||
1488 | 1450 | ||
1489 | static void iwl_teardown_interface(struct iwl_priv *priv, | 1451 | static void iwl_teardown_interface(struct iwl_priv *priv, |
1490 | struct ieee80211_vif *vif, | 1452 | struct ieee80211_vif *vif, |
@@ -1537,7 +1499,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
1537 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1499 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
1538 | 1500 | ||
1539 | } | 1501 | } |
1540 | EXPORT_SYMBOL(iwl_mac_remove_interface); | ||
1541 | 1502 | ||
1542 | int iwl_alloc_txq_mem(struct iwl_priv *priv) | 1503 | int iwl_alloc_txq_mem(struct iwl_priv *priv) |
1543 | { | 1504 | { |
@@ -1552,14 +1513,12 @@ int iwl_alloc_txq_mem(struct iwl_priv *priv) | |||
1552 | } | 1513 | } |
1553 | return 0; | 1514 | return 0; |
1554 | } | 1515 | } |
1555 | EXPORT_SYMBOL(iwl_alloc_txq_mem); | ||
1556 | 1516 | ||
1557 | void iwl_free_txq_mem(struct iwl_priv *priv) | 1517 | void iwl_free_txq_mem(struct iwl_priv *priv) |
1558 | { | 1518 | { |
1559 | kfree(priv->txq); | 1519 | kfree(priv->txq); |
1560 | priv->txq = NULL; | 1520 | priv->txq = NULL; |
1561 | } | 1521 | } |
1562 | EXPORT_SYMBOL(iwl_free_txq_mem); | ||
1563 | 1522 | ||
1564 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1523 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1565 | 1524 | ||
@@ -1598,7 +1557,6 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv) | |||
1598 | iwl_reset_traffic_log(priv); | 1557 | iwl_reset_traffic_log(priv); |
1599 | return 0; | 1558 | return 0; |
1600 | } | 1559 | } |
1601 | EXPORT_SYMBOL(iwl_alloc_traffic_mem); | ||
1602 | 1560 | ||
1603 | void iwl_free_traffic_mem(struct iwl_priv *priv) | 1561 | void iwl_free_traffic_mem(struct iwl_priv *priv) |
1604 | { | 1562 | { |
@@ -1608,7 +1566,6 @@ void iwl_free_traffic_mem(struct iwl_priv *priv) | |||
1608 | kfree(priv->rx_traffic); | 1566 | kfree(priv->rx_traffic); |
1609 | priv->rx_traffic = NULL; | 1567 | priv->rx_traffic = NULL; |
1610 | } | 1568 | } |
1611 | EXPORT_SYMBOL(iwl_free_traffic_mem); | ||
1612 | 1569 | ||
1613 | void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv, | 1570 | void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv, |
1614 | u16 length, struct ieee80211_hdr *header) | 1571 | u16 length, struct ieee80211_hdr *header) |
@@ -1633,7 +1590,6 @@ void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv, | |||
1633 | (priv->tx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES; | 1590 | (priv->tx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES; |
1634 | } | 1591 | } |
1635 | } | 1592 | } |
1636 | EXPORT_SYMBOL(iwl_dbg_log_tx_data_frame); | ||
1637 | 1593 | ||
1638 | void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, | 1594 | void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, |
1639 | u16 length, struct ieee80211_hdr *header) | 1595 | u16 length, struct ieee80211_hdr *header) |
@@ -1658,7 +1614,6 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, | |||
1658 | (priv->rx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES; | 1614 | (priv->rx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES; |
1659 | } | 1615 | } |
1660 | } | 1616 | } |
1661 | EXPORT_SYMBOL(iwl_dbg_log_rx_data_frame); | ||
1662 | 1617 | ||
1663 | const char *get_mgmt_string(int cmd) | 1618 | const char *get_mgmt_string(int cmd) |
1664 | { | 1619 | { |
@@ -1795,7 +1750,6 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) | |||
1795 | stats->data_bytes += len; | 1750 | stats->data_bytes += len; |
1796 | } | 1751 | } |
1797 | } | 1752 | } |
1798 | EXPORT_SYMBOL(iwl_update_stats); | ||
1799 | #endif | 1753 | #endif |
1800 | 1754 | ||
1801 | static void iwl_force_rf_reset(struct iwl_priv *priv) | 1755 | static void iwl_force_rf_reset(struct iwl_priv *priv) |
@@ -1934,7 +1888,6 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
1934 | mutex_unlock(&priv->mutex); | 1888 | mutex_unlock(&priv->mutex); |
1935 | return err; | 1889 | return err; |
1936 | } | 1890 | } |
1937 | EXPORT_SYMBOL(iwl_mac_change_interface); | ||
1938 | 1891 | ||
1939 | /* | 1892 | /* |
1940 | * On every watchdog tick we check (latest) time stamp. If it does not | 1893 | * On every watchdog tick we check (latest) time stamp. If it does not |
@@ -2006,7 +1959,6 @@ void iwl_bg_watchdog(unsigned long data) | |||
2006 | mod_timer(&priv->watchdog, jiffies + | 1959 | mod_timer(&priv->watchdog, jiffies + |
2007 | msecs_to_jiffies(IWL_WD_TICK(timeout))); | 1960 | msecs_to_jiffies(IWL_WD_TICK(timeout))); |
2008 | } | 1961 | } |
2009 | EXPORT_SYMBOL(iwl_bg_watchdog); | ||
2010 | 1962 | ||
2011 | void iwl_setup_watchdog(struct iwl_priv *priv) | 1963 | void iwl_setup_watchdog(struct iwl_priv *priv) |
2012 | { | 1964 | { |
@@ -2018,7 +1970,6 @@ void iwl_setup_watchdog(struct iwl_priv *priv) | |||
2018 | else | 1970 | else |
2019 | del_timer(&priv->watchdog); | 1971 | del_timer(&priv->watchdog); |
2020 | } | 1972 | } |
2021 | EXPORT_SYMBOL(iwl_setup_watchdog); | ||
2022 | 1973 | ||
2023 | /* | 1974 | /* |
2024 | * extended beacon time format | 1975 | * extended beacon time format |
@@ -2044,7 +1995,6 @@ u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval) | |||
2044 | 1995 | ||
2045 | return (quot << priv->hw_params.beacon_time_tsf_bits) + rem; | 1996 | return (quot << priv->hw_params.beacon_time_tsf_bits) + rem; |
2046 | } | 1997 | } |
2047 | EXPORT_SYMBOL(iwl_usecs_to_beacons); | ||
2048 | 1998 | ||
2049 | /* base is usually what we get from ucode with each received frame, | 1999 | /* base is usually what we get from ucode with each received frame, |
2050 | * the same as HW timer counter counting down | 2000 | * the same as HW timer counter counting down |
@@ -2072,7 +2022,6 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, | |||
2072 | 2022 | ||
2073 | return cpu_to_le32(res); | 2023 | return cpu_to_le32(res); |
2074 | } | 2024 | } |
2075 | EXPORT_SYMBOL(iwl_add_beacon_time); | ||
2076 | 2025 | ||
2077 | #ifdef CONFIG_PM | 2026 | #ifdef CONFIG_PM |
2078 | 2027 | ||
@@ -2092,7 +2041,6 @@ int iwl_pci_suspend(struct device *device) | |||
2092 | 2041 | ||
2093 | return 0; | 2042 | return 0; |
2094 | } | 2043 | } |
2095 | EXPORT_SYMBOL(iwl_pci_suspend); | ||
2096 | 2044 | ||
2097 | int iwl_pci_resume(struct device *device) | 2045 | int iwl_pci_resume(struct device *device) |
2098 | { | 2046 | { |
@@ -2121,7 +2069,6 @@ int iwl_pci_resume(struct device *device) | |||
2121 | 2069 | ||
2122 | return 0; | 2070 | return 0; |
2123 | } | 2071 | } |
2124 | EXPORT_SYMBOL(iwl_pci_resume); | ||
2125 | 2072 | ||
2126 | const struct dev_pm_ops iwl_pm_ops = { | 2073 | const struct dev_pm_ops iwl_pm_ops = { |
2127 | .suspend = iwl_pci_suspend, | 2074 | .suspend = iwl_pci_suspend, |
@@ -2131,6 +2078,5 @@ const struct dev_pm_ops iwl_pm_ops = { | |||
2131 | .poweroff = iwl_pci_suspend, | 2078 | .poweroff = iwl_pci_suspend, |
2132 | .restore = iwl_pci_resume, | 2079 | .restore = iwl_pci_resume, |
2133 | }; | 2080 | }; |
2134 | EXPORT_SYMBOL(iwl_pm_ops); | ||
2135 | 2081 | ||
2136 | #endif /* CONFIG_PM */ | 2082 | #endif /* CONFIG_PM */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index bc7a965c18f..8842411f1cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -1788,7 +1788,6 @@ err: | |||
1788 | iwl_dbgfs_unregister(priv); | 1788 | iwl_dbgfs_unregister(priv); |
1789 | return -ENOMEM; | 1789 | return -ENOMEM; |
1790 | } | 1790 | } |
1791 | EXPORT_SYMBOL(iwl_dbgfs_register); | ||
1792 | 1791 | ||
1793 | /** | 1792 | /** |
1794 | * Remove the debugfs files and directories | 1793 | * Remove the debugfs files and directories |
@@ -1802,7 +1801,6 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) | |||
1802 | debugfs_remove_recursive(priv->debugfs_dir); | 1801 | debugfs_remove_recursive(priv->debugfs_dir); |
1803 | priv->debugfs_dir = NULL; | 1802 | priv->debugfs_dir = NULL; |
1804 | } | 1803 | } |
1805 | EXPORT_SYMBOL(iwl_dbgfs_unregister); | ||
1806 | 1804 | ||
1807 | 1805 | ||
1808 | 1806 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 065615ee040..58165c769cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -43,14 +43,14 @@ | |||
43 | #include "iwl-prph.h" | 43 | #include "iwl-prph.h" |
44 | #include "iwl-fh.h" | 44 | #include "iwl-fh.h" |
45 | #include "iwl-debug.h" | 45 | #include "iwl-debug.h" |
46 | #include "iwl-4965-hw.h" | ||
47 | #include "iwl-3945-hw.h" | ||
48 | #include "iwl-agn-hw.h" | 46 | #include "iwl-agn-hw.h" |
49 | #include "iwl-led.h" | 47 | #include "iwl-led.h" |
50 | #include "iwl-power.h" | 48 | #include "iwl-power.h" |
51 | #include "iwl-agn-rs.h" | 49 | #include "iwl-agn-rs.h" |
52 | #include "iwl-agn-tt.h" | 50 | #include "iwl-agn-tt.h" |
53 | 51 | ||
52 | #define U32_PAD(n) ((4-(n))&0x3) | ||
53 | |||
54 | struct iwl_tx_queue; | 54 | struct iwl_tx_queue; |
55 | 55 | ||
56 | /* CT-KILL constants */ | 56 | /* CT-KILL constants */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 358cfd7e5af..833194a2c63 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -222,7 +222,6 @@ const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) | |||
222 | BUG_ON(offset >= priv->cfg->base_params->eeprom_size); | 222 | BUG_ON(offset >= priv->cfg->base_params->eeprom_size); |
223 | return &priv->eeprom[offset]; | 223 | return &priv->eeprom[offset]; |
224 | } | 224 | } |
225 | EXPORT_SYMBOL(iwlcore_eeprom_query_addr); | ||
226 | 225 | ||
227 | static int iwl_init_otp_access(struct iwl_priv *priv) | 226 | static int iwl_init_otp_access(struct iwl_priv *priv) |
228 | { | 227 | { |
@@ -382,7 +381,6 @@ const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) | |||
382 | { | 381 | { |
383 | return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset); | 382 | return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset); |
384 | } | 383 | } |
385 | EXPORT_SYMBOL(iwl_eeprom_query_addr); | ||
386 | 384 | ||
387 | u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) | 385 | u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) |
388 | { | 386 | { |
@@ -390,7 +388,6 @@ u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) | |||
390 | return 0; | 388 | return 0; |
391 | return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); | 389 | return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); |
392 | } | 390 | } |
393 | EXPORT_SYMBOL(iwl_eeprom_query16); | ||
394 | 391 | ||
395 | /** | 392 | /** |
396 | * iwl_eeprom_init - read EEPROM contents | 393 | * iwl_eeprom_init - read EEPROM contents |
@@ -509,14 +506,12 @@ err: | |||
509 | alloc_err: | 506 | alloc_err: |
510 | return ret; | 507 | return ret; |
511 | } | 508 | } |
512 | EXPORT_SYMBOL(iwl_eeprom_init); | ||
513 | 509 | ||
514 | void iwl_eeprom_free(struct iwl_priv *priv) | 510 | void iwl_eeprom_free(struct iwl_priv *priv) |
515 | { | 511 | { |
516 | kfree(priv->eeprom); | 512 | kfree(priv->eeprom); |
517 | priv->eeprom = NULL; | 513 | priv->eeprom = NULL; |
518 | } | 514 | } |
519 | EXPORT_SYMBOL(iwl_eeprom_free); | ||
520 | 515 | ||
521 | static void iwl_init_band_reference(const struct iwl_priv *priv, | 516 | static void iwl_init_band_reference(const struct iwl_priv *priv, |
522 | int eep_band, int *eeprom_ch_count, | 517 | int eep_band, int *eeprom_ch_count, |
@@ -779,7 +774,6 @@ int iwl_init_channel_map(struct iwl_priv *priv) | |||
779 | 774 | ||
780 | return 0; | 775 | return 0; |
781 | } | 776 | } |
782 | EXPORT_SYMBOL(iwl_init_channel_map); | ||
783 | 777 | ||
784 | /* | 778 | /* |
785 | * iwl_free_channel_map - undo allocations in iwl_init_channel_map | 779 | * iwl_free_channel_map - undo allocations in iwl_init_channel_map |
@@ -789,7 +783,6 @@ void iwl_free_channel_map(struct iwl_priv *priv) | |||
789 | kfree(priv->channel_info); | 783 | kfree(priv->channel_info); |
790 | priv->channel_count = 0; | 784 | priv->channel_count = 0; |
791 | } | 785 | } |
792 | EXPORT_SYMBOL(iwl_free_channel_map); | ||
793 | 786 | ||
794 | /** | 787 | /** |
795 | * iwl_get_channel_info - Find driver's private channel info | 788 | * iwl_get_channel_info - Find driver's private channel info |
@@ -818,4 +811,3 @@ const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv, | |||
818 | 811 | ||
819 | return NULL; | 812 | return NULL; |
820 | } | 813 | } |
821 | EXPORT_SYMBOL(iwl_get_channel_info); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index e4b953d7b7b..02499f68468 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c | |||
@@ -114,7 +114,6 @@ const char *get_cmd_string(u8 cmd) | |||
114 | 114 | ||
115 | } | 115 | } |
116 | } | 116 | } |
117 | EXPORT_SYMBOL(get_cmd_string); | ||
118 | 117 | ||
119 | #define HOST_COMPLETE_TIMEOUT (HZ / 2) | 118 | #define HOST_COMPLETE_TIMEOUT (HZ / 2) |
120 | 119 | ||
@@ -253,7 +252,6 @@ out: | |||
253 | mutex_unlock(&priv->sync_cmd_mutex); | 252 | mutex_unlock(&priv->sync_cmd_mutex); |
254 | return ret; | 253 | return ret; |
255 | } | 254 | } |
256 | EXPORT_SYMBOL(iwl_send_cmd_sync); | ||
257 | 255 | ||
258 | int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | 256 | int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) |
259 | { | 257 | { |
@@ -262,7 +260,6 @@ int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
262 | 260 | ||
263 | return iwl_send_cmd_sync(priv, cmd); | 261 | return iwl_send_cmd_sync(priv, cmd); |
264 | } | 262 | } |
265 | EXPORT_SYMBOL(iwl_send_cmd); | ||
266 | 263 | ||
267 | int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data) | 264 | int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data) |
268 | { | 265 | { |
@@ -274,7 +271,6 @@ int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data) | |||
274 | 271 | ||
275 | return iwl_send_cmd_sync(priv, &cmd); | 272 | return iwl_send_cmd_sync(priv, &cmd); |
276 | } | 273 | } |
277 | EXPORT_SYMBOL(iwl_send_cmd_pdu); | ||
278 | 274 | ||
279 | int iwl_send_cmd_pdu_async(struct iwl_priv *priv, | 275 | int iwl_send_cmd_pdu_async(struct iwl_priv *priv, |
280 | u8 id, u16 len, const void *data, | 276 | u8 id, u16 len, const void *data, |
@@ -293,4 +289,3 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, | |||
293 | 289 | ||
294 | return iwl_send_cmd_async(priv, &cmd); | 290 | return iwl_send_cmd_async(priv, &cmd); |
295 | } | 291 | } |
296 | EXPORT_SYMBOL(iwl_send_cmd_pdu_async); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 074ad227522..d7f2a0bb32c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
@@ -175,7 +175,6 @@ void iwl_leds_init(struct iwl_priv *priv) | |||
175 | 175 | ||
176 | priv->led_registered = true; | 176 | priv->led_registered = true; |
177 | } | 177 | } |
178 | EXPORT_SYMBOL(iwl_leds_init); | ||
179 | 178 | ||
180 | void iwl_leds_exit(struct iwl_priv *priv) | 179 | void iwl_leds_exit(struct iwl_priv *priv) |
181 | { | 180 | { |
@@ -185,4 +184,3 @@ void iwl_leds_exit(struct iwl_priv *priv) | |||
185 | led_classdev_unregister(&priv->led); | 184 | led_classdev_unregister(&priv->led); |
186 | kfree(priv->led.name); | 185 | kfree(priv->led.name); |
187 | } | 186 | } |
188 | EXPORT_SYMBOL(iwl_leds_exit); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-legacy.c b/drivers/net/wireless/iwlwifi/iwl-legacy.c deleted file mode 100644 index e1ace3ce30b..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-legacy.c +++ /dev/null | |||
@@ -1,657 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | *****************************************************************************/ | ||
28 | |||
29 | #include <linux/kernel.h> | ||
30 | #include <net/mac80211.h> | ||
31 | |||
32 | #include "iwl-dev.h" | ||
33 | #include "iwl-core.h" | ||
34 | #include "iwl-helpers.h" | ||
35 | #include "iwl-legacy.h" | ||
36 | |||
37 | static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | ||
38 | { | ||
39 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
40 | return; | ||
41 | |||
42 | if (!ctx->is_active) | ||
43 | return; | ||
44 | |||
45 | ctx->qos_data.def_qos_parm.qos_flags = 0; | ||
46 | |||
47 | if (ctx->qos_data.qos_active) | ||
48 | ctx->qos_data.def_qos_parm.qos_flags |= | ||
49 | QOS_PARAM_FLG_UPDATE_EDCA_MSK; | ||
50 | |||
51 | if (ctx->ht.enabled) | ||
52 | ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; | ||
53 | |||
54 | IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", | ||
55 | ctx->qos_data.qos_active, | ||
56 | ctx->qos_data.def_qos_parm.qos_flags); | ||
57 | |||
58 | iwl_send_cmd_pdu_async(priv, ctx->qos_cmd, | ||
59 | sizeof(struct iwl_qosparam_cmd), | ||
60 | &ctx->qos_data.def_qos_parm, NULL); | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * iwl_legacy_mac_config - mac80211 config callback | ||
65 | */ | ||
66 | int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed) | ||
67 | { | ||
68 | struct iwl_priv *priv = hw->priv; | ||
69 | const struct iwl_channel_info *ch_info; | ||
70 | struct ieee80211_conf *conf = &hw->conf; | ||
71 | struct ieee80211_channel *channel = conf->channel; | ||
72 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | ||
73 | struct iwl_rxon_context *ctx; | ||
74 | unsigned long flags = 0; | ||
75 | int ret = 0; | ||
76 | u16 ch; | ||
77 | int scan_active = 0; | ||
78 | bool ht_changed[NUM_IWL_RXON_CTX] = {}; | ||
79 | |||
80 | if (WARN_ON(!priv->cfg->ops->legacy)) | ||
81 | return -EOPNOTSUPP; | ||
82 | |||
83 | mutex_lock(&priv->mutex); | ||
84 | |||
85 | IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", | ||
86 | channel->hw_value, changed); | ||
87 | |||
88 | if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { | ||
89 | scan_active = 1; | ||
90 | IWL_DEBUG_MAC80211(priv, "scan active\n"); | ||
91 | } | ||
92 | |||
93 | if (changed & (IEEE80211_CONF_CHANGE_SMPS | | ||
94 | IEEE80211_CONF_CHANGE_CHANNEL)) { | ||
95 | /* mac80211 uses static for non-HT which is what we want */ | ||
96 | priv->current_ht_config.smps = conf->smps_mode; | ||
97 | |||
98 | /* | ||
99 | * Recalculate chain counts. | ||
100 | * | ||
101 | * If monitor mode is enabled then mac80211 will | ||
102 | * set up the SM PS mode to OFF if an HT channel is | ||
103 | * configured. | ||
104 | */ | ||
105 | if (priv->cfg->ops->hcmd->set_rxon_chain) | ||
106 | for_each_context(priv, ctx) | ||
107 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); | ||
108 | } | ||
109 | |||
110 | /* during scanning mac80211 will delay channel setting until | ||
111 | * scan finish with changed = 0 | ||
112 | */ | ||
113 | if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) { | ||
114 | if (scan_active) | ||
115 | goto set_ch_out; | ||
116 | |||
117 | ch = channel->hw_value; | ||
118 | ch_info = iwl_get_channel_info(priv, channel->band, ch); | ||
119 | if (!is_channel_valid(ch_info)) { | ||
120 | IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); | ||
121 | ret = -EINVAL; | ||
122 | goto set_ch_out; | ||
123 | } | ||
124 | |||
125 | spin_lock_irqsave(&priv->lock, flags); | ||
126 | |||
127 | for_each_context(priv, ctx) { | ||
128 | /* Configure HT40 channels */ | ||
129 | if (ctx->ht.enabled != conf_is_ht(conf)) { | ||
130 | ctx->ht.enabled = conf_is_ht(conf); | ||
131 | ht_changed[ctx->ctxid] = true; | ||
132 | } | ||
133 | if (ctx->ht.enabled) { | ||
134 | if (conf_is_ht40_minus(conf)) { | ||
135 | ctx->ht.extension_chan_offset = | ||
136 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
137 | ctx->ht.is_40mhz = true; | ||
138 | } else if (conf_is_ht40_plus(conf)) { | ||
139 | ctx->ht.extension_chan_offset = | ||
140 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
141 | ctx->ht.is_40mhz = true; | ||
142 | } else { | ||
143 | ctx->ht.extension_chan_offset = | ||
144 | IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
145 | ctx->ht.is_40mhz = false; | ||
146 | } | ||
147 | } else | ||
148 | ctx->ht.is_40mhz = false; | ||
149 | |||
150 | /* | ||
151 | * Default to no protection. Protection mode will | ||
152 | * later be set from BSS config in iwl_ht_conf | ||
153 | */ | ||
154 | ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; | ||
155 | |||
156 | /* if we are switching from ht to 2.4 clear flags | ||
157 | * from any ht related info since 2.4 does not | ||
158 | * support ht */ | ||
159 | if ((le16_to_cpu(ctx->staging.channel) != ch)) | ||
160 | ctx->staging.flags = 0; | ||
161 | |||
162 | iwl_set_rxon_channel(priv, channel, ctx); | ||
163 | iwl_set_rxon_ht(priv, ht_conf); | ||
164 | |||
165 | iwl_set_flags_for_band(priv, ctx, channel->band, | ||
166 | ctx->vif); | ||
167 | } | ||
168 | |||
169 | spin_unlock_irqrestore(&priv->lock, flags); | ||
170 | |||
171 | if (priv->cfg->ops->legacy->update_bcast_stations) | ||
172 | ret = priv->cfg->ops->legacy->update_bcast_stations(priv); | ||
173 | |||
174 | set_ch_out: | ||
175 | /* The list of supported rates and rate mask can be different | ||
176 | * for each band; since the band may have changed, reset | ||
177 | * the rate mask to what mac80211 lists */ | ||
178 | iwl_set_rate(priv); | ||
179 | } | ||
180 | |||
181 | if (changed & (IEEE80211_CONF_CHANGE_PS | | ||
182 | IEEE80211_CONF_CHANGE_IDLE)) { | ||
183 | ret = iwl_power_update_mode(priv, false); | ||
184 | if (ret) | ||
185 | IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n"); | ||
186 | } | ||
187 | |||
188 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | ||
189 | IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", | ||
190 | priv->tx_power_user_lmt, conf->power_level); | ||
191 | |||
192 | iwl_set_tx_power(priv, conf->power_level, false); | ||
193 | } | ||
194 | |||
195 | if (!iwl_is_ready(priv)) { | ||
196 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); | ||
197 | goto out; | ||
198 | } | ||
199 | |||
200 | if (scan_active) | ||
201 | goto out; | ||
202 | |||
203 | for_each_context(priv, ctx) { | ||
204 | if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging))) | ||
205 | iwlcore_commit_rxon(priv, ctx); | ||
206 | else | ||
207 | IWL_DEBUG_INFO(priv, | ||
208 | "Not re-sending same RXON configuration.\n"); | ||
209 | if (ht_changed[ctx->ctxid]) | ||
210 | iwl_update_qos(priv, ctx); | ||
211 | } | ||
212 | |||
213 | out: | ||
214 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
215 | mutex_unlock(&priv->mutex); | ||
216 | return ret; | ||
217 | } | ||
218 | EXPORT_SYMBOL(iwl_legacy_mac_config); | ||
219 | |||
220 | void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw) | ||
221 | { | ||
222 | struct iwl_priv *priv = hw->priv; | ||
223 | unsigned long flags; | ||
224 | /* IBSS can only be the IWL_RXON_CTX_BSS context */ | ||
225 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
226 | |||
227 | if (WARN_ON(!priv->cfg->ops->legacy)) | ||
228 | return; | ||
229 | |||
230 | mutex_lock(&priv->mutex); | ||
231 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
232 | |||
233 | spin_lock_irqsave(&priv->lock, flags); | ||
234 | memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config)); | ||
235 | spin_unlock_irqrestore(&priv->lock, flags); | ||
236 | |||
237 | spin_lock_irqsave(&priv->lock, flags); | ||
238 | |||
239 | /* new association get rid of ibss beacon skb */ | ||
240 | if (priv->beacon_skb) | ||
241 | dev_kfree_skb(priv->beacon_skb); | ||
242 | |||
243 | priv->beacon_skb = NULL; | ||
244 | |||
245 | priv->timestamp = 0; | ||
246 | |||
247 | spin_unlock_irqrestore(&priv->lock, flags); | ||
248 | |||
249 | iwl_scan_cancel_timeout(priv, 100); | ||
250 | if (!iwl_is_ready_rf(priv)) { | ||
251 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); | ||
252 | mutex_unlock(&priv->mutex); | ||
253 | return; | ||
254 | } | ||
255 | |||
256 | /* we are restarting association process | ||
257 | * clear RXON_FILTER_ASSOC_MSK bit | ||
258 | */ | ||
259 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
260 | iwlcore_commit_rxon(priv, ctx); | ||
261 | |||
262 | iwl_set_rate(priv); | ||
263 | |||
264 | mutex_unlock(&priv->mutex); | ||
265 | |||
266 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
267 | } | ||
268 | EXPORT_SYMBOL(iwl_legacy_mac_reset_tsf); | ||
269 | |||
270 | static void iwl_ht_conf(struct iwl_priv *priv, | ||
271 | struct ieee80211_vif *vif) | ||
272 | { | ||
273 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | ||
274 | struct ieee80211_sta *sta; | ||
275 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
276 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | ||
277 | |||
278 | IWL_DEBUG_ASSOC(priv, "enter:\n"); | ||
279 | |||
280 | if (!ctx->ht.enabled) | ||
281 | return; | ||
282 | |||
283 | ctx->ht.protection = | ||
284 | bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; | ||
285 | ctx->ht.non_gf_sta_present = | ||
286 | !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | ||
287 | |||
288 | ht_conf->single_chain_sufficient = false; | ||
289 | |||
290 | switch (vif->type) { | ||
291 | case NL80211_IFTYPE_STATION: | ||
292 | rcu_read_lock(); | ||
293 | sta = ieee80211_find_sta(vif, bss_conf->bssid); | ||
294 | if (sta) { | ||
295 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
296 | int maxstreams; | ||
297 | |||
298 | maxstreams = (ht_cap->mcs.tx_params & | ||
299 | IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) | ||
300 | >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; | ||
301 | maxstreams += 1; | ||
302 | |||
303 | if ((ht_cap->mcs.rx_mask[1] == 0) && | ||
304 | (ht_cap->mcs.rx_mask[2] == 0)) | ||
305 | ht_conf->single_chain_sufficient = true; | ||
306 | if (maxstreams <= 1) | ||
307 | ht_conf->single_chain_sufficient = true; | ||
308 | } else { | ||
309 | /* | ||
310 | * If at all, this can only happen through a race | ||
311 | * when the AP disconnects us while we're still | ||
312 | * setting up the connection, in that case mac80211 | ||
313 | * will soon tell us about that. | ||
314 | */ | ||
315 | ht_conf->single_chain_sufficient = true; | ||
316 | } | ||
317 | rcu_read_unlock(); | ||
318 | break; | ||
319 | case NL80211_IFTYPE_ADHOC: | ||
320 | ht_conf->single_chain_sufficient = true; | ||
321 | break; | ||
322 | default: | ||
323 | break; | ||
324 | } | ||
325 | |||
326 | IWL_DEBUG_ASSOC(priv, "leave\n"); | ||
327 | } | ||
328 | |||
329 | static inline void iwl_set_no_assoc(struct iwl_priv *priv, | ||
330 | struct ieee80211_vif *vif) | ||
331 | { | ||
332 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | ||
333 | |||
334 | /* | ||
335 | * inform the ucode that there is no longer an | ||
336 | * association and that no more packets should be | ||
337 | * sent | ||
338 | */ | ||
339 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
340 | ctx->staging.assoc_id = 0; | ||
341 | iwlcore_commit_rxon(priv, ctx); | ||
342 | } | ||
343 | |||
344 | static void iwlcore_beacon_update(struct ieee80211_hw *hw, | ||
345 | struct ieee80211_vif *vif) | ||
346 | { | ||
347 | struct iwl_priv *priv = hw->priv; | ||
348 | unsigned long flags; | ||
349 | __le64 timestamp; | ||
350 | struct sk_buff *skb = ieee80211_beacon_get(hw, vif); | ||
351 | |||
352 | if (!skb) | ||
353 | return; | ||
354 | |||
355 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
356 | |||
357 | lockdep_assert_held(&priv->mutex); | ||
358 | |||
359 | if (!priv->beacon_ctx) { | ||
360 | IWL_ERR(priv, "update beacon but no beacon context!\n"); | ||
361 | dev_kfree_skb(skb); | ||
362 | return; | ||
363 | } | ||
364 | |||
365 | spin_lock_irqsave(&priv->lock, flags); | ||
366 | |||
367 | if (priv->beacon_skb) | ||
368 | dev_kfree_skb(priv->beacon_skb); | ||
369 | |||
370 | priv->beacon_skb = skb; | ||
371 | |||
372 | timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; | ||
373 | priv->timestamp = le64_to_cpu(timestamp); | ||
374 | |||
375 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
376 | spin_unlock_irqrestore(&priv->lock, flags); | ||
377 | |||
378 | if (!iwl_is_ready_rf(priv)) { | ||
379 | IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); | ||
380 | return; | ||
381 | } | ||
382 | |||
383 | priv->cfg->ops->legacy->post_associate(priv); | ||
384 | } | ||
385 | |||
386 | void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw, | ||
387 | struct ieee80211_vif *vif, | ||
388 | struct ieee80211_bss_conf *bss_conf, | ||
389 | u32 changes) | ||
390 | { | ||
391 | struct iwl_priv *priv = hw->priv; | ||
392 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | ||
393 | int ret; | ||
394 | |||
395 | if (WARN_ON(!priv->cfg->ops->legacy)) | ||
396 | return; | ||
397 | |||
398 | IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); | ||
399 | |||
400 | if (!iwl_is_alive(priv)) | ||
401 | return; | ||
402 | |||
403 | mutex_lock(&priv->mutex); | ||
404 | |||
405 | if (changes & BSS_CHANGED_QOS) { | ||
406 | unsigned long flags; | ||
407 | |||
408 | spin_lock_irqsave(&priv->lock, flags); | ||
409 | ctx->qos_data.qos_active = bss_conf->qos; | ||
410 | iwl_update_qos(priv, ctx); | ||
411 | spin_unlock_irqrestore(&priv->lock, flags); | ||
412 | } | ||
413 | |||
414 | if (changes & BSS_CHANGED_BEACON_ENABLED) { | ||
415 | /* | ||
416 | * the add_interface code must make sure we only ever | ||
417 | * have a single interface that could be beaconing at | ||
418 | * any time. | ||
419 | */ | ||
420 | if (vif->bss_conf.enable_beacon) | ||
421 | priv->beacon_ctx = ctx; | ||
422 | else | ||
423 | priv->beacon_ctx = NULL; | ||
424 | } | ||
425 | |||
426 | if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) { | ||
427 | dev_kfree_skb(priv->beacon_skb); | ||
428 | priv->beacon_skb = ieee80211_beacon_get(hw, vif); | ||
429 | } | ||
430 | |||
431 | if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP) | ||
432 | iwl_send_rxon_timing(priv, ctx); | ||
433 | |||
434 | if (changes & BSS_CHANGED_BSSID) { | ||
435 | IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid); | ||
436 | |||
437 | /* | ||
438 | * If there is currently a HW scan going on in the | ||
439 | * background then we need to cancel it else the RXON | ||
440 | * below/in post_associate will fail. | ||
441 | */ | ||
442 | if (iwl_scan_cancel_timeout(priv, 100)) { | ||
443 | IWL_WARN(priv, "Aborted scan still in progress after 100ms\n"); | ||
444 | IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); | ||
445 | mutex_unlock(&priv->mutex); | ||
446 | return; | ||
447 | } | ||
448 | |||
449 | /* mac80211 only sets assoc when in STATION mode */ | ||
450 | if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) { | ||
451 | memcpy(ctx->staging.bssid_addr, | ||
452 | bss_conf->bssid, ETH_ALEN); | ||
453 | |||
454 | /* currently needed in a few places */ | ||
455 | memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); | ||
456 | } else { | ||
457 | ctx->staging.filter_flags &= | ||
458 | ~RXON_FILTER_ASSOC_MSK; | ||
459 | } | ||
460 | |||
461 | } | ||
462 | |||
463 | /* | ||
464 | * This needs to be after setting the BSSID in case | ||
465 | * mac80211 decides to do both changes at once because | ||
466 | * it will invoke post_associate. | ||
467 | */ | ||
468 | if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON) | ||
469 | iwlcore_beacon_update(hw, vif); | ||
470 | |||
471 | if (changes & BSS_CHANGED_ERP_PREAMBLE) { | ||
472 | IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", | ||
473 | bss_conf->use_short_preamble); | ||
474 | if (bss_conf->use_short_preamble) | ||
475 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | ||
476 | else | ||
477 | ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | ||
478 | } | ||
479 | |||
480 | if (changes & BSS_CHANGED_ERP_CTS_PROT) { | ||
481 | IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot); | ||
482 | if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) | ||
483 | ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; | ||
484 | else | ||
485 | ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; | ||
486 | if (bss_conf->use_cts_prot) | ||
487 | ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; | ||
488 | else | ||
489 | ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN; | ||
490 | } | ||
491 | |||
492 | if (changes & BSS_CHANGED_BASIC_RATES) { | ||
493 | /* XXX use this information | ||
494 | * | ||
495 | * To do that, remove code from iwl_set_rate() and put something | ||
496 | * like this here: | ||
497 | * | ||
498 | if (A-band) | ||
499 | ctx->staging.ofdm_basic_rates = | ||
500 | bss_conf->basic_rates; | ||
501 | else | ||
502 | ctx->staging.ofdm_basic_rates = | ||
503 | bss_conf->basic_rates >> 4; | ||
504 | ctx->staging.cck_basic_rates = | ||
505 | bss_conf->basic_rates & 0xF; | ||
506 | */ | ||
507 | } | ||
508 | |||
509 | if (changes & BSS_CHANGED_HT) { | ||
510 | iwl_ht_conf(priv, vif); | ||
511 | |||
512 | if (priv->cfg->ops->hcmd->set_rxon_chain) | ||
513 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); | ||
514 | } | ||
515 | |||
516 | if (changes & BSS_CHANGED_ASSOC) { | ||
517 | IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); | ||
518 | if (bss_conf->assoc) { | ||
519 | priv->timestamp = bss_conf->timestamp; | ||
520 | |||
521 | if (!iwl_is_rfkill(priv)) | ||
522 | priv->cfg->ops->legacy->post_associate(priv); | ||
523 | } else | ||
524 | iwl_set_no_assoc(priv, vif); | ||
525 | } | ||
526 | |||
527 | if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) { | ||
528 | IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n", | ||
529 | changes); | ||
530 | ret = iwl_send_rxon_assoc(priv, ctx); | ||
531 | if (!ret) { | ||
532 | /* Sync active_rxon with latest change. */ | ||
533 | memcpy((void *)&ctx->active, | ||
534 | &ctx->staging, | ||
535 | sizeof(struct iwl_rxon_cmd)); | ||
536 | } | ||
537 | } | ||
538 | |||
539 | if (changes & BSS_CHANGED_BEACON_ENABLED) { | ||
540 | if (vif->bss_conf.enable_beacon) { | ||
541 | memcpy(ctx->staging.bssid_addr, | ||
542 | bss_conf->bssid, ETH_ALEN); | ||
543 | memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); | ||
544 | priv->cfg->ops->legacy->config_ap(priv); | ||
545 | } else | ||
546 | iwl_set_no_assoc(priv, vif); | ||
547 | } | ||
548 | |||
549 | if (changes & BSS_CHANGED_IBSS) { | ||
550 | ret = priv->cfg->ops->legacy->manage_ibss_station(priv, vif, | ||
551 | bss_conf->ibss_joined); | ||
552 | if (ret) | ||
553 | IWL_ERR(priv, "failed to %s IBSS station %pM\n", | ||
554 | bss_conf->ibss_joined ? "add" : "remove", | ||
555 | bss_conf->bssid); | ||
556 | } | ||
557 | |||
558 | mutex_unlock(&priv->mutex); | ||
559 | |||
560 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
561 | } | ||
562 | EXPORT_SYMBOL(iwl_legacy_mac_bss_info_changed); | ||
563 | |||
564 | irqreturn_t iwl_isr_legacy(int irq, void *data) | ||
565 | { | ||
566 | struct iwl_priv *priv = data; | ||
567 | u32 inta, inta_mask; | ||
568 | u32 inta_fh; | ||
569 | unsigned long flags; | ||
570 | if (!priv) | ||
571 | return IRQ_NONE; | ||
572 | |||
573 | spin_lock_irqsave(&priv->lock, flags); | ||
574 | |||
575 | /* Disable (but don't clear!) interrupts here to avoid | ||
576 | * back-to-back ISRs and sporadic interrupts from our NIC. | ||
577 | * If we have something to service, the tasklet will re-enable ints. | ||
578 | * If we *don't* have something, we'll re-enable before leaving here. */ | ||
579 | inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ | ||
580 | iwl_write32(priv, CSR_INT_MASK, 0x00000000); | ||
581 | |||
582 | /* Discover which interrupts are active/pending */ | ||
583 | inta = iwl_read32(priv, CSR_INT); | ||
584 | inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); | ||
585 | |||
586 | /* Ignore interrupt if there's nothing in NIC to service. | ||
587 | * This may be due to IRQ shared with another device, | ||
588 | * or due to sporadic interrupts thrown from our NIC. */ | ||
589 | if (!inta && !inta_fh) { | ||
590 | IWL_DEBUG_ISR(priv, | ||
591 | "Ignore interrupt, inta == 0, inta_fh == 0\n"); | ||
592 | goto none; | ||
593 | } | ||
594 | |||
595 | if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { | ||
596 | /* Hardware disappeared. It might have already raised | ||
597 | * an interrupt */ | ||
598 | IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); | ||
599 | goto unplugged; | ||
600 | } | ||
601 | |||
602 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", | ||
603 | inta, inta_mask, inta_fh); | ||
604 | |||
605 | inta &= ~CSR_INT_BIT_SCD; | ||
606 | |||
607 | /* iwl_irq_tasklet() will service interrupts and re-enable them */ | ||
608 | if (likely(inta || inta_fh)) | ||
609 | tasklet_schedule(&priv->irq_tasklet); | ||
610 | |||
611 | unplugged: | ||
612 | spin_unlock_irqrestore(&priv->lock, flags); | ||
613 | return IRQ_HANDLED; | ||
614 | |||
615 | none: | ||
616 | /* re-enable interrupts here since we don't have anything to service. */ | ||
617 | /* only Re-enable if disabled by irq */ | ||
618 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) | ||
619 | iwl_enable_interrupts(priv); | ||
620 | spin_unlock_irqrestore(&priv->lock, flags); | ||
621 | return IRQ_NONE; | ||
622 | } | ||
623 | EXPORT_SYMBOL(iwl_isr_legacy); | ||
624 | |||
625 | /* | ||
626 | * iwl_legacy_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this | ||
627 | * function. | ||
628 | */ | ||
629 | void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv, | ||
630 | struct ieee80211_tx_info *info, | ||
631 | __le16 fc, __le32 *tx_flags) | ||
632 | { | ||
633 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { | ||
634 | *tx_flags |= TX_CMD_FLG_RTS_MSK; | ||
635 | *tx_flags &= ~TX_CMD_FLG_CTS_MSK; | ||
636 | *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | ||
637 | |||
638 | if (!ieee80211_is_mgmt(fc)) | ||
639 | return; | ||
640 | |||
641 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { | ||
642 | case cpu_to_le16(IEEE80211_STYPE_AUTH): | ||
643 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): | ||
644 | case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): | ||
645 | case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): | ||
646 | *tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
647 | *tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
648 | break; | ||
649 | } | ||
650 | } else if (info->control.rates[0].flags & | ||
651 | IEEE80211_TX_RC_USE_CTS_PROTECT) { | ||
652 | *tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
653 | *tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
654 | *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | ||
655 | } | ||
656 | } | ||
657 | EXPORT_SYMBOL(iwl_legacy_tx_cmd_protection); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-legacy.h b/drivers/net/wireless/iwlwifi/iwl-legacy.h deleted file mode 100644 index 9f7b2f93596..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-legacy.h +++ /dev/null | |||
@@ -1,79 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | #ifndef __iwl_legacy_h__ | ||
64 | #define __iwl_legacy_h__ | ||
65 | |||
66 | /* mac80211 handlers */ | ||
67 | int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed); | ||
68 | void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw); | ||
69 | void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw, | ||
70 | struct ieee80211_vif *vif, | ||
71 | struct ieee80211_bss_conf *bss_conf, | ||
72 | u32 changes); | ||
73 | void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv, | ||
74 | struct ieee80211_tx_info *info, | ||
75 | __le16 fc, __le32 *tx_flags); | ||
76 | |||
77 | irqreturn_t iwl_isr_legacy(int irq, void *data); | ||
78 | |||
79 | #endif /* __iwl_legacy_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 1d1bf3234d8..576795e2c75 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -425,7 +425,6 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, | |||
425 | 425 | ||
426 | return ret; | 426 | return ret; |
427 | } | 427 | } |
428 | EXPORT_SYMBOL(iwl_power_set_mode); | ||
429 | 428 | ||
430 | int iwl_power_update_mode(struct iwl_priv *priv, bool force) | 429 | int iwl_power_update_mode(struct iwl_priv *priv, bool force) |
431 | { | 430 | { |
@@ -434,7 +433,6 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) | |||
434 | iwl_power_build_cmd(priv, &cmd); | 433 | iwl_power_build_cmd(priv, &cmd); |
435 | return iwl_power_set_mode(priv, &cmd, force); | 434 | return iwl_power_set_mode(priv, &cmd, force); |
436 | } | 435 | } |
437 | EXPORT_SYMBOL(iwl_power_update_mode); | ||
438 | 436 | ||
439 | /* initialize to default */ | 437 | /* initialize to default */ |
440 | void iwl_power_initialize(struct iwl_priv *priv) | 438 | void iwl_power_initialize(struct iwl_priv *priv) |
@@ -448,4 +446,3 @@ void iwl_power_initialize(struct iwl_priv *priv) | |||
448 | memset(&priv->power_data.sleep_cmd, 0, | 446 | memset(&priv->power_data.sleep_cmd, 0, |
449 | sizeof(priv->power_data.sleep_cmd)); | 447 | sizeof(priv->power_data.sleep_cmd)); |
450 | } | 448 | } |
451 | EXPORT_SYMBOL(iwl_power_initialize); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index bc89393fb69..a21f6fe10fb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -118,7 +118,6 @@ int iwl_rx_queue_space(const struct iwl_rx_queue *q) | |||
118 | s = 0; | 118 | s = 0; |
119 | return s; | 119 | return s; |
120 | } | 120 | } |
121 | EXPORT_SYMBOL(iwl_rx_queue_space); | ||
122 | 121 | ||
123 | /** | 122 | /** |
124 | * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue | 123 | * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue |
@@ -170,7 +169,6 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q | |||
170 | exit_unlock: | 169 | exit_unlock: |
171 | spin_unlock_irqrestore(&q->lock, flags); | 170 | spin_unlock_irqrestore(&q->lock, flags); |
172 | } | 171 | } |
173 | EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); | ||
174 | 172 | ||
175 | int iwl_rx_queue_alloc(struct iwl_priv *priv) | 173 | int iwl_rx_queue_alloc(struct iwl_priv *priv) |
176 | { | 174 | { |
@@ -211,7 +209,6 @@ err_rb: | |||
211 | err_bd: | 209 | err_bd: |
212 | return -ENOMEM; | 210 | return -ENOMEM; |
213 | } | 211 | } |
214 | EXPORT_SYMBOL(iwl_rx_queue_alloc); | ||
215 | 212 | ||
216 | 213 | ||
217 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | 214 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, |
@@ -229,7 +226,6 @@ void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | |||
229 | memcpy(&priv->measure_report, report, sizeof(*report)); | 226 | memcpy(&priv->measure_report, report, sizeof(*report)); |
230 | priv->measurement_status |= MEASUREMENT_READY; | 227 | priv->measurement_status |= MEASUREMENT_READY; |
231 | } | 228 | } |
232 | EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif); | ||
233 | 229 | ||
234 | void iwl_recover_from_statistics(struct iwl_priv *priv, | 230 | void iwl_recover_from_statistics(struct iwl_priv *priv, |
235 | struct iwl_rx_packet *pkt) | 231 | struct iwl_rx_packet *pkt) |
@@ -249,7 +245,6 @@ void iwl_recover_from_statistics(struct iwl_priv *priv, | |||
249 | !priv->cfg->ops->lib->check_plcp_health(priv, pkt)) | 245 | !priv->cfg->ops->lib->check_plcp_health(priv, pkt)) |
250 | iwl_force_reset(priv, IWL_RF_RESET, false); | 246 | iwl_force_reset(priv, IWL_RF_RESET, false); |
251 | } | 247 | } |
252 | EXPORT_SYMBOL(iwl_recover_from_statistics); | ||
253 | 248 | ||
254 | /* | 249 | /* |
255 | * returns non-zero if packet should be dropped | 250 | * returns non-zero if packet should be dropped |
@@ -302,4 +297,3 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, | |||
302 | } | 297 | } |
303 | return 0; | 298 | return 0; |
304 | } | 299 | } |
305 | EXPORT_SYMBOL(iwl_set_decrypted_flag); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 08f1bea8b65..faa6d34cb65 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -155,7 +155,6 @@ int iwl_scan_cancel(struct iwl_priv *priv) | |||
155 | queue_work(priv->workqueue, &priv->abort_scan); | 155 | queue_work(priv->workqueue, &priv->abort_scan); |
156 | return 0; | 156 | return 0; |
157 | } | 157 | } |
158 | EXPORT_SYMBOL(iwl_scan_cancel); | ||
159 | 158 | ||
160 | /** | 159 | /** |
161 | * iwl_scan_cancel_timeout - Cancel any currently executing HW scan | 160 | * iwl_scan_cancel_timeout - Cancel any currently executing HW scan |
@@ -180,7 +179,6 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) | |||
180 | 179 | ||
181 | return test_bit(STATUS_SCAN_HW, &priv->status); | 180 | return test_bit(STATUS_SCAN_HW, &priv->status); |
182 | } | 181 | } |
183 | EXPORT_SYMBOL(iwl_scan_cancel_timeout); | ||
184 | 182 | ||
185 | /* Service response to REPLY_SCAN_CMD (0x80) */ | 183 | /* Service response to REPLY_SCAN_CMD (0x80) */ |
186 | static void iwl_rx_reply_scan(struct iwl_priv *priv, | 184 | static void iwl_rx_reply_scan(struct iwl_priv *priv, |
@@ -288,7 +286,6 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) | |||
288 | priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] = | 286 | priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] = |
289 | iwl_rx_scan_complete_notif; | 287 | iwl_rx_scan_complete_notif; |
290 | } | 288 | } |
291 | EXPORT_SYMBOL(iwl_setup_rx_scan_handlers); | ||
292 | 289 | ||
293 | inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, | 290 | inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, |
294 | enum ieee80211_band band, | 291 | enum ieee80211_band band, |
@@ -301,7 +298,6 @@ inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, | |||
301 | return IWL_ACTIVE_DWELL_TIME_24 + | 298 | return IWL_ACTIVE_DWELL_TIME_24 + |
302 | IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); | 299 | IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); |
303 | } | 300 | } |
304 | EXPORT_SYMBOL(iwl_get_active_dwell_time); | ||
305 | 301 | ||
306 | u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | 302 | u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, |
307 | enum ieee80211_band band, | 303 | enum ieee80211_band band, |
@@ -333,7 +329,6 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | |||
333 | 329 | ||
334 | return passive; | 330 | return passive; |
335 | } | 331 | } |
336 | EXPORT_SYMBOL(iwl_get_passive_dwell_time); | ||
337 | 332 | ||
338 | void iwl_init_scan_params(struct iwl_priv *priv) | 333 | void iwl_init_scan_params(struct iwl_priv *priv) |
339 | { | 334 | { |
@@ -343,7 +338,6 @@ void iwl_init_scan_params(struct iwl_priv *priv) | |||
343 | if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) | 338 | if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) |
344 | priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx; | 339 | priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx; |
345 | } | 340 | } |
346 | EXPORT_SYMBOL(iwl_init_scan_params); | ||
347 | 341 | ||
348 | static int __must_check iwl_scan_initiate(struct iwl_priv *priv, | 342 | static int __must_check iwl_scan_initiate(struct iwl_priv *priv, |
349 | struct ieee80211_vif *vif, | 343 | struct ieee80211_vif *vif, |
@@ -439,7 +433,6 @@ out_unlock: | |||
439 | 433 | ||
440 | return ret; | 434 | return ret; |
441 | } | 435 | } |
442 | EXPORT_SYMBOL(iwl_mac_hw_scan); | ||
443 | 436 | ||
444 | /* | 437 | /* |
445 | * internal short scan, this function should only been called while associated. | 438 | * internal short scan, this function should only been called while associated. |
@@ -536,7 +529,6 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | |||
536 | 529 | ||
537 | return (u16)len; | 530 | return (u16)len; |
538 | } | 531 | } |
539 | EXPORT_SYMBOL(iwl_fill_probe_req); | ||
540 | 532 | ||
541 | static void iwl_bg_abort_scan(struct work_struct *work) | 533 | static void iwl_bg_abort_scan(struct work_struct *work) |
542 | { | 534 | { |
@@ -621,7 +613,6 @@ void iwl_setup_scan_deferred_work(struct iwl_priv *priv) | |||
621 | INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan); | 613 | INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan); |
622 | INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); | 614 | INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); |
623 | } | 615 | } |
624 | EXPORT_SYMBOL(iwl_setup_scan_deferred_work); | ||
625 | 616 | ||
626 | void iwl_cancel_scan_deferred_work(struct iwl_priv *priv) | 617 | void iwl_cancel_scan_deferred_work(struct iwl_priv *priv) |
627 | { | 618 | { |
@@ -635,4 +626,3 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv) | |||
635 | mutex_unlock(&priv->mutex); | 626 | mutex_unlock(&priv->mutex); |
636 | } | 627 | } |
637 | } | 628 | } |
638 | EXPORT_SYMBOL(iwl_cancel_scan_deferred_work); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 49493d17651..bc90a12408a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -169,7 +169,6 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
169 | 169 | ||
170 | return ret; | 170 | return ret; |
171 | } | 171 | } |
172 | EXPORT_SYMBOL(iwl_send_add_sta); | ||
173 | 172 | ||
174 | static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, | 173 | static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, |
175 | struct ieee80211_sta *sta, | 174 | struct ieee80211_sta *sta, |
@@ -316,7 +315,6 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | |||
316 | return sta_id; | 315 | return sta_id; |
317 | 316 | ||
318 | } | 317 | } |
319 | EXPORT_SYMBOL_GPL(iwl_prep_station); | ||
320 | 318 | ||
321 | #define STA_WAIT_TIMEOUT (HZ/2) | 319 | #define STA_WAIT_TIMEOUT (HZ/2) |
322 | 320 | ||
@@ -379,7 +377,6 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | |||
379 | *sta_id_r = sta_id; | 377 | *sta_id_r = sta_id; |
380 | return ret; | 378 | return ret; |
381 | } | 379 | } |
382 | EXPORT_SYMBOL(iwl_add_station_common); | ||
383 | 380 | ||
384 | /** | 381 | /** |
385 | * iwl_sta_ucode_deactivate - deactivate ucode status for a station | 382 | * iwl_sta_ucode_deactivate - deactivate ucode status for a station |
@@ -513,7 +510,6 @@ out_err: | |||
513 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 510 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
514 | return -EINVAL; | 511 | return -EINVAL; |
515 | } | 512 | } |
516 | EXPORT_SYMBOL_GPL(iwl_remove_station); | ||
517 | 513 | ||
518 | /** | 514 | /** |
519 | * iwl_clear_ucode_stations - clear ucode station table bits | 515 | * iwl_clear_ucode_stations - clear ucode station table bits |
@@ -548,7 +544,6 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv, | |||
548 | if (!cleared) | 544 | if (!cleared) |
549 | IWL_DEBUG_INFO(priv, "No active stations found to be cleared\n"); | 545 | IWL_DEBUG_INFO(priv, "No active stations found to be cleared\n"); |
550 | } | 546 | } |
551 | EXPORT_SYMBOL(iwl_clear_ucode_stations); | ||
552 | 547 | ||
553 | /** | 548 | /** |
554 | * iwl_restore_stations() - Restore driver known stations to device | 549 | * iwl_restore_stations() - Restore driver known stations to device |
@@ -625,7 +620,6 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
625 | else | 620 | else |
626 | IWL_DEBUG_INFO(priv, "Restoring all known stations .... complete.\n"); | 621 | IWL_DEBUG_INFO(priv, "Restoring all known stations .... complete.\n"); |
627 | } | 622 | } |
628 | EXPORT_SYMBOL(iwl_restore_stations); | ||
629 | 623 | ||
630 | void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | 624 | void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) |
631 | { | 625 | { |
@@ -668,7 +662,6 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
668 | priv->stations[sta_id].sta.sta.addr, ret); | 662 | priv->stations[sta_id].sta.sta.addr, ret); |
669 | iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); | 663 | iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); |
670 | } | 664 | } |
671 | EXPORT_SYMBOL(iwl_reprogram_ap_sta); | ||
672 | 665 | ||
673 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv) | 666 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv) |
674 | { | 667 | { |
@@ -680,7 +673,6 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv) | |||
680 | 673 | ||
681 | return WEP_INVALID_OFFSET; | 674 | return WEP_INVALID_OFFSET; |
682 | } | 675 | } |
683 | EXPORT_SYMBOL(iwl_get_free_ucode_key_index); | ||
684 | 676 | ||
685 | void iwl_dealloc_bcast_stations(struct iwl_priv *priv) | 677 | void iwl_dealloc_bcast_stations(struct iwl_priv *priv) |
686 | { | 678 | { |
@@ -700,7 +692,6 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv) | |||
700 | } | 692 | } |
701 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 693 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
702 | } | 694 | } |
703 | EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_stations); | ||
704 | 695 | ||
705 | #ifdef CONFIG_IWLWIFI_DEBUG | 696 | #ifdef CONFIG_IWLWIFI_DEBUG |
706 | static void iwl_dump_lq_cmd(struct iwl_priv *priv, | 697 | static void iwl_dump_lq_cmd(struct iwl_priv *priv, |
@@ -810,7 +801,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | |||
810 | } | 801 | } |
811 | return ret; | 802 | return ret; |
812 | } | 803 | } |
813 | EXPORT_SYMBOL(iwl_send_lq_cmd); | ||
814 | 804 | ||
815 | int iwl_mac_sta_remove(struct ieee80211_hw *hw, | 805 | int iwl_mac_sta_remove(struct ieee80211_hw *hw, |
816 | struct ieee80211_vif *vif, | 806 | struct ieee80211_vif *vif, |
@@ -832,4 +822,3 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw, | |||
832 | mutex_unlock(&priv->mutex); | 822 | mutex_unlock(&priv->mutex); |
833 | return ret; | 823 | return ret; |
834 | } | 824 | } |
835 | EXPORT_SYMBOL(iwl_mac_sta_remove); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 073b6ce6141..7e607d39da1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -84,7 +84,6 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
84 | } | 84 | } |
85 | txq->need_update = 0; | 85 | txq->need_update = 0; |
86 | } | 86 | } |
87 | EXPORT_SYMBOL(iwl_txq_update_write_ptr); | ||
88 | 87 | ||
89 | /** | 88 | /** |
90 | * iwl_tx_queue_free - Deallocate DMA queue. | 89 | * iwl_tx_queue_free - Deallocate DMA queue. |
@@ -131,7 +130,6 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) | |||
131 | /* 0-fill queue descriptor structure */ | 130 | /* 0-fill queue descriptor structure */ |
132 | memset(txq, 0, sizeof(*txq)); | 131 | memset(txq, 0, sizeof(*txq)); |
133 | } | 132 | } |
134 | EXPORT_SYMBOL(iwl_tx_queue_free); | ||
135 | 133 | ||
136 | /** | 134 | /** |
137 | * iwl_cmd_queue_free - Deallocate DMA queue. | 135 | * iwl_cmd_queue_free - Deallocate DMA queue. |
@@ -193,7 +191,6 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) | |||
193 | /* 0-fill queue descriptor structure */ | 191 | /* 0-fill queue descriptor structure */ |
194 | memset(txq, 0, sizeof(*txq)); | 192 | memset(txq, 0, sizeof(*txq)); |
195 | } | 193 | } |
196 | EXPORT_SYMBOL(iwl_cmd_queue_free); | ||
197 | 194 | ||
198 | /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** | 195 | /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** |
199 | * DMA services | 196 | * DMA services |
@@ -233,7 +230,6 @@ int iwl_queue_space(const struct iwl_queue *q) | |||
233 | s = 0; | 230 | s = 0; |
234 | return s; | 231 | return s; |
235 | } | 232 | } |
236 | EXPORT_SYMBOL(iwl_queue_space); | ||
237 | 233 | ||
238 | 234 | ||
239 | /** | 235 | /** |
@@ -384,7 +380,6 @@ out_free_arrays: | |||
384 | 380 | ||
385 | return -ENOMEM; | 381 | return -ENOMEM; |
386 | } | 382 | } |
387 | EXPORT_SYMBOL(iwl_tx_queue_init); | ||
388 | 383 | ||
389 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | 384 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, |
390 | int slots_num, u32 txq_id) | 385 | int slots_num, u32 txq_id) |
@@ -404,7 +399,6 @@ void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | |||
404 | /* Tell device where to find queue */ | 399 | /* Tell device where to find queue */ |
405 | priv->cfg->ops->lib->txq_init(priv, txq); | 400 | priv->cfg->ops->lib->txq_init(priv, txq); |
406 | } | 401 | } |
407 | EXPORT_SYMBOL(iwl_tx_queue_reset); | ||
408 | 402 | ||
409 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ | 403 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ |
410 | 404 | ||
@@ -641,4 +635,3 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
641 | } | 635 | } |
642 | meta->flags = 0; | 636 | meta->flags = 0; |
643 | } | 637 | } |
644 | EXPORT_SYMBOL(iwl_tx_cmd_complete); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c deleted file mode 100644 index adcef735180..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ /dev/null | |||
@@ -1,4334 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * Portions of this file are derived from the ipw3945 project, as well | ||
6 | * as portions of the ieee80211 subsystem header files. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of version 2 of the GNU General Public License as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution in the | ||
22 | * file called LICENSE. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
31 | |||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <linux/pci.h> | ||
36 | #include <linux/pci-aspm.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/dma-mapping.h> | ||
39 | #include <linux/delay.h> | ||
40 | #include <linux/sched.h> | ||
41 | #include <linux/skbuff.h> | ||
42 | #include <linux/netdevice.h> | ||
43 | #include <linux/wireless.h> | ||
44 | #include <linux/firmware.h> | ||
45 | #include <linux/etherdevice.h> | ||
46 | #include <linux/if_arp.h> | ||
47 | |||
48 | #include <net/ieee80211_radiotap.h> | ||
49 | #include <net/mac80211.h> | ||
50 | |||
51 | #include <asm/div64.h> | ||
52 | |||
53 | #define DRV_NAME "iwl3945" | ||
54 | |||
55 | #include "iwl-fh.h" | ||
56 | #include "iwl-3945-fh.h" | ||
57 | #include "iwl-commands.h" | ||
58 | #include "iwl-sta.h" | ||
59 | #include "iwl-3945.h" | ||
60 | #include "iwl-core.h" | ||
61 | #include "iwl-helpers.h" | ||
62 | #include "iwl-dev.h" | ||
63 | #include "iwl-spectrum.h" | ||
64 | #include "iwl-legacy.h" | ||
65 | |||
66 | /* | ||
67 | * module name, copyright, version, etc. | ||
68 | */ | ||
69 | |||
70 | #define DRV_DESCRIPTION \ | ||
71 | "Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux" | ||
72 | |||
73 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
74 | #define VD "d" | ||
75 | #else | ||
76 | #define VD | ||
77 | #endif | ||
78 | |||
79 | /* | ||
80 | * add "s" to indicate spectrum measurement included. | ||
81 | * we add it here to be consistent with previous releases in which | ||
82 | * this was configurable. | ||
83 | */ | ||
84 | #define DRV_VERSION IWLWIFI_VERSION VD "s" | ||
85 | #define DRV_COPYRIGHT "Copyright(c) 2003-2010 Intel Corporation" | ||
86 | #define DRV_AUTHOR "<ilw@linux.intel.com>" | ||
87 | |||
88 | MODULE_DESCRIPTION(DRV_DESCRIPTION); | ||
89 | MODULE_VERSION(DRV_VERSION); | ||
90 | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | ||
91 | MODULE_LICENSE("GPL"); | ||
92 | |||
93 | /* module parameters */ | ||
94 | struct iwl_mod_params iwl3945_mod_params = { | ||
95 | .sw_crypto = 1, | ||
96 | .restart_fw = 1, | ||
97 | /* the rest are 0 by default */ | ||
98 | }; | ||
99 | |||
100 | /** | ||
101 | * iwl3945_get_antenna_flags - Get antenna flags for RXON command | ||
102 | * @priv: eeprom and antenna fields are used to determine antenna flags | ||
103 | * | ||
104 | * priv->eeprom39 is used to determine if antenna AUX/MAIN are reversed | ||
105 | * iwl3945_mod_params.antenna specifies the antenna diversity mode: | ||
106 | * | ||
107 | * IWL_ANTENNA_DIVERSITY - NIC selects best antenna by itself | ||
108 | * IWL_ANTENNA_MAIN - Force MAIN antenna | ||
109 | * IWL_ANTENNA_AUX - Force AUX antenna | ||
110 | */ | ||
111 | __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv) | ||
112 | { | ||
113 | struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; | ||
114 | |||
115 | switch (iwl3945_mod_params.antenna) { | ||
116 | case IWL_ANTENNA_DIVERSITY: | ||
117 | return 0; | ||
118 | |||
119 | case IWL_ANTENNA_MAIN: | ||
120 | if (eeprom->antenna_switch_type) | ||
121 | return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK; | ||
122 | return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK; | ||
123 | |||
124 | case IWL_ANTENNA_AUX: | ||
125 | if (eeprom->antenna_switch_type) | ||
126 | return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK; | ||
127 | return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK; | ||
128 | } | ||
129 | |||
130 | /* bad antenna selector value */ | ||
131 | IWL_ERR(priv, "Bad antenna selector value (0x%x)\n", | ||
132 | iwl3945_mod_params.antenna); | ||
133 | |||
134 | return 0; /* "diversity" is default if error */ | ||
135 | } | ||
136 | |||
137 | static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv, | ||
138 | struct ieee80211_key_conf *keyconf, | ||
139 | u8 sta_id) | ||
140 | { | ||
141 | unsigned long flags; | ||
142 | __le16 key_flags = 0; | ||
143 | int ret; | ||
144 | |||
145 | key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); | ||
146 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); | ||
147 | |||
148 | if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id) | ||
149 | key_flags |= STA_KEY_MULTICAST_MSK; | ||
150 | |||
151 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
152 | keyconf->hw_key_idx = keyconf->keyidx; | ||
153 | key_flags &= ~STA_KEY_FLG_INVALID; | ||
154 | |||
155 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
156 | priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; | ||
157 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; | ||
158 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, | ||
159 | keyconf->keylen); | ||
160 | |||
161 | memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, | ||
162 | keyconf->keylen); | ||
163 | |||
164 | if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) | ||
165 | == STA_KEY_FLG_NO_ENC) | ||
166 | priv->stations[sta_id].sta.key.key_offset = | ||
167 | iwl_get_free_ucode_key_index(priv); | ||
168 | /* else, we are overriding an existing key => no need to allocated room | ||
169 | * in uCode. */ | ||
170 | |||
171 | WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, | ||
172 | "no space for a new key"); | ||
173 | |||
174 | priv->stations[sta_id].sta.key.key_flags = key_flags; | ||
175 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | ||
176 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
177 | |||
178 | IWL_DEBUG_INFO(priv, "hwcrypto: modify ucode station key info\n"); | ||
179 | |||
180 | ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
181 | |||
182 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
183 | |||
184 | return ret; | ||
185 | } | ||
186 | |||
187 | static int iwl3945_set_tkip_dynamic_key_info(struct iwl_priv *priv, | ||
188 | struct ieee80211_key_conf *keyconf, | ||
189 | u8 sta_id) | ||
190 | { | ||
191 | return -EOPNOTSUPP; | ||
192 | } | ||
193 | |||
194 | static int iwl3945_set_wep_dynamic_key_info(struct iwl_priv *priv, | ||
195 | struct ieee80211_key_conf *keyconf, | ||
196 | u8 sta_id) | ||
197 | { | ||
198 | return -EOPNOTSUPP; | ||
199 | } | ||
200 | |||
201 | static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) | ||
202 | { | ||
203 | unsigned long flags; | ||
204 | struct iwl_addsta_cmd sta_cmd; | ||
205 | |||
206 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
207 | memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key)); | ||
208 | memset(&priv->stations[sta_id].sta.key, 0, | ||
209 | sizeof(struct iwl4965_keyinfo)); | ||
210 | priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; | ||
211 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | ||
212 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
213 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); | ||
214 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
215 | |||
216 | IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n"); | ||
217 | return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); | ||
218 | } | ||
219 | |||
220 | static int iwl3945_set_dynamic_key(struct iwl_priv *priv, | ||
221 | struct ieee80211_key_conf *keyconf, u8 sta_id) | ||
222 | { | ||
223 | int ret = 0; | ||
224 | |||
225 | keyconf->hw_key_idx = HW_KEY_DYNAMIC; | ||
226 | |||
227 | switch (keyconf->cipher) { | ||
228 | case WLAN_CIPHER_SUITE_CCMP: | ||
229 | ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id); | ||
230 | break; | ||
231 | case WLAN_CIPHER_SUITE_TKIP: | ||
232 | ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id); | ||
233 | break; | ||
234 | case WLAN_CIPHER_SUITE_WEP40: | ||
235 | case WLAN_CIPHER_SUITE_WEP104: | ||
236 | ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id); | ||
237 | break; | ||
238 | default: | ||
239 | IWL_ERR(priv, "Unknown alg: %s alg=%x\n", __func__, | ||
240 | keyconf->cipher); | ||
241 | ret = -EINVAL; | ||
242 | } | ||
243 | |||
244 | IWL_DEBUG_WEP(priv, "Set dynamic key: alg=%x len=%d idx=%d sta=%d ret=%d\n", | ||
245 | keyconf->cipher, keyconf->keylen, keyconf->keyidx, | ||
246 | sta_id, ret); | ||
247 | |||
248 | return ret; | ||
249 | } | ||
250 | |||
251 | static int iwl3945_remove_static_key(struct iwl_priv *priv) | ||
252 | { | ||
253 | int ret = -EOPNOTSUPP; | ||
254 | |||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | static int iwl3945_set_static_key(struct iwl_priv *priv, | ||
259 | struct ieee80211_key_conf *key) | ||
260 | { | ||
261 | if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || | ||
262 | key->cipher == WLAN_CIPHER_SUITE_WEP104) | ||
263 | return -EOPNOTSUPP; | ||
264 | |||
265 | IWL_ERR(priv, "Static key invalid: cipher %x\n", key->cipher); | ||
266 | return -EINVAL; | ||
267 | } | ||
268 | |||
269 | static void iwl3945_clear_free_frames(struct iwl_priv *priv) | ||
270 | { | ||
271 | struct list_head *element; | ||
272 | |||
273 | IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n", | ||
274 | priv->frames_count); | ||
275 | |||
276 | while (!list_empty(&priv->free_frames)) { | ||
277 | element = priv->free_frames.next; | ||
278 | list_del(element); | ||
279 | kfree(list_entry(element, struct iwl3945_frame, list)); | ||
280 | priv->frames_count--; | ||
281 | } | ||
282 | |||
283 | if (priv->frames_count) { | ||
284 | IWL_WARN(priv, "%d frames still in use. Did we lose one?\n", | ||
285 | priv->frames_count); | ||
286 | priv->frames_count = 0; | ||
287 | } | ||
288 | } | ||
289 | |||
290 | static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl_priv *priv) | ||
291 | { | ||
292 | struct iwl3945_frame *frame; | ||
293 | struct list_head *element; | ||
294 | if (list_empty(&priv->free_frames)) { | ||
295 | frame = kzalloc(sizeof(*frame), GFP_KERNEL); | ||
296 | if (!frame) { | ||
297 | IWL_ERR(priv, "Could not allocate frame!\n"); | ||
298 | return NULL; | ||
299 | } | ||
300 | |||
301 | priv->frames_count++; | ||
302 | return frame; | ||
303 | } | ||
304 | |||
305 | element = priv->free_frames.next; | ||
306 | list_del(element); | ||
307 | return list_entry(element, struct iwl3945_frame, list); | ||
308 | } | ||
309 | |||
310 | static void iwl3945_free_frame(struct iwl_priv *priv, struct iwl3945_frame *frame) | ||
311 | { | ||
312 | memset(frame, 0, sizeof(*frame)); | ||
313 | list_add(&frame->list, &priv->free_frames); | ||
314 | } | ||
315 | |||
316 | unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, | ||
317 | struct ieee80211_hdr *hdr, | ||
318 | int left) | ||
319 | { | ||
320 | |||
321 | if (!iwl_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->beacon_skb) | ||
322 | return 0; | ||
323 | |||
324 | if (priv->beacon_skb->len > left) | ||
325 | return 0; | ||
326 | |||
327 | memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len); | ||
328 | |||
329 | return priv->beacon_skb->len; | ||
330 | } | ||
331 | |||
332 | static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) | ||
333 | { | ||
334 | struct iwl3945_frame *frame; | ||
335 | unsigned int frame_size; | ||
336 | int rc; | ||
337 | u8 rate; | ||
338 | |||
339 | frame = iwl3945_get_free_frame(priv); | ||
340 | |||
341 | if (!frame) { | ||
342 | IWL_ERR(priv, "Could not obtain free frame buffer for beacon " | ||
343 | "command.\n"); | ||
344 | return -ENOMEM; | ||
345 | } | ||
346 | |||
347 | rate = iwl_rate_get_lowest_plcp(priv, | ||
348 | &priv->contexts[IWL_RXON_CTX_BSS]); | ||
349 | |||
350 | frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate); | ||
351 | |||
352 | rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, | ||
353 | &frame->u.cmd[0]); | ||
354 | |||
355 | iwl3945_free_frame(priv, frame); | ||
356 | |||
357 | return rc; | ||
358 | } | ||
359 | |||
360 | static void iwl3945_unset_hw_params(struct iwl_priv *priv) | ||
361 | { | ||
362 | if (priv->_3945.shared_virt) | ||
363 | dma_free_coherent(&priv->pci_dev->dev, | ||
364 | sizeof(struct iwl3945_shared), | ||
365 | priv->_3945.shared_virt, | ||
366 | priv->_3945.shared_phys); | ||
367 | } | ||
368 | |||
369 | static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | ||
370 | struct ieee80211_tx_info *info, | ||
371 | struct iwl_device_cmd *cmd, | ||
372 | struct sk_buff *skb_frag, | ||
373 | int sta_id) | ||
374 | { | ||
375 | struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload; | ||
376 | struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; | ||
377 | |||
378 | tx_cmd->sec_ctl = 0; | ||
379 | |||
380 | switch (keyinfo->cipher) { | ||
381 | case WLAN_CIPHER_SUITE_CCMP: | ||
382 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; | ||
383 | memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen); | ||
384 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); | ||
385 | break; | ||
386 | |||
387 | case WLAN_CIPHER_SUITE_TKIP: | ||
388 | break; | ||
389 | |||
390 | case WLAN_CIPHER_SUITE_WEP104: | ||
391 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; | ||
392 | /* fall through */ | ||
393 | case WLAN_CIPHER_SUITE_WEP40: | ||
394 | tx_cmd->sec_ctl |= TX_CMD_SEC_WEP | | ||
395 | (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; | ||
396 | |||
397 | memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen); | ||
398 | |||
399 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " | ||
400 | "with key %d\n", info->control.hw_key->hw_key_idx); | ||
401 | break; | ||
402 | |||
403 | default: | ||
404 | IWL_ERR(priv, "Unknown encode cipher %x\n", keyinfo->cipher); | ||
405 | break; | ||
406 | } | ||
407 | } | ||
408 | |||
409 | /* | ||
410 | * handle build REPLY_TX command notification. | ||
411 | */ | ||
412 | static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, | ||
413 | struct iwl_device_cmd *cmd, | ||
414 | struct ieee80211_tx_info *info, | ||
415 | struct ieee80211_hdr *hdr, u8 std_id) | ||
416 | { | ||
417 | struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload; | ||
418 | __le32 tx_flags = tx_cmd->tx_flags; | ||
419 | __le16 fc = hdr->frame_control; | ||
420 | |||
421 | tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
422 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { | ||
423 | tx_flags |= TX_CMD_FLG_ACK_MSK; | ||
424 | if (ieee80211_is_mgmt(fc)) | ||
425 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
426 | if (ieee80211_is_probe_resp(fc) && | ||
427 | !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) | ||
428 | tx_flags |= TX_CMD_FLG_TSF_MSK; | ||
429 | } else { | ||
430 | tx_flags &= (~TX_CMD_FLG_ACK_MSK); | ||
431 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
432 | } | ||
433 | |||
434 | tx_cmd->sta_id = std_id; | ||
435 | if (ieee80211_has_morefrags(fc)) | ||
436 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; | ||
437 | |||
438 | if (ieee80211_is_data_qos(fc)) { | ||
439 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
440 | tx_cmd->tid_tspec = qc[0] & 0xf; | ||
441 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; | ||
442 | } else { | ||
443 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
444 | } | ||
445 | |||
446 | priv->cfg->ops->utils->tx_cmd_protection(priv, info, fc, &tx_flags); | ||
447 | |||
448 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); | ||
449 | if (ieee80211_is_mgmt(fc)) { | ||
450 | if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) | ||
451 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3); | ||
452 | else | ||
453 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2); | ||
454 | } else { | ||
455 | tx_cmd->timeout.pm_frame_timeout = 0; | ||
456 | } | ||
457 | |||
458 | tx_cmd->driver_txop = 0; | ||
459 | tx_cmd->tx_flags = tx_flags; | ||
460 | tx_cmd->next_frame_len = 0; | ||
461 | } | ||
462 | |||
463 | /* | ||
464 | * start REPLY_TX command process | ||
465 | */ | ||
466 | static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | ||
467 | { | ||
468 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
469 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
470 | struct iwl3945_tx_cmd *tx_cmd; | ||
471 | struct iwl_tx_queue *txq = NULL; | ||
472 | struct iwl_queue *q = NULL; | ||
473 | struct iwl_device_cmd *out_cmd; | ||
474 | struct iwl_cmd_meta *out_meta; | ||
475 | dma_addr_t phys_addr; | ||
476 | dma_addr_t txcmd_phys; | ||
477 | int txq_id = skb_get_queue_mapping(skb); | ||
478 | u16 len, idx, hdr_len; | ||
479 | u8 id; | ||
480 | u8 unicast; | ||
481 | u8 sta_id; | ||
482 | u8 tid = 0; | ||
483 | __le16 fc; | ||
484 | u8 wait_write_ptr = 0; | ||
485 | unsigned long flags; | ||
486 | |||
487 | spin_lock_irqsave(&priv->lock, flags); | ||
488 | if (iwl_is_rfkill(priv)) { | ||
489 | IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); | ||
490 | goto drop_unlock; | ||
491 | } | ||
492 | |||
493 | if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) { | ||
494 | IWL_ERR(priv, "ERROR: No TX rate available.\n"); | ||
495 | goto drop_unlock; | ||
496 | } | ||
497 | |||
498 | unicast = !is_multicast_ether_addr(hdr->addr1); | ||
499 | id = 0; | ||
500 | |||
501 | fc = hdr->frame_control; | ||
502 | |||
503 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
504 | if (ieee80211_is_auth(fc)) | ||
505 | IWL_DEBUG_TX(priv, "Sending AUTH frame\n"); | ||
506 | else if (ieee80211_is_assoc_req(fc)) | ||
507 | IWL_DEBUG_TX(priv, "Sending ASSOC frame\n"); | ||
508 | else if (ieee80211_is_reassoc_req(fc)) | ||
509 | IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); | ||
510 | #endif | ||
511 | |||
512 | spin_unlock_irqrestore(&priv->lock, flags); | ||
513 | |||
514 | hdr_len = ieee80211_hdrlen(fc); | ||
515 | |||
516 | /* Find index into station table for destination station */ | ||
517 | sta_id = iwl_sta_id_or_broadcast( | ||
518 | priv, &priv->contexts[IWL_RXON_CTX_BSS], | ||
519 | info->control.sta); | ||
520 | if (sta_id == IWL_INVALID_STATION) { | ||
521 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", | ||
522 | hdr->addr1); | ||
523 | goto drop; | ||
524 | } | ||
525 | |||
526 | IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id); | ||
527 | |||
528 | if (ieee80211_is_data_qos(fc)) { | ||
529 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
530 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
531 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
532 | goto drop; | ||
533 | } | ||
534 | |||
535 | /* Descriptor for chosen Tx queue */ | ||
536 | txq = &priv->txq[txq_id]; | ||
537 | q = &txq->q; | ||
538 | |||
539 | if ((iwl_queue_space(q) < q->high_mark)) | ||
540 | goto drop; | ||
541 | |||
542 | spin_lock_irqsave(&priv->lock, flags); | ||
543 | |||
544 | idx = get_cmd_index(q, q->write_ptr, 0); | ||
545 | |||
546 | /* Set up driver data for this TFD */ | ||
547 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); | ||
548 | txq->txb[q->write_ptr].skb = skb; | ||
549 | txq->txb[q->write_ptr].ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
550 | |||
551 | /* Init first empty entry in queue's array of Tx/cmd buffers */ | ||
552 | out_cmd = txq->cmd[idx]; | ||
553 | out_meta = &txq->meta[idx]; | ||
554 | tx_cmd = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload; | ||
555 | memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); | ||
556 | memset(tx_cmd, 0, sizeof(*tx_cmd)); | ||
557 | |||
558 | /* | ||
559 | * Set up the Tx-command (not MAC!) header. | ||
560 | * Store the chosen Tx queue and TFD index within the sequence field; | ||
561 | * after Tx, uCode's Tx response will return this value so driver can | ||
562 | * locate the frame within the tx queue and do post-tx processing. | ||
563 | */ | ||
564 | out_cmd->hdr.cmd = REPLY_TX; | ||
565 | out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | | ||
566 | INDEX_TO_SEQ(q->write_ptr))); | ||
567 | |||
568 | /* Copy MAC header from skb into command buffer */ | ||
569 | memcpy(tx_cmd->hdr, hdr, hdr_len); | ||
570 | |||
571 | |||
572 | if (info->control.hw_key) | ||
573 | iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id); | ||
574 | |||
575 | /* TODO need this for burst mode later on */ | ||
576 | iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id); | ||
577 | |||
578 | /* set is_hcca to 0; it probably will never be implemented */ | ||
579 | iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0); | ||
580 | |||
581 | /* Total # bytes to be transmitted */ | ||
582 | len = (u16)skb->len; | ||
583 | tx_cmd->len = cpu_to_le16(len); | ||
584 | |||
585 | iwl_dbg_log_tx_data_frame(priv, len, hdr); | ||
586 | iwl_update_stats(priv, true, fc, len); | ||
587 | tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK; | ||
588 | tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK; | ||
589 | |||
590 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | ||
591 | txq->need_update = 1; | ||
592 | } else { | ||
593 | wait_write_ptr = 1; | ||
594 | txq->need_update = 0; | ||
595 | } | ||
596 | |||
597 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n", | ||
598 | le16_to_cpu(out_cmd->hdr.sequence)); | ||
599 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); | ||
600 | iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd)); | ||
601 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, | ||
602 | ieee80211_hdrlen(fc)); | ||
603 | |||
604 | /* | ||
605 | * Use the first empty entry in this queue's command buffer array | ||
606 | * to contain the Tx command and MAC header concatenated together | ||
607 | * (payload data will be in another buffer). | ||
608 | * Size of this varies, due to varying MAC header length. | ||
609 | * If end is not dword aligned, we'll have 2 extra bytes at the end | ||
610 | * of the MAC header (device reads on dword boundaries). | ||
611 | * We'll tell device about this padding later. | ||
612 | */ | ||
613 | len = sizeof(struct iwl3945_tx_cmd) + | ||
614 | sizeof(struct iwl_cmd_header) + hdr_len; | ||
615 | len = (len + 3) & ~3; | ||
616 | |||
617 | /* Physical address of this Tx command's header (not MAC header!), | ||
618 | * within command buffer array. */ | ||
619 | txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr, | ||
620 | len, PCI_DMA_TODEVICE); | ||
621 | /* we do not map meta data ... so we can safely access address to | ||
622 | * provide to unmap command*/ | ||
623 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); | ||
624 | dma_unmap_len_set(out_meta, len, len); | ||
625 | |||
626 | /* Add buffer containing Tx command and MAC(!) header to TFD's | ||
627 | * first entry */ | ||
628 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
629 | txcmd_phys, len, 1, 0); | ||
630 | |||
631 | |||
632 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | ||
633 | * if any (802.11 null frames have no payload). */ | ||
634 | len = skb->len - hdr_len; | ||
635 | if (len) { | ||
636 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, | ||
637 | len, PCI_DMA_TODEVICE); | ||
638 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
639 | phys_addr, len, | ||
640 | 0, U32_PAD(len)); | ||
641 | } | ||
642 | |||
643 | |||
644 | /* Tell device the write index *just past* this latest filled TFD */ | ||
645 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | ||
646 | iwl_txq_update_write_ptr(priv, txq); | ||
647 | spin_unlock_irqrestore(&priv->lock, flags); | ||
648 | |||
649 | if ((iwl_queue_space(q) < q->high_mark) | ||
650 | && priv->mac80211_registered) { | ||
651 | if (wait_write_ptr) { | ||
652 | spin_lock_irqsave(&priv->lock, flags); | ||
653 | txq->need_update = 1; | ||
654 | iwl_txq_update_write_ptr(priv, txq); | ||
655 | spin_unlock_irqrestore(&priv->lock, flags); | ||
656 | } | ||
657 | |||
658 | iwl_stop_queue(priv, txq); | ||
659 | } | ||
660 | |||
661 | return 0; | ||
662 | |||
663 | drop_unlock: | ||
664 | spin_unlock_irqrestore(&priv->lock, flags); | ||
665 | drop: | ||
666 | return -1; | ||
667 | } | ||
668 | |||
669 | static int iwl3945_get_measurement(struct iwl_priv *priv, | ||
670 | struct ieee80211_measurement_params *params, | ||
671 | u8 type) | ||
672 | { | ||
673 | struct iwl_spectrum_cmd spectrum; | ||
674 | struct iwl_rx_packet *pkt; | ||
675 | struct iwl_host_cmd cmd = { | ||
676 | .id = REPLY_SPECTRUM_MEASUREMENT_CMD, | ||
677 | .data = (void *)&spectrum, | ||
678 | .flags = CMD_WANT_SKB, | ||
679 | }; | ||
680 | u32 add_time = le64_to_cpu(params->start_time); | ||
681 | int rc; | ||
682 | int spectrum_resp_status; | ||
683 | int duration = le16_to_cpu(params->duration); | ||
684 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
685 | |||
686 | if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) | ||
687 | add_time = iwl_usecs_to_beacons(priv, | ||
688 | le64_to_cpu(params->start_time) - priv->_3945.last_tsf, | ||
689 | le16_to_cpu(ctx->timing.beacon_interval)); | ||
690 | |||
691 | memset(&spectrum, 0, sizeof(spectrum)); | ||
692 | |||
693 | spectrum.channel_count = cpu_to_le16(1); | ||
694 | spectrum.flags = | ||
695 | RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK; | ||
696 | spectrum.filter_flags = MEASUREMENT_FILTER_FLAG; | ||
697 | cmd.len = sizeof(spectrum); | ||
698 | spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len)); | ||
699 | |||
700 | if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) | ||
701 | spectrum.start_time = | ||
702 | iwl_add_beacon_time(priv, | ||
703 | priv->_3945.last_beacon_time, add_time, | ||
704 | le16_to_cpu(ctx->timing.beacon_interval)); | ||
705 | else | ||
706 | spectrum.start_time = 0; | ||
707 | |||
708 | spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT); | ||
709 | spectrum.channels[0].channel = params->channel; | ||
710 | spectrum.channels[0].type = type; | ||
711 | if (ctx->active.flags & RXON_FLG_BAND_24G_MSK) | ||
712 | spectrum.flags |= RXON_FLG_BAND_24G_MSK | | ||
713 | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK; | ||
714 | |||
715 | rc = iwl_send_cmd_sync(priv, &cmd); | ||
716 | if (rc) | ||
717 | return rc; | ||
718 | |||
719 | pkt = (struct iwl_rx_packet *)cmd.reply_page; | ||
720 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
721 | IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n"); | ||
722 | rc = -EIO; | ||
723 | } | ||
724 | |||
725 | spectrum_resp_status = le16_to_cpu(pkt->u.spectrum.status); | ||
726 | switch (spectrum_resp_status) { | ||
727 | case 0: /* Command will be handled */ | ||
728 | if (pkt->u.spectrum.id != 0xff) { | ||
729 | IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n", | ||
730 | pkt->u.spectrum.id); | ||
731 | priv->measurement_status &= ~MEASUREMENT_READY; | ||
732 | } | ||
733 | priv->measurement_status |= MEASUREMENT_ACTIVE; | ||
734 | rc = 0; | ||
735 | break; | ||
736 | |||
737 | case 1: /* Command will not be handled */ | ||
738 | rc = -EAGAIN; | ||
739 | break; | ||
740 | } | ||
741 | |||
742 | iwl_free_pages(priv, cmd.reply_page); | ||
743 | |||
744 | return rc; | ||
745 | } | ||
746 | |||
747 | static void iwl3945_rx_reply_alive(struct iwl_priv *priv, | ||
748 | struct iwl_rx_mem_buffer *rxb) | ||
749 | { | ||
750 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
751 | struct iwl_alive_resp *palive; | ||
752 | struct delayed_work *pwork; | ||
753 | |||
754 | palive = &pkt->u.alive_frame; | ||
755 | |||
756 | IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision " | ||
757 | "0x%01X 0x%01X\n", | ||
758 | palive->is_valid, palive->ver_type, | ||
759 | palive->ver_subtype); | ||
760 | |||
761 | if (palive->ver_subtype == INITIALIZE_SUBTYPE) { | ||
762 | IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); | ||
763 | memcpy(&priv->card_alive_init, &pkt->u.alive_frame, | ||
764 | sizeof(struct iwl_alive_resp)); | ||
765 | pwork = &priv->init_alive_start; | ||
766 | } else { | ||
767 | IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); | ||
768 | memcpy(&priv->card_alive, &pkt->u.alive_frame, | ||
769 | sizeof(struct iwl_alive_resp)); | ||
770 | pwork = &priv->alive_start; | ||
771 | iwl3945_disable_events(priv); | ||
772 | } | ||
773 | |||
774 | /* We delay the ALIVE response by 5ms to | ||
775 | * give the HW RF Kill time to activate... */ | ||
776 | if (palive->is_valid == UCODE_VALID_OK) | ||
777 | queue_delayed_work(priv->workqueue, pwork, | ||
778 | msecs_to_jiffies(5)); | ||
779 | else | ||
780 | IWL_WARN(priv, "uCode did not respond OK.\n"); | ||
781 | } | ||
782 | |||
783 | static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv, | ||
784 | struct iwl_rx_mem_buffer *rxb) | ||
785 | { | ||
786 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
787 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
788 | #endif | ||
789 | |||
790 | IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status); | ||
791 | } | ||
792 | |||
793 | static void iwl3945_bg_beacon_update(struct work_struct *work) | ||
794 | { | ||
795 | struct iwl_priv *priv = | ||
796 | container_of(work, struct iwl_priv, beacon_update); | ||
797 | struct sk_buff *beacon; | ||
798 | |||
799 | /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ | ||
800 | beacon = ieee80211_beacon_get(priv->hw, | ||
801 | priv->contexts[IWL_RXON_CTX_BSS].vif); | ||
802 | |||
803 | if (!beacon) { | ||
804 | IWL_ERR(priv, "update beacon failed\n"); | ||
805 | return; | ||
806 | } | ||
807 | |||
808 | mutex_lock(&priv->mutex); | ||
809 | /* new beacon skb is allocated every time; dispose previous.*/ | ||
810 | if (priv->beacon_skb) | ||
811 | dev_kfree_skb(priv->beacon_skb); | ||
812 | |||
813 | priv->beacon_skb = beacon; | ||
814 | mutex_unlock(&priv->mutex); | ||
815 | |||
816 | iwl3945_send_beacon_cmd(priv); | ||
817 | } | ||
818 | |||
819 | static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, | ||
820 | struct iwl_rx_mem_buffer *rxb) | ||
821 | { | ||
822 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
823 | struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status); | ||
824 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
825 | u8 rate = beacon->beacon_notify_hdr.rate; | ||
826 | |||
827 | IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " | ||
828 | "tsf %d %d rate %d\n", | ||
829 | le32_to_cpu(beacon->beacon_notify_hdr.status) & TX_STATUS_MSK, | ||
830 | beacon->beacon_notify_hdr.failure_frame, | ||
831 | le32_to_cpu(beacon->ibss_mgr_status), | ||
832 | le32_to_cpu(beacon->high_tsf), | ||
833 | le32_to_cpu(beacon->low_tsf), rate); | ||
834 | #endif | ||
835 | |||
836 | priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); | ||
837 | |||
838 | if ((priv->iw_mode == NL80211_IFTYPE_AP) && | ||
839 | (!test_bit(STATUS_EXIT_PENDING, &priv->status))) | ||
840 | queue_work(priv->workqueue, &priv->beacon_update); | ||
841 | } | ||
842 | |||
843 | /* Handle notification from uCode that card's power state is changing | ||
844 | * due to software, hardware, or critical temperature RFKILL */ | ||
845 | static void iwl3945_rx_card_state_notif(struct iwl_priv *priv, | ||
846 | struct iwl_rx_mem_buffer *rxb) | ||
847 | { | ||
848 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
849 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); | ||
850 | unsigned long status = priv->status; | ||
851 | |||
852 | IWL_WARN(priv, "Card state received: HW:%s SW:%s\n", | ||
853 | (flags & HW_CARD_DISABLED) ? "Kill" : "On", | ||
854 | (flags & SW_CARD_DISABLED) ? "Kill" : "On"); | ||
855 | |||
856 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, | ||
857 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | ||
858 | |||
859 | if (flags & HW_CARD_DISABLED) | ||
860 | set_bit(STATUS_RF_KILL_HW, &priv->status); | ||
861 | else | ||
862 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | ||
863 | |||
864 | |||
865 | iwl_scan_cancel(priv); | ||
866 | |||
867 | if ((test_bit(STATUS_RF_KILL_HW, &status) != | ||
868 | test_bit(STATUS_RF_KILL_HW, &priv->status))) | ||
869 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, | ||
870 | test_bit(STATUS_RF_KILL_HW, &priv->status)); | ||
871 | else | ||
872 | wake_up_interruptible(&priv->wait_command_queue); | ||
873 | } | ||
874 | |||
875 | /** | ||
876 | * iwl3945_setup_rx_handlers - Initialize Rx handler callbacks | ||
877 | * | ||
878 | * Setup the RX handlers for each of the reply types sent from the uCode | ||
879 | * to the host. | ||
880 | * | ||
881 | * This function chains into the hardware specific files for them to setup | ||
882 | * any hardware specific handlers as well. | ||
883 | */ | ||
884 | static void iwl3945_setup_rx_handlers(struct iwl_priv *priv) | ||
885 | { | ||
886 | priv->rx_handlers[REPLY_ALIVE] = iwl3945_rx_reply_alive; | ||
887 | priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta; | ||
888 | priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; | ||
889 | priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; | ||
890 | priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] = | ||
891 | iwl_rx_spectrum_measure_notif; | ||
892 | priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; | ||
893 | priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = | ||
894 | iwl_rx_pm_debug_statistics_notif; | ||
895 | priv->rx_handlers[BEACON_NOTIFICATION] = iwl3945_rx_beacon_notif; | ||
896 | |||
897 | /* | ||
898 | * The same handler is used for both the REPLY to a discrete | ||
899 | * statistics request from the host as well as for the periodic | ||
900 | * statistics notifications (after received beacons) from the uCode. | ||
901 | */ | ||
902 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_reply_statistics; | ||
903 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics; | ||
904 | |||
905 | iwl_setup_rx_scan_handlers(priv); | ||
906 | priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif; | ||
907 | |||
908 | /* Set up hardware specific Rx handlers */ | ||
909 | iwl3945_hw_rx_handler_setup(priv); | ||
910 | } | ||
911 | |||
912 | /************************** RX-FUNCTIONS ****************************/ | ||
913 | /* | ||
914 | * Rx theory of operation | ||
915 | * | ||
916 | * The host allocates 32 DMA target addresses and passes the host address | ||
917 | * to the firmware at register IWL_RFDS_TABLE_LOWER + N * RFD_SIZE where N is | ||
918 | * 0 to 31 | ||
919 | * | ||
920 | * Rx Queue Indexes | ||
921 | * The host/firmware share two index registers for managing the Rx buffers. | ||
922 | * | ||
923 | * The READ index maps to the first position that the firmware may be writing | ||
924 | * to -- the driver can read up to (but not including) this position and get | ||
925 | * good data. | ||
926 | * The READ index is managed by the firmware once the card is enabled. | ||
927 | * | ||
928 | * The WRITE index maps to the last position the driver has read from -- the | ||
929 | * position preceding WRITE is the last slot the firmware can place a packet. | ||
930 | * | ||
931 | * The queue is empty (no good data) if WRITE = READ - 1, and is full if | ||
932 | * WRITE = READ. | ||
933 | * | ||
934 | * During initialization, the host sets up the READ queue position to the first | ||
935 | * INDEX position, and WRITE to the last (READ - 1 wrapped) | ||
936 | * | ||
937 | * When the firmware places a packet in a buffer, it will advance the READ index | ||
938 | * and fire the RX interrupt. The driver can then query the READ index and | ||
939 | * process as many packets as possible, moving the WRITE index forward as it | ||
940 | * resets the Rx queue buffers with new memory. | ||
941 | * | ||
942 | * The management in the driver is as follows: | ||
943 | * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When | ||
944 | * iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled | ||
945 | * to replenish the iwl->rxq->rx_free. | ||
946 | * + In iwl3945_rx_replenish (scheduled) if 'processed' != 'read' then the | ||
947 | * iwl->rxq is replenished and the READ INDEX is updated (updating the | ||
948 | * 'processed' and 'read' driver indexes as well) | ||
949 | * + A received packet is processed and handed to the kernel network stack, | ||
950 | * detached from the iwl->rxq. The driver 'processed' index is updated. | ||
951 | * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free | ||
952 | * list. If there are no allocated buffers in iwl->rxq->rx_free, the READ | ||
953 | * INDEX is not incremented and iwl->status(RX_STALLED) is set. If there | ||
954 | * were enough free buffers and RX_STALLED is set it is cleared. | ||
955 | * | ||
956 | * | ||
957 | * Driver sequence: | ||
958 | * | ||
959 | * iwl3945_rx_replenish() Replenishes rx_free list from rx_used, and calls | ||
960 | * iwl3945_rx_queue_restock | ||
961 | * iwl3945_rx_queue_restock() Moves available buffers from rx_free into Rx | ||
962 | * queue, updates firmware pointers, and updates | ||
963 | * the WRITE index. If insufficient rx_free buffers | ||
964 | * are available, schedules iwl3945_rx_replenish | ||
965 | * | ||
966 | * -- enable interrupts -- | ||
967 | * ISR - iwl3945_rx() Detach iwl_rx_mem_buffers from pool up to the | ||
968 | * READ INDEX, detaching the SKB from the pool. | ||
969 | * Moves the packet buffer from queue to rx_used. | ||
970 | * Calls iwl3945_rx_queue_restock to refill any empty | ||
971 | * slots. | ||
972 | * ... | ||
973 | * | ||
974 | */ | ||
975 | |||
976 | /** | ||
977 | * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr | ||
978 | */ | ||
979 | static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv, | ||
980 | dma_addr_t dma_addr) | ||
981 | { | ||
982 | return cpu_to_le32((u32)dma_addr); | ||
983 | } | ||
984 | |||
985 | /** | ||
986 | * iwl3945_rx_queue_restock - refill RX queue from pre-allocated pool | ||
987 | * | ||
988 | * If there are slots in the RX queue that need to be restocked, | ||
989 | * and we have free pre-allocated buffers, fill the ranks as much | ||
990 | * as we can, pulling from rx_free. | ||
991 | * | ||
992 | * This moves the 'write' index forward to catch up with 'processed', and | ||
993 | * also updates the memory address in the firmware to reference the new | ||
994 | * target buffer. | ||
995 | */ | ||
996 | static void iwl3945_rx_queue_restock(struct iwl_priv *priv) | ||
997 | { | ||
998 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
999 | struct list_head *element; | ||
1000 | struct iwl_rx_mem_buffer *rxb; | ||
1001 | unsigned long flags; | ||
1002 | int write; | ||
1003 | |||
1004 | spin_lock_irqsave(&rxq->lock, flags); | ||
1005 | write = rxq->write & ~0x7; | ||
1006 | while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { | ||
1007 | /* Get next free Rx buffer, remove from free list */ | ||
1008 | element = rxq->rx_free.next; | ||
1009 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | ||
1010 | list_del(element); | ||
1011 | |||
1012 | /* Point to Rx buffer via next RBD in circular buffer */ | ||
1013 | rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->page_dma); | ||
1014 | rxq->queue[rxq->write] = rxb; | ||
1015 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; | ||
1016 | rxq->free_count--; | ||
1017 | } | ||
1018 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
1019 | /* If the pre-allocated buffer pool is dropping low, schedule to | ||
1020 | * refill it */ | ||
1021 | if (rxq->free_count <= RX_LOW_WATERMARK) | ||
1022 | queue_work(priv->workqueue, &priv->rx_replenish); | ||
1023 | |||
1024 | |||
1025 | /* If we've added more space for the firmware to place data, tell it. | ||
1026 | * Increment device's write pointer in multiples of 8. */ | ||
1027 | if ((rxq->write_actual != (rxq->write & ~0x7)) | ||
1028 | || (abs(rxq->write - rxq->read) > 7)) { | ||
1029 | spin_lock_irqsave(&rxq->lock, flags); | ||
1030 | rxq->need_update = 1; | ||
1031 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
1032 | iwl_rx_queue_update_write_ptr(priv, rxq); | ||
1033 | } | ||
1034 | } | ||
1035 | |||
1036 | /** | ||
1037 | * iwl3945_rx_replenish - Move all used packet from rx_used to rx_free | ||
1038 | * | ||
1039 | * When moving to rx_free an SKB is allocated for the slot. | ||
1040 | * | ||
1041 | * Also restock the Rx queue via iwl3945_rx_queue_restock. | ||
1042 | * This is called as a scheduled work item (except for during initialization) | ||
1043 | */ | ||
1044 | static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) | ||
1045 | { | ||
1046 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
1047 | struct list_head *element; | ||
1048 | struct iwl_rx_mem_buffer *rxb; | ||
1049 | struct page *page; | ||
1050 | unsigned long flags; | ||
1051 | gfp_t gfp_mask = priority; | ||
1052 | |||
1053 | while (1) { | ||
1054 | spin_lock_irqsave(&rxq->lock, flags); | ||
1055 | |||
1056 | if (list_empty(&rxq->rx_used)) { | ||
1057 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
1058 | return; | ||
1059 | } | ||
1060 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
1061 | |||
1062 | if (rxq->free_count > RX_LOW_WATERMARK) | ||
1063 | gfp_mask |= __GFP_NOWARN; | ||
1064 | |||
1065 | if (priv->hw_params.rx_page_order > 0) | ||
1066 | gfp_mask |= __GFP_COMP; | ||
1067 | |||
1068 | /* Alloc a new receive buffer */ | ||
1069 | page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); | ||
1070 | if (!page) { | ||
1071 | if (net_ratelimit()) | ||
1072 | IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n"); | ||
1073 | if ((rxq->free_count <= RX_LOW_WATERMARK) && | ||
1074 | net_ratelimit()) | ||
1075 | IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n", | ||
1076 | priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", | ||
1077 | rxq->free_count); | ||
1078 | /* We don't reschedule replenish work here -- we will | ||
1079 | * call the restock method and if it still needs | ||
1080 | * more buffers it will schedule replenish */ | ||
1081 | break; | ||
1082 | } | ||
1083 | |||
1084 | spin_lock_irqsave(&rxq->lock, flags); | ||
1085 | if (list_empty(&rxq->rx_used)) { | ||
1086 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
1087 | __free_pages(page, priv->hw_params.rx_page_order); | ||
1088 | return; | ||
1089 | } | ||
1090 | element = rxq->rx_used.next; | ||
1091 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | ||
1092 | list_del(element); | ||
1093 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
1094 | |||
1095 | rxb->page = page; | ||
1096 | /* Get physical address of RB/SKB */ | ||
1097 | rxb->page_dma = pci_map_page(priv->pci_dev, page, 0, | ||
1098 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
1099 | PCI_DMA_FROMDEVICE); | ||
1100 | |||
1101 | spin_lock_irqsave(&rxq->lock, flags); | ||
1102 | |||
1103 | list_add_tail(&rxb->list, &rxq->rx_free); | ||
1104 | rxq->free_count++; | ||
1105 | priv->alloc_rxb_page++; | ||
1106 | |||
1107 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
1108 | } | ||
1109 | } | ||
1110 | |||
1111 | void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
1112 | { | ||
1113 | unsigned long flags; | ||
1114 | int i; | ||
1115 | spin_lock_irqsave(&rxq->lock, flags); | ||
1116 | INIT_LIST_HEAD(&rxq->rx_free); | ||
1117 | INIT_LIST_HEAD(&rxq->rx_used); | ||
1118 | /* Fill the rx_used queue with _all_ of the Rx buffers */ | ||
1119 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { | ||
1120 | /* In the reset function, these buffers may have been allocated | ||
1121 | * to an SKB, so we need to unmap and free potential storage */ | ||
1122 | if (rxq->pool[i].page != NULL) { | ||
1123 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, | ||
1124 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
1125 | PCI_DMA_FROMDEVICE); | ||
1126 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
1127 | rxq->pool[i].page = NULL; | ||
1128 | } | ||
1129 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | ||
1130 | } | ||
1131 | |||
1132 | /* Set us so that we have processed and used all buffers, but have | ||
1133 | * not restocked the Rx queue with fresh buffers */ | ||
1134 | rxq->read = rxq->write = 0; | ||
1135 | rxq->write_actual = 0; | ||
1136 | rxq->free_count = 0; | ||
1137 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
1138 | } | ||
1139 | |||
1140 | void iwl3945_rx_replenish(void *data) | ||
1141 | { | ||
1142 | struct iwl_priv *priv = data; | ||
1143 | unsigned long flags; | ||
1144 | |||
1145 | iwl3945_rx_allocate(priv, GFP_KERNEL); | ||
1146 | |||
1147 | spin_lock_irqsave(&priv->lock, flags); | ||
1148 | iwl3945_rx_queue_restock(priv); | ||
1149 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1150 | } | ||
1151 | |||
1152 | static void iwl3945_rx_replenish_now(struct iwl_priv *priv) | ||
1153 | { | ||
1154 | iwl3945_rx_allocate(priv, GFP_ATOMIC); | ||
1155 | |||
1156 | iwl3945_rx_queue_restock(priv); | ||
1157 | } | ||
1158 | |||
1159 | |||
1160 | /* Assumes that the skb field of the buffers in 'pool' is kept accurate. | ||
1161 | * If an SKB has been detached, the POOL needs to have its SKB set to NULL | ||
1162 | * This free routine walks the list of POOL entries and if SKB is set to | ||
1163 | * non NULL it is unmapped and freed | ||
1164 | */ | ||
1165 | static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
1166 | { | ||
1167 | int i; | ||
1168 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { | ||
1169 | if (rxq->pool[i].page != NULL) { | ||
1170 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, | ||
1171 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
1172 | PCI_DMA_FROMDEVICE); | ||
1173 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
1174 | rxq->pool[i].page = NULL; | ||
1175 | } | ||
1176 | } | ||
1177 | |||
1178 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, | ||
1179 | rxq->bd_dma); | ||
1180 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), | ||
1181 | rxq->rb_stts, rxq->rb_stts_dma); | ||
1182 | rxq->bd = NULL; | ||
1183 | rxq->rb_stts = NULL; | ||
1184 | } | ||
1185 | |||
1186 | |||
1187 | /* Convert linear signal-to-noise ratio into dB */ | ||
1188 | static u8 ratio2dB[100] = { | ||
1189 | /* 0 1 2 3 4 5 6 7 8 9 */ | ||
1190 | 0, 0, 6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */ | ||
1191 | 20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */ | ||
1192 | 26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */ | ||
1193 | 29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */ | ||
1194 | 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */ | ||
1195 | 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */ | ||
1196 | 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */ | ||
1197 | 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */ | ||
1198 | 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */ | ||
1199 | 39, 39, 39, 39, 39, 40, 40, 40, 40, 40 /* 90 - 99 */ | ||
1200 | }; | ||
1201 | |||
1202 | /* Calculates a relative dB value from a ratio of linear | ||
1203 | * (i.e. not dB) signal levels. | ||
1204 | * Conversion assumes that levels are voltages (20*log), not powers (10*log). */ | ||
1205 | int iwl3945_calc_db_from_ratio(int sig_ratio) | ||
1206 | { | ||
1207 | /* 1000:1 or higher just report as 60 dB */ | ||
1208 | if (sig_ratio >= 1000) | ||
1209 | return 60; | ||
1210 | |||
1211 | /* 100:1 or higher, divide by 10 and use table, | ||
1212 | * add 20 dB to make up for divide by 10 */ | ||
1213 | if (sig_ratio >= 100) | ||
1214 | return 20 + (int)ratio2dB[sig_ratio/10]; | ||
1215 | |||
1216 | /* We shouldn't see this */ | ||
1217 | if (sig_ratio < 1) | ||
1218 | return 0; | ||
1219 | |||
1220 | /* Use table for ratios 1:1 - 99:1 */ | ||
1221 | return (int)ratio2dB[sig_ratio]; | ||
1222 | } | ||
1223 | |||
1224 | /** | ||
1225 | * iwl3945_rx_handle - Main entry function for receiving responses from uCode | ||
1226 | * | ||
1227 | * Uses the priv->rx_handlers callback function array to invoke | ||
1228 | * the appropriate handlers, including command responses, | ||
1229 | * frame-received notifications, and other notifications. | ||
1230 | */ | ||
1231 | static void iwl3945_rx_handle(struct iwl_priv *priv) | ||
1232 | { | ||
1233 | struct iwl_rx_mem_buffer *rxb; | ||
1234 | struct iwl_rx_packet *pkt; | ||
1235 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
1236 | u32 r, i; | ||
1237 | int reclaim; | ||
1238 | unsigned long flags; | ||
1239 | u8 fill_rx = 0; | ||
1240 | u32 count = 8; | ||
1241 | int total_empty = 0; | ||
1242 | |||
1243 | /* uCode's read index (stored in shared DRAM) indicates the last Rx | ||
1244 | * buffer that the driver may process (last buffer filled by ucode). */ | ||
1245 | r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF; | ||
1246 | i = rxq->read; | ||
1247 | |||
1248 | /* calculate total frames need to be restock after handling RX */ | ||
1249 | total_empty = r - rxq->write_actual; | ||
1250 | if (total_empty < 0) | ||
1251 | total_empty += RX_QUEUE_SIZE; | ||
1252 | |||
1253 | if (total_empty > (RX_QUEUE_SIZE / 2)) | ||
1254 | fill_rx = 1; | ||
1255 | /* Rx interrupt, but nothing sent from uCode */ | ||
1256 | if (i == r) | ||
1257 | IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); | ||
1258 | |||
1259 | while (i != r) { | ||
1260 | int len; | ||
1261 | |||
1262 | rxb = rxq->queue[i]; | ||
1263 | |||
1264 | /* If an RXB doesn't have a Rx queue slot associated with it, | ||
1265 | * then a bug has been introduced in the queue refilling | ||
1266 | * routines -- catch it here */ | ||
1267 | BUG_ON(rxb == NULL); | ||
1268 | |||
1269 | rxq->queue[i] = NULL; | ||
1270 | |||
1271 | pci_unmap_page(priv->pci_dev, rxb->page_dma, | ||
1272 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
1273 | PCI_DMA_FROMDEVICE); | ||
1274 | pkt = rxb_addr(rxb); | ||
1275 | |||
1276 | len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
1277 | len += sizeof(u32); /* account for status word */ | ||
1278 | trace_iwlwifi_dev_rx(priv, pkt, len); | ||
1279 | |||
1280 | /* Reclaim a command buffer only if this packet is a response | ||
1281 | * to a (driver-originated) command. | ||
1282 | * If the packet (e.g. Rx frame) originated from uCode, | ||
1283 | * there is no command buffer to reclaim. | ||
1284 | * Ucode should set SEQ_RX_FRAME bit if ucode-originated, | ||
1285 | * but apparently a few don't get set; catch them here. */ | ||
1286 | reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) && | ||
1287 | (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && | ||
1288 | (pkt->hdr.cmd != REPLY_TX); | ||
1289 | |||
1290 | /* Based on type of command response or notification, | ||
1291 | * handle those that need handling via function in | ||
1292 | * rx_handlers table. See iwl3945_setup_rx_handlers() */ | ||
1293 | if (priv->rx_handlers[pkt->hdr.cmd]) { | ||
1294 | IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i, | ||
1295 | get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); | ||
1296 | priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; | ||
1297 | priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); | ||
1298 | } else { | ||
1299 | /* No handling needed */ | ||
1300 | IWL_DEBUG_RX(priv, | ||
1301 | "r %d i %d No handler needed for %s, 0x%02x\n", | ||
1302 | r, i, get_cmd_string(pkt->hdr.cmd), | ||
1303 | pkt->hdr.cmd); | ||
1304 | } | ||
1305 | |||
1306 | /* | ||
1307 | * XXX: After here, we should always check rxb->page | ||
1308 | * against NULL before touching it or its virtual | ||
1309 | * memory (pkt). Because some rx_handler might have | ||
1310 | * already taken or freed the pages. | ||
1311 | */ | ||
1312 | |||
1313 | if (reclaim) { | ||
1314 | /* Invoke any callbacks, transfer the buffer to caller, | ||
1315 | * and fire off the (possibly) blocking iwl_send_cmd() | ||
1316 | * as we reclaim the driver command queue */ | ||
1317 | if (rxb->page) | ||
1318 | iwl_tx_cmd_complete(priv, rxb); | ||
1319 | else | ||
1320 | IWL_WARN(priv, "Claim null rxb?\n"); | ||
1321 | } | ||
1322 | |||
1323 | /* Reuse the page if possible. For notification packets and | ||
1324 | * SKBs that fail to Rx correctly, add them back into the | ||
1325 | * rx_free list for reuse later. */ | ||
1326 | spin_lock_irqsave(&rxq->lock, flags); | ||
1327 | if (rxb->page != NULL) { | ||
1328 | rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page, | ||
1329 | 0, PAGE_SIZE << priv->hw_params.rx_page_order, | ||
1330 | PCI_DMA_FROMDEVICE); | ||
1331 | list_add_tail(&rxb->list, &rxq->rx_free); | ||
1332 | rxq->free_count++; | ||
1333 | } else | ||
1334 | list_add_tail(&rxb->list, &rxq->rx_used); | ||
1335 | |||
1336 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
1337 | |||
1338 | i = (i + 1) & RX_QUEUE_MASK; | ||
1339 | /* If there are a lot of unused frames, | ||
1340 | * restock the Rx queue so ucode won't assert. */ | ||
1341 | if (fill_rx) { | ||
1342 | count++; | ||
1343 | if (count >= 8) { | ||
1344 | rxq->read = i; | ||
1345 | iwl3945_rx_replenish_now(priv); | ||
1346 | count = 0; | ||
1347 | } | ||
1348 | } | ||
1349 | } | ||
1350 | |||
1351 | /* Backtrack one entry */ | ||
1352 | rxq->read = i; | ||
1353 | if (fill_rx) | ||
1354 | iwl3945_rx_replenish_now(priv); | ||
1355 | else | ||
1356 | iwl3945_rx_queue_restock(priv); | ||
1357 | } | ||
1358 | |||
1359 | /* call this function to flush any scheduled tasklet */ | ||
1360 | static inline void iwl_synchronize_irq(struct iwl_priv *priv) | ||
1361 | { | ||
1362 | /* wait to make sure we flush pending tasklet*/ | ||
1363 | synchronize_irq(priv->pci_dev->irq); | ||
1364 | tasklet_kill(&priv->irq_tasklet); | ||
1365 | } | ||
1366 | |||
1367 | static const char *desc_lookup(int i) | ||
1368 | { | ||
1369 | switch (i) { | ||
1370 | case 1: | ||
1371 | return "FAIL"; | ||
1372 | case 2: | ||
1373 | return "BAD_PARAM"; | ||
1374 | case 3: | ||
1375 | return "BAD_CHECKSUM"; | ||
1376 | case 4: | ||
1377 | return "NMI_INTERRUPT"; | ||
1378 | case 5: | ||
1379 | return "SYSASSERT"; | ||
1380 | case 6: | ||
1381 | return "FATAL_ERROR"; | ||
1382 | } | ||
1383 | |||
1384 | return "UNKNOWN"; | ||
1385 | } | ||
1386 | |||
1387 | #define ERROR_START_OFFSET (1 * sizeof(u32)) | ||
1388 | #define ERROR_ELEM_SIZE (7 * sizeof(u32)) | ||
1389 | |||
1390 | void iwl3945_dump_nic_error_log(struct iwl_priv *priv) | ||
1391 | { | ||
1392 | u32 i; | ||
1393 | u32 desc, time, count, base, data1; | ||
1394 | u32 blink1, blink2, ilink1, ilink2; | ||
1395 | |||
1396 | base = le32_to_cpu(priv->card_alive.error_event_table_ptr); | ||
1397 | |||
1398 | if (!iwl3945_hw_valid_rtc_data_addr(base)) { | ||
1399 | IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base); | ||
1400 | return; | ||
1401 | } | ||
1402 | |||
1403 | |||
1404 | count = iwl_read_targ_mem(priv, base); | ||
1405 | |||
1406 | if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { | ||
1407 | IWL_ERR(priv, "Start IWL Error Log Dump:\n"); | ||
1408 | IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", | ||
1409 | priv->status, count); | ||
1410 | } | ||
1411 | |||
1412 | IWL_ERR(priv, "Desc Time asrtPC blink2 " | ||
1413 | "ilink1 nmiPC Line\n"); | ||
1414 | for (i = ERROR_START_OFFSET; | ||
1415 | i < (count * ERROR_ELEM_SIZE) + ERROR_START_OFFSET; | ||
1416 | i += ERROR_ELEM_SIZE) { | ||
1417 | desc = iwl_read_targ_mem(priv, base + i); | ||
1418 | time = | ||
1419 | iwl_read_targ_mem(priv, base + i + 1 * sizeof(u32)); | ||
1420 | blink1 = | ||
1421 | iwl_read_targ_mem(priv, base + i + 2 * sizeof(u32)); | ||
1422 | blink2 = | ||
1423 | iwl_read_targ_mem(priv, base + i + 3 * sizeof(u32)); | ||
1424 | ilink1 = | ||
1425 | iwl_read_targ_mem(priv, base + i + 4 * sizeof(u32)); | ||
1426 | ilink2 = | ||
1427 | iwl_read_targ_mem(priv, base + i + 5 * sizeof(u32)); | ||
1428 | data1 = | ||
1429 | iwl_read_targ_mem(priv, base + i + 6 * sizeof(u32)); | ||
1430 | |||
1431 | IWL_ERR(priv, | ||
1432 | "%-13s (0x%X) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n", | ||
1433 | desc_lookup(desc), desc, time, blink1, blink2, | ||
1434 | ilink1, ilink2, data1); | ||
1435 | trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, 0, | ||
1436 | 0, blink1, blink2, ilink1, ilink2); | ||
1437 | } | ||
1438 | } | ||
1439 | |||
1440 | #define EVENT_START_OFFSET (6 * sizeof(u32)) | ||
1441 | |||
1442 | /** | ||
1443 | * iwl3945_print_event_log - Dump error event log to syslog | ||
1444 | * | ||
1445 | */ | ||
1446 | static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, | ||
1447 | u32 num_events, u32 mode, | ||
1448 | int pos, char **buf, size_t bufsz) | ||
1449 | { | ||
1450 | u32 i; | ||
1451 | u32 base; /* SRAM byte address of event log header */ | ||
1452 | u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ | ||
1453 | u32 ptr; /* SRAM byte address of log data */ | ||
1454 | u32 ev, time, data; /* event log data */ | ||
1455 | unsigned long reg_flags; | ||
1456 | |||
1457 | if (num_events == 0) | ||
1458 | return pos; | ||
1459 | |||
1460 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | ||
1461 | |||
1462 | if (mode == 0) | ||
1463 | event_size = 2 * sizeof(u32); | ||
1464 | else | ||
1465 | event_size = 3 * sizeof(u32); | ||
1466 | |||
1467 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); | ||
1468 | |||
1469 | /* Make sure device is powered up for SRAM reads */ | ||
1470 | spin_lock_irqsave(&priv->reg_lock, reg_flags); | ||
1471 | iwl_grab_nic_access(priv); | ||
1472 | |||
1473 | /* Set starting address; reads will auto-increment */ | ||
1474 | _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); | ||
1475 | rmb(); | ||
1476 | |||
1477 | /* "time" is actually "data" for mode 0 (no timestamp). | ||
1478 | * place event id # at far right for easier visual parsing. */ | ||
1479 | for (i = 0; i < num_events; i++) { | ||
1480 | ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
1481 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
1482 | if (mode == 0) { | ||
1483 | /* data, ev */ | ||
1484 | if (bufsz) { | ||
1485 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
1486 | "0x%08x:%04u\n", | ||
1487 | time, ev); | ||
1488 | } else { | ||
1489 | IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); | ||
1490 | trace_iwlwifi_dev_ucode_event(priv, 0, | ||
1491 | time, ev); | ||
1492 | } | ||
1493 | } else { | ||
1494 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
1495 | if (bufsz) { | ||
1496 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
1497 | "%010u:0x%08x:%04u\n", | ||
1498 | time, data, ev); | ||
1499 | } else { | ||
1500 | IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", | ||
1501 | time, data, ev); | ||
1502 | trace_iwlwifi_dev_ucode_event(priv, time, | ||
1503 | data, ev); | ||
1504 | } | ||
1505 | } | ||
1506 | } | ||
1507 | |||
1508 | /* Allow device to power down */ | ||
1509 | iwl_release_nic_access(priv); | ||
1510 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | ||
1511 | return pos; | ||
1512 | } | ||
1513 | |||
1514 | /** | ||
1515 | * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog | ||
1516 | */ | ||
1517 | static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | ||
1518 | u32 num_wraps, u32 next_entry, | ||
1519 | u32 size, u32 mode, | ||
1520 | int pos, char **buf, size_t bufsz) | ||
1521 | { | ||
1522 | /* | ||
1523 | * display the newest DEFAULT_LOG_ENTRIES entries | ||
1524 | * i.e the entries just before the next ont that uCode would fill. | ||
1525 | */ | ||
1526 | if (num_wraps) { | ||
1527 | if (next_entry < size) { | ||
1528 | pos = iwl3945_print_event_log(priv, | ||
1529 | capacity - (size - next_entry), | ||
1530 | size - next_entry, mode, | ||
1531 | pos, buf, bufsz); | ||
1532 | pos = iwl3945_print_event_log(priv, 0, | ||
1533 | next_entry, mode, | ||
1534 | pos, buf, bufsz); | ||
1535 | } else | ||
1536 | pos = iwl3945_print_event_log(priv, next_entry - size, | ||
1537 | size, mode, | ||
1538 | pos, buf, bufsz); | ||
1539 | } else { | ||
1540 | if (next_entry < size) | ||
1541 | pos = iwl3945_print_event_log(priv, 0, | ||
1542 | next_entry, mode, | ||
1543 | pos, buf, bufsz); | ||
1544 | else | ||
1545 | pos = iwl3945_print_event_log(priv, next_entry - size, | ||
1546 | size, mode, | ||
1547 | pos, buf, bufsz); | ||
1548 | } | ||
1549 | return pos; | ||
1550 | } | ||
1551 | |||
1552 | #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) | ||
1553 | |||
1554 | int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | ||
1555 | char **buf, bool display) | ||
1556 | { | ||
1557 | u32 base; /* SRAM byte address of event log header */ | ||
1558 | u32 capacity; /* event log capacity in # entries */ | ||
1559 | u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ | ||
1560 | u32 num_wraps; /* # times uCode wrapped to top of log */ | ||
1561 | u32 next_entry; /* index of next entry to be written by uCode */ | ||
1562 | u32 size; /* # entries that we'll print */ | ||
1563 | int pos = 0; | ||
1564 | size_t bufsz = 0; | ||
1565 | |||
1566 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | ||
1567 | if (!iwl3945_hw_valid_rtc_data_addr(base)) { | ||
1568 | IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); | ||
1569 | return -EINVAL; | ||
1570 | } | ||
1571 | |||
1572 | /* event log header */ | ||
1573 | capacity = iwl_read_targ_mem(priv, base); | ||
1574 | mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); | ||
1575 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | ||
1576 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | ||
1577 | |||
1578 | if (capacity > priv->cfg->base_params->max_event_log_size) { | ||
1579 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", | ||
1580 | capacity, priv->cfg->base_params->max_event_log_size); | ||
1581 | capacity = priv->cfg->base_params->max_event_log_size; | ||
1582 | } | ||
1583 | |||
1584 | if (next_entry > priv->cfg->base_params->max_event_log_size) { | ||
1585 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", | ||
1586 | next_entry, priv->cfg->base_params->max_event_log_size); | ||
1587 | next_entry = priv->cfg->base_params->max_event_log_size; | ||
1588 | } | ||
1589 | |||
1590 | size = num_wraps ? capacity : next_entry; | ||
1591 | |||
1592 | /* bail out if nothing in log */ | ||
1593 | if (size == 0) { | ||
1594 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); | ||
1595 | return pos; | ||
1596 | } | ||
1597 | |||
1598 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1599 | if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log) | ||
1600 | size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES) | ||
1601 | ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size; | ||
1602 | #else | ||
1603 | size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES) | ||
1604 | ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size; | ||
1605 | #endif | ||
1606 | |||
1607 | IWL_ERR(priv, "Start IWL Event Log Dump: display last %d count\n", | ||
1608 | size); | ||
1609 | |||
1610 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1611 | if (display) { | ||
1612 | if (full_log) | ||
1613 | bufsz = capacity * 48; | ||
1614 | else | ||
1615 | bufsz = size * 48; | ||
1616 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
1617 | if (!*buf) | ||
1618 | return -ENOMEM; | ||
1619 | } | ||
1620 | if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { | ||
1621 | /* if uCode has wrapped back to top of log, | ||
1622 | * start at the oldest entry, | ||
1623 | * i.e the next one that uCode would fill. | ||
1624 | */ | ||
1625 | if (num_wraps) | ||
1626 | pos = iwl3945_print_event_log(priv, next_entry, | ||
1627 | capacity - next_entry, mode, | ||
1628 | pos, buf, bufsz); | ||
1629 | |||
1630 | /* (then/else) start at top of log */ | ||
1631 | pos = iwl3945_print_event_log(priv, 0, next_entry, mode, | ||
1632 | pos, buf, bufsz); | ||
1633 | } else | ||
1634 | pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps, | ||
1635 | next_entry, size, mode, | ||
1636 | pos, buf, bufsz); | ||
1637 | #else | ||
1638 | pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps, | ||
1639 | next_entry, size, mode, | ||
1640 | pos, buf, bufsz); | ||
1641 | #endif | ||
1642 | return pos; | ||
1643 | } | ||
1644 | |||
1645 | static void iwl3945_irq_tasklet(struct iwl_priv *priv) | ||
1646 | { | ||
1647 | u32 inta, handled = 0; | ||
1648 | u32 inta_fh; | ||
1649 | unsigned long flags; | ||
1650 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1651 | u32 inta_mask; | ||
1652 | #endif | ||
1653 | |||
1654 | spin_lock_irqsave(&priv->lock, flags); | ||
1655 | |||
1656 | /* Ack/clear/reset pending uCode interrupts. | ||
1657 | * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, | ||
1658 | * and will clear only when CSR_FH_INT_STATUS gets cleared. */ | ||
1659 | inta = iwl_read32(priv, CSR_INT); | ||
1660 | iwl_write32(priv, CSR_INT, inta); | ||
1661 | |||
1662 | /* Ack/clear/reset pending flow-handler (DMA) interrupts. | ||
1663 | * Any new interrupts that happen after this, either while we're | ||
1664 | * in this tasklet, or later, will show up in next ISR/tasklet. */ | ||
1665 | inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); | ||
1666 | iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); | ||
1667 | |||
1668 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1669 | if (iwl_get_debug_level(priv) & IWL_DL_ISR) { | ||
1670 | /* just for debug */ | ||
1671 | inta_mask = iwl_read32(priv, CSR_INT_MASK); | ||
1672 | IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", | ||
1673 | inta, inta_mask, inta_fh); | ||
1674 | } | ||
1675 | #endif | ||
1676 | |||
1677 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1678 | |||
1679 | /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not | ||
1680 | * atomic, make sure that inta covers all the interrupts that | ||
1681 | * we've discovered, even if FH interrupt came in just after | ||
1682 | * reading CSR_INT. */ | ||
1683 | if (inta_fh & CSR39_FH_INT_RX_MASK) | ||
1684 | inta |= CSR_INT_BIT_FH_RX; | ||
1685 | if (inta_fh & CSR39_FH_INT_TX_MASK) | ||
1686 | inta |= CSR_INT_BIT_FH_TX; | ||
1687 | |||
1688 | /* Now service all interrupt bits discovered above. */ | ||
1689 | if (inta & CSR_INT_BIT_HW_ERR) { | ||
1690 | IWL_ERR(priv, "Hardware error detected. Restarting.\n"); | ||
1691 | |||
1692 | /* Tell the device to stop sending interrupts */ | ||
1693 | iwl_disable_interrupts(priv); | ||
1694 | |||
1695 | priv->isr_stats.hw++; | ||
1696 | iwl_irq_handle_error(priv); | ||
1697 | |||
1698 | handled |= CSR_INT_BIT_HW_ERR; | ||
1699 | |||
1700 | return; | ||
1701 | } | ||
1702 | |||
1703 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1704 | if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { | ||
1705 | /* NIC fires this, but we don't use it, redundant with WAKEUP */ | ||
1706 | if (inta & CSR_INT_BIT_SCD) { | ||
1707 | IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " | ||
1708 | "the frame/frames.\n"); | ||
1709 | priv->isr_stats.sch++; | ||
1710 | } | ||
1711 | |||
1712 | /* Alive notification via Rx interrupt will do the real work */ | ||
1713 | if (inta & CSR_INT_BIT_ALIVE) { | ||
1714 | IWL_DEBUG_ISR(priv, "Alive interrupt\n"); | ||
1715 | priv->isr_stats.alive++; | ||
1716 | } | ||
1717 | } | ||
1718 | #endif | ||
1719 | /* Safely ignore these bits for debug checks below */ | ||
1720 | inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE); | ||
1721 | |||
1722 | /* Error detected by uCode */ | ||
1723 | if (inta & CSR_INT_BIT_SW_ERR) { | ||
1724 | IWL_ERR(priv, "Microcode SW error detected. " | ||
1725 | "Restarting 0x%X.\n", inta); | ||
1726 | priv->isr_stats.sw++; | ||
1727 | iwl_irq_handle_error(priv); | ||
1728 | handled |= CSR_INT_BIT_SW_ERR; | ||
1729 | } | ||
1730 | |||
1731 | /* uCode wakes up after power-down sleep */ | ||
1732 | if (inta & CSR_INT_BIT_WAKEUP) { | ||
1733 | IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); | ||
1734 | iwl_rx_queue_update_write_ptr(priv, &priv->rxq); | ||
1735 | iwl_txq_update_write_ptr(priv, &priv->txq[0]); | ||
1736 | iwl_txq_update_write_ptr(priv, &priv->txq[1]); | ||
1737 | iwl_txq_update_write_ptr(priv, &priv->txq[2]); | ||
1738 | iwl_txq_update_write_ptr(priv, &priv->txq[3]); | ||
1739 | iwl_txq_update_write_ptr(priv, &priv->txq[4]); | ||
1740 | iwl_txq_update_write_ptr(priv, &priv->txq[5]); | ||
1741 | |||
1742 | priv->isr_stats.wakeup++; | ||
1743 | handled |= CSR_INT_BIT_WAKEUP; | ||
1744 | } | ||
1745 | |||
1746 | /* All uCode command responses, including Tx command responses, | ||
1747 | * Rx "responses" (frame-received notification), and other | ||
1748 | * notifications from uCode come through here*/ | ||
1749 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { | ||
1750 | iwl3945_rx_handle(priv); | ||
1751 | priv->isr_stats.rx++; | ||
1752 | handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); | ||
1753 | } | ||
1754 | |||
1755 | if (inta & CSR_INT_BIT_FH_TX) { | ||
1756 | IWL_DEBUG_ISR(priv, "Tx interrupt\n"); | ||
1757 | priv->isr_stats.tx++; | ||
1758 | |||
1759 | iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6)); | ||
1760 | iwl_write_direct32(priv, FH39_TCSR_CREDIT | ||
1761 | (FH39_SRVC_CHNL), 0x0); | ||
1762 | handled |= CSR_INT_BIT_FH_TX; | ||
1763 | } | ||
1764 | |||
1765 | if (inta & ~handled) { | ||
1766 | IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); | ||
1767 | priv->isr_stats.unhandled++; | ||
1768 | } | ||
1769 | |||
1770 | if (inta & ~priv->inta_mask) { | ||
1771 | IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", | ||
1772 | inta & ~priv->inta_mask); | ||
1773 | IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh); | ||
1774 | } | ||
1775 | |||
1776 | /* Re-enable all interrupts */ | ||
1777 | /* only Re-enable if disabled by irq */ | ||
1778 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) | ||
1779 | iwl_enable_interrupts(priv); | ||
1780 | |||
1781 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1782 | if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { | ||
1783 | inta = iwl_read32(priv, CSR_INT); | ||
1784 | inta_mask = iwl_read32(priv, CSR_INT_MASK); | ||
1785 | inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); | ||
1786 | IWL_DEBUG_ISR(priv, "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, " | ||
1787 | "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); | ||
1788 | } | ||
1789 | #endif | ||
1790 | } | ||
1791 | |||
1792 | static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv, | ||
1793 | struct ieee80211_vif *vif, | ||
1794 | enum ieee80211_band band, | ||
1795 | struct iwl3945_scan_channel *scan_ch) | ||
1796 | { | ||
1797 | const struct ieee80211_supported_band *sband; | ||
1798 | u16 passive_dwell = 0; | ||
1799 | u16 active_dwell = 0; | ||
1800 | int added = 0; | ||
1801 | u8 channel = 0; | ||
1802 | |||
1803 | sband = iwl_get_hw_mode(priv, band); | ||
1804 | if (!sband) { | ||
1805 | IWL_ERR(priv, "invalid band\n"); | ||
1806 | return added; | ||
1807 | } | ||
1808 | |||
1809 | active_dwell = iwl_get_active_dwell_time(priv, band, 0); | ||
1810 | passive_dwell = iwl_get_passive_dwell_time(priv, band, vif); | ||
1811 | |||
1812 | if (passive_dwell <= active_dwell) | ||
1813 | passive_dwell = active_dwell + 1; | ||
1814 | |||
1815 | |||
1816 | channel = iwl_get_single_channel_number(priv, band); | ||
1817 | |||
1818 | if (channel) { | ||
1819 | scan_ch->channel = channel; | ||
1820 | scan_ch->type = 0; /* passive */ | ||
1821 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | ||
1822 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | ||
1823 | /* Set txpower levels to defaults */ | ||
1824 | scan_ch->tpc.dsp_atten = 110; | ||
1825 | if (band == IEEE80211_BAND_5GHZ) | ||
1826 | scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
1827 | else | ||
1828 | scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3)); | ||
1829 | added++; | ||
1830 | } else | ||
1831 | IWL_ERR(priv, "no valid channel found\n"); | ||
1832 | return added; | ||
1833 | } | ||
1834 | |||
1835 | static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, | ||
1836 | enum ieee80211_band band, | ||
1837 | u8 is_active, u8 n_probes, | ||
1838 | struct iwl3945_scan_channel *scan_ch, | ||
1839 | struct ieee80211_vif *vif) | ||
1840 | { | ||
1841 | struct ieee80211_channel *chan; | ||
1842 | const struct ieee80211_supported_band *sband; | ||
1843 | const struct iwl_channel_info *ch_info; | ||
1844 | u16 passive_dwell = 0; | ||
1845 | u16 active_dwell = 0; | ||
1846 | int added, i; | ||
1847 | |||
1848 | sband = iwl_get_hw_mode(priv, band); | ||
1849 | if (!sband) | ||
1850 | return 0; | ||
1851 | |||
1852 | active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); | ||
1853 | passive_dwell = iwl_get_passive_dwell_time(priv, band, vif); | ||
1854 | |||
1855 | if (passive_dwell <= active_dwell) | ||
1856 | passive_dwell = active_dwell + 1; | ||
1857 | |||
1858 | for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) { | ||
1859 | chan = priv->scan_request->channels[i]; | ||
1860 | |||
1861 | if (chan->band != band) | ||
1862 | continue; | ||
1863 | |||
1864 | scan_ch->channel = chan->hw_value; | ||
1865 | |||
1866 | ch_info = iwl_get_channel_info(priv, band, scan_ch->channel); | ||
1867 | if (!is_channel_valid(ch_info)) { | ||
1868 | IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n", | ||
1869 | scan_ch->channel); | ||
1870 | continue; | ||
1871 | } | ||
1872 | |||
1873 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | ||
1874 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | ||
1875 | /* If passive , set up for auto-switch | ||
1876 | * and use long active_dwell time. | ||
1877 | */ | ||
1878 | if (!is_active || is_channel_passive(ch_info) || | ||
1879 | (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) { | ||
1880 | scan_ch->type = 0; /* passive */ | ||
1881 | if (IWL_UCODE_API(priv->ucode_ver) == 1) | ||
1882 | scan_ch->active_dwell = cpu_to_le16(passive_dwell - 1); | ||
1883 | } else { | ||
1884 | scan_ch->type = 1; /* active */ | ||
1885 | } | ||
1886 | |||
1887 | /* Set direct probe bits. These may be used both for active | ||
1888 | * scan channels (probes gets sent right away), | ||
1889 | * or for passive channels (probes get se sent only after | ||
1890 | * hearing clear Rx packet).*/ | ||
1891 | if (IWL_UCODE_API(priv->ucode_ver) >= 2) { | ||
1892 | if (n_probes) | ||
1893 | scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes); | ||
1894 | } else { | ||
1895 | /* uCode v1 does not allow setting direct probe bits on | ||
1896 | * passive channel. */ | ||
1897 | if ((scan_ch->type & 1) && n_probes) | ||
1898 | scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes); | ||
1899 | } | ||
1900 | |||
1901 | /* Set txpower levels to defaults */ | ||
1902 | scan_ch->tpc.dsp_atten = 110; | ||
1903 | /* scan_pwr_info->tpc.dsp_atten; */ | ||
1904 | |||
1905 | /*scan_pwr_info->tpc.tx_gain; */ | ||
1906 | if (band == IEEE80211_BAND_5GHZ) | ||
1907 | scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
1908 | else { | ||
1909 | scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3)); | ||
1910 | /* NOTE: if we were doing 6Mb OFDM for scans we'd use | ||
1911 | * power level: | ||
1912 | * scan_ch->tpc.tx_gain = ((1 << 5) | (2 << 3)) | 3; | ||
1913 | */ | ||
1914 | } | ||
1915 | |||
1916 | IWL_DEBUG_SCAN(priv, "Scanning %d [%s %d]\n", | ||
1917 | scan_ch->channel, | ||
1918 | (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE", | ||
1919 | (scan_ch->type & 1) ? | ||
1920 | active_dwell : passive_dwell); | ||
1921 | |||
1922 | scan_ch++; | ||
1923 | added++; | ||
1924 | } | ||
1925 | |||
1926 | IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); | ||
1927 | return added; | ||
1928 | } | ||
1929 | |||
1930 | static void iwl3945_init_hw_rates(struct iwl_priv *priv, | ||
1931 | struct ieee80211_rate *rates) | ||
1932 | { | ||
1933 | int i; | ||
1934 | |||
1935 | for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) { | ||
1936 | rates[i].bitrate = iwl3945_rates[i].ieee * 5; | ||
1937 | rates[i].hw_value = i; /* Rate scaling will work on indexes */ | ||
1938 | rates[i].hw_value_short = i; | ||
1939 | rates[i].flags = 0; | ||
1940 | if ((i > IWL39_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) { | ||
1941 | /* | ||
1942 | * If CCK != 1M then set short preamble rate flag. | ||
1943 | */ | ||
1944 | rates[i].flags |= (iwl3945_rates[i].plcp == 10) ? | ||
1945 | 0 : IEEE80211_RATE_SHORT_PREAMBLE; | ||
1946 | } | ||
1947 | } | ||
1948 | } | ||
1949 | |||
1950 | /****************************************************************************** | ||
1951 | * | ||
1952 | * uCode download functions | ||
1953 | * | ||
1954 | ******************************************************************************/ | ||
1955 | |||
1956 | static void iwl3945_dealloc_ucode_pci(struct iwl_priv *priv) | ||
1957 | { | ||
1958 | iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code); | ||
1959 | iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data); | ||
1960 | iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup); | ||
1961 | iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init); | ||
1962 | iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data); | ||
1963 | iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot); | ||
1964 | } | ||
1965 | |||
1966 | /** | ||
1967 | * iwl3945_verify_inst_full - verify runtime uCode image in card vs. host, | ||
1968 | * looking at all data. | ||
1969 | */ | ||
1970 | static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 len) | ||
1971 | { | ||
1972 | u32 val; | ||
1973 | u32 save_len = len; | ||
1974 | int rc = 0; | ||
1975 | u32 errcnt; | ||
1976 | |||
1977 | IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); | ||
1978 | |||
1979 | iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, | ||
1980 | IWL39_RTC_INST_LOWER_BOUND); | ||
1981 | |||
1982 | errcnt = 0; | ||
1983 | for (; len > 0; len -= sizeof(u32), image++) { | ||
1984 | /* read data comes through single port, auto-incr addr */ | ||
1985 | /* NOTE: Use the debugless read so we don't flood kernel log | ||
1986 | * if IWL_DL_IO is set */ | ||
1987 | val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
1988 | if (val != le32_to_cpu(*image)) { | ||
1989 | IWL_ERR(priv, "uCode INST section is invalid at " | ||
1990 | "offset 0x%x, is 0x%x, s/b 0x%x\n", | ||
1991 | save_len - len, val, le32_to_cpu(*image)); | ||
1992 | rc = -EIO; | ||
1993 | errcnt++; | ||
1994 | if (errcnt >= 20) | ||
1995 | break; | ||
1996 | } | ||
1997 | } | ||
1998 | |||
1999 | |||
2000 | if (!errcnt) | ||
2001 | IWL_DEBUG_INFO(priv, | ||
2002 | "ucode image in INSTRUCTION memory is good\n"); | ||
2003 | |||
2004 | return rc; | ||
2005 | } | ||
2006 | |||
2007 | |||
2008 | /** | ||
2009 | * iwl3945_verify_inst_sparse - verify runtime uCode image in card vs. host, | ||
2010 | * using sample data 100 bytes apart. If these sample points are good, | ||
2011 | * it's a pretty good bet that everything between them is good, too. | ||
2012 | */ | ||
2013 | static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len) | ||
2014 | { | ||
2015 | u32 val; | ||
2016 | int rc = 0; | ||
2017 | u32 errcnt = 0; | ||
2018 | u32 i; | ||
2019 | |||
2020 | IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); | ||
2021 | |||
2022 | for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { | ||
2023 | /* read data comes through single port, auto-incr addr */ | ||
2024 | /* NOTE: Use the debugless read so we don't flood kernel log | ||
2025 | * if IWL_DL_IO is set */ | ||
2026 | iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, | ||
2027 | i + IWL39_RTC_INST_LOWER_BOUND); | ||
2028 | val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
2029 | if (val != le32_to_cpu(*image)) { | ||
2030 | #if 0 /* Enable this if you want to see details */ | ||
2031 | IWL_ERR(priv, "uCode INST section is invalid at " | ||
2032 | "offset 0x%x, is 0x%x, s/b 0x%x\n", | ||
2033 | i, val, *image); | ||
2034 | #endif | ||
2035 | rc = -EIO; | ||
2036 | errcnt++; | ||
2037 | if (errcnt >= 3) | ||
2038 | break; | ||
2039 | } | ||
2040 | } | ||
2041 | |||
2042 | return rc; | ||
2043 | } | ||
2044 | |||
2045 | |||
2046 | /** | ||
2047 | * iwl3945_verify_ucode - determine which instruction image is in SRAM, | ||
2048 | * and verify its contents | ||
2049 | */ | ||
2050 | static int iwl3945_verify_ucode(struct iwl_priv *priv) | ||
2051 | { | ||
2052 | __le32 *image; | ||
2053 | u32 len; | ||
2054 | int rc = 0; | ||
2055 | |||
2056 | /* Try bootstrap */ | ||
2057 | image = (__le32 *)priv->ucode_boot.v_addr; | ||
2058 | len = priv->ucode_boot.len; | ||
2059 | rc = iwl3945_verify_inst_sparse(priv, image, len); | ||
2060 | if (rc == 0) { | ||
2061 | IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n"); | ||
2062 | return 0; | ||
2063 | } | ||
2064 | |||
2065 | /* Try initialize */ | ||
2066 | image = (__le32 *)priv->ucode_init.v_addr; | ||
2067 | len = priv->ucode_init.len; | ||
2068 | rc = iwl3945_verify_inst_sparse(priv, image, len); | ||
2069 | if (rc == 0) { | ||
2070 | IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n"); | ||
2071 | return 0; | ||
2072 | } | ||
2073 | |||
2074 | /* Try runtime/protocol */ | ||
2075 | image = (__le32 *)priv->ucode_code.v_addr; | ||
2076 | len = priv->ucode_code.len; | ||
2077 | rc = iwl3945_verify_inst_sparse(priv, image, len); | ||
2078 | if (rc == 0) { | ||
2079 | IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n"); | ||
2080 | return 0; | ||
2081 | } | ||
2082 | |||
2083 | IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); | ||
2084 | |||
2085 | /* Since nothing seems to match, show first several data entries in | ||
2086 | * instruction SRAM, so maybe visual inspection will give a clue. | ||
2087 | * Selection of bootstrap image (vs. other images) is arbitrary. */ | ||
2088 | image = (__le32 *)priv->ucode_boot.v_addr; | ||
2089 | len = priv->ucode_boot.len; | ||
2090 | rc = iwl3945_verify_inst_full(priv, image, len); | ||
2091 | |||
2092 | return rc; | ||
2093 | } | ||
2094 | |||
2095 | static void iwl3945_nic_start(struct iwl_priv *priv) | ||
2096 | { | ||
2097 | /* Remove all resets to allow NIC to operate */ | ||
2098 | iwl_write32(priv, CSR_RESET, 0); | ||
2099 | } | ||
2100 | |||
2101 | #define IWL3945_UCODE_GET(item) \ | ||
2102 | static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode)\ | ||
2103 | { \ | ||
2104 | return le32_to_cpu(ucode->u.v1.item); \ | ||
2105 | } | ||
2106 | |||
2107 | static u32 iwl3945_ucode_get_header_size(u32 api_ver) | ||
2108 | { | ||
2109 | return 24; | ||
2110 | } | ||
2111 | |||
2112 | static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode) | ||
2113 | { | ||
2114 | return (u8 *) ucode->u.v1.data; | ||
2115 | } | ||
2116 | |||
2117 | IWL3945_UCODE_GET(inst_size); | ||
2118 | IWL3945_UCODE_GET(data_size); | ||
2119 | IWL3945_UCODE_GET(init_size); | ||
2120 | IWL3945_UCODE_GET(init_data_size); | ||
2121 | IWL3945_UCODE_GET(boot_size); | ||
2122 | |||
2123 | /** | ||
2124 | * iwl3945_read_ucode - Read uCode images from disk file. | ||
2125 | * | ||
2126 | * Copy into buffers for card to fetch via bus-mastering | ||
2127 | */ | ||
2128 | static int iwl3945_read_ucode(struct iwl_priv *priv) | ||
2129 | { | ||
2130 | const struct iwl_ucode_header *ucode; | ||
2131 | int ret = -EINVAL, index; | ||
2132 | const struct firmware *ucode_raw; | ||
2133 | /* firmware file name contains uCode/driver compatibility version */ | ||
2134 | const char *name_pre = priv->cfg->fw_name_pre; | ||
2135 | const unsigned int api_max = priv->cfg->ucode_api_max; | ||
2136 | const unsigned int api_min = priv->cfg->ucode_api_min; | ||
2137 | char buf[25]; | ||
2138 | u8 *src; | ||
2139 | size_t len; | ||
2140 | u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size; | ||
2141 | |||
2142 | /* Ask kernel firmware_class module to get the boot firmware off disk. | ||
2143 | * request_firmware() is synchronous, file is in memory on return. */ | ||
2144 | for (index = api_max; index >= api_min; index--) { | ||
2145 | sprintf(buf, "%s%u%s", name_pre, index, ".ucode"); | ||
2146 | ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev); | ||
2147 | if (ret < 0) { | ||
2148 | IWL_ERR(priv, "%s firmware file req failed: %d\n", | ||
2149 | buf, ret); | ||
2150 | if (ret == -ENOENT) | ||
2151 | continue; | ||
2152 | else | ||
2153 | goto error; | ||
2154 | } else { | ||
2155 | if (index < api_max) | ||
2156 | IWL_ERR(priv, "Loaded firmware %s, " | ||
2157 | "which is deprecated. " | ||
2158 | " Please use API v%u instead.\n", | ||
2159 | buf, api_max); | ||
2160 | IWL_DEBUG_INFO(priv, "Got firmware '%s' file " | ||
2161 | "(%zd bytes) from disk\n", | ||
2162 | buf, ucode_raw->size); | ||
2163 | break; | ||
2164 | } | ||
2165 | } | ||
2166 | |||
2167 | if (ret < 0) | ||
2168 | goto error; | ||
2169 | |||
2170 | /* Make sure that we got at least our header! */ | ||
2171 | if (ucode_raw->size < iwl3945_ucode_get_header_size(1)) { | ||
2172 | IWL_ERR(priv, "File size way too small!\n"); | ||
2173 | ret = -EINVAL; | ||
2174 | goto err_release; | ||
2175 | } | ||
2176 | |||
2177 | /* Data from ucode file: header followed by uCode images */ | ||
2178 | ucode = (struct iwl_ucode_header *)ucode_raw->data; | ||
2179 | |||
2180 | priv->ucode_ver = le32_to_cpu(ucode->ver); | ||
2181 | api_ver = IWL_UCODE_API(priv->ucode_ver); | ||
2182 | inst_size = iwl3945_ucode_get_inst_size(ucode); | ||
2183 | data_size = iwl3945_ucode_get_data_size(ucode); | ||
2184 | init_size = iwl3945_ucode_get_init_size(ucode); | ||
2185 | init_data_size = iwl3945_ucode_get_init_data_size(ucode); | ||
2186 | boot_size = iwl3945_ucode_get_boot_size(ucode); | ||
2187 | src = iwl3945_ucode_get_data(ucode); | ||
2188 | |||
2189 | /* api_ver should match the api version forming part of the | ||
2190 | * firmware filename ... but we don't check for that and only rely | ||
2191 | * on the API version read from firmware header from here on forward */ | ||
2192 | |||
2193 | if (api_ver < api_min || api_ver > api_max) { | ||
2194 | IWL_ERR(priv, "Driver unable to support your firmware API. " | ||
2195 | "Driver supports v%u, firmware is v%u.\n", | ||
2196 | api_max, api_ver); | ||
2197 | priv->ucode_ver = 0; | ||
2198 | ret = -EINVAL; | ||
2199 | goto err_release; | ||
2200 | } | ||
2201 | if (api_ver != api_max) | ||
2202 | IWL_ERR(priv, "Firmware has old API version. Expected %u, " | ||
2203 | "got %u. New firmware can be obtained " | ||
2204 | "from http://www.intellinuxwireless.org.\n", | ||
2205 | api_max, api_ver); | ||
2206 | |||
2207 | IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n", | ||
2208 | IWL_UCODE_MAJOR(priv->ucode_ver), | ||
2209 | IWL_UCODE_MINOR(priv->ucode_ver), | ||
2210 | IWL_UCODE_API(priv->ucode_ver), | ||
2211 | IWL_UCODE_SERIAL(priv->ucode_ver)); | ||
2212 | |||
2213 | snprintf(priv->hw->wiphy->fw_version, | ||
2214 | sizeof(priv->hw->wiphy->fw_version), | ||
2215 | "%u.%u.%u.%u", | ||
2216 | IWL_UCODE_MAJOR(priv->ucode_ver), | ||
2217 | IWL_UCODE_MINOR(priv->ucode_ver), | ||
2218 | IWL_UCODE_API(priv->ucode_ver), | ||
2219 | IWL_UCODE_SERIAL(priv->ucode_ver)); | ||
2220 | |||
2221 | IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", | ||
2222 | priv->ucode_ver); | ||
2223 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", | ||
2224 | inst_size); | ||
2225 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %u\n", | ||
2226 | data_size); | ||
2227 | IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %u\n", | ||
2228 | init_size); | ||
2229 | IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %u\n", | ||
2230 | init_data_size); | ||
2231 | IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n", | ||
2232 | boot_size); | ||
2233 | |||
2234 | |||
2235 | /* Verify size of file vs. image size info in file's header */ | ||
2236 | if (ucode_raw->size != iwl3945_ucode_get_header_size(api_ver) + | ||
2237 | inst_size + data_size + init_size + | ||
2238 | init_data_size + boot_size) { | ||
2239 | |||
2240 | IWL_DEBUG_INFO(priv, | ||
2241 | "uCode file size %zd does not match expected size\n", | ||
2242 | ucode_raw->size); | ||
2243 | ret = -EINVAL; | ||
2244 | goto err_release; | ||
2245 | } | ||
2246 | |||
2247 | /* Verify that uCode images will fit in card's SRAM */ | ||
2248 | if (inst_size > IWL39_MAX_INST_SIZE) { | ||
2249 | IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n", | ||
2250 | inst_size); | ||
2251 | ret = -EINVAL; | ||
2252 | goto err_release; | ||
2253 | } | ||
2254 | |||
2255 | if (data_size > IWL39_MAX_DATA_SIZE) { | ||
2256 | IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n", | ||
2257 | data_size); | ||
2258 | ret = -EINVAL; | ||
2259 | goto err_release; | ||
2260 | } | ||
2261 | if (init_size > IWL39_MAX_INST_SIZE) { | ||
2262 | IWL_DEBUG_INFO(priv, | ||
2263 | "uCode init instr len %d too large to fit in\n", | ||
2264 | init_size); | ||
2265 | ret = -EINVAL; | ||
2266 | goto err_release; | ||
2267 | } | ||
2268 | if (init_data_size > IWL39_MAX_DATA_SIZE) { | ||
2269 | IWL_DEBUG_INFO(priv, | ||
2270 | "uCode init data len %d too large to fit in\n", | ||
2271 | init_data_size); | ||
2272 | ret = -EINVAL; | ||
2273 | goto err_release; | ||
2274 | } | ||
2275 | if (boot_size > IWL39_MAX_BSM_SIZE) { | ||
2276 | IWL_DEBUG_INFO(priv, | ||
2277 | "uCode boot instr len %d too large to fit in\n", | ||
2278 | boot_size); | ||
2279 | ret = -EINVAL; | ||
2280 | goto err_release; | ||
2281 | } | ||
2282 | |||
2283 | /* Allocate ucode buffers for card's bus-master loading ... */ | ||
2284 | |||
2285 | /* Runtime instructions and 2 copies of data: | ||
2286 | * 1) unmodified from disk | ||
2287 | * 2) backup cache for save/restore during power-downs */ | ||
2288 | priv->ucode_code.len = inst_size; | ||
2289 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code); | ||
2290 | |||
2291 | priv->ucode_data.len = data_size; | ||
2292 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); | ||
2293 | |||
2294 | priv->ucode_data_backup.len = data_size; | ||
2295 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup); | ||
2296 | |||
2297 | if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr || | ||
2298 | !priv->ucode_data_backup.v_addr) | ||
2299 | goto err_pci_alloc; | ||
2300 | |||
2301 | /* Initialization instructions and data */ | ||
2302 | if (init_size && init_data_size) { | ||
2303 | priv->ucode_init.len = init_size; | ||
2304 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init); | ||
2305 | |||
2306 | priv->ucode_init_data.len = init_data_size; | ||
2307 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data); | ||
2308 | |||
2309 | if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr) | ||
2310 | goto err_pci_alloc; | ||
2311 | } | ||
2312 | |||
2313 | /* Bootstrap (instructions only, no data) */ | ||
2314 | if (boot_size) { | ||
2315 | priv->ucode_boot.len = boot_size; | ||
2316 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot); | ||
2317 | |||
2318 | if (!priv->ucode_boot.v_addr) | ||
2319 | goto err_pci_alloc; | ||
2320 | } | ||
2321 | |||
2322 | /* Copy images into buffers for card's bus-master reads ... */ | ||
2323 | |||
2324 | /* Runtime instructions (first block of data in file) */ | ||
2325 | len = inst_size; | ||
2326 | IWL_DEBUG_INFO(priv, | ||
2327 | "Copying (but not loading) uCode instr len %zd\n", len); | ||
2328 | memcpy(priv->ucode_code.v_addr, src, len); | ||
2329 | src += len; | ||
2330 | |||
2331 | IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", | ||
2332 | priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); | ||
2333 | |||
2334 | /* Runtime data (2nd block) | ||
2335 | * NOTE: Copy into backup buffer will be done in iwl3945_up() */ | ||
2336 | len = data_size; | ||
2337 | IWL_DEBUG_INFO(priv, | ||
2338 | "Copying (but not loading) uCode data len %zd\n", len); | ||
2339 | memcpy(priv->ucode_data.v_addr, src, len); | ||
2340 | memcpy(priv->ucode_data_backup.v_addr, src, len); | ||
2341 | src += len; | ||
2342 | |||
2343 | /* Initialization instructions (3rd block) */ | ||
2344 | if (init_size) { | ||
2345 | len = init_size; | ||
2346 | IWL_DEBUG_INFO(priv, | ||
2347 | "Copying (but not loading) init instr len %zd\n", len); | ||
2348 | memcpy(priv->ucode_init.v_addr, src, len); | ||
2349 | src += len; | ||
2350 | } | ||
2351 | |||
2352 | /* Initialization data (4th block) */ | ||
2353 | if (init_data_size) { | ||
2354 | len = init_data_size; | ||
2355 | IWL_DEBUG_INFO(priv, | ||
2356 | "Copying (but not loading) init data len %zd\n", len); | ||
2357 | memcpy(priv->ucode_init_data.v_addr, src, len); | ||
2358 | src += len; | ||
2359 | } | ||
2360 | |||
2361 | /* Bootstrap instructions (5th block) */ | ||
2362 | len = boot_size; | ||
2363 | IWL_DEBUG_INFO(priv, | ||
2364 | "Copying (but not loading) boot instr len %zd\n", len); | ||
2365 | memcpy(priv->ucode_boot.v_addr, src, len); | ||
2366 | |||
2367 | /* We have our copies now, allow OS release its copies */ | ||
2368 | release_firmware(ucode_raw); | ||
2369 | return 0; | ||
2370 | |||
2371 | err_pci_alloc: | ||
2372 | IWL_ERR(priv, "failed to allocate pci memory\n"); | ||
2373 | ret = -ENOMEM; | ||
2374 | iwl3945_dealloc_ucode_pci(priv); | ||
2375 | |||
2376 | err_release: | ||
2377 | release_firmware(ucode_raw); | ||
2378 | |||
2379 | error: | ||
2380 | return ret; | ||
2381 | } | ||
2382 | |||
2383 | |||
2384 | /** | ||
2385 | * iwl3945_set_ucode_ptrs - Set uCode address location | ||
2386 | * | ||
2387 | * Tell initialization uCode where to find runtime uCode. | ||
2388 | * | ||
2389 | * BSM registers initially contain pointers to initialization uCode. | ||
2390 | * We need to replace them to load runtime uCode inst and data, | ||
2391 | * and to save runtime data when powering down. | ||
2392 | */ | ||
2393 | static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv) | ||
2394 | { | ||
2395 | dma_addr_t pinst; | ||
2396 | dma_addr_t pdata; | ||
2397 | |||
2398 | /* bits 31:0 for 3945 */ | ||
2399 | pinst = priv->ucode_code.p_addr; | ||
2400 | pdata = priv->ucode_data_backup.p_addr; | ||
2401 | |||
2402 | /* Tell bootstrap uCode where to find image to load */ | ||
2403 | iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); | ||
2404 | iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); | ||
2405 | iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, | ||
2406 | priv->ucode_data.len); | ||
2407 | |||
2408 | /* Inst byte count must be last to set up, bit 31 signals uCode | ||
2409 | * that all new ptr/size info is in place */ | ||
2410 | iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, | ||
2411 | priv->ucode_code.len | BSM_DRAM_INST_LOAD); | ||
2412 | |||
2413 | IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n"); | ||
2414 | |||
2415 | return 0; | ||
2416 | } | ||
2417 | |||
2418 | /** | ||
2419 | * iwl3945_init_alive_start - Called after REPLY_ALIVE notification received | ||
2420 | * | ||
2421 | * Called after REPLY_ALIVE notification received from "initialize" uCode. | ||
2422 | * | ||
2423 | * Tell "initialize" uCode to go ahead and load the runtime uCode. | ||
2424 | */ | ||
2425 | static void iwl3945_init_alive_start(struct iwl_priv *priv) | ||
2426 | { | ||
2427 | /* Check alive response for "valid" sign from uCode */ | ||
2428 | if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { | ||
2429 | /* We had an error bringing up the hardware, so take it | ||
2430 | * all the way back down so we can try again */ | ||
2431 | IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); | ||
2432 | goto restart; | ||
2433 | } | ||
2434 | |||
2435 | /* Bootstrap uCode has loaded initialize uCode ... verify inst image. | ||
2436 | * This is a paranoid check, because we would not have gotten the | ||
2437 | * "initialize" alive if code weren't properly loaded. */ | ||
2438 | if (iwl3945_verify_ucode(priv)) { | ||
2439 | /* Runtime instruction load was bad; | ||
2440 | * take it all the way back down so we can try again */ | ||
2441 | IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); | ||
2442 | goto restart; | ||
2443 | } | ||
2444 | |||
2445 | /* Send pointers to protocol/runtime uCode image ... init code will | ||
2446 | * load and launch runtime uCode, which will send us another "Alive" | ||
2447 | * notification. */ | ||
2448 | IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); | ||
2449 | if (iwl3945_set_ucode_ptrs(priv)) { | ||
2450 | /* Runtime instruction load won't happen; | ||
2451 | * take it all the way back down so we can try again */ | ||
2452 | IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n"); | ||
2453 | goto restart; | ||
2454 | } | ||
2455 | return; | ||
2456 | |||
2457 | restart: | ||
2458 | queue_work(priv->workqueue, &priv->restart); | ||
2459 | } | ||
2460 | |||
2461 | /** | ||
2462 | * iwl3945_alive_start - called after REPLY_ALIVE notification received | ||
2463 | * from protocol/runtime uCode (initialization uCode's | ||
2464 | * Alive gets handled by iwl3945_init_alive_start()). | ||
2465 | */ | ||
2466 | static void iwl3945_alive_start(struct iwl_priv *priv) | ||
2467 | { | ||
2468 | int thermal_spin = 0; | ||
2469 | u32 rfkill; | ||
2470 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
2471 | |||
2472 | IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); | ||
2473 | |||
2474 | if (priv->card_alive.is_valid != UCODE_VALID_OK) { | ||
2475 | /* We had an error bringing up the hardware, so take it | ||
2476 | * all the way back down so we can try again */ | ||
2477 | IWL_DEBUG_INFO(priv, "Alive failed.\n"); | ||
2478 | goto restart; | ||
2479 | } | ||
2480 | |||
2481 | /* Initialize uCode has loaded Runtime uCode ... verify inst image. | ||
2482 | * This is a paranoid check, because we would not have gotten the | ||
2483 | * "runtime" alive if code weren't properly loaded. */ | ||
2484 | if (iwl3945_verify_ucode(priv)) { | ||
2485 | /* Runtime instruction load was bad; | ||
2486 | * take it all the way back down so we can try again */ | ||
2487 | IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n"); | ||
2488 | goto restart; | ||
2489 | } | ||
2490 | |||
2491 | rfkill = iwl_read_prph(priv, APMG_RFKILL_REG); | ||
2492 | IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill); | ||
2493 | |||
2494 | if (rfkill & 0x1) { | ||
2495 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | ||
2496 | /* if RFKILL is not on, then wait for thermal | ||
2497 | * sensor in adapter to kick in */ | ||
2498 | while (iwl3945_hw_get_temperature(priv) == 0) { | ||
2499 | thermal_spin++; | ||
2500 | udelay(10); | ||
2501 | } | ||
2502 | |||
2503 | if (thermal_spin) | ||
2504 | IWL_DEBUG_INFO(priv, "Thermal calibration took %dus\n", | ||
2505 | thermal_spin * 10); | ||
2506 | } else | ||
2507 | set_bit(STATUS_RF_KILL_HW, &priv->status); | ||
2508 | |||
2509 | /* After the ALIVE response, we can send commands to 3945 uCode */ | ||
2510 | set_bit(STATUS_ALIVE, &priv->status); | ||
2511 | |||
2512 | /* Enable watchdog to monitor the driver tx queues */ | ||
2513 | iwl_setup_watchdog(priv); | ||
2514 | |||
2515 | if (iwl_is_rfkill(priv)) | ||
2516 | return; | ||
2517 | |||
2518 | ieee80211_wake_queues(priv->hw); | ||
2519 | |||
2520 | priv->active_rate = IWL_RATES_MASK_3945; | ||
2521 | |||
2522 | iwl_power_update_mode(priv, true); | ||
2523 | |||
2524 | if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) { | ||
2525 | struct iwl3945_rxon_cmd *active_rxon = | ||
2526 | (struct iwl3945_rxon_cmd *)(&ctx->active); | ||
2527 | |||
2528 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; | ||
2529 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
2530 | } else { | ||
2531 | /* Initialize our rx_config data */ | ||
2532 | iwl_connection_init_rx_config(priv, ctx); | ||
2533 | } | ||
2534 | |||
2535 | /* Configure Bluetooth device coexistence support */ | ||
2536 | priv->cfg->ops->hcmd->send_bt_config(priv); | ||
2537 | |||
2538 | set_bit(STATUS_READY, &priv->status); | ||
2539 | |||
2540 | /* Configure the adapter for unassociated operation */ | ||
2541 | iwl3945_commit_rxon(priv, ctx); | ||
2542 | |||
2543 | iwl3945_reg_txpower_periodic(priv); | ||
2544 | |||
2545 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); | ||
2546 | wake_up_interruptible(&priv->wait_command_queue); | ||
2547 | |||
2548 | return; | ||
2549 | |||
2550 | restart: | ||
2551 | queue_work(priv->workqueue, &priv->restart); | ||
2552 | } | ||
2553 | |||
2554 | static void iwl3945_cancel_deferred_work(struct iwl_priv *priv); | ||
2555 | |||
2556 | static void __iwl3945_down(struct iwl_priv *priv) | ||
2557 | { | ||
2558 | unsigned long flags; | ||
2559 | int exit_pending; | ||
2560 | |||
2561 | IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); | ||
2562 | |||
2563 | iwl_scan_cancel_timeout(priv, 200); | ||
2564 | |||
2565 | exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status); | ||
2566 | |||
2567 | /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set | ||
2568 | * to prevent rearm timer */ | ||
2569 | del_timer_sync(&priv->watchdog); | ||
2570 | |||
2571 | /* Station information will now be cleared in device */ | ||
2572 | iwl_clear_ucode_stations(priv, NULL); | ||
2573 | iwl_dealloc_bcast_stations(priv); | ||
2574 | iwl_clear_driver_stations(priv); | ||
2575 | |||
2576 | /* Unblock any waiting calls */ | ||
2577 | wake_up_interruptible_all(&priv->wait_command_queue); | ||
2578 | |||
2579 | /* Wipe out the EXIT_PENDING status bit if we are not actually | ||
2580 | * exiting the module */ | ||
2581 | if (!exit_pending) | ||
2582 | clear_bit(STATUS_EXIT_PENDING, &priv->status); | ||
2583 | |||
2584 | /* stop and reset the on-board processor */ | ||
2585 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | ||
2586 | |||
2587 | /* tell the device to stop sending interrupts */ | ||
2588 | spin_lock_irqsave(&priv->lock, flags); | ||
2589 | iwl_disable_interrupts(priv); | ||
2590 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2591 | iwl_synchronize_irq(priv); | ||
2592 | |||
2593 | if (priv->mac80211_registered) | ||
2594 | ieee80211_stop_queues(priv->hw); | ||
2595 | |||
2596 | /* If we have not previously called iwl3945_init() then | ||
2597 | * clear all bits but the RF Kill bits and return */ | ||
2598 | if (!iwl_is_init(priv)) { | ||
2599 | priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) << | ||
2600 | STATUS_RF_KILL_HW | | ||
2601 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << | ||
2602 | STATUS_GEO_CONFIGURED | | ||
2603 | test_bit(STATUS_EXIT_PENDING, &priv->status) << | ||
2604 | STATUS_EXIT_PENDING; | ||
2605 | goto exit; | ||
2606 | } | ||
2607 | |||
2608 | /* ...otherwise clear out all the status bits but the RF Kill | ||
2609 | * bit and continue taking the NIC down. */ | ||
2610 | priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << | ||
2611 | STATUS_RF_KILL_HW | | ||
2612 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << | ||
2613 | STATUS_GEO_CONFIGURED | | ||
2614 | test_bit(STATUS_FW_ERROR, &priv->status) << | ||
2615 | STATUS_FW_ERROR | | ||
2616 | test_bit(STATUS_EXIT_PENDING, &priv->status) << | ||
2617 | STATUS_EXIT_PENDING; | ||
2618 | |||
2619 | iwl3945_hw_txq_ctx_stop(priv); | ||
2620 | iwl3945_hw_rxq_stop(priv); | ||
2621 | |||
2622 | /* Power-down device's busmaster DMA clocks */ | ||
2623 | iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); | ||
2624 | udelay(5); | ||
2625 | |||
2626 | /* Stop the device, and put it in low power state */ | ||
2627 | iwl_apm_stop(priv); | ||
2628 | |||
2629 | exit: | ||
2630 | memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); | ||
2631 | |||
2632 | if (priv->beacon_skb) | ||
2633 | dev_kfree_skb(priv->beacon_skb); | ||
2634 | priv->beacon_skb = NULL; | ||
2635 | |||
2636 | /* clear out any free frames */ | ||
2637 | iwl3945_clear_free_frames(priv); | ||
2638 | } | ||
2639 | |||
2640 | static void iwl3945_down(struct iwl_priv *priv) | ||
2641 | { | ||
2642 | mutex_lock(&priv->mutex); | ||
2643 | __iwl3945_down(priv); | ||
2644 | mutex_unlock(&priv->mutex); | ||
2645 | |||
2646 | iwl3945_cancel_deferred_work(priv); | ||
2647 | } | ||
2648 | |||
2649 | #define MAX_HW_RESTARTS 5 | ||
2650 | |||
2651 | static int iwl3945_alloc_bcast_station(struct iwl_priv *priv) | ||
2652 | { | ||
2653 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
2654 | unsigned long flags; | ||
2655 | u8 sta_id; | ||
2656 | |||
2657 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
2658 | sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL); | ||
2659 | if (sta_id == IWL_INVALID_STATION) { | ||
2660 | IWL_ERR(priv, "Unable to prepare broadcast station\n"); | ||
2661 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
2662 | |||
2663 | return -EINVAL; | ||
2664 | } | ||
2665 | |||
2666 | priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; | ||
2667 | priv->stations[sta_id].used |= IWL_STA_BCAST; | ||
2668 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
2669 | |||
2670 | return 0; | ||
2671 | } | ||
2672 | |||
2673 | static int __iwl3945_up(struct iwl_priv *priv) | ||
2674 | { | ||
2675 | int rc, i; | ||
2676 | |||
2677 | rc = iwl3945_alloc_bcast_station(priv); | ||
2678 | if (rc) | ||
2679 | return rc; | ||
2680 | |||
2681 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | ||
2682 | IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); | ||
2683 | return -EIO; | ||
2684 | } | ||
2685 | |||
2686 | if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) { | ||
2687 | IWL_ERR(priv, "ucode not available for device bring up\n"); | ||
2688 | return -EIO; | ||
2689 | } | ||
2690 | |||
2691 | /* If platform's RF_KILL switch is NOT set to KILL */ | ||
2692 | if (iwl_read32(priv, CSR_GP_CNTRL) & | ||
2693 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) | ||
2694 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | ||
2695 | else { | ||
2696 | set_bit(STATUS_RF_KILL_HW, &priv->status); | ||
2697 | IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n"); | ||
2698 | return -ENODEV; | ||
2699 | } | ||
2700 | |||
2701 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); | ||
2702 | |||
2703 | rc = iwl3945_hw_nic_init(priv); | ||
2704 | if (rc) { | ||
2705 | IWL_ERR(priv, "Unable to int nic\n"); | ||
2706 | return rc; | ||
2707 | } | ||
2708 | |||
2709 | /* make sure rfkill handshake bits are cleared */ | ||
2710 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
2711 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, | ||
2712 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | ||
2713 | |||
2714 | /* clear (again), then enable host interrupts */ | ||
2715 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); | ||
2716 | iwl_enable_interrupts(priv); | ||
2717 | |||
2718 | /* really make sure rfkill handshake bits are cleared */ | ||
2719 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
2720 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
2721 | |||
2722 | /* Copy original ucode data image from disk into backup cache. | ||
2723 | * This will be used to initialize the on-board processor's | ||
2724 | * data SRAM for a clean start when the runtime program first loads. */ | ||
2725 | memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr, | ||
2726 | priv->ucode_data.len); | ||
2727 | |||
2728 | /* We return success when we resume from suspend and rf_kill is on. */ | ||
2729 | if (test_bit(STATUS_RF_KILL_HW, &priv->status)) | ||
2730 | return 0; | ||
2731 | |||
2732 | for (i = 0; i < MAX_HW_RESTARTS; i++) { | ||
2733 | |||
2734 | /* load bootstrap state machine, | ||
2735 | * load bootstrap program into processor's memory, | ||
2736 | * prepare to load the "initialize" uCode */ | ||
2737 | rc = priv->cfg->ops->lib->load_ucode(priv); | ||
2738 | |||
2739 | if (rc) { | ||
2740 | IWL_ERR(priv, | ||
2741 | "Unable to set up bootstrap uCode: %d\n", rc); | ||
2742 | continue; | ||
2743 | } | ||
2744 | |||
2745 | /* start card; "initialize" will load runtime ucode */ | ||
2746 | iwl3945_nic_start(priv); | ||
2747 | |||
2748 | IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n"); | ||
2749 | |||
2750 | return 0; | ||
2751 | } | ||
2752 | |||
2753 | set_bit(STATUS_EXIT_PENDING, &priv->status); | ||
2754 | __iwl3945_down(priv); | ||
2755 | clear_bit(STATUS_EXIT_PENDING, &priv->status); | ||
2756 | |||
2757 | /* tried to restart and config the device for as long as our | ||
2758 | * patience could withstand */ | ||
2759 | IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i); | ||
2760 | return -EIO; | ||
2761 | } | ||
2762 | |||
2763 | |||
2764 | /***************************************************************************** | ||
2765 | * | ||
2766 | * Workqueue callbacks | ||
2767 | * | ||
2768 | *****************************************************************************/ | ||
2769 | |||
2770 | static void iwl3945_bg_init_alive_start(struct work_struct *data) | ||
2771 | { | ||
2772 | struct iwl_priv *priv = | ||
2773 | container_of(data, struct iwl_priv, init_alive_start.work); | ||
2774 | |||
2775 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
2776 | return; | ||
2777 | |||
2778 | mutex_lock(&priv->mutex); | ||
2779 | iwl3945_init_alive_start(priv); | ||
2780 | mutex_unlock(&priv->mutex); | ||
2781 | } | ||
2782 | |||
2783 | static void iwl3945_bg_alive_start(struct work_struct *data) | ||
2784 | { | ||
2785 | struct iwl_priv *priv = | ||
2786 | container_of(data, struct iwl_priv, alive_start.work); | ||
2787 | |||
2788 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
2789 | return; | ||
2790 | |||
2791 | mutex_lock(&priv->mutex); | ||
2792 | iwl3945_alive_start(priv); | ||
2793 | mutex_unlock(&priv->mutex); | ||
2794 | } | ||
2795 | |||
2796 | /* | ||
2797 | * 3945 cannot interrupt driver when hardware rf kill switch toggles; | ||
2798 | * driver must poll CSR_GP_CNTRL_REG register for change. This register | ||
2799 | * *is* readable even when device has been SW_RESET into low power mode | ||
2800 | * (e.g. during RF KILL). | ||
2801 | */ | ||
2802 | static void iwl3945_rfkill_poll(struct work_struct *data) | ||
2803 | { | ||
2804 | struct iwl_priv *priv = | ||
2805 | container_of(data, struct iwl_priv, _3945.rfkill_poll.work); | ||
2806 | bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status); | ||
2807 | bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL) | ||
2808 | & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); | ||
2809 | |||
2810 | if (new_rfkill != old_rfkill) { | ||
2811 | if (new_rfkill) | ||
2812 | set_bit(STATUS_RF_KILL_HW, &priv->status); | ||
2813 | else | ||
2814 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | ||
2815 | |||
2816 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, new_rfkill); | ||
2817 | |||
2818 | IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n", | ||
2819 | new_rfkill ? "disable radio" : "enable radio"); | ||
2820 | } | ||
2821 | |||
2822 | /* Keep this running, even if radio now enabled. This will be | ||
2823 | * cancelled in mac_start() if system decides to start again */ | ||
2824 | queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll, | ||
2825 | round_jiffies_relative(2 * HZ)); | ||
2826 | |||
2827 | } | ||
2828 | |||
2829 | int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | ||
2830 | { | ||
2831 | struct iwl_host_cmd cmd = { | ||
2832 | .id = REPLY_SCAN_CMD, | ||
2833 | .len = sizeof(struct iwl3945_scan_cmd), | ||
2834 | .flags = CMD_SIZE_HUGE, | ||
2835 | }; | ||
2836 | struct iwl3945_scan_cmd *scan; | ||
2837 | u8 n_probes = 0; | ||
2838 | enum ieee80211_band band; | ||
2839 | bool is_active = false; | ||
2840 | int ret; | ||
2841 | |||
2842 | lockdep_assert_held(&priv->mutex); | ||
2843 | |||
2844 | if (!priv->scan_cmd) { | ||
2845 | priv->scan_cmd = kmalloc(sizeof(struct iwl3945_scan_cmd) + | ||
2846 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); | ||
2847 | if (!priv->scan_cmd) { | ||
2848 | IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n"); | ||
2849 | return -ENOMEM; | ||
2850 | } | ||
2851 | } | ||
2852 | scan = priv->scan_cmd; | ||
2853 | memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE); | ||
2854 | |||
2855 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; | ||
2856 | scan->quiet_time = IWL_ACTIVE_QUIET_TIME; | ||
2857 | |||
2858 | if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) { | ||
2859 | u16 interval = 0; | ||
2860 | u32 extra; | ||
2861 | u32 suspend_time = 100; | ||
2862 | u32 scan_suspend_time = 100; | ||
2863 | |||
2864 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); | ||
2865 | |||
2866 | if (priv->is_internal_short_scan) | ||
2867 | interval = 0; | ||
2868 | else | ||
2869 | interval = vif->bss_conf.beacon_int; | ||
2870 | |||
2871 | scan->suspend_time = 0; | ||
2872 | scan->max_out_time = cpu_to_le32(200 * 1024); | ||
2873 | if (!interval) | ||
2874 | interval = suspend_time; | ||
2875 | /* | ||
2876 | * suspend time format: | ||
2877 | * 0-19: beacon interval in usec (time before exec.) | ||
2878 | * 20-23: 0 | ||
2879 | * 24-31: number of beacons (suspend between channels) | ||
2880 | */ | ||
2881 | |||
2882 | extra = (suspend_time / interval) << 24; | ||
2883 | scan_suspend_time = 0xFF0FFFFF & | ||
2884 | (extra | ((suspend_time % interval) * 1024)); | ||
2885 | |||
2886 | scan->suspend_time = cpu_to_le32(scan_suspend_time); | ||
2887 | IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", | ||
2888 | scan_suspend_time, interval); | ||
2889 | } | ||
2890 | |||
2891 | if (priv->is_internal_short_scan) { | ||
2892 | IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); | ||
2893 | } else if (priv->scan_request->n_ssids) { | ||
2894 | int i, p = 0; | ||
2895 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); | ||
2896 | for (i = 0; i < priv->scan_request->n_ssids; i++) { | ||
2897 | /* always does wildcard anyway */ | ||
2898 | if (!priv->scan_request->ssids[i].ssid_len) | ||
2899 | continue; | ||
2900 | scan->direct_scan[p].id = WLAN_EID_SSID; | ||
2901 | scan->direct_scan[p].len = | ||
2902 | priv->scan_request->ssids[i].ssid_len; | ||
2903 | memcpy(scan->direct_scan[p].ssid, | ||
2904 | priv->scan_request->ssids[i].ssid, | ||
2905 | priv->scan_request->ssids[i].ssid_len); | ||
2906 | n_probes++; | ||
2907 | p++; | ||
2908 | } | ||
2909 | is_active = true; | ||
2910 | } else | ||
2911 | IWL_DEBUG_SCAN(priv, "Kicking off passive scan.\n"); | ||
2912 | |||
2913 | /* We don't build a direct scan probe request; the uCode will do | ||
2914 | * that based on the direct_mask added to each channel entry */ | ||
2915 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; | ||
2916 | scan->tx_cmd.sta_id = priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id; | ||
2917 | scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
2918 | |||
2919 | /* flags + rate selection */ | ||
2920 | |||
2921 | switch (priv->scan_band) { | ||
2922 | case IEEE80211_BAND_2GHZ: | ||
2923 | scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; | ||
2924 | scan->tx_cmd.rate = IWL_RATE_1M_PLCP; | ||
2925 | band = IEEE80211_BAND_2GHZ; | ||
2926 | break; | ||
2927 | case IEEE80211_BAND_5GHZ: | ||
2928 | scan->tx_cmd.rate = IWL_RATE_6M_PLCP; | ||
2929 | band = IEEE80211_BAND_5GHZ; | ||
2930 | break; | ||
2931 | default: | ||
2932 | IWL_WARN(priv, "Invalid scan band\n"); | ||
2933 | return -EIO; | ||
2934 | } | ||
2935 | |||
2936 | /* | ||
2937 | * If active scaning is requested but a certain channel | ||
2938 | * is marked passive, we can do active scanning if we | ||
2939 | * detect transmissions. | ||
2940 | */ | ||
2941 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : | ||
2942 | IWL_GOOD_CRC_TH_DISABLED; | ||
2943 | |||
2944 | if (!priv->is_internal_short_scan) { | ||
2945 | scan->tx_cmd.len = cpu_to_le16( | ||
2946 | iwl_fill_probe_req(priv, | ||
2947 | (struct ieee80211_mgmt *)scan->data, | ||
2948 | vif->addr, | ||
2949 | priv->scan_request->ie, | ||
2950 | priv->scan_request->ie_len, | ||
2951 | IWL_MAX_SCAN_SIZE - sizeof(*scan))); | ||
2952 | } else { | ||
2953 | /* use bcast addr, will not be transmitted but must be valid */ | ||
2954 | scan->tx_cmd.len = cpu_to_le16( | ||
2955 | iwl_fill_probe_req(priv, | ||
2956 | (struct ieee80211_mgmt *)scan->data, | ||
2957 | iwl_bcast_addr, NULL, 0, | ||
2958 | IWL_MAX_SCAN_SIZE - sizeof(*scan))); | ||
2959 | } | ||
2960 | /* select Rx antennas */ | ||
2961 | scan->flags |= iwl3945_get_antenna_flags(priv); | ||
2962 | |||
2963 | if (priv->is_internal_short_scan) { | ||
2964 | scan->channel_count = | ||
2965 | iwl3945_get_single_channel_for_scan(priv, vif, band, | ||
2966 | (void *)&scan->data[le16_to_cpu( | ||
2967 | scan->tx_cmd.len)]); | ||
2968 | } else { | ||
2969 | scan->channel_count = | ||
2970 | iwl3945_get_channels_for_scan(priv, band, is_active, n_probes, | ||
2971 | (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif); | ||
2972 | } | ||
2973 | |||
2974 | if (scan->channel_count == 0) { | ||
2975 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); | ||
2976 | return -EIO; | ||
2977 | } | ||
2978 | |||
2979 | cmd.len += le16_to_cpu(scan->tx_cmd.len) + | ||
2980 | scan->channel_count * sizeof(struct iwl3945_scan_channel); | ||
2981 | cmd.data = scan; | ||
2982 | scan->len = cpu_to_le16(cmd.len); | ||
2983 | |||
2984 | set_bit(STATUS_SCAN_HW, &priv->status); | ||
2985 | ret = iwl_send_cmd_sync(priv, &cmd); | ||
2986 | if (ret) | ||
2987 | clear_bit(STATUS_SCAN_HW, &priv->status); | ||
2988 | return ret; | ||
2989 | } | ||
2990 | |||
2991 | void iwl3945_post_scan(struct iwl_priv *priv) | ||
2992 | { | ||
2993 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
2994 | |||
2995 | /* | ||
2996 | * Since setting the RXON may have been deferred while | ||
2997 | * performing the scan, fire one off if needed | ||
2998 | */ | ||
2999 | if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) | ||
3000 | iwl3945_commit_rxon(priv, ctx); | ||
3001 | } | ||
3002 | |||
3003 | static void iwl3945_bg_restart(struct work_struct *data) | ||
3004 | { | ||
3005 | struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); | ||
3006 | |||
3007 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
3008 | return; | ||
3009 | |||
3010 | if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { | ||
3011 | struct iwl_rxon_context *ctx; | ||
3012 | mutex_lock(&priv->mutex); | ||
3013 | for_each_context(priv, ctx) | ||
3014 | ctx->vif = NULL; | ||
3015 | priv->is_open = 0; | ||
3016 | mutex_unlock(&priv->mutex); | ||
3017 | iwl3945_down(priv); | ||
3018 | ieee80211_restart_hw(priv->hw); | ||
3019 | } else { | ||
3020 | iwl3945_down(priv); | ||
3021 | |||
3022 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
3023 | return; | ||
3024 | |||
3025 | mutex_lock(&priv->mutex); | ||
3026 | __iwl3945_up(priv); | ||
3027 | mutex_unlock(&priv->mutex); | ||
3028 | } | ||
3029 | } | ||
3030 | |||
3031 | static void iwl3945_bg_rx_replenish(struct work_struct *data) | ||
3032 | { | ||
3033 | struct iwl_priv *priv = | ||
3034 | container_of(data, struct iwl_priv, rx_replenish); | ||
3035 | |||
3036 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
3037 | return; | ||
3038 | |||
3039 | mutex_lock(&priv->mutex); | ||
3040 | iwl3945_rx_replenish(priv); | ||
3041 | mutex_unlock(&priv->mutex); | ||
3042 | } | ||
3043 | |||
3044 | void iwl3945_post_associate(struct iwl_priv *priv) | ||
3045 | { | ||
3046 | int rc = 0; | ||
3047 | struct ieee80211_conf *conf = NULL; | ||
3048 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
3049 | |||
3050 | if (!ctx->vif || !priv->is_open) | ||
3051 | return; | ||
3052 | |||
3053 | if (ctx->vif->type == NL80211_IFTYPE_AP) { | ||
3054 | IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); | ||
3055 | return; | ||
3056 | } | ||
3057 | |||
3058 | IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", | ||
3059 | ctx->vif->bss_conf.aid, ctx->active.bssid_addr); | ||
3060 | |||
3061 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
3062 | return; | ||
3063 | |||
3064 | iwl_scan_cancel_timeout(priv, 200); | ||
3065 | |||
3066 | conf = ieee80211_get_hw_conf(priv->hw); | ||
3067 | |||
3068 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
3069 | iwl3945_commit_rxon(priv, ctx); | ||
3070 | |||
3071 | rc = iwl_send_rxon_timing(priv, ctx); | ||
3072 | if (rc) | ||
3073 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " | ||
3074 | "Attempting to continue.\n"); | ||
3075 | |||
3076 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; | ||
3077 | |||
3078 | ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid); | ||
3079 | |||
3080 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", | ||
3081 | ctx->vif->bss_conf.aid, ctx->vif->bss_conf.beacon_int); | ||
3082 | |||
3083 | if (ctx->vif->bss_conf.use_short_preamble) | ||
3084 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | ||
3085 | else | ||
3086 | ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | ||
3087 | |||
3088 | if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { | ||
3089 | if (ctx->vif->bss_conf.use_short_slot) | ||
3090 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; | ||
3091 | else | ||
3092 | ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | ||
3093 | } | ||
3094 | |||
3095 | iwl3945_commit_rxon(priv, ctx); | ||
3096 | |||
3097 | switch (ctx->vif->type) { | ||
3098 | case NL80211_IFTYPE_STATION: | ||
3099 | iwl3945_rate_scale_init(priv->hw, IWL_AP_ID); | ||
3100 | break; | ||
3101 | case NL80211_IFTYPE_ADHOC: | ||
3102 | iwl3945_send_beacon_cmd(priv); | ||
3103 | break; | ||
3104 | default: | ||
3105 | IWL_ERR(priv, "%s Should not be called in %d mode\n", | ||
3106 | __func__, ctx->vif->type); | ||
3107 | break; | ||
3108 | } | ||
3109 | } | ||
3110 | |||
3111 | /***************************************************************************** | ||
3112 | * | ||
3113 | * mac80211 entry point functions | ||
3114 | * | ||
3115 | *****************************************************************************/ | ||
3116 | |||
3117 | #define UCODE_READY_TIMEOUT (2 * HZ) | ||
3118 | |||
3119 | static int iwl3945_mac_start(struct ieee80211_hw *hw) | ||
3120 | { | ||
3121 | struct iwl_priv *priv = hw->priv; | ||
3122 | int ret; | ||
3123 | |||
3124 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
3125 | |||
3126 | /* we should be verifying the device is ready to be opened */ | ||
3127 | mutex_lock(&priv->mutex); | ||
3128 | |||
3129 | /* fetch ucode file from disk, alloc and copy to bus-master buffers ... | ||
3130 | * ucode filename and max sizes are card-specific. */ | ||
3131 | |||
3132 | if (!priv->ucode_code.len) { | ||
3133 | ret = iwl3945_read_ucode(priv); | ||
3134 | if (ret) { | ||
3135 | IWL_ERR(priv, "Could not read microcode: %d\n", ret); | ||
3136 | mutex_unlock(&priv->mutex); | ||
3137 | goto out_release_irq; | ||
3138 | } | ||
3139 | } | ||
3140 | |||
3141 | ret = __iwl3945_up(priv); | ||
3142 | |||
3143 | mutex_unlock(&priv->mutex); | ||
3144 | |||
3145 | if (ret) | ||
3146 | goto out_release_irq; | ||
3147 | |||
3148 | IWL_DEBUG_INFO(priv, "Start UP work.\n"); | ||
3149 | |||
3150 | /* Wait for START_ALIVE from ucode. Otherwise callbacks from | ||
3151 | * mac80211 will not be run successfully. */ | ||
3152 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, | ||
3153 | test_bit(STATUS_READY, &priv->status), | ||
3154 | UCODE_READY_TIMEOUT); | ||
3155 | if (!ret) { | ||
3156 | if (!test_bit(STATUS_READY, &priv->status)) { | ||
3157 | IWL_ERR(priv, | ||
3158 | "Wait for START_ALIVE timeout after %dms.\n", | ||
3159 | jiffies_to_msecs(UCODE_READY_TIMEOUT)); | ||
3160 | ret = -ETIMEDOUT; | ||
3161 | goto out_release_irq; | ||
3162 | } | ||
3163 | } | ||
3164 | |||
3165 | /* ucode is running and will send rfkill notifications, | ||
3166 | * no need to poll the killswitch state anymore */ | ||
3167 | cancel_delayed_work(&priv->_3945.rfkill_poll); | ||
3168 | |||
3169 | priv->is_open = 1; | ||
3170 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
3171 | return 0; | ||
3172 | |||
3173 | out_release_irq: | ||
3174 | priv->is_open = 0; | ||
3175 | IWL_DEBUG_MAC80211(priv, "leave - failed\n"); | ||
3176 | return ret; | ||
3177 | } | ||
3178 | |||
3179 | static void iwl3945_mac_stop(struct ieee80211_hw *hw) | ||
3180 | { | ||
3181 | struct iwl_priv *priv = hw->priv; | ||
3182 | |||
3183 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
3184 | |||
3185 | if (!priv->is_open) { | ||
3186 | IWL_DEBUG_MAC80211(priv, "leave - skip\n"); | ||
3187 | return; | ||
3188 | } | ||
3189 | |||
3190 | priv->is_open = 0; | ||
3191 | |||
3192 | iwl3945_down(priv); | ||
3193 | |||
3194 | flush_workqueue(priv->workqueue); | ||
3195 | |||
3196 | /* start polling the killswitch state again */ | ||
3197 | queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll, | ||
3198 | round_jiffies_relative(2 * HZ)); | ||
3199 | |||
3200 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
3201 | } | ||
3202 | |||
3203 | static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
3204 | { | ||
3205 | struct iwl_priv *priv = hw->priv; | ||
3206 | |||
3207 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
3208 | |||
3209 | IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, | ||
3210 | ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); | ||
3211 | |||
3212 | if (iwl3945_tx_skb(priv, skb)) | ||
3213 | dev_kfree_skb_any(skb); | ||
3214 | |||
3215 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
3216 | return NETDEV_TX_OK; | ||
3217 | } | ||
3218 | |||
3219 | void iwl3945_config_ap(struct iwl_priv *priv) | ||
3220 | { | ||
3221 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
3222 | struct ieee80211_vif *vif = ctx->vif; | ||
3223 | int rc = 0; | ||
3224 | |||
3225 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
3226 | return; | ||
3227 | |||
3228 | /* The following should be done only at AP bring up */ | ||
3229 | if (!(iwl_is_associated(priv, IWL_RXON_CTX_BSS))) { | ||
3230 | |||
3231 | /* RXON - unassoc (to set timing command) */ | ||
3232 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
3233 | iwl3945_commit_rxon(priv, ctx); | ||
3234 | |||
3235 | /* RXON Timing */ | ||
3236 | rc = iwl_send_rxon_timing(priv, ctx); | ||
3237 | if (rc) | ||
3238 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " | ||
3239 | "Attempting to continue.\n"); | ||
3240 | |||
3241 | ctx->staging.assoc_id = 0; | ||
3242 | |||
3243 | if (vif->bss_conf.use_short_preamble) | ||
3244 | ctx->staging.flags |= | ||
3245 | RXON_FLG_SHORT_PREAMBLE_MSK; | ||
3246 | else | ||
3247 | ctx->staging.flags &= | ||
3248 | ~RXON_FLG_SHORT_PREAMBLE_MSK; | ||
3249 | |||
3250 | if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { | ||
3251 | if (vif->bss_conf.use_short_slot) | ||
3252 | ctx->staging.flags |= | ||
3253 | RXON_FLG_SHORT_SLOT_MSK; | ||
3254 | else | ||
3255 | ctx->staging.flags &= | ||
3256 | ~RXON_FLG_SHORT_SLOT_MSK; | ||
3257 | } | ||
3258 | /* restore RXON assoc */ | ||
3259 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; | ||
3260 | iwl3945_commit_rxon(priv, ctx); | ||
3261 | } | ||
3262 | iwl3945_send_beacon_cmd(priv); | ||
3263 | |||
3264 | /* FIXME - we need to add code here to detect a totally new | ||
3265 | * configuration, reset the AP, unassoc, rxon timing, assoc, | ||
3266 | * clear sta table, add BCAST sta... */ | ||
3267 | } | ||
3268 | |||
3269 | static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||
3270 | struct ieee80211_vif *vif, | ||
3271 | struct ieee80211_sta *sta, | ||
3272 | struct ieee80211_key_conf *key) | ||
3273 | { | ||
3274 | struct iwl_priv *priv = hw->priv; | ||
3275 | int ret = 0; | ||
3276 | u8 sta_id = IWL_INVALID_STATION; | ||
3277 | u8 static_key; | ||
3278 | |||
3279 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
3280 | |||
3281 | if (iwl3945_mod_params.sw_crypto) { | ||
3282 | IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); | ||
3283 | return -EOPNOTSUPP; | ||
3284 | } | ||
3285 | |||
3286 | /* | ||
3287 | * To support IBSS RSN, don't program group keys in IBSS, the | ||
3288 | * hardware will then not attempt to decrypt the frames. | ||
3289 | */ | ||
3290 | if (vif->type == NL80211_IFTYPE_ADHOC && | ||
3291 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | ||
3292 | return -EOPNOTSUPP; | ||
3293 | |||
3294 | static_key = !iwl_is_associated(priv, IWL_RXON_CTX_BSS); | ||
3295 | |||
3296 | if (!static_key) { | ||
3297 | sta_id = iwl_sta_id_or_broadcast( | ||
3298 | priv, &priv->contexts[IWL_RXON_CTX_BSS], sta); | ||
3299 | if (sta_id == IWL_INVALID_STATION) | ||
3300 | return -EINVAL; | ||
3301 | } | ||
3302 | |||
3303 | mutex_lock(&priv->mutex); | ||
3304 | iwl_scan_cancel_timeout(priv, 100); | ||
3305 | |||
3306 | switch (cmd) { | ||
3307 | case SET_KEY: | ||
3308 | if (static_key) | ||
3309 | ret = iwl3945_set_static_key(priv, key); | ||
3310 | else | ||
3311 | ret = iwl3945_set_dynamic_key(priv, key, sta_id); | ||
3312 | IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n"); | ||
3313 | break; | ||
3314 | case DISABLE_KEY: | ||
3315 | if (static_key) | ||
3316 | ret = iwl3945_remove_static_key(priv); | ||
3317 | else | ||
3318 | ret = iwl3945_clear_sta_key_info(priv, sta_id); | ||
3319 | IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n"); | ||
3320 | break; | ||
3321 | default: | ||
3322 | ret = -EINVAL; | ||
3323 | } | ||
3324 | |||
3325 | mutex_unlock(&priv->mutex); | ||
3326 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
3327 | |||
3328 | return ret; | ||
3329 | } | ||
3330 | |||
3331 | static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, | ||
3332 | struct ieee80211_vif *vif, | ||
3333 | struct ieee80211_sta *sta) | ||
3334 | { | ||
3335 | struct iwl_priv *priv = hw->priv; | ||
3336 | struct iwl3945_sta_priv *sta_priv = (void *)sta->drv_priv; | ||
3337 | int ret; | ||
3338 | bool is_ap = vif->type == NL80211_IFTYPE_STATION; | ||
3339 | u8 sta_id; | ||
3340 | |||
3341 | IWL_DEBUG_INFO(priv, "received request to add station %pM\n", | ||
3342 | sta->addr); | ||
3343 | mutex_lock(&priv->mutex); | ||
3344 | IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n", | ||
3345 | sta->addr); | ||
3346 | sta_priv->common.sta_id = IWL_INVALID_STATION; | ||
3347 | |||
3348 | |||
3349 | ret = iwl_add_station_common(priv, &priv->contexts[IWL_RXON_CTX_BSS], | ||
3350 | sta->addr, is_ap, sta, &sta_id); | ||
3351 | if (ret) { | ||
3352 | IWL_ERR(priv, "Unable to add station %pM (%d)\n", | ||
3353 | sta->addr, ret); | ||
3354 | /* Should we return success if return code is EEXIST ? */ | ||
3355 | mutex_unlock(&priv->mutex); | ||
3356 | return ret; | ||
3357 | } | ||
3358 | |||
3359 | sta_priv->common.sta_id = sta_id; | ||
3360 | |||
3361 | /* Initialize rate scaling */ | ||
3362 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", | ||
3363 | sta->addr); | ||
3364 | iwl3945_rs_rate_init(priv, sta, sta_id); | ||
3365 | mutex_unlock(&priv->mutex); | ||
3366 | |||
3367 | return 0; | ||
3368 | } | ||
3369 | |||
3370 | static void iwl3945_configure_filter(struct ieee80211_hw *hw, | ||
3371 | unsigned int changed_flags, | ||
3372 | unsigned int *total_flags, | ||
3373 | u64 multicast) | ||
3374 | { | ||
3375 | struct iwl_priv *priv = hw->priv; | ||
3376 | __le32 filter_or = 0, filter_nand = 0; | ||
3377 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
3378 | |||
3379 | #define CHK(test, flag) do { \ | ||
3380 | if (*total_flags & (test)) \ | ||
3381 | filter_or |= (flag); \ | ||
3382 | else \ | ||
3383 | filter_nand |= (flag); \ | ||
3384 | } while (0) | ||
3385 | |||
3386 | IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", | ||
3387 | changed_flags, *total_flags); | ||
3388 | |||
3389 | CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); | ||
3390 | CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); | ||
3391 | CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); | ||
3392 | |||
3393 | #undef CHK | ||
3394 | |||
3395 | mutex_lock(&priv->mutex); | ||
3396 | |||
3397 | ctx->staging.filter_flags &= ~filter_nand; | ||
3398 | ctx->staging.filter_flags |= filter_or; | ||
3399 | |||
3400 | /* | ||
3401 | * Not committing directly because hardware can perform a scan, | ||
3402 | * but even if hw is ready, committing here breaks for some reason, | ||
3403 | * we'll eventually commit the filter flags change anyway. | ||
3404 | */ | ||
3405 | |||
3406 | mutex_unlock(&priv->mutex); | ||
3407 | |||
3408 | /* | ||
3409 | * Receiving all multicast frames is always enabled by the | ||
3410 | * default flags setup in iwl_connection_init_rx_config() | ||
3411 | * since we currently do not support programming multicast | ||
3412 | * filters into the device. | ||
3413 | */ | ||
3414 | *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | | ||
3415 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; | ||
3416 | } | ||
3417 | |||
3418 | |||
3419 | /***************************************************************************** | ||
3420 | * | ||
3421 | * sysfs attributes | ||
3422 | * | ||
3423 | *****************************************************************************/ | ||
3424 | |||
3425 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3426 | |||
3427 | /* | ||
3428 | * The following adds a new attribute to the sysfs representation | ||
3429 | * of this device driver (i.e. a new file in /sys/bus/pci/drivers/iwl/) | ||
3430 | * used for controlling the debug level. | ||
3431 | * | ||
3432 | * See the level definitions in iwl for details. | ||
3433 | * | ||
3434 | * The debug_level being managed using sysfs below is a per device debug | ||
3435 | * level that is used instead of the global debug level if it (the per | ||
3436 | * device debug level) is set. | ||
3437 | */ | ||
3438 | static ssize_t show_debug_level(struct device *d, | ||
3439 | struct device_attribute *attr, char *buf) | ||
3440 | { | ||
3441 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3442 | return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv)); | ||
3443 | } | ||
3444 | static ssize_t store_debug_level(struct device *d, | ||
3445 | struct device_attribute *attr, | ||
3446 | const char *buf, size_t count) | ||
3447 | { | ||
3448 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3449 | unsigned long val; | ||
3450 | int ret; | ||
3451 | |||
3452 | ret = strict_strtoul(buf, 0, &val); | ||
3453 | if (ret) | ||
3454 | IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf); | ||
3455 | else { | ||
3456 | priv->debug_level = val; | ||
3457 | if (iwl_alloc_traffic_mem(priv)) | ||
3458 | IWL_ERR(priv, | ||
3459 | "Not enough memory to generate traffic log\n"); | ||
3460 | } | ||
3461 | return strnlen(buf, count); | ||
3462 | } | ||
3463 | |||
3464 | static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, | ||
3465 | show_debug_level, store_debug_level); | ||
3466 | |||
3467 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
3468 | |||
3469 | static ssize_t show_temperature(struct device *d, | ||
3470 | struct device_attribute *attr, char *buf) | ||
3471 | { | ||
3472 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3473 | |||
3474 | if (!iwl_is_alive(priv)) | ||
3475 | return -EAGAIN; | ||
3476 | |||
3477 | return sprintf(buf, "%d\n", iwl3945_hw_get_temperature(priv)); | ||
3478 | } | ||
3479 | |||
3480 | static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); | ||
3481 | |||
3482 | static ssize_t show_tx_power(struct device *d, | ||
3483 | struct device_attribute *attr, char *buf) | ||
3484 | { | ||
3485 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3486 | return sprintf(buf, "%d\n", priv->tx_power_user_lmt); | ||
3487 | } | ||
3488 | |||
3489 | static ssize_t store_tx_power(struct device *d, | ||
3490 | struct device_attribute *attr, | ||
3491 | const char *buf, size_t count) | ||
3492 | { | ||
3493 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3494 | char *p = (char *)buf; | ||
3495 | u32 val; | ||
3496 | |||
3497 | val = simple_strtoul(p, &p, 10); | ||
3498 | if (p == buf) | ||
3499 | IWL_INFO(priv, ": %s is not in decimal form.\n", buf); | ||
3500 | else | ||
3501 | iwl3945_hw_reg_set_txpower(priv, val); | ||
3502 | |||
3503 | return count; | ||
3504 | } | ||
3505 | |||
3506 | static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); | ||
3507 | |||
3508 | static ssize_t show_flags(struct device *d, | ||
3509 | struct device_attribute *attr, char *buf) | ||
3510 | { | ||
3511 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3512 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
3513 | |||
3514 | return sprintf(buf, "0x%04X\n", ctx->active.flags); | ||
3515 | } | ||
3516 | |||
3517 | static ssize_t store_flags(struct device *d, | ||
3518 | struct device_attribute *attr, | ||
3519 | const char *buf, size_t count) | ||
3520 | { | ||
3521 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3522 | u32 flags = simple_strtoul(buf, NULL, 0); | ||
3523 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
3524 | |||
3525 | mutex_lock(&priv->mutex); | ||
3526 | if (le32_to_cpu(ctx->staging.flags) != flags) { | ||
3527 | /* Cancel any currently running scans... */ | ||
3528 | if (iwl_scan_cancel_timeout(priv, 100)) | ||
3529 | IWL_WARN(priv, "Could not cancel scan.\n"); | ||
3530 | else { | ||
3531 | IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n", | ||
3532 | flags); | ||
3533 | ctx->staging.flags = cpu_to_le32(flags); | ||
3534 | iwl3945_commit_rxon(priv, ctx); | ||
3535 | } | ||
3536 | } | ||
3537 | mutex_unlock(&priv->mutex); | ||
3538 | |||
3539 | return count; | ||
3540 | } | ||
3541 | |||
3542 | static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags); | ||
3543 | |||
3544 | static ssize_t show_filter_flags(struct device *d, | ||
3545 | struct device_attribute *attr, char *buf) | ||
3546 | { | ||
3547 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3548 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
3549 | |||
3550 | return sprintf(buf, "0x%04X\n", | ||
3551 | le32_to_cpu(ctx->active.filter_flags)); | ||
3552 | } | ||
3553 | |||
3554 | static ssize_t store_filter_flags(struct device *d, | ||
3555 | struct device_attribute *attr, | ||
3556 | const char *buf, size_t count) | ||
3557 | { | ||
3558 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3559 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
3560 | u32 filter_flags = simple_strtoul(buf, NULL, 0); | ||
3561 | |||
3562 | mutex_lock(&priv->mutex); | ||
3563 | if (le32_to_cpu(ctx->staging.filter_flags) != filter_flags) { | ||
3564 | /* Cancel any currently running scans... */ | ||
3565 | if (iwl_scan_cancel_timeout(priv, 100)) | ||
3566 | IWL_WARN(priv, "Could not cancel scan.\n"); | ||
3567 | else { | ||
3568 | IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = " | ||
3569 | "0x%04X\n", filter_flags); | ||
3570 | ctx->staging.filter_flags = | ||
3571 | cpu_to_le32(filter_flags); | ||
3572 | iwl3945_commit_rxon(priv, ctx); | ||
3573 | } | ||
3574 | } | ||
3575 | mutex_unlock(&priv->mutex); | ||
3576 | |||
3577 | return count; | ||
3578 | } | ||
3579 | |||
3580 | static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, | ||
3581 | store_filter_flags); | ||
3582 | |||
3583 | static ssize_t show_measurement(struct device *d, | ||
3584 | struct device_attribute *attr, char *buf) | ||
3585 | { | ||
3586 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3587 | struct iwl_spectrum_notification measure_report; | ||
3588 | u32 size = sizeof(measure_report), len = 0, ofs = 0; | ||
3589 | u8 *data = (u8 *)&measure_report; | ||
3590 | unsigned long flags; | ||
3591 | |||
3592 | spin_lock_irqsave(&priv->lock, flags); | ||
3593 | if (!(priv->measurement_status & MEASUREMENT_READY)) { | ||
3594 | spin_unlock_irqrestore(&priv->lock, flags); | ||
3595 | return 0; | ||
3596 | } | ||
3597 | memcpy(&measure_report, &priv->measure_report, size); | ||
3598 | priv->measurement_status = 0; | ||
3599 | spin_unlock_irqrestore(&priv->lock, flags); | ||
3600 | |||
3601 | while (size && (PAGE_SIZE - len)) { | ||
3602 | hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len, | ||
3603 | PAGE_SIZE - len, 1); | ||
3604 | len = strlen(buf); | ||
3605 | if (PAGE_SIZE - len) | ||
3606 | buf[len++] = '\n'; | ||
3607 | |||
3608 | ofs += 16; | ||
3609 | size -= min(size, 16U); | ||
3610 | } | ||
3611 | |||
3612 | return len; | ||
3613 | } | ||
3614 | |||
3615 | static ssize_t store_measurement(struct device *d, | ||
3616 | struct device_attribute *attr, | ||
3617 | const char *buf, size_t count) | ||
3618 | { | ||
3619 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3620 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
3621 | struct ieee80211_measurement_params params = { | ||
3622 | .channel = le16_to_cpu(ctx->active.channel), | ||
3623 | .start_time = cpu_to_le64(priv->_3945.last_tsf), | ||
3624 | .duration = cpu_to_le16(1), | ||
3625 | }; | ||
3626 | u8 type = IWL_MEASURE_BASIC; | ||
3627 | u8 buffer[32]; | ||
3628 | u8 channel; | ||
3629 | |||
3630 | if (count) { | ||
3631 | char *p = buffer; | ||
3632 | strncpy(buffer, buf, min(sizeof(buffer), count)); | ||
3633 | channel = simple_strtoul(p, NULL, 0); | ||
3634 | if (channel) | ||
3635 | params.channel = channel; | ||
3636 | |||
3637 | p = buffer; | ||
3638 | while (*p && *p != ' ') | ||
3639 | p++; | ||
3640 | if (*p) | ||
3641 | type = simple_strtoul(p + 1, NULL, 0); | ||
3642 | } | ||
3643 | |||
3644 | IWL_DEBUG_INFO(priv, "Invoking measurement of type %d on " | ||
3645 | "channel %d (for '%s')\n", type, params.channel, buf); | ||
3646 | iwl3945_get_measurement(priv, ¶ms, type); | ||
3647 | |||
3648 | return count; | ||
3649 | } | ||
3650 | |||
3651 | static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, | ||
3652 | show_measurement, store_measurement); | ||
3653 | |||
3654 | static ssize_t store_retry_rate(struct device *d, | ||
3655 | struct device_attribute *attr, | ||
3656 | const char *buf, size_t count) | ||
3657 | { | ||
3658 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3659 | |||
3660 | priv->retry_rate = simple_strtoul(buf, NULL, 0); | ||
3661 | if (priv->retry_rate <= 0) | ||
3662 | priv->retry_rate = 1; | ||
3663 | |||
3664 | return count; | ||
3665 | } | ||
3666 | |||
3667 | static ssize_t show_retry_rate(struct device *d, | ||
3668 | struct device_attribute *attr, char *buf) | ||
3669 | { | ||
3670 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3671 | return sprintf(buf, "%d", priv->retry_rate); | ||
3672 | } | ||
3673 | |||
3674 | static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate, | ||
3675 | store_retry_rate); | ||
3676 | |||
3677 | |||
3678 | static ssize_t show_channels(struct device *d, | ||
3679 | struct device_attribute *attr, char *buf) | ||
3680 | { | ||
3681 | /* all this shit doesn't belong into sysfs anyway */ | ||
3682 | return 0; | ||
3683 | } | ||
3684 | |||
3685 | static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL); | ||
3686 | |||
3687 | static ssize_t show_antenna(struct device *d, | ||
3688 | struct device_attribute *attr, char *buf) | ||
3689 | { | ||
3690 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3691 | |||
3692 | if (!iwl_is_alive(priv)) | ||
3693 | return -EAGAIN; | ||
3694 | |||
3695 | return sprintf(buf, "%d\n", iwl3945_mod_params.antenna); | ||
3696 | } | ||
3697 | |||
3698 | static ssize_t store_antenna(struct device *d, | ||
3699 | struct device_attribute *attr, | ||
3700 | const char *buf, size_t count) | ||
3701 | { | ||
3702 | struct iwl_priv *priv __maybe_unused = dev_get_drvdata(d); | ||
3703 | int ant; | ||
3704 | |||
3705 | if (count == 0) | ||
3706 | return 0; | ||
3707 | |||
3708 | if (sscanf(buf, "%1i", &ant) != 1) { | ||
3709 | IWL_DEBUG_INFO(priv, "not in hex or decimal form.\n"); | ||
3710 | return count; | ||
3711 | } | ||
3712 | |||
3713 | if ((ant >= 0) && (ant <= 2)) { | ||
3714 | IWL_DEBUG_INFO(priv, "Setting antenna select to %d.\n", ant); | ||
3715 | iwl3945_mod_params.antenna = (enum iwl3945_antenna)ant; | ||
3716 | } else | ||
3717 | IWL_DEBUG_INFO(priv, "Bad antenna select value %d.\n", ant); | ||
3718 | |||
3719 | |||
3720 | return count; | ||
3721 | } | ||
3722 | |||
3723 | static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna); | ||
3724 | |||
3725 | static ssize_t show_status(struct device *d, | ||
3726 | struct device_attribute *attr, char *buf) | ||
3727 | { | ||
3728 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3729 | if (!iwl_is_alive(priv)) | ||
3730 | return -EAGAIN; | ||
3731 | return sprintf(buf, "0x%08x\n", (int)priv->status); | ||
3732 | } | ||
3733 | |||
3734 | static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); | ||
3735 | |||
3736 | static ssize_t dump_error_log(struct device *d, | ||
3737 | struct device_attribute *attr, | ||
3738 | const char *buf, size_t count) | ||
3739 | { | ||
3740 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3741 | char *p = (char *)buf; | ||
3742 | |||
3743 | if (p[0] == '1') | ||
3744 | iwl3945_dump_nic_error_log(priv); | ||
3745 | |||
3746 | return strnlen(buf, count); | ||
3747 | } | ||
3748 | |||
3749 | static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log); | ||
3750 | |||
3751 | /***************************************************************************** | ||
3752 | * | ||
3753 | * driver setup and tear down | ||
3754 | * | ||
3755 | *****************************************************************************/ | ||
3756 | |||
3757 | static void iwl3945_setup_deferred_work(struct iwl_priv *priv) | ||
3758 | { | ||
3759 | priv->workqueue = create_singlethread_workqueue(DRV_NAME); | ||
3760 | |||
3761 | init_waitqueue_head(&priv->wait_command_queue); | ||
3762 | |||
3763 | INIT_WORK(&priv->restart, iwl3945_bg_restart); | ||
3764 | INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish); | ||
3765 | INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); | ||
3766 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); | ||
3767 | INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); | ||
3768 | INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll); | ||
3769 | |||
3770 | iwl_setup_scan_deferred_work(priv); | ||
3771 | |||
3772 | iwl3945_hw_setup_deferred_work(priv); | ||
3773 | |||
3774 | init_timer(&priv->watchdog); | ||
3775 | priv->watchdog.data = (unsigned long)priv; | ||
3776 | priv->watchdog.function = iwl_bg_watchdog; | ||
3777 | |||
3778 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | ||
3779 | iwl3945_irq_tasklet, (unsigned long)priv); | ||
3780 | } | ||
3781 | |||
3782 | static void iwl3945_cancel_deferred_work(struct iwl_priv *priv) | ||
3783 | { | ||
3784 | iwl3945_hw_cancel_deferred_work(priv); | ||
3785 | |||
3786 | cancel_delayed_work_sync(&priv->init_alive_start); | ||
3787 | cancel_delayed_work(&priv->alive_start); | ||
3788 | cancel_work_sync(&priv->beacon_update); | ||
3789 | |||
3790 | iwl_cancel_scan_deferred_work(priv); | ||
3791 | } | ||
3792 | |||
3793 | static struct attribute *iwl3945_sysfs_entries[] = { | ||
3794 | &dev_attr_antenna.attr, | ||
3795 | &dev_attr_channels.attr, | ||
3796 | &dev_attr_dump_errors.attr, | ||
3797 | &dev_attr_flags.attr, | ||
3798 | &dev_attr_filter_flags.attr, | ||
3799 | &dev_attr_measurement.attr, | ||
3800 | &dev_attr_retry_rate.attr, | ||
3801 | &dev_attr_status.attr, | ||
3802 | &dev_attr_temperature.attr, | ||
3803 | &dev_attr_tx_power.attr, | ||
3804 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3805 | &dev_attr_debug_level.attr, | ||
3806 | #endif | ||
3807 | NULL | ||
3808 | }; | ||
3809 | |||
3810 | static struct attribute_group iwl3945_attribute_group = { | ||
3811 | .name = NULL, /* put in device directory */ | ||
3812 | .attrs = iwl3945_sysfs_entries, | ||
3813 | }; | ||
3814 | |||
3815 | struct ieee80211_ops iwl3945_hw_ops = { | ||
3816 | .tx = iwl3945_mac_tx, | ||
3817 | .start = iwl3945_mac_start, | ||
3818 | .stop = iwl3945_mac_stop, | ||
3819 | .add_interface = iwl_mac_add_interface, | ||
3820 | .remove_interface = iwl_mac_remove_interface, | ||
3821 | .change_interface = iwl_mac_change_interface, | ||
3822 | .config = iwl_legacy_mac_config, | ||
3823 | .configure_filter = iwl3945_configure_filter, | ||
3824 | .set_key = iwl3945_mac_set_key, | ||
3825 | .conf_tx = iwl_mac_conf_tx, | ||
3826 | .reset_tsf = iwl_legacy_mac_reset_tsf, | ||
3827 | .bss_info_changed = iwl_legacy_mac_bss_info_changed, | ||
3828 | .hw_scan = iwl_mac_hw_scan, | ||
3829 | .sta_add = iwl3945_mac_sta_add, | ||
3830 | .sta_remove = iwl_mac_sta_remove, | ||
3831 | .tx_last_beacon = iwl_mac_tx_last_beacon, | ||
3832 | }; | ||
3833 | |||
3834 | static int iwl3945_init_drv(struct iwl_priv *priv) | ||
3835 | { | ||
3836 | int ret; | ||
3837 | struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; | ||
3838 | |||
3839 | priv->retry_rate = 1; | ||
3840 | priv->beacon_skb = NULL; | ||
3841 | |||
3842 | spin_lock_init(&priv->sta_lock); | ||
3843 | spin_lock_init(&priv->hcmd_lock); | ||
3844 | |||
3845 | INIT_LIST_HEAD(&priv->free_frames); | ||
3846 | |||
3847 | mutex_init(&priv->mutex); | ||
3848 | mutex_init(&priv->sync_cmd_mutex); | ||
3849 | |||
3850 | priv->ieee_channels = NULL; | ||
3851 | priv->ieee_rates = NULL; | ||
3852 | priv->band = IEEE80211_BAND_2GHZ; | ||
3853 | |||
3854 | priv->iw_mode = NL80211_IFTYPE_STATION; | ||
3855 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; | ||
3856 | |||
3857 | /* initialize force reset */ | ||
3858 | priv->force_reset[IWL_RF_RESET].reset_duration = | ||
3859 | IWL_DELAY_NEXT_FORCE_RF_RESET; | ||
3860 | priv->force_reset[IWL_FW_RESET].reset_duration = | ||
3861 | IWL_DELAY_NEXT_FORCE_FW_RELOAD; | ||
3862 | |||
3863 | |||
3864 | priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; | ||
3865 | priv->tx_power_next = IWL_DEFAULT_TX_POWER; | ||
3866 | |||
3867 | if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { | ||
3868 | IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n", | ||
3869 | eeprom->version); | ||
3870 | ret = -EINVAL; | ||
3871 | goto err; | ||
3872 | } | ||
3873 | ret = iwl_init_channel_map(priv); | ||
3874 | if (ret) { | ||
3875 | IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); | ||
3876 | goto err; | ||
3877 | } | ||
3878 | |||
3879 | /* Set up txpower settings in driver for all channels */ | ||
3880 | if (iwl3945_txpower_set_from_eeprom(priv)) { | ||
3881 | ret = -EIO; | ||
3882 | goto err_free_channel_map; | ||
3883 | } | ||
3884 | |||
3885 | ret = iwlcore_init_geos(priv); | ||
3886 | if (ret) { | ||
3887 | IWL_ERR(priv, "initializing geos failed: %d\n", ret); | ||
3888 | goto err_free_channel_map; | ||
3889 | } | ||
3890 | iwl3945_init_hw_rates(priv, priv->ieee_rates); | ||
3891 | |||
3892 | return 0; | ||
3893 | |||
3894 | err_free_channel_map: | ||
3895 | iwl_free_channel_map(priv); | ||
3896 | err: | ||
3897 | return ret; | ||
3898 | } | ||
3899 | |||
3900 | #define IWL3945_MAX_PROBE_REQUEST 200 | ||
3901 | |||
3902 | static int iwl3945_setup_mac(struct iwl_priv *priv) | ||
3903 | { | ||
3904 | int ret; | ||
3905 | struct ieee80211_hw *hw = priv->hw; | ||
3906 | |||
3907 | hw->rate_control_algorithm = "iwl-3945-rs"; | ||
3908 | hw->sta_data_size = sizeof(struct iwl3945_sta_priv); | ||
3909 | hw->vif_data_size = sizeof(struct iwl_vif_priv); | ||
3910 | |||
3911 | /* Tell mac80211 our characteristics */ | ||
3912 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | ||
3913 | IEEE80211_HW_SPECTRUM_MGMT; | ||
3914 | |||
3915 | if (!priv->cfg->base_params->broken_powersave) | ||
3916 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | | ||
3917 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | ||
3918 | |||
3919 | hw->wiphy->interface_modes = | ||
3920 | priv->contexts[IWL_RXON_CTX_BSS].interface_modes; | ||
3921 | |||
3922 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | | ||
3923 | WIPHY_FLAG_DISABLE_BEACON_HINTS | | ||
3924 | WIPHY_FLAG_IBSS_RSN; | ||
3925 | |||
3926 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; | ||
3927 | /* we create the 802.11 header and a zero-length SSID element */ | ||
3928 | hw->wiphy->max_scan_ie_len = IWL3945_MAX_PROBE_REQUEST - 24 - 2; | ||
3929 | |||
3930 | /* Default value; 4 EDCA QOS priorities */ | ||
3931 | hw->queues = 4; | ||
3932 | |||
3933 | if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) | ||
3934 | priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
3935 | &priv->bands[IEEE80211_BAND_2GHZ]; | ||
3936 | |||
3937 | if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) | ||
3938 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
3939 | &priv->bands[IEEE80211_BAND_5GHZ]; | ||
3940 | |||
3941 | iwl_leds_init(priv); | ||
3942 | |||
3943 | ret = ieee80211_register_hw(priv->hw); | ||
3944 | if (ret) { | ||
3945 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); | ||
3946 | return ret; | ||
3947 | } | ||
3948 | priv->mac80211_registered = 1; | ||
3949 | |||
3950 | return 0; | ||
3951 | } | ||
3952 | |||
3953 | static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | ||
3954 | { | ||
3955 | int err = 0, i; | ||
3956 | struct iwl_priv *priv; | ||
3957 | struct ieee80211_hw *hw; | ||
3958 | struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); | ||
3959 | struct iwl3945_eeprom *eeprom; | ||
3960 | unsigned long flags; | ||
3961 | |||
3962 | /*********************** | ||
3963 | * 1. Allocating HW data | ||
3964 | * ********************/ | ||
3965 | |||
3966 | /* mac80211 allocates memory for this device instance, including | ||
3967 | * space for this driver's private structure */ | ||
3968 | hw = iwl_alloc_all(cfg); | ||
3969 | if (hw == NULL) { | ||
3970 | pr_err("Can not allocate network device\n"); | ||
3971 | err = -ENOMEM; | ||
3972 | goto out; | ||
3973 | } | ||
3974 | priv = hw->priv; | ||
3975 | SET_IEEE80211_DEV(hw, &pdev->dev); | ||
3976 | |||
3977 | priv->cmd_queue = IWL39_CMD_QUEUE_NUM; | ||
3978 | |||
3979 | /* 3945 has only one valid context */ | ||
3980 | priv->valid_contexts = BIT(IWL_RXON_CTX_BSS); | ||
3981 | |||
3982 | for (i = 0; i < NUM_IWL_RXON_CTX; i++) | ||
3983 | priv->contexts[i].ctxid = i; | ||
3984 | |||
3985 | priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON; | ||
3986 | priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING; | ||
3987 | priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC; | ||
3988 | priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; | ||
3989 | priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; | ||
3990 | priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; | ||
3991 | priv->contexts[IWL_RXON_CTX_BSS].interface_modes = | ||
3992 | BIT(NL80211_IFTYPE_STATION) | | ||
3993 | BIT(NL80211_IFTYPE_ADHOC); | ||
3994 | priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS; | ||
3995 | priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS; | ||
3996 | priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS; | ||
3997 | |||
3998 | /* | ||
3999 | * Disabling hardware scan means that mac80211 will perform scans | ||
4000 | * "the hard way", rather than using device's scan. | ||
4001 | */ | ||
4002 | if (iwl3945_mod_params.disable_hw_scan) { | ||
4003 | dev_printk(KERN_DEBUG, &(pdev->dev), | ||
4004 | "sw scan support is deprecated\n"); | ||
4005 | iwl3945_hw_ops.hw_scan = NULL; | ||
4006 | } | ||
4007 | |||
4008 | |||
4009 | IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); | ||
4010 | priv->cfg = cfg; | ||
4011 | priv->pci_dev = pdev; | ||
4012 | priv->inta_mask = CSR_INI_SET_MASK; | ||
4013 | |||
4014 | if (iwl_alloc_traffic_mem(priv)) | ||
4015 | IWL_ERR(priv, "Not enough memory to generate traffic log\n"); | ||
4016 | |||
4017 | /*************************** | ||
4018 | * 2. Initializing PCI bus | ||
4019 | * *************************/ | ||
4020 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | | ||
4021 | PCIE_LINK_STATE_CLKPM); | ||
4022 | |||
4023 | if (pci_enable_device(pdev)) { | ||
4024 | err = -ENODEV; | ||
4025 | goto out_ieee80211_free_hw; | ||
4026 | } | ||
4027 | |||
4028 | pci_set_master(pdev); | ||
4029 | |||
4030 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
4031 | if (!err) | ||
4032 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
4033 | if (err) { | ||
4034 | IWL_WARN(priv, "No suitable DMA available.\n"); | ||
4035 | goto out_pci_disable_device; | ||
4036 | } | ||
4037 | |||
4038 | pci_set_drvdata(pdev, priv); | ||
4039 | err = pci_request_regions(pdev, DRV_NAME); | ||
4040 | if (err) | ||
4041 | goto out_pci_disable_device; | ||
4042 | |||
4043 | /*********************** | ||
4044 | * 3. Read REV Register | ||
4045 | * ********************/ | ||
4046 | priv->hw_base = pci_iomap(pdev, 0, 0); | ||
4047 | if (!priv->hw_base) { | ||
4048 | err = -ENODEV; | ||
4049 | goto out_pci_release_regions; | ||
4050 | } | ||
4051 | |||
4052 | IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n", | ||
4053 | (unsigned long long) pci_resource_len(pdev, 0)); | ||
4054 | IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base); | ||
4055 | |||
4056 | /* We disable the RETRY_TIMEOUT register (0x41) to keep | ||
4057 | * PCI Tx retries from interfering with C3 CPU state */ | ||
4058 | pci_write_config_byte(pdev, 0x41, 0x00); | ||
4059 | |||
4060 | /* these spin locks will be used in apm_ops.init and EEPROM access | ||
4061 | * we should init now | ||
4062 | */ | ||
4063 | spin_lock_init(&priv->reg_lock); | ||
4064 | spin_lock_init(&priv->lock); | ||
4065 | |||
4066 | /* | ||
4067 | * stop and reset the on-board processor just in case it is in a | ||
4068 | * strange state ... like being left stranded by a primary kernel | ||
4069 | * and this is now the kdump kernel trying to start up | ||
4070 | */ | ||
4071 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | ||
4072 | |||
4073 | /*********************** | ||
4074 | * 4. Read EEPROM | ||
4075 | * ********************/ | ||
4076 | |||
4077 | /* Read the EEPROM */ | ||
4078 | err = iwl_eeprom_init(priv); | ||
4079 | if (err) { | ||
4080 | IWL_ERR(priv, "Unable to init EEPROM\n"); | ||
4081 | goto out_iounmap; | ||
4082 | } | ||
4083 | /* MAC Address location in EEPROM same for 3945/4965 */ | ||
4084 | eeprom = (struct iwl3945_eeprom *)priv->eeprom; | ||
4085 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", eeprom->mac_address); | ||
4086 | SET_IEEE80211_PERM_ADDR(priv->hw, eeprom->mac_address); | ||
4087 | |||
4088 | /*********************** | ||
4089 | * 5. Setup HW Constants | ||
4090 | * ********************/ | ||
4091 | /* Device-specific setup */ | ||
4092 | if (iwl3945_hw_set_hw_params(priv)) { | ||
4093 | IWL_ERR(priv, "failed to set hw settings\n"); | ||
4094 | goto out_eeprom_free; | ||
4095 | } | ||
4096 | |||
4097 | /*********************** | ||
4098 | * 6. Setup priv | ||
4099 | * ********************/ | ||
4100 | |||
4101 | err = iwl3945_init_drv(priv); | ||
4102 | if (err) { | ||
4103 | IWL_ERR(priv, "initializing driver failed\n"); | ||
4104 | goto out_unset_hw_params; | ||
4105 | } | ||
4106 | |||
4107 | IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s\n", | ||
4108 | priv->cfg->name); | ||
4109 | |||
4110 | /*********************** | ||
4111 | * 7. Setup Services | ||
4112 | * ********************/ | ||
4113 | |||
4114 | spin_lock_irqsave(&priv->lock, flags); | ||
4115 | iwl_disable_interrupts(priv); | ||
4116 | spin_unlock_irqrestore(&priv->lock, flags); | ||
4117 | |||
4118 | pci_enable_msi(priv->pci_dev); | ||
4119 | |||
4120 | err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr, | ||
4121 | IRQF_SHARED, DRV_NAME, priv); | ||
4122 | if (err) { | ||
4123 | IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); | ||
4124 | goto out_disable_msi; | ||
4125 | } | ||
4126 | |||
4127 | err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group); | ||
4128 | if (err) { | ||
4129 | IWL_ERR(priv, "failed to create sysfs device attributes\n"); | ||
4130 | goto out_release_irq; | ||
4131 | } | ||
4132 | |||
4133 | iwl_set_rxon_channel(priv, | ||
4134 | &priv->bands[IEEE80211_BAND_2GHZ].channels[5], | ||
4135 | &priv->contexts[IWL_RXON_CTX_BSS]); | ||
4136 | iwl3945_setup_deferred_work(priv); | ||
4137 | iwl3945_setup_rx_handlers(priv); | ||
4138 | iwl_power_initialize(priv); | ||
4139 | |||
4140 | /********************************* | ||
4141 | * 8. Setup and Register mac80211 | ||
4142 | * *******************************/ | ||
4143 | |||
4144 | iwl_enable_interrupts(priv); | ||
4145 | |||
4146 | err = iwl3945_setup_mac(priv); | ||
4147 | if (err) | ||
4148 | goto out_remove_sysfs; | ||
4149 | |||
4150 | err = iwl_dbgfs_register(priv, DRV_NAME); | ||
4151 | if (err) | ||
4152 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); | ||
4153 | |||
4154 | /* Start monitoring the killswitch */ | ||
4155 | queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll, | ||
4156 | 2 * HZ); | ||
4157 | |||
4158 | return 0; | ||
4159 | |||
4160 | out_remove_sysfs: | ||
4161 | destroy_workqueue(priv->workqueue); | ||
4162 | priv->workqueue = NULL; | ||
4163 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); | ||
4164 | out_release_irq: | ||
4165 | free_irq(priv->pci_dev->irq, priv); | ||
4166 | out_disable_msi: | ||
4167 | pci_disable_msi(priv->pci_dev); | ||
4168 | iwlcore_free_geos(priv); | ||
4169 | iwl_free_channel_map(priv); | ||
4170 | out_unset_hw_params: | ||
4171 | iwl3945_unset_hw_params(priv); | ||
4172 | out_eeprom_free: | ||
4173 | iwl_eeprom_free(priv); | ||
4174 | out_iounmap: | ||
4175 | pci_iounmap(pdev, priv->hw_base); | ||
4176 | out_pci_release_regions: | ||
4177 | pci_release_regions(pdev); | ||
4178 | out_pci_disable_device: | ||
4179 | pci_set_drvdata(pdev, NULL); | ||
4180 | pci_disable_device(pdev); | ||
4181 | out_ieee80211_free_hw: | ||
4182 | iwl_free_traffic_mem(priv); | ||
4183 | ieee80211_free_hw(priv->hw); | ||
4184 | out: | ||
4185 | return err; | ||
4186 | } | ||
4187 | |||
4188 | static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) | ||
4189 | { | ||
4190 | struct iwl_priv *priv = pci_get_drvdata(pdev); | ||
4191 | unsigned long flags; | ||
4192 | |||
4193 | if (!priv) | ||
4194 | return; | ||
4195 | |||
4196 | IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); | ||
4197 | |||
4198 | iwl_dbgfs_unregister(priv); | ||
4199 | |||
4200 | set_bit(STATUS_EXIT_PENDING, &priv->status); | ||
4201 | |||
4202 | iwl_leds_exit(priv); | ||
4203 | |||
4204 | if (priv->mac80211_registered) { | ||
4205 | ieee80211_unregister_hw(priv->hw); | ||
4206 | priv->mac80211_registered = 0; | ||
4207 | } else { | ||
4208 | iwl3945_down(priv); | ||
4209 | } | ||
4210 | |||
4211 | /* | ||
4212 | * Make sure device is reset to low power before unloading driver. | ||
4213 | * This may be redundant with iwl_down(), but there are paths to | ||
4214 | * run iwl_down() without calling apm_ops.stop(), and there are | ||
4215 | * paths to avoid running iwl_down() at all before leaving driver. | ||
4216 | * This (inexpensive) call *makes sure* device is reset. | ||
4217 | */ | ||
4218 | iwl_apm_stop(priv); | ||
4219 | |||
4220 | /* make sure we flush any pending irq or | ||
4221 | * tasklet for the driver | ||
4222 | */ | ||
4223 | spin_lock_irqsave(&priv->lock, flags); | ||
4224 | iwl_disable_interrupts(priv); | ||
4225 | spin_unlock_irqrestore(&priv->lock, flags); | ||
4226 | |||
4227 | iwl_synchronize_irq(priv); | ||
4228 | |||
4229 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); | ||
4230 | |||
4231 | cancel_delayed_work_sync(&priv->_3945.rfkill_poll); | ||
4232 | |||
4233 | iwl3945_dealloc_ucode_pci(priv); | ||
4234 | |||
4235 | if (priv->rxq.bd) | ||
4236 | iwl3945_rx_queue_free(priv, &priv->rxq); | ||
4237 | iwl3945_hw_txq_ctx_free(priv); | ||
4238 | |||
4239 | iwl3945_unset_hw_params(priv); | ||
4240 | |||
4241 | /*netif_stop_queue(dev); */ | ||
4242 | flush_workqueue(priv->workqueue); | ||
4243 | |||
4244 | /* ieee80211_unregister_hw calls iwl3945_mac_stop, which flushes | ||
4245 | * priv->workqueue... so we can't take down the workqueue | ||
4246 | * until now... */ | ||
4247 | destroy_workqueue(priv->workqueue); | ||
4248 | priv->workqueue = NULL; | ||
4249 | iwl_free_traffic_mem(priv); | ||
4250 | |||
4251 | free_irq(pdev->irq, priv); | ||
4252 | pci_disable_msi(pdev); | ||
4253 | |||
4254 | pci_iounmap(pdev, priv->hw_base); | ||
4255 | pci_release_regions(pdev); | ||
4256 | pci_disable_device(pdev); | ||
4257 | pci_set_drvdata(pdev, NULL); | ||
4258 | |||
4259 | iwl_free_channel_map(priv); | ||
4260 | iwlcore_free_geos(priv); | ||
4261 | kfree(priv->scan_cmd); | ||
4262 | if (priv->beacon_skb) | ||
4263 | dev_kfree_skb(priv->beacon_skb); | ||
4264 | |||
4265 | ieee80211_free_hw(priv->hw); | ||
4266 | } | ||
4267 | |||
4268 | |||
4269 | /***************************************************************************** | ||
4270 | * | ||
4271 | * driver and module entry point | ||
4272 | * | ||
4273 | *****************************************************************************/ | ||
4274 | |||
4275 | static struct pci_driver iwl3945_driver = { | ||
4276 | .name = DRV_NAME, | ||
4277 | .id_table = iwl3945_hw_card_ids, | ||
4278 | .probe = iwl3945_pci_probe, | ||
4279 | .remove = __devexit_p(iwl3945_pci_remove), | ||
4280 | .driver.pm = IWL_PM_OPS, | ||
4281 | }; | ||
4282 | |||
4283 | static int __init iwl3945_init(void) | ||
4284 | { | ||
4285 | |||
4286 | int ret; | ||
4287 | pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); | ||
4288 | pr_info(DRV_COPYRIGHT "\n"); | ||
4289 | |||
4290 | ret = iwl3945_rate_control_register(); | ||
4291 | if (ret) { | ||
4292 | pr_err("Unable to register rate control algorithm: %d\n", ret); | ||
4293 | return ret; | ||
4294 | } | ||
4295 | |||
4296 | ret = pci_register_driver(&iwl3945_driver); | ||
4297 | if (ret) { | ||
4298 | pr_err("Unable to initialize PCI module\n"); | ||
4299 | goto error_register; | ||
4300 | } | ||
4301 | |||
4302 | return ret; | ||
4303 | |||
4304 | error_register: | ||
4305 | iwl3945_rate_control_unregister(); | ||
4306 | return ret; | ||
4307 | } | ||
4308 | |||
4309 | static void __exit iwl3945_exit(void) | ||
4310 | { | ||
4311 | pci_unregister_driver(&iwl3945_driver); | ||
4312 | iwl3945_rate_control_unregister(); | ||
4313 | } | ||
4314 | |||
4315 | MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX)); | ||
4316 | |||
4317 | module_param_named(antenna, iwl3945_mod_params.antenna, int, S_IRUGO); | ||
4318 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | ||
4319 | module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, S_IRUGO); | ||
4320 | MODULE_PARM_DESC(swcrypto, | ||
4321 | "using software crypto (default 1 [software])\n"); | ||
4322 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
4323 | module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR); | ||
4324 | MODULE_PARM_DESC(debug, "debug output mask"); | ||
4325 | #endif | ||
4326 | module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, | ||
4327 | int, S_IRUGO); | ||
4328 | MODULE_PARM_DESC(disable_hw_scan, | ||
4329 | "disable hardware scanning (default 0) (deprecated)"); | ||
4330 | module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, S_IRUGO); | ||
4331 | MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error"); | ||
4332 | |||
4333 | module_exit(iwl3945_exit); | ||
4334 | module_init(iwl3945_init); | ||