diff options
author | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2010-10-08 19:05:19 -0400 |
---|---|---|
committer | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2010-10-14 12:47:42 -0400 |
commit | 3be63ff0ae196b371728ba8fc8aca12eafcae218 (patch) | |
tree | 7fbecb72849ffbe60ff927e345c3d34bbdd9ab50 /drivers/net/wireless/iwlwifi | |
parent | 40bbfd4c1b336b8841bef9933b6e09252ace56b8 (diff) |
iwlwifi: move agn only eeprom functions to separate file
Some of the functions in iwl-eeprom.c file are for agn devices only,
Those functions do not have to be part of iwlcore.ko, so move those
to iwl-agn-eeprom.c file.
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r-- | drivers/net/wireless/iwlwifi/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c | 454 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-eeprom.c | 374 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-eeprom.h | 7 |
5 files changed, 476 insertions, 367 deletions
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index b4b24b67892c..63edbe2e557f 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -12,7 +12,7 @@ obj-$(CONFIG_IWLAGN) += iwlagn.o | |||
12 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o | 12 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o |
13 | iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o | 13 | iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o |
14 | iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o | 14 | iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o |
15 | iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o | 15 | iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o |
16 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o | 16 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o |
17 | 17 | ||
18 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o | 18 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c new file mode 100644 index 000000000000..a650baba0809 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c | |||
@@ -0,0 +1,454 @@ | |||
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 | |||
64 | #include <linux/kernel.h> | ||
65 | #include <linux/module.h> | ||
66 | #include <linux/slab.h> | ||
67 | #include <linux/init.h> | ||
68 | |||
69 | #include <net/mac80211.h> | ||
70 | |||
71 | #include "iwl-commands.h" | ||
72 | #include "iwl-dev.h" | ||
73 | #include "iwl-core.h" | ||
74 | #include "iwl-debug.h" | ||
75 | #include "iwl-agn.h" | ||
76 | #include "iwl-io.h" | ||
77 | |||
78 | /************************** EEPROM BANDS **************************** | ||
79 | * | ||
80 | * The iwl_eeprom_band definitions below provide the mapping from the | ||
81 | * EEPROM contents to the specific channel number supported for each | ||
82 | * band. | ||
83 | * | ||
84 | * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3 | ||
85 | * definition below maps to physical channel 42 in the 5.2GHz spectrum. | ||
86 | * The specific geography and calibration information for that channel | ||
87 | * is contained in the eeprom map itself. | ||
88 | * | ||
89 | * During init, we copy the eeprom information and channel map | ||
90 | * information into priv->channel_info_24/52 and priv->channel_map_24/52 | ||
91 | * | ||
92 | * channel_map_24/52 provides the index in the channel_info array for a | ||
93 | * given channel. We have to have two separate maps as there is channel | ||
94 | * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and | ||
95 | * band_2 | ||
96 | * | ||
97 | * A value of 0xff stored in the channel_map indicates that the channel | ||
98 | * is not supported by the hardware at all. | ||
99 | * | ||
100 | * A value of 0xfe in the channel_map indicates that the channel is not | ||
101 | * valid for Tx with the current hardware. This means that | ||
102 | * while the system can tune and receive on a given channel, it may not | ||
103 | * be able to associate or transmit any frames on that | ||
104 | * channel. There is no corresponding channel information for that | ||
105 | * entry. | ||
106 | * | ||
107 | *********************************************************************/ | ||
108 | |||
109 | /** | ||
110 | * struct iwl_txpwr_section: eeprom section information | ||
111 | * @offset: indirect address into eeprom image | ||
112 | * @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section | ||
113 | * @band: band type for the section | ||
114 | * @is_common - true: common section, false: channel section | ||
115 | * @is_cck - true: cck section, false: not cck section | ||
116 | * @is_ht_40 - true: all channel in the section are HT40 channel, | ||
117 | * false: legacy or HT 20 MHz | ||
118 | * ignore if it is common section | ||
119 | * @iwl_eeprom_section_channel: channel array in the section, | ||
120 | * ignore if common section | ||
121 | */ | ||
122 | struct iwl_txpwr_section { | ||
123 | u32 offset; | ||
124 | u8 count; | ||
125 | enum ieee80211_band band; | ||
126 | bool is_common; | ||
127 | bool is_cck; | ||
128 | bool is_ht40; | ||
129 | u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS]; | ||
130 | }; | ||
131 | |||
132 | /** | ||
133 | * section 1 - 3 are regulatory tx power apply to all channels based on | ||
134 | * modulation: CCK, OFDM | ||
135 | * Band: 2.4GHz, 5.2GHz | ||
136 | * section 4 - 10 are regulatory tx power apply to specified channels | ||
137 | * For example: | ||
138 | * 1L - Channel 1 Legacy | ||
139 | * 1HT - Channel 1 HT | ||
140 | * (1,+1) - Channel 1 HT40 "_above_" | ||
141 | * | ||
142 | * Section 1: all CCK channels | ||
143 | * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels | ||
144 | * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels | ||
145 | * Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT | ||
146 | * Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1) | ||
147 | * Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT | ||
148 | * Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1) | ||
149 | * Section 8: 2.4 GHz channel: 13L, 13HT | ||
150 | * Section 9: 2.4 GHz channel: 140L, 140HT | ||
151 | * Section 10: 2.4 GHz 40MHz channels: (132,+1) (44,+1) | ||
152 | * | ||
153 | */ | ||
154 | static const struct iwl_txpwr_section enhinfo[] = { | ||
155 | { EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false }, | ||
156 | { EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false }, | ||
157 | { EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false }, | ||
158 | { EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ, | ||
159 | false, false, false, | ||
160 | {1, 1, 2, 2, 10, 10, 11, 11 } }, | ||
161 | { EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ, | ||
162 | false, false, true, | ||
163 | { 1, 2, 6, 7, 9 } }, | ||
164 | { EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ, | ||
165 | false, false, false, | ||
166 | { 36, 64, 100, 36, 64, 100 } }, | ||
167 | { EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ, | ||
168 | false, false, true, | ||
169 | { 36, 60, 100 } }, | ||
170 | { EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ, | ||
171 | false, false, false, | ||
172 | { 13, 13 } }, | ||
173 | { EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ, | ||
174 | false, false, false, | ||
175 | { 140, 140 } }, | ||
176 | { EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ, | ||
177 | false, false, true, | ||
178 | { 132, 44 } }, | ||
179 | }; | ||
180 | |||
181 | /****************************************************************************** | ||
182 | * | ||
183 | * EEPROM related functions | ||
184 | * | ||
185 | ******************************************************************************/ | ||
186 | |||
187 | /* | ||
188 | * The device's EEPROM semaphore prevents conflicts between driver and uCode | ||
189 | * when accessing the EEPROM; each access is a series of pulses to/from the | ||
190 | * EEPROM chip, not a single event, so even reads could conflict if they | ||
191 | * weren't arbitrated by the semaphore. | ||
192 | */ | ||
193 | int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv) | ||
194 | { | ||
195 | u16 count; | ||
196 | int ret; | ||
197 | |||
198 | for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { | ||
199 | /* Request semaphore */ | ||
200 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
201 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
202 | |||
203 | /* See if we got it */ | ||
204 | ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
205 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
206 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
207 | EEPROM_SEM_TIMEOUT); | ||
208 | if (ret >= 0) { | ||
209 | IWL_DEBUG_IO(priv, | ||
210 | "Acquired semaphore after %d tries.\n", | ||
211 | count+1); | ||
212 | return ret; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv) | ||
220 | { | ||
221 | iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
222 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
223 | |||
224 | } | ||
225 | |||
226 | int iwl_eeprom_check_version(struct iwl_priv *priv) | ||
227 | { | ||
228 | u16 eeprom_ver; | ||
229 | u16 calib_ver; | ||
230 | |||
231 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | ||
232 | calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv); | ||
233 | |||
234 | if (eeprom_ver < priv->cfg->eeprom_ver || | ||
235 | calib_ver < priv->cfg->eeprom_calib_ver) | ||
236 | goto err; | ||
237 | |||
238 | IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n", | ||
239 | eeprom_ver, calib_ver); | ||
240 | |||
241 | return 0; | ||
242 | err: | ||
243 | IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x " | ||
244 | "CALIB=0x%x < 0x%x\n", | ||
245 | eeprom_ver, priv->cfg->eeprom_ver, | ||
246 | calib_ver, priv->cfg->eeprom_calib_ver); | ||
247 | return -EINVAL; | ||
248 | |||
249 | } | ||
250 | |||
251 | void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac) | ||
252 | { | ||
253 | const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv, | ||
254 | EEPROM_MAC_ADDRESS); | ||
255 | memcpy(mac, addr, ETH_ALEN); | ||
256 | } | ||
257 | |||
258 | /** | ||
259 | * iwl_get_max_txpower_avg - get the highest tx power from all chains. | ||
260 | * find the highest tx power from all chains for the channel | ||
261 | */ | ||
262 | static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, | ||
263 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, | ||
264 | int element, s8 *max_txpower_in_half_dbm) | ||
265 | { | ||
266 | s8 max_txpower_avg = 0; /* (dBm) */ | ||
267 | |||
268 | IWL_DEBUG_INFO(priv, "%d - " | ||
269 | "chain_a: %d dB chain_b: %d dB " | ||
270 | "chain_c: %d dB mimo2: %d dB mimo3: %d dB\n", | ||
271 | element, | ||
272 | enhanced_txpower[element].chain_a_max >> 1, | ||
273 | enhanced_txpower[element].chain_b_max >> 1, | ||
274 | enhanced_txpower[element].chain_c_max >> 1, | ||
275 | enhanced_txpower[element].mimo2_max >> 1, | ||
276 | enhanced_txpower[element].mimo3_max >> 1); | ||
277 | /* Take the highest tx power from any valid chains */ | ||
278 | if ((priv->cfg->valid_tx_ant & ANT_A) && | ||
279 | (enhanced_txpower[element].chain_a_max > max_txpower_avg)) | ||
280 | max_txpower_avg = enhanced_txpower[element].chain_a_max; | ||
281 | if ((priv->cfg->valid_tx_ant & ANT_B) && | ||
282 | (enhanced_txpower[element].chain_b_max > max_txpower_avg)) | ||
283 | max_txpower_avg = enhanced_txpower[element].chain_b_max; | ||
284 | if ((priv->cfg->valid_tx_ant & ANT_C) && | ||
285 | (enhanced_txpower[element].chain_c_max > max_txpower_avg)) | ||
286 | max_txpower_avg = enhanced_txpower[element].chain_c_max; | ||
287 | if (((priv->cfg->valid_tx_ant == ANT_AB) | | ||
288 | (priv->cfg->valid_tx_ant == ANT_BC) | | ||
289 | (priv->cfg->valid_tx_ant == ANT_AC)) && | ||
290 | (enhanced_txpower[element].mimo2_max > max_txpower_avg)) | ||
291 | max_txpower_avg = enhanced_txpower[element].mimo2_max; | ||
292 | if ((priv->cfg->valid_tx_ant == ANT_ABC) && | ||
293 | (enhanced_txpower[element].mimo3_max > max_txpower_avg)) | ||
294 | max_txpower_avg = enhanced_txpower[element].mimo3_max; | ||
295 | |||
296 | /* | ||
297 | * max. tx power in EEPROM is in 1/2 dBm format | ||
298 | * convert from 1/2 dBm to dBm (round-up convert) | ||
299 | * but we also do not want to loss 1/2 dBm resolution which | ||
300 | * will impact performance | ||
301 | */ | ||
302 | *max_txpower_in_half_dbm = max_txpower_avg; | ||
303 | return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1); | ||
304 | } | ||
305 | |||
306 | /** | ||
307 | * iwl_update_common_txpower: update channel tx power | ||
308 | * update tx power per band based on EEPROM enhanced tx power info. | ||
309 | */ | ||
310 | static s8 iwl_update_common_txpower(struct iwl_priv *priv, | ||
311 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, | ||
312 | int section, int element, s8 *max_txpower_in_half_dbm) | ||
313 | { | ||
314 | struct iwl_channel_info *ch_info; | ||
315 | int ch; | ||
316 | bool is_ht40 = false; | ||
317 | s8 max_txpower_avg; /* (dBm) */ | ||
318 | |||
319 | /* it is common section, contain all type (Legacy, HT and HT40) | ||
320 | * based on the element in the section to determine | ||
321 | * is it HT 40 or not | ||
322 | */ | ||
323 | if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX) | ||
324 | is_ht40 = true; | ||
325 | max_txpower_avg = | ||
326 | iwl_get_max_txpower_avg(priv, enhanced_txpower, | ||
327 | element, max_txpower_in_half_dbm); | ||
328 | |||
329 | ch_info = priv->channel_info; | ||
330 | |||
331 | for (ch = 0; ch < priv->channel_count; ch++) { | ||
332 | /* find matching band and update tx power if needed */ | ||
333 | if ((ch_info->band == enhinfo[section].band) && | ||
334 | (ch_info->max_power_avg < max_txpower_avg) && | ||
335 | (!is_ht40)) { | ||
336 | /* Update regulatory-based run-time data */ | ||
337 | ch_info->max_power_avg = ch_info->curr_txpow = | ||
338 | max_txpower_avg; | ||
339 | ch_info->scan_power = max_txpower_avg; | ||
340 | } | ||
341 | if ((ch_info->band == enhinfo[section].band) && is_ht40 && | ||
342 | (ch_info->ht40_max_power_avg < max_txpower_avg)) { | ||
343 | /* Update regulatory-based run-time data */ | ||
344 | ch_info->ht40_max_power_avg = max_txpower_avg; | ||
345 | } | ||
346 | ch_info++; | ||
347 | } | ||
348 | return max_txpower_avg; | ||
349 | } | ||
350 | |||
351 | /** | ||
352 | * iwl_update_channel_txpower: update channel tx power | ||
353 | * update channel tx power based on EEPROM enhanced tx power info. | ||
354 | */ | ||
355 | static s8 iwl_update_channel_txpower(struct iwl_priv *priv, | ||
356 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, | ||
357 | int section, int element, s8 *max_txpower_in_half_dbm) | ||
358 | { | ||
359 | struct iwl_channel_info *ch_info; | ||
360 | int ch; | ||
361 | u8 channel; | ||
362 | s8 max_txpower_avg; /* (dBm) */ | ||
363 | |||
364 | channel = enhinfo[section].iwl_eeprom_section_channel[element]; | ||
365 | max_txpower_avg = | ||
366 | iwl_get_max_txpower_avg(priv, enhanced_txpower, | ||
367 | element, max_txpower_in_half_dbm); | ||
368 | |||
369 | ch_info = priv->channel_info; | ||
370 | for (ch = 0; ch < priv->channel_count; ch++) { | ||
371 | /* find matching channel and update tx power if needed */ | ||
372 | if (ch_info->channel == channel) { | ||
373 | if ((ch_info->max_power_avg < max_txpower_avg) && | ||
374 | (!enhinfo[section].is_ht40)) { | ||
375 | /* Update regulatory-based run-time data */ | ||
376 | ch_info->max_power_avg = max_txpower_avg; | ||
377 | ch_info->curr_txpow = max_txpower_avg; | ||
378 | ch_info->scan_power = max_txpower_avg; | ||
379 | } | ||
380 | if ((enhinfo[section].is_ht40) && | ||
381 | (ch_info->ht40_max_power_avg < max_txpower_avg)) { | ||
382 | /* Update regulatory-based run-time data */ | ||
383 | ch_info->ht40_max_power_avg = max_txpower_avg; | ||
384 | } | ||
385 | break; | ||
386 | } | ||
387 | ch_info++; | ||
388 | } | ||
389 | return max_txpower_avg; | ||
390 | } | ||
391 | |||
392 | /** | ||
393 | * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info | ||
394 | */ | ||
395 | void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) | ||
396 | { | ||
397 | int eeprom_section_count = 0; | ||
398 | int section, element; | ||
399 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower; | ||
400 | u32 offset; | ||
401 | s8 max_txpower_avg; /* (dBm) */ | ||
402 | s8 max_txpower_in_half_dbm; /* (half-dBm) */ | ||
403 | |||
404 | /* Loop through all the sections | ||
405 | * adjust bands and channel's max tx power | ||
406 | * Set the tx_power_user_lmt to the highest power | ||
407 | * supported by any channels and chains | ||
408 | */ | ||
409 | for (section = 0; section < ARRAY_SIZE(enhinfo); section++) { | ||
410 | eeprom_section_count = enhinfo[section].count; | ||
411 | offset = enhinfo[section].offset; | ||
412 | enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *) | ||
413 | iwl_eeprom_query_addr(priv, offset); | ||
414 | |||
415 | /* | ||
416 | * check for valid entry - | ||
417 | * different version of EEPROM might contain different set | ||
418 | * of enhanced tx power table | ||
419 | * always check for valid entry before process | ||
420 | * the information | ||
421 | */ | ||
422 | if (!enhanced_txpower->common || enhanced_txpower->reserved) | ||
423 | continue; | ||
424 | |||
425 | for (element = 0; element < eeprom_section_count; element++) { | ||
426 | if (enhinfo[section].is_common) | ||
427 | max_txpower_avg = | ||
428 | iwl_update_common_txpower(priv, | ||
429 | enhanced_txpower, section, | ||
430 | element, | ||
431 | &max_txpower_in_half_dbm); | ||
432 | else | ||
433 | max_txpower_avg = | ||
434 | iwl_update_channel_txpower(priv, | ||
435 | enhanced_txpower, section, | ||
436 | element, | ||
437 | &max_txpower_in_half_dbm); | ||
438 | |||
439 | /* Update the tx_power_user_lmt to the highest power | ||
440 | * supported by any channel */ | ||
441 | if (max_txpower_avg > priv->tx_power_user_lmt) | ||
442 | priv->tx_power_user_lmt = max_txpower_avg; | ||
443 | |||
444 | /* | ||
445 | * Update the tx_power_lmt_in_half_dbm to | ||
446 | * the highest power supported by any channel | ||
447 | */ | ||
448 | if (max_txpower_in_half_dbm > | ||
449 | priv->tx_power_lmt_in_half_dbm) | ||
450 | priv->tx_power_lmt_in_half_dbm = | ||
451 | max_txpower_in_half_dbm; | ||
452 | } | ||
453 | } | ||
454 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index b4deef4e91db..f525d55f2c0f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -312,4 +312,10 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) | |||
312 | return cpu_to_le32(flags|(u32)rate); | 312 | return cpu_to_le32(flags|(u32)rate); |
313 | } | 313 | } |
314 | 314 | ||
315 | /* eeprom */ | ||
316 | void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv); | ||
317 | void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); | ||
318 | int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv); | ||
319 | void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); | ||
320 | |||
315 | #endif /* __iwl_agn_h__ */ | 321 | #endif /* __iwl_agn_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 66eccb12159d..87cd10ff285d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -136,78 +136,6 @@ static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */ | |||
136 | 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 | 136 | 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 |
137 | }; | 137 | }; |
138 | 138 | ||
139 | /** | ||
140 | * struct iwl_txpwr_section: eeprom section information | ||
141 | * @offset: indirect address into eeprom image | ||
142 | * @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section | ||
143 | * @band: band type for the section | ||
144 | * @is_common - true: common section, false: channel section | ||
145 | * @is_cck - true: cck section, false: not cck section | ||
146 | * @is_ht_40 - true: all channel in the section are HT40 channel, | ||
147 | * false: legacy or HT 20 MHz | ||
148 | * ignore if it is common section | ||
149 | * @iwl_eeprom_section_channel: channel array in the section, | ||
150 | * ignore if common section | ||
151 | */ | ||
152 | struct iwl_txpwr_section { | ||
153 | u32 offset; | ||
154 | u8 count; | ||
155 | enum ieee80211_band band; | ||
156 | bool is_common; | ||
157 | bool is_cck; | ||
158 | bool is_ht40; | ||
159 | u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS]; | ||
160 | }; | ||
161 | |||
162 | /** | ||
163 | * section 1 - 3 are regulatory tx power apply to all channels based on | ||
164 | * modulation: CCK, OFDM | ||
165 | * Band: 2.4GHz, 5.2GHz | ||
166 | * section 4 - 10 are regulatory tx power apply to specified channels | ||
167 | * For example: | ||
168 | * 1L - Channel 1 Legacy | ||
169 | * 1HT - Channel 1 HT | ||
170 | * (1,+1) - Channel 1 HT40 "_above_" | ||
171 | * | ||
172 | * Section 1: all CCK channels | ||
173 | * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels | ||
174 | * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels | ||
175 | * Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT | ||
176 | * Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1) | ||
177 | * Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT | ||
178 | * Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1) | ||
179 | * Section 8: 2.4 GHz channel: 13L, 13HT | ||
180 | * Section 9: 2.4 GHz channel: 140L, 140HT | ||
181 | * Section 10: 2.4 GHz 40MHz channels: (132,+1) (44,+1) | ||
182 | * | ||
183 | */ | ||
184 | static const struct iwl_txpwr_section enhinfo[] = { | ||
185 | { EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false }, | ||
186 | { EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false }, | ||
187 | { EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false }, | ||
188 | { EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ, | ||
189 | false, false, false, | ||
190 | {1, 1, 2, 2, 10, 10, 11, 11 } }, | ||
191 | { EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ, | ||
192 | false, false, true, | ||
193 | { 1, 2, 6, 7, 9 } }, | ||
194 | { EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ, | ||
195 | false, false, false, | ||
196 | { 36, 64, 100, 36, 64, 100 } }, | ||
197 | { EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ, | ||
198 | false, false, true, | ||
199 | { 36, 60, 100 } }, | ||
200 | { EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ, | ||
201 | false, false, false, | ||
202 | { 13, 13 } }, | ||
203 | { EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ, | ||
204 | false, false, false, | ||
205 | { 140, 140 } }, | ||
206 | { EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ, | ||
207 | false, false, true, | ||
208 | { 132, 44 } }, | ||
209 | }; | ||
210 | |||
211 | /****************************************************************************** | 139 | /****************************************************************************** |
212 | * | 140 | * |
213 | * EEPROM related functions | 141 | * EEPROM related functions |
@@ -289,46 +217,6 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv) | |||
289 | return nvm_type; | 217 | return nvm_type; |
290 | } | 218 | } |
291 | 219 | ||
292 | /* | ||
293 | * The device's EEPROM semaphore prevents conflicts between driver and uCode | ||
294 | * when accessing the EEPROM; each access is a series of pulses to/from the | ||
295 | * EEPROM chip, not a single event, so even reads could conflict if they | ||
296 | * weren't arbitrated by the semaphore. | ||
297 | */ | ||
298 | int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv) | ||
299 | { | ||
300 | u16 count; | ||
301 | int ret; | ||
302 | |||
303 | for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { | ||
304 | /* Request semaphore */ | ||
305 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
306 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
307 | |||
308 | /* See if we got it */ | ||
309 | ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
310 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
311 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
312 | EEPROM_SEM_TIMEOUT); | ||
313 | if (ret >= 0) { | ||
314 | IWL_DEBUG_IO(priv, "Acquired semaphore after %d tries.\n", | ||
315 | count+1); | ||
316 | return ret; | ||
317 | } | ||
318 | } | ||
319 | |||
320 | return ret; | ||
321 | } | ||
322 | EXPORT_SYMBOL(iwlcore_eeprom_acquire_semaphore); | ||
323 | |||
324 | void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv) | ||
325 | { | ||
326 | iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
327 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
328 | |||
329 | } | ||
330 | EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore); | ||
331 | |||
332 | const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) | 220 | const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) |
333 | { | 221 | { |
334 | BUG_ON(offset >= priv->cfg->base_params->eeprom_size); | 222 | BUG_ON(offset >= priv->cfg->base_params->eeprom_size); |
@@ -490,6 +378,20 @@ static int iwl_find_otp_image(struct iwl_priv *priv, | |||
490 | return -EINVAL; | 378 | return -EINVAL; |
491 | } | 379 | } |
492 | 380 | ||
381 | const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) | ||
382 | { | ||
383 | return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset); | ||
384 | } | ||
385 | EXPORT_SYMBOL(iwl_eeprom_query_addr); | ||
386 | |||
387 | u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) | ||
388 | { | ||
389 | if (!priv->eeprom) | ||
390 | return 0; | ||
391 | return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); | ||
392 | } | ||
393 | EXPORT_SYMBOL(iwl_eeprom_query16); | ||
394 | |||
493 | /** | 395 | /** |
494 | * iwl_eeprom_init - read EEPROM contents | 396 | * iwl_eeprom_init - read EEPROM contents |
495 | * | 397 | * |
@@ -616,53 +518,6 @@ void iwl_eeprom_free(struct iwl_priv *priv) | |||
616 | } | 518 | } |
617 | EXPORT_SYMBOL(iwl_eeprom_free); | 519 | EXPORT_SYMBOL(iwl_eeprom_free); |
618 | 520 | ||
619 | int iwl_eeprom_check_version(struct iwl_priv *priv) | ||
620 | { | ||
621 | u16 eeprom_ver; | ||
622 | u16 calib_ver; | ||
623 | |||
624 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | ||
625 | calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv); | ||
626 | |||
627 | if (eeprom_ver < priv->cfg->eeprom_ver || | ||
628 | calib_ver < priv->cfg->eeprom_calib_ver) | ||
629 | goto err; | ||
630 | |||
631 | IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n", | ||
632 | eeprom_ver, calib_ver); | ||
633 | |||
634 | return 0; | ||
635 | err: | ||
636 | IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n", | ||
637 | eeprom_ver, priv->cfg->eeprom_ver, | ||
638 | calib_ver, priv->cfg->eeprom_calib_ver); | ||
639 | return -EINVAL; | ||
640 | |||
641 | } | ||
642 | EXPORT_SYMBOL(iwl_eeprom_check_version); | ||
643 | |||
644 | const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) | ||
645 | { | ||
646 | return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset); | ||
647 | } | ||
648 | EXPORT_SYMBOL(iwl_eeprom_query_addr); | ||
649 | |||
650 | u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) | ||
651 | { | ||
652 | if (!priv->eeprom) | ||
653 | return 0; | ||
654 | return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); | ||
655 | } | ||
656 | EXPORT_SYMBOL(iwl_eeprom_query16); | ||
657 | |||
658 | void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac) | ||
659 | { | ||
660 | const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv, | ||
661 | EEPROM_MAC_ADDRESS); | ||
662 | memcpy(mac, addr, ETH_ALEN); | ||
663 | } | ||
664 | EXPORT_SYMBOL(iwl_eeprom_get_mac); | ||
665 | |||
666 | static void iwl_init_band_reference(const struct iwl_priv *priv, | 521 | static void iwl_init_band_reference(const struct iwl_priv *priv, |
667 | int eep_band, int *eeprom_ch_count, | 522 | int eep_band, int *eeprom_ch_count, |
668 | const struct iwl_eeprom_channel **eeprom_ch_info, | 523 | const struct iwl_eeprom_channel **eeprom_ch_info, |
@@ -721,7 +576,6 @@ static void iwl_init_band_reference(const struct iwl_priv *priv, | |||
721 | 576 | ||
722 | #define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \ | 577 | #define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \ |
723 | ? # x " " : "") | 578 | ? # x " " : "") |
724 | |||
725 | /** | 579 | /** |
726 | * iwl_mod_ht40_chan_info - Copy ht40 channel info into driver's priv. | 580 | * iwl_mod_ht40_chan_info - Copy ht40 channel info into driver's priv. |
727 | * | 581 | * |
@@ -765,205 +619,6 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv, | |||
765 | return 0; | 619 | return 0; |
766 | } | 620 | } |
767 | 621 | ||
768 | /** | ||
769 | * iwl_get_max_txpower_avg - get the highest tx power from all chains. | ||
770 | * find the highest tx power from all chains for the channel | ||
771 | */ | ||
772 | static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, | ||
773 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, | ||
774 | int element, s8 *max_txpower_in_half_dbm) | ||
775 | { | ||
776 | s8 max_txpower_avg = 0; /* (dBm) */ | ||
777 | |||
778 | IWL_DEBUG_INFO(priv, "%d - " | ||
779 | "chain_a: %d dB chain_b: %d dB " | ||
780 | "chain_c: %d dB mimo2: %d dB mimo3: %d dB\n", | ||
781 | element, | ||
782 | enhanced_txpower[element].chain_a_max >> 1, | ||
783 | enhanced_txpower[element].chain_b_max >> 1, | ||
784 | enhanced_txpower[element].chain_c_max >> 1, | ||
785 | enhanced_txpower[element].mimo2_max >> 1, | ||
786 | enhanced_txpower[element].mimo3_max >> 1); | ||
787 | /* Take the highest tx power from any valid chains */ | ||
788 | if ((priv->cfg->valid_tx_ant & ANT_A) && | ||
789 | (enhanced_txpower[element].chain_a_max > max_txpower_avg)) | ||
790 | max_txpower_avg = enhanced_txpower[element].chain_a_max; | ||
791 | if ((priv->cfg->valid_tx_ant & ANT_B) && | ||
792 | (enhanced_txpower[element].chain_b_max > max_txpower_avg)) | ||
793 | max_txpower_avg = enhanced_txpower[element].chain_b_max; | ||
794 | if ((priv->cfg->valid_tx_ant & ANT_C) && | ||
795 | (enhanced_txpower[element].chain_c_max > max_txpower_avg)) | ||
796 | max_txpower_avg = enhanced_txpower[element].chain_c_max; | ||
797 | if (((priv->cfg->valid_tx_ant == ANT_AB) | | ||
798 | (priv->cfg->valid_tx_ant == ANT_BC) | | ||
799 | (priv->cfg->valid_tx_ant == ANT_AC)) && | ||
800 | (enhanced_txpower[element].mimo2_max > max_txpower_avg)) | ||
801 | max_txpower_avg = enhanced_txpower[element].mimo2_max; | ||
802 | if ((priv->cfg->valid_tx_ant == ANT_ABC) && | ||
803 | (enhanced_txpower[element].mimo3_max > max_txpower_avg)) | ||
804 | max_txpower_avg = enhanced_txpower[element].mimo3_max; | ||
805 | |||
806 | /* | ||
807 | * max. tx power in EEPROM is in 1/2 dBm format | ||
808 | * convert from 1/2 dBm to dBm (round-up convert) | ||
809 | * but we also do not want to loss 1/2 dBm resolution which | ||
810 | * will impact performance | ||
811 | */ | ||
812 | *max_txpower_in_half_dbm = max_txpower_avg; | ||
813 | return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1); | ||
814 | } | ||
815 | |||
816 | /** | ||
817 | * iwl_update_common_txpower: update channel tx power | ||
818 | * update tx power per band based on EEPROM enhanced tx power info. | ||
819 | */ | ||
820 | static s8 iwl_update_common_txpower(struct iwl_priv *priv, | ||
821 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, | ||
822 | int section, int element, s8 *max_txpower_in_half_dbm) | ||
823 | { | ||
824 | struct iwl_channel_info *ch_info; | ||
825 | int ch; | ||
826 | bool is_ht40 = false; | ||
827 | s8 max_txpower_avg; /* (dBm) */ | ||
828 | |||
829 | /* it is common section, contain all type (Legacy, HT and HT40) | ||
830 | * based on the element in the section to determine | ||
831 | * is it HT 40 or not | ||
832 | */ | ||
833 | if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX) | ||
834 | is_ht40 = true; | ||
835 | max_txpower_avg = | ||
836 | iwl_get_max_txpower_avg(priv, enhanced_txpower, | ||
837 | element, max_txpower_in_half_dbm); | ||
838 | |||
839 | ch_info = priv->channel_info; | ||
840 | |||
841 | for (ch = 0; ch < priv->channel_count; ch++) { | ||
842 | /* find matching band and update tx power if needed */ | ||
843 | if ((ch_info->band == enhinfo[section].band) && | ||
844 | (ch_info->max_power_avg < max_txpower_avg) && | ||
845 | (!is_ht40)) { | ||
846 | /* Update regulatory-based run-time data */ | ||
847 | ch_info->max_power_avg = ch_info->curr_txpow = | ||
848 | max_txpower_avg; | ||
849 | ch_info->scan_power = max_txpower_avg; | ||
850 | } | ||
851 | if ((ch_info->band == enhinfo[section].band) && is_ht40 && | ||
852 | (ch_info->ht40_max_power_avg < max_txpower_avg)) { | ||
853 | /* Update regulatory-based run-time data */ | ||
854 | ch_info->ht40_max_power_avg = max_txpower_avg; | ||
855 | } | ||
856 | ch_info++; | ||
857 | } | ||
858 | return max_txpower_avg; | ||
859 | } | ||
860 | |||
861 | /** | ||
862 | * iwl_update_channel_txpower: update channel tx power | ||
863 | * update channel tx power based on EEPROM enhanced tx power info. | ||
864 | */ | ||
865 | static s8 iwl_update_channel_txpower(struct iwl_priv *priv, | ||
866 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, | ||
867 | int section, int element, s8 *max_txpower_in_half_dbm) | ||
868 | { | ||
869 | struct iwl_channel_info *ch_info; | ||
870 | int ch; | ||
871 | u8 channel; | ||
872 | s8 max_txpower_avg; /* (dBm) */ | ||
873 | |||
874 | channel = enhinfo[section].iwl_eeprom_section_channel[element]; | ||
875 | max_txpower_avg = | ||
876 | iwl_get_max_txpower_avg(priv, enhanced_txpower, | ||
877 | element, max_txpower_in_half_dbm); | ||
878 | |||
879 | ch_info = priv->channel_info; | ||
880 | for (ch = 0; ch < priv->channel_count; ch++) { | ||
881 | /* find matching channel and update tx power if needed */ | ||
882 | if (ch_info->channel == channel) { | ||
883 | if ((ch_info->max_power_avg < max_txpower_avg) && | ||
884 | (!enhinfo[section].is_ht40)) { | ||
885 | /* Update regulatory-based run-time data */ | ||
886 | ch_info->max_power_avg = max_txpower_avg; | ||
887 | ch_info->curr_txpow = max_txpower_avg; | ||
888 | ch_info->scan_power = max_txpower_avg; | ||
889 | } | ||
890 | if ((enhinfo[section].is_ht40) && | ||
891 | (ch_info->ht40_max_power_avg < max_txpower_avg)) { | ||
892 | /* Update regulatory-based run-time data */ | ||
893 | ch_info->ht40_max_power_avg = max_txpower_avg; | ||
894 | } | ||
895 | break; | ||
896 | } | ||
897 | ch_info++; | ||
898 | } | ||
899 | return max_txpower_avg; | ||
900 | } | ||
901 | |||
902 | /** | ||
903 | * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info | ||
904 | */ | ||
905 | void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) | ||
906 | { | ||
907 | int eeprom_section_count = 0; | ||
908 | int section, element; | ||
909 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower; | ||
910 | u32 offset; | ||
911 | s8 max_txpower_avg; /* (dBm) */ | ||
912 | s8 max_txpower_in_half_dbm; /* (half-dBm) */ | ||
913 | |||
914 | /* Loop through all the sections | ||
915 | * adjust bands and channel's max tx power | ||
916 | * Set the tx_power_user_lmt to the highest power | ||
917 | * supported by any channels and chains | ||
918 | */ | ||
919 | for (section = 0; section < ARRAY_SIZE(enhinfo); section++) { | ||
920 | eeprom_section_count = enhinfo[section].count; | ||
921 | offset = enhinfo[section].offset; | ||
922 | enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *) | ||
923 | iwl_eeprom_query_addr(priv, offset); | ||
924 | |||
925 | /* | ||
926 | * check for valid entry - | ||
927 | * different version of EEPROM might contain different set | ||
928 | * of enhanced tx power table | ||
929 | * always check for valid entry before process | ||
930 | * the information | ||
931 | */ | ||
932 | if (!enhanced_txpower->common || enhanced_txpower->reserved) | ||
933 | continue; | ||
934 | |||
935 | for (element = 0; element < eeprom_section_count; element++) { | ||
936 | if (enhinfo[section].is_common) | ||
937 | max_txpower_avg = | ||
938 | iwl_update_common_txpower(priv, | ||
939 | enhanced_txpower, section, | ||
940 | element, | ||
941 | &max_txpower_in_half_dbm); | ||
942 | else | ||
943 | max_txpower_avg = | ||
944 | iwl_update_channel_txpower(priv, | ||
945 | enhanced_txpower, section, | ||
946 | element, | ||
947 | &max_txpower_in_half_dbm); | ||
948 | |||
949 | /* Update the tx_power_user_lmt to the highest power | ||
950 | * supported by any channel */ | ||
951 | if (max_txpower_avg > priv->tx_power_user_lmt) | ||
952 | priv->tx_power_user_lmt = max_txpower_avg; | ||
953 | |||
954 | /* | ||
955 | * Update the tx_power_lmt_in_half_dbm to | ||
956 | * the highest power supported by any channel | ||
957 | */ | ||
958 | if (max_txpower_in_half_dbm > | ||
959 | priv->tx_power_lmt_in_half_dbm) | ||
960 | priv->tx_power_lmt_in_half_dbm = | ||
961 | max_txpower_in_half_dbm; | ||
962 | } | ||
963 | } | ||
964 | } | ||
965 | EXPORT_SYMBOL(iwlcore_eeprom_enhanced_txpower); | ||
966 | |||
967 | #define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \ | 622 | #define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \ |
968 | ? # x " " : "") | 623 | ? # x " " : "") |
969 | 624 | ||
@@ -1161,4 +816,3 @@ const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv, | |||
1161 | return NULL; | 816 | return NULL; |
1162 | } | 817 | } |
1163 | EXPORT_SYMBOL(iwl_get_channel_info); | 818 | EXPORT_SYMBOL(iwl_get_channel_info); |
1164 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 2ae0a11e523b..d9b590625ae4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h | |||
@@ -501,18 +501,13 @@ struct iwl_eeprom_ops { | |||
501 | }; | 501 | }; |
502 | 502 | ||
503 | 503 | ||
504 | void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); | ||
505 | int iwl_eeprom_init(struct iwl_priv *priv); | 504 | int iwl_eeprom_init(struct iwl_priv *priv); |
506 | void iwl_eeprom_free(struct iwl_priv *priv); | 505 | void iwl_eeprom_free(struct iwl_priv *priv); |
507 | int iwl_eeprom_check_version(struct iwl_priv *priv); | 506 | int iwl_eeprom_check_version(struct iwl_priv *priv); |
508 | const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); | 507 | const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); |
509 | u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset); | ||
510 | |||
511 | int iwlcore_eeprom_verify_signature(struct iwl_priv *priv); | 508 | int iwlcore_eeprom_verify_signature(struct iwl_priv *priv); |
512 | int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv); | 509 | u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset); |
513 | void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); | ||
514 | const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); | 510 | const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); |
515 | void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv); | ||
516 | int iwl_init_channel_map(struct iwl_priv *priv); | 511 | int iwl_init_channel_map(struct iwl_priv *priv); |
517 | void iwl_free_channel_map(struct iwl_priv *priv); | 512 | void iwl_free_channel_map(struct iwl_priv *priv); |
518 | const struct iwl_channel_info *iwl_get_channel_info( | 513 | const struct iwl_channel_info *iwl_get_channel_info( |