Merge tag 'amlogic-dt-2' of https://git.kernel.org/pub/scm/linux/kernel/git/khilman...
[linux-2.6-block.git] / drivers / net / wireless / intel / iwlwifi / iwl-nvm-parse.c
CommitLineData
b1e1adfa
JB
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 *
51368bf7 8 * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
5f0d98f2 9 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
29108495 10 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
b1e1adfa
JB
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of version 2 of the GNU General Public License as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
24 * USA
25 *
26 * The full GNU General Public License is included in this distribution
410dc5aa 27 * in the file called COPYING.
b1e1adfa
JB
28 *
29 * Contact Information:
d01c5366 30 * Intel Linux Wireless <linuxwifi@intel.com>
b1e1adfa
JB
31 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
32 *
33 * BSD LICENSE
34 *
51368bf7 35 * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
5f0d98f2 36 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
29108495 37 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
b1e1adfa
JB
38 * All rights reserved.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 *
44 * * Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * * Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in
48 * the documentation and/or other materials provided with the
49 * distribution.
50 * * Neither the name Intel Corporation nor the names of its
51 * contributors may be used to endorse or promote products derived
52 * from this software without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
55 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
56 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
57 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
58 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
59 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
60 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
61 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
62 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
63 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
64 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
65 *****************************************************************************/
66#include <linux/types.h>
67#include <linux/slab.h>
68#include <linux/export.h>
9f32e017 69#include <linux/etherdevice.h>
1e0b393a 70#include <linux/pci.h>
813df5ce 71
48e29340 72#include "iwl-drv.h"
b1e1adfa
JB
73#include "iwl-modparams.h"
74#include "iwl-nvm-parse.h"
afd5b170 75#include "iwl-prph.h"
17c867bf
SS
76#include "iwl-io.h"
77#include "iwl-csr.h"
813df5ce 78#include "fw/acpi.h"
77e30e10 79#include "fw/api/nvm-reg.h"
b1e1adfa
JB
80
81/* NVM offsets (in words) definitions */
44fd09da 82enum nvm_offsets {
b1e1adfa 83 /* NVM HW-Section offset (in words) definitions */
01a9c948 84 SUBSYSTEM_ID = 0x0A,
b1e1adfa
JB
85 HW_ADDR = 0x15,
86
77db0a3c 87 /* NVM SW-Section offset (in words) definitions */
b1e1adfa
JB
88 NVM_SW_SECTION = 0x1C0,
89 NVM_VERSION = 0,
90 RADIO_CFG = 1,
91 SKU = 2,
92 N_HW_ADDRS = 3,
93 NVM_CHANNELS = 0x1E0 - NVM_SW_SECTION,
94
77db0a3c 95 /* NVM calibration section offset (in words) definitions */
b1e1adfa 96 NVM_CALIB_SECTION = 0x2B8,
44fd09da
CRI
97 XTAL_CALIB = 0x316 - NVM_CALIB_SECTION,
98
99 /* NVM REGULATORY -Section offset (in words) definitions */
100 NVM_CHANNELS_SDP = 0,
b1e1adfa
JB
101};
102
7042678d 103enum ext_nvm_offsets {
77db0a3c 104 /* NVM HW-Section offset (in words) definitions */
7042678d 105 MAC_ADDRESS_OVERRIDE_EXT_NVM = 1,
77db0a3c
EH
106
107 /* NVM SW-Section offset (in words) definitions */
7042678d
SS
108 NVM_VERSION_EXT_NVM = 0,
109 RADIO_CFG_FAMILY_EXT_NVM = 0,
5dd9c68a
EG
110 SKU_FAMILY_8000 = 2,
111 N_HW_ADDRS_FAMILY_8000 = 3,
ce500071 112
77db0a3c 113 /* NVM REGULATORY -Section offset (in words) definitions */
7042678d
SS
114 NVM_CHANNELS_EXTENDED = 0,
115 NVM_LAR_OFFSET_OLD = 0x4C7,
116 NVM_LAR_OFFSET = 0x507,
117 NVM_LAR_ENABLED = 0x7,
77db0a3c
EH
118};
119
b1e1adfa
JB
120/* SKU Capabilities (actual values from NVM definition) */
121enum nvm_sku_bits {
5f0d98f2
EG
122 NVM_SKU_CAP_BAND_24GHZ = BIT(0),
123 NVM_SKU_CAP_BAND_52GHZ = BIT(1),
124 NVM_SKU_CAP_11N_ENABLE = BIT(2),
125 NVM_SKU_CAP_11AC_ENABLE = BIT(3),
126 NVM_SKU_CAP_MIMO_DISABLE = BIT(5),
b1e1adfa
JB
127};
128
b1e1adfa
JB
129/*
130 * These are the channel numbers in the order that they are stored in the NVM
131 */
132static const u8 iwl_nvm_channels[] = {
133 /* 2.4 GHz */
134 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
135 /* 5 GHz */
136 36, 40, 44 , 48, 52, 56, 60, 64,
137 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
138 149, 153, 157, 161, 165
139};
140
7042678d 141static const u8 iwl_ext_nvm_channels[] = {
77db0a3c 142 /* 2.4 GHz */
9b1c9a66 143 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
77db0a3c
EH
144 /* 5 GHz */
145 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92,
146 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
147 149, 153, 157, 161, 165, 169, 173, 177, 181
148};
149
77e30e10
HD
150#define IWL_NVM_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels)
151#define IWL_NVM_NUM_CHANNELS_EXT ARRAY_SIZE(iwl_ext_nvm_channels)
749f1fe1 152#define NUM_2GHZ_CHANNELS 14
7042678d 153#define NUM_2GHZ_CHANNELS_EXT 14
749f1fe1
EH
154#define FIRST_2GHZ_HT_MINUS 5
155#define LAST_2GHZ_HT_PLUS 9
b281c93d
MG
156#define LAST_5GHZ_HT 165
157#define LAST_5GHZ_HT_FAMILY_8000 181
ce500071 158#define N_HW_ADDR_MASK 0xF
b1e1adfa 159
b1e1adfa
JB
160/* rate data (static) */
161static struct ieee80211_rate iwl_cfg80211_rates[] = {
162 { .bitrate = 1 * 10, .hw_value = 0, .hw_value_short = 0, },
163 { .bitrate = 2 * 10, .hw_value = 1, .hw_value_short = 1,
164 .flags = IEEE80211_RATE_SHORT_PREAMBLE, },
165 { .bitrate = 5.5 * 10, .hw_value = 2, .hw_value_short = 2,
166 .flags = IEEE80211_RATE_SHORT_PREAMBLE, },
167 { .bitrate = 11 * 10, .hw_value = 3, .hw_value_short = 3,
168 .flags = IEEE80211_RATE_SHORT_PREAMBLE, },
169 { .bitrate = 6 * 10, .hw_value = 4, .hw_value_short = 4, },
170 { .bitrate = 9 * 10, .hw_value = 5, .hw_value_short = 5, },
171 { .bitrate = 12 * 10, .hw_value = 6, .hw_value_short = 6, },
172 { .bitrate = 18 * 10, .hw_value = 7, .hw_value_short = 7, },
173 { .bitrate = 24 * 10, .hw_value = 8, .hw_value_short = 8, },
174 { .bitrate = 36 * 10, .hw_value = 9, .hw_value_short = 9, },
175 { .bitrate = 48 * 10, .hw_value = 10, .hw_value_short = 10, },
176 { .bitrate = 54 * 10, .hw_value = 11, .hw_value_short = 11, },
177};
178#define RATES_24_OFFS 0
179#define N_RATES_24 ARRAY_SIZE(iwl_cfg80211_rates)
180#define RATES_52_OFFS 4
181#define N_RATES_52 (N_RATES_24 - RATES_52_OFFS)
182
183/**
184 * enum iwl_nvm_channel_flags - channel flags in NVM
185 * @NVM_CHANNEL_VALID: channel is usable for this SKU/geo
186 * @NVM_CHANNEL_IBSS: usable as an IBSS channel
187 * @NVM_CHANNEL_ACTIVE: active scanning allowed
188 * @NVM_CHANNEL_RADAR: radar detection required
9ee6dace
DS
189 * @NVM_CHANNEL_INDOOR_ONLY: only indoor use is allowed
190 * @NVM_CHANNEL_GO_CONCURRENT: GO operation is allowed when connected to BSS
191 * on same channel on 2.4 or same UNII band on 5.2
b823cf3b
LC
192 * @NVM_CHANNEL_UNIFORM: uniform spreading required
193 * @NVM_CHANNEL_20MHZ: 20 MHz channel okay
194 * @NVM_CHANNEL_40MHZ: 40 MHz channel okay
195 * @NVM_CHANNEL_80MHZ: 80 MHz channel okay
196 * @NVM_CHANNEL_160MHZ: 160 MHz channel okay
197 * @NVM_CHANNEL_DC_HIGH: DC HIGH required/allowed (?)
b1e1adfa
JB
198 */
199enum iwl_nvm_channel_flags {
b823cf3b
LC
200 NVM_CHANNEL_VALID = BIT(0),
201 NVM_CHANNEL_IBSS = BIT(1),
202 NVM_CHANNEL_ACTIVE = BIT(3),
203 NVM_CHANNEL_RADAR = BIT(4),
204 NVM_CHANNEL_INDOOR_ONLY = BIT(5),
205 NVM_CHANNEL_GO_CONCURRENT = BIT(6),
206 NVM_CHANNEL_UNIFORM = BIT(7),
207 NVM_CHANNEL_20MHZ = BIT(8),
208 NVM_CHANNEL_40MHZ = BIT(9),
209 NVM_CHANNEL_80MHZ = BIT(10),
210 NVM_CHANNEL_160MHZ = BIT(11),
211 NVM_CHANNEL_DC_HIGH = BIT(12),
b1e1adfa
JB
212};
213
d8c73e45
JB
214static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
215 int chan, u16 flags)
216{
b1e1adfa 217#define CHECK_AND_PRINT_I(x) \
d8c73e45
JB
218 ((flags & NVM_CHANNEL_##x) ? " " #x : "")
219
220 if (!(flags & NVM_CHANNEL_VALID)) {
221 IWL_DEBUG_DEV(dev, level, "Ch. %d: 0x%x: No traffic\n",
222 chan, flags);
223 return;
224 }
225
226 /* Note: already can print up to 101 characters, 110 is the limit! */
227 IWL_DEBUG_DEV(dev, level,
228 "Ch. %d: 0x%x:%s%s%s%s%s%s%s%s%s%s%s%s\n",
229 chan, flags,
230 CHECK_AND_PRINT_I(VALID),
231 CHECK_AND_PRINT_I(IBSS),
232 CHECK_AND_PRINT_I(ACTIVE),
233 CHECK_AND_PRINT_I(RADAR),
234 CHECK_AND_PRINT_I(INDOOR_ONLY),
235 CHECK_AND_PRINT_I(GO_CONCURRENT),
236 CHECK_AND_PRINT_I(UNIFORM),
237 CHECK_AND_PRINT_I(20MHZ),
238 CHECK_AND_PRINT_I(40MHZ),
239 CHECK_AND_PRINT_I(80MHZ),
240 CHECK_AND_PRINT_I(160MHZ),
241 CHECK_AND_PRINT_I(DC_HIGH));
242#undef CHECK_AND_PRINT_I
243}
b1e1adfa 244
770ceda6 245static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
b281c93d 246 u16 nvm_flags, const struct iwl_cfg *cfg)
770ceda6
AN
247{
248 u32 flags = IEEE80211_CHAN_NO_HT40;
b281c93d
MG
249 u32 last_5ghz_ht = LAST_5GHZ_HT;
250
44fd09da 251 if (cfg->nvm_type == IWL_NVM_EXT)
b281c93d 252 last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;
770ceda6
AN
253
254 if (!is_5ghz && (nvm_flags & NVM_CHANNEL_40MHZ)) {
255 if (ch_num <= LAST_2GHZ_HT_PLUS)
256 flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
257 if (ch_num >= FIRST_2GHZ_HT_MINUS)
258 flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
b281c93d 259 } else if (ch_num <= last_5ghz_ht && (nvm_flags & NVM_CHANNEL_40MHZ)) {
770ceda6
AN
260 if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
261 flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
262 else
263 flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
264 }
265 if (!(nvm_flags & NVM_CHANNEL_80MHZ))
266 flags |= IEEE80211_CHAN_NO_80MHZ;
267 if (!(nvm_flags & NVM_CHANNEL_160MHZ))
268 flags |= IEEE80211_CHAN_NO_160MHZ;
269
270 if (!(nvm_flags & NVM_CHANNEL_IBSS))
271 flags |= IEEE80211_CHAN_NO_IR;
272
273 if (!(nvm_flags & NVM_CHANNEL_ACTIVE))
274 flags |= IEEE80211_CHAN_NO_IR;
275
276 if (nvm_flags & NVM_CHANNEL_RADAR)
277 flags |= IEEE80211_CHAN_RADAR;
278
279 if (nvm_flags & NVM_CHANNEL_INDOOR_ONLY)
280 flags |= IEEE80211_CHAN_INDOOR_ONLY;
281
282 /* Set the GO concurrent flag only in case that NO_IR is set.
283 * Otherwise it is meaningless
284 */
285 if ((nvm_flags & NVM_CHANNEL_GO_CONCURRENT) &&
286 (flags & IEEE80211_CHAN_NO_IR))
06f207fc 287 flags |= IEEE80211_CHAN_IR_CONCURRENT;
770ceda6
AN
288
289 return flags;
290}
291
b1e1adfa
JB
292static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
293 struct iwl_nvm_data *data,
770ceda6 294 const __le16 * const nvm_ch_flags,
01a9c948 295 bool lar_supported, bool no_wide_in_5ghz)
b1e1adfa
JB
296{
297 int ch_idx;
298 int n_channels = 0;
299 struct ieee80211_channel *channel;
300 u16 ch_flags;
749f1fe1 301 int num_of_ch, num_2ghz_channels;
77db0a3c
EH
302 const u8 *nvm_chan;
303
44fd09da 304 if (cfg->nvm_type != IWL_NVM_EXT) {
77e30e10 305 num_of_ch = IWL_NVM_NUM_CHANNELS;
77db0a3c 306 nvm_chan = &iwl_nvm_channels[0];
749f1fe1 307 num_2ghz_channels = NUM_2GHZ_CHANNELS;
77db0a3c 308 } else {
77e30e10 309 num_of_ch = IWL_NVM_NUM_CHANNELS_EXT;
7042678d
SS
310 nvm_chan = &iwl_ext_nvm_channels[0];
311 num_2ghz_channels = NUM_2GHZ_CHANNELS_EXT;
77db0a3c 312 }
b1e1adfa 313
77db0a3c 314 for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
01a9c948
LC
315 bool is_5ghz = (ch_idx >= num_2ghz_channels);
316
b1e1adfa 317 ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx);
c5128654 318
01a9c948 319 if (is_5ghz && !data->sku_cap_band_52GHz_enable)
a76f3bfe 320 continue;
c5128654 321
01a9c948
LC
322 /* workaround to disable wide channels in 5GHz */
323 if (no_wide_in_5ghz && is_5ghz) {
324 ch_flags &= ~(NVM_CHANNEL_40MHZ |
325 NVM_CHANNEL_80MHZ |
326 NVM_CHANNEL_160MHZ);
327 }
328
4896d764
GG
329 if (ch_flags & NVM_CHANNEL_160MHZ)
330 data->vht160_supported = true;
331
770ceda6 332 if (!lar_supported && !(ch_flags & NVM_CHANNEL_VALID)) {
a76f3bfe
EP
333 /*
334 * Channels might become valid later if lar is
335 * supported, hence we still want to add them to
336 * the list of supported channels to cfg80211.
337 */
d8c73e45
JB
338 iwl_nvm_print_channel_flags(dev, IWL_DL_EEPROM,
339 nvm_chan[ch_idx], ch_flags);
b1e1adfa
JB
340 continue;
341 }
342
343 channel = &data->channels[n_channels];
344 n_channels++;
345
77db0a3c 346 channel->hw_value = nvm_chan[ch_idx];
01a9c948
LC
347 channel->band = is_5ghz ?
348 NL80211_BAND_5GHZ : NL80211_BAND_2GHZ;
b1e1adfa
JB
349 channel->center_freq =
350 ieee80211_channel_to_frequency(
351 channel->hw_value, channel->band);
352
b1e1adfa
JB
353 /* Initialize regulatory-based run-time data */
354
88f2fd73
MG
355 /*
356 * Default value - highest tx power value. max_power
357 * is not used in mvm, and is used for backwards compatibility
358 */
22d059a5 359 channel->max_power = IWL_DEFAULT_MAX_TX_POWER;
770ceda6
AN
360
361 /* don't put limitations in case we're using LAR */
362 if (!lar_supported)
363 channel->flags = iwl_get_channel_flags(nvm_chan[ch_idx],
364 ch_idx, is_5ghz,
b281c93d 365 ch_flags, cfg);
770ceda6
AN
366 else
367 channel->flags = 0;
368
d8c73e45
JB
369 iwl_nvm_print_channel_flags(dev, IWL_DL_EEPROM,
370 channel->hw_value, ch_flags);
371 IWL_DEBUG_EEPROM(dev, "Ch. %d: %ddBm\n",
372 channel->hw_value, channel->max_power);
b1e1adfa
JB
373 }
374
375 return n_channels;
376}
377
33158fef
EL
378static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
379 struct iwl_nvm_data *data,
6ca89f1f
JB
380 struct ieee80211_sta_vht_cap *vht_cap,
381 u8 tx_chains, u8 rx_chains)
33158fef 382{
6ca89f1f
JB
383 int num_rx_ants = num_of_ant(rx_chains);
384 int num_tx_ants = num_of_ant(tx_chains);
c064ddf3
EH
385 unsigned int max_ampdu_exponent = (cfg->max_vht_ampdu_exponent ?:
386 IEEE80211_VHT_MAX_AMPDU_1024K);
48e6de61 387
33158fef
EL
388 vht_cap->vht_supported = true;
389
390 vht_cap->cap = IEEE80211_VHT_CAP_SHORT_GI_80 |
391 IEEE80211_VHT_CAP_RXSTBC_1 |
392 IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
e36b766d 393 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT |
c064ddf3
EH
394 max_ampdu_exponent <<
395 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
33158fef 396
4896d764 397 if (data->vht160_supported)
fbbd4859
GG
398 vht_cap->cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
399 IEEE80211_VHT_CAP_SHORT_GI_160;
4896d764 400
e48c947f
SS
401 if (cfg->vht_mu_mimo_supported)
402 vht_cap->cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
403
a3576ff2
ES
404 if (cfg->ht_params->ldpc)
405 vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC;
406
5f0d98f2
EG
407 if (data->sku_cap_mimo_disabled) {
408 num_rx_ants = 1;
409 num_tx_ants = 1;
410 }
411
6ca89f1f 412 if (num_tx_ants > 1)
5f7a6f9b 413 vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC;
6ca89f1f
JB
414 else
415 vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
5f7a6f9b 416
6c4fbcbc 417 switch (iwlwifi_mod_params.amsdu_size) {
4bdd4dfe
EG
418 case IWL_AMSDU_DEF:
419 if (cfg->mq_rx_supported)
420 vht_cap->cap |=
421 IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
422 else
423 vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
424 break;
6c4fbcbc
EG
425 case IWL_AMSDU_4K:
426 vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
427 break;
428 case IWL_AMSDU_8K:
33158fef 429 vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
6c4fbcbc
EG
430 break;
431 case IWL_AMSDU_12K:
432 vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
433 break;
434 default:
435 break;
436 }
33158fef
EL
437
438 vht_cap->vht_mcs.rx_mcs_map =
439 cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 |
440 IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 |
441 IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 |
442 IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |
443 IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 |
444 IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 |
445 IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |
446 IEEE80211_VHT_MCS_NOT_SUPPORTED << 14);
447
6ca89f1f
JB
448 if (num_rx_ants == 1 || cfg->rx_with_siso_diversity) {
449 vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN;
33158fef
EL
450 /* this works because NOT_SUPPORTED == 3 */
451 vht_cap->vht_mcs.rx_mcs_map |=
452 cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2);
453 }
454
455 vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map;
456}
457
29108495
SS
458void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
459 struct iwl_nvm_data *data, const __le16 *nvm_ch_flags,
01a9c948
LC
460 u8 tx_chains, u8 rx_chains, bool lar_supported,
461 bool no_wide_in_5ghz)
b1e1adfa 462{
77db0a3c 463 int n_channels;
b1e1adfa
JB
464 int n_used = 0;
465 struct ieee80211_supported_band *sband;
466
29108495 467 n_channels = iwl_init_channel_map(dev, cfg, data, nvm_ch_flags,
01a9c948 468 lar_supported, no_wide_in_5ghz);
57fbcce3
JB
469 sband = &data->bands[NL80211_BAND_2GHZ];
470 sband->band = NL80211_BAND_2GHZ;
b1e1adfa
JB
471 sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
472 sband->n_bitrates = N_RATES_24;
473 n_used += iwl_init_sband_channels(data, sband, n_channels,
57fbcce3
JB
474 NL80211_BAND_2GHZ);
475 iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_2GHZ,
9ce4fa72 476 tx_chains, rx_chains);
b1e1adfa 477
57fbcce3
JB
478 sband = &data->bands[NL80211_BAND_5GHZ];
479 sband->band = NL80211_BAND_5GHZ;
b1e1adfa
JB
480 sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS];
481 sband->n_bitrates = N_RATES_52;
482 n_used += iwl_init_sband_channels(data, sband, n_channels,
57fbcce3
JB
483 NL80211_BAND_5GHZ);
484 iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_5GHZ,
9ce4fa72 485 tx_chains, rx_chains);
0d0985ad 486 if (data->sku_cap_11ac_enable && !iwlwifi_mod_params.disable_11ac)
6ca89f1f
JB
487 iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap,
488 tx_chains, rx_chains);
b1e1adfa
JB
489
490 if (n_channels != n_used)
491 IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n",
492 n_used, n_channels);
493}
29108495 494IWL_EXPORT_SYMBOL(iwl_init_sbands);
b1e1adfa 495
5dd9c68a
EG
496static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
497 const __le16 *phy_sku)
77db0a3c 498{
44fd09da 499 if (cfg->nvm_type != IWL_NVM_EXT)
77db0a3c 500 return le16_to_cpup(nvm_sw + SKU);
ce500071 501
5dd9c68a 502 return le32_to_cpup((__le32 *)(phy_sku + SKU_FAMILY_8000));
77db0a3c
EH
503}
504
5dd9c68a 505static int iwl_get_nvm_version(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
77db0a3c 506{
44fd09da 507 if (cfg->nvm_type != IWL_NVM_EXT)
77db0a3c
EH
508 return le16_to_cpup(nvm_sw + NVM_VERSION);
509 else
510 return le32_to_cpup((__le32 *)(nvm_sw +
7042678d 511 NVM_VERSION_EXT_NVM));
77db0a3c
EH
512}
513
5dd9c68a
EG
514static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
515 const __le16 *phy_sku)
77db0a3c 516{
44fd09da 517 if (cfg->nvm_type != IWL_NVM_EXT)
77db0a3c 518 return le16_to_cpup(nvm_sw + RADIO_CFG);
ce500071 519
7042678d 520 return le32_to_cpup((__le32 *)(phy_sku + RADIO_CFG_FAMILY_EXT_NVM));
ce500071 521
77db0a3c
EH
522}
523
5dd9c68a 524static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
77db0a3c 525{
ce500071
EH
526 int n_hw_addr;
527
44fd09da 528 if (cfg->nvm_type != IWL_NVM_EXT)
77db0a3c 529 return le16_to_cpup(nvm_sw + N_HW_ADDRS);
ce500071 530
5dd9c68a 531 n_hw_addr = le32_to_cpup((__le32 *)(nvm_sw + N_HW_ADDRS_FAMILY_8000));
ce500071
EH
532
533 return n_hw_addr & N_HW_ADDR_MASK;
77db0a3c
EH
534}
535
536static void iwl_set_radio_cfg(const struct iwl_cfg *cfg,
537 struct iwl_nvm_data *data,
538 u32 radio_cfg)
539{
44fd09da 540 if (cfg->nvm_type != IWL_NVM_EXT) {
77db0a3c
EH
541 data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg);
542 data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg);
543 data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg);
544 data->radio_cfg_pnum = NVM_RF_CFG_PNUM_MSK(radio_cfg);
77db0a3c
EH
545 return;
546 }
547
548 /* set the radio configuration for family 8000 */
7042678d
SS
549 data->radio_cfg_type = EXT_NVM_RF_CFG_TYPE_MSK(radio_cfg);
550 data->radio_cfg_step = EXT_NVM_RF_CFG_STEP_MSK(radio_cfg);
551 data->radio_cfg_dash = EXT_NVM_RF_CFG_DASH_MSK(radio_cfg);
552 data->radio_cfg_pnum = EXT_NVM_RF_CFG_FLAVOR_MSK(radio_cfg);
553 data->valid_tx_ant = EXT_NVM_RF_CFG_TX_ANT_MSK(radio_cfg);
554 data->valid_rx_ant = EXT_NVM_RF_CFG_RX_ANT_MSK(radio_cfg);
77db0a3c
EH
555}
556
17c867bf
SS
557static void iwl_flip_hw_address(__le32 mac_addr0, __le32 mac_addr1, u8 *dest)
558{
559 const u8 *hw_addr;
560
561 hw_addr = (const u8 *)&mac_addr0;
562 dest[0] = hw_addr[3];
563 dest[1] = hw_addr[2];
564 dest[2] = hw_addr[1];
565 dest[3] = hw_addr[0];
566
567 hw_addr = (const u8 *)&mac_addr1;
568 dest[4] = hw_addr[1];
569 dest[5] = hw_addr[0];
570}
571
29108495
SS
572void iwl_set_hw_address_from_csr(struct iwl_trans *trans,
573 struct iwl_nvm_data *data)
17c867bf
SS
574{
575 __le32 mac_addr0 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR0_STRAP));
576 __le32 mac_addr1 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR1_STRAP));
577
a6c934b3
HD
578 iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);
579 /*
580 * If the OEM fused a valid address, use it instead of the one in the
581 * OTP
582 */
583 if (is_valid_ether_addr(data->hw_addr))
584 return;
585
586 mac_addr0 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR0_OTP));
587 mac_addr1 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR1_OTP));
17c867bf
SS
588
589 iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);
590}
29108495 591IWL_EXPORT_SYMBOL(iwl_set_hw_address_from_csr);
17c867bf 592
afd5b170 593static void iwl_set_hw_address_family_8000(struct iwl_trans *trans,
6a68a39f 594 const struct iwl_cfg *cfg,
9f32e017
EH
595 struct iwl_nvm_data *data,
596 const __le16 *mac_override,
8fe34b06 597 const __be16 *nvm_hw)
9f32e017
EH
598{
599 const u8 *hw_addr;
600
601 if (mac_override) {
18f84673
LK
602 static const u8 reserved_mac[] = {
603 0x02, 0xcc, 0xaa, 0xff, 0xee, 0x00
604 };
605
9f32e017 606 hw_addr = (const u8 *)(mac_override +
7042678d 607 MAC_ADDRESS_OVERRIDE_EXT_NVM);
9f32e017 608
be88a1ad
LK
609 /*
610 * Store the MAC address from MAO section.
611 * No byte swapping is required in MAO section
612 */
613 memcpy(data->hw_addr, hw_addr, ETH_ALEN);
9f32e017 614
18f84673
LK
615 /*
616 * Force the use of the OTP MAC address in case of reserved MAC
617 * address in the NVM, or if address is given but invalid.
618 */
619 if (is_valid_ether_addr(data->hw_addr) &&
620 memcmp(reserved_mac, hw_addr, ETH_ALEN) != 0)
9f32e017 621 return;
6a68a39f 622
afd5b170
SS
623 IWL_ERR(trans,
624 "mac address from nvm override section is not valid\n");
9f32e017
EH
625 }
626
6a68a39f 627 if (nvm_hw) {
afd5b170
SS
628 /* read the mac address from WFMP registers */
629 __le32 mac_addr0 = cpu_to_le32(iwl_trans_read_prph(trans,
630 WFMP_MAC_ADDR_0));
631 __le32 mac_addr1 = cpu_to_le32(iwl_trans_read_prph(trans,
632 WFMP_MAC_ADDR_1));
17c867bf
SS
633
634 iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);
1e0b393a 635
6a68a39f
EH
636 return;
637 }
9f32e017 638
afd5b170
SS
639 IWL_ERR(trans, "mac address is not found\n");
640}
641
17c867bf
SS
642static int iwl_set_hw_address(struct iwl_trans *trans,
643 const struct iwl_cfg *cfg,
8fe34b06 644 struct iwl_nvm_data *data, const __be16 *nvm_hw,
17c867bf 645 const __le16 *mac_override)
afd5b170 646{
17c867bf
SS
647 if (cfg->mac_addr_from_csr) {
648 iwl_set_hw_address_from_csr(trans, data);
44fd09da 649 } else if (cfg->nvm_type != IWL_NVM_EXT) {
afd5b170
SS
650 const u8 *hw_addr = (const u8 *)(nvm_hw + HW_ADDR);
651
652 /* The byte order is little endian 16 bit, meaning 214365 */
653 data->hw_addr[0] = hw_addr[1];
654 data->hw_addr[1] = hw_addr[0];
655 data->hw_addr[2] = hw_addr[3];
656 data->hw_addr[3] = hw_addr[2];
657 data->hw_addr[4] = hw_addr[5];
658 data->hw_addr[5] = hw_addr[4];
659 } else {
660 iwl_set_hw_address_family_8000(trans, cfg, data,
661 mac_override, nvm_hw);
662 }
17c867bf
SS
663
664 if (!is_valid_ether_addr(data->hw_addr)) {
665 IWL_ERR(trans, "no valid mac address was found\n");
666 return -EINVAL;
667 }
668
4409e72b
LC
669 IWL_INFO(trans, "base HW address: %pM\n", data->hw_addr);
670
17c867bf 671 return 0;
9f32e017
EH
672}
673
01a9c948
LC
674static bool
675iwl_nvm_no_wide_in_5ghz(struct device *dev, const struct iwl_cfg *cfg,
8fe34b06 676 const __be16 *nvm_hw)
01a9c948
LC
677{
678 /*
679 * Workaround a bug in Indonesia SKUs where the regulatory in
680 * some 7000-family OTPs erroneously allow wide channels in
681 * 5GHz. To check for Indonesia, we take the SKU value from
682 * bits 1-4 in the subsystem ID and check if it is either 5 or
683 * 9. In those cases, we need to force-disable wide channels
684 * in 5GHz otherwise the FW will throw a sysassert when we try
685 * to use them.
686 */
687 if (cfg->device_family == IWL_DEVICE_FAMILY_7000) {
688 /*
689 * Unlike the other sections in the NVM, the hw
690 * section uses big-endian.
691 */
8fe34b06 692 u16 subsystem_id = be16_to_cpup(nvm_hw + SUBSYSTEM_ID);
01a9c948
LC
693 u8 sku = (subsystem_id & 0x1e) >> 1;
694
695 if (sku == 5 || sku == 9) {
696 IWL_DEBUG_EEPROM(dev,
697 "disabling wide channels in 5GHz (0x%0x %d)\n",
698 subsystem_id, sku);
699 return true;
700 }
701 }
702
703 return false;
704}
705
b1e1adfa 706struct iwl_nvm_data *
afd5b170 707iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
8fe34b06 708 const __be16 *nvm_hw, const __le16 *nvm_sw,
77db0a3c 709 const __le16 *nvm_calib, const __le16 *regulatory,
ce500071 710 const __le16 *mac_override, const __le16 *phy_sku,
afd5b170 711 u8 tx_chains, u8 rx_chains, bool lar_fw_supported)
b1e1adfa 712{
afd5b170 713 struct device *dev = trans->dev;
b1e1adfa 714 struct iwl_nvm_data *data;
afd5b170 715 bool lar_enabled;
01a9c948 716 bool no_wide_in_5ghz = iwl_nvm_no_wide_in_5ghz(dev, cfg, nvm_hw);
afd5b170 717 u32 sku, radio_cfg;
d0d15197 718 u16 lar_config;
afd5b170 719 const __le16 *ch_section;
77db0a3c 720
44fd09da 721 if (cfg->nvm_type != IWL_NVM_EXT)
77db0a3c
EH
722 data = kzalloc(sizeof(*data) +
723 sizeof(struct ieee80211_channel) *
77e30e10 724 IWL_NVM_NUM_CHANNELS,
77db0a3c
EH
725 GFP_KERNEL);
726 else
727 data = kzalloc(sizeof(*data) +
728 sizeof(struct ieee80211_channel) *
77e30e10 729 IWL_NVM_NUM_CHANNELS_EXT,
77db0a3c 730 GFP_KERNEL);
b1e1adfa
JB
731 if (!data)
732 return NULL;
733
77db0a3c 734 data->nvm_version = iwl_get_nvm_version(cfg, nvm_sw);
b1e1adfa 735
5dd9c68a 736 radio_cfg = iwl_get_radio_cfg(cfg, nvm_sw, phy_sku);
77db0a3c 737 iwl_set_radio_cfg(cfg, data, radio_cfg);
a0544272
MH
738 if (data->valid_tx_ant)
739 tx_chains &= data->valid_tx_ant;
740 if (data->valid_rx_ant)
741 rx_chains &= data->valid_rx_ant;
b1e1adfa 742
5dd9c68a 743 sku = iwl_get_sku(cfg, nvm_sw, phy_sku);
b1e1adfa
JB
744 data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ;
745 data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ;
746 data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE;
747 if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
748 data->sku_cap_11n_enable = false;
2926f958
EP
749 data->sku_cap_11ac_enable = data->sku_cap_11n_enable &&
750 (sku & NVM_SKU_CAP_11AC_ENABLE);
5f0d98f2 751 data->sku_cap_mimo_disabled = sku & NVM_SKU_CAP_MIMO_DISABLE;
b1e1adfa 752
5dd9c68a 753 data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw);
b1e1adfa 754
44fd09da 755 if (cfg->nvm_type != IWL_NVM_EXT) {
77db0a3c
EH
756 /* Checking for required sections */
757 if (!nvm_calib) {
afd5b170
SS
758 IWL_ERR(trans,
759 "Can't parse empty Calib NVM sections\n");
1270c416 760 kfree(data);
77db0a3c
EH
761 return NULL;
762 }
44fd09da
CRI
763
764 ch_section = cfg->nvm_type == IWL_NVM_SDP ?
765 &regulatory[NVM_CHANNELS_SDP] :
766 &nvm_sw[NVM_CHANNELS];
767
77db0a3c
EH
768 /* in family 8000 Xtal calibration values moved to OTP */
769 data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB);
770 data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1);
afd5b170 771 lar_enabled = true;
77db0a3c 772 } else {
f5528631 773 u16 lar_offset = data->nvm_version < 0xE39 ?
7042678d
SS
774 NVM_LAR_OFFSET_OLD :
775 NVM_LAR_OFFSET;
f5528631
AN
776
777 lar_config = le16_to_cpup(regulatory + lar_offset);
d0d15197 778 data->lar_enabled = !!(lar_config &
7042678d 779 NVM_LAR_ENABLED);
afd5b170 780 lar_enabled = data->lar_enabled;
7042678d 781 ch_section = &regulatory[NVM_CHANNELS_EXTENDED];
77db0a3c 782 }
b1e1adfa 783
17c867bf
SS
784 /* If no valid mac address was found - bail out */
785 if (iwl_set_hw_address(trans, cfg, data, nvm_hw, mac_override)) {
786 kfree(data);
787 return NULL;
788 }
789
afd5b170 790 iwl_init_sbands(dev, cfg, data, ch_section, tx_chains, rx_chains,
01a9c948 791 lar_fw_supported && lar_enabled, no_wide_in_5ghz);
33b2f684 792 data->calib_version = 255;
b1e1adfa
JB
793
794 return data;
795}
48e29340 796IWL_EXPORT_SYMBOL(iwl_parse_nvm_data);
af45a900
AN
797
798static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan,
b281c93d
MG
799 int ch_idx, u16 nvm_flags,
800 const struct iwl_cfg *cfg)
af45a900
AN
801{
802 u32 flags = NL80211_RRF_NO_HT40;
b281c93d
MG
803 u32 last_5ghz_ht = LAST_5GHZ_HT;
804
44fd09da 805 if (cfg->nvm_type == IWL_NVM_EXT)
b281c93d 806 last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;
af45a900
AN
807
808 if (ch_idx < NUM_2GHZ_CHANNELS &&
809 (nvm_flags & NVM_CHANNEL_40MHZ)) {
810 if (nvm_chan[ch_idx] <= LAST_2GHZ_HT_PLUS)
811 flags &= ~NL80211_RRF_NO_HT40PLUS;
812 if (nvm_chan[ch_idx] >= FIRST_2GHZ_HT_MINUS)
813 flags &= ~NL80211_RRF_NO_HT40MINUS;
b281c93d 814 } else if (nvm_chan[ch_idx] <= last_5ghz_ht &&
af45a900
AN
815 (nvm_flags & NVM_CHANNEL_40MHZ)) {
816 if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
817 flags &= ~NL80211_RRF_NO_HT40PLUS;
818 else
819 flags &= ~NL80211_RRF_NO_HT40MINUS;
820 }
821
822 if (!(nvm_flags & NVM_CHANNEL_80MHZ))
823 flags |= NL80211_RRF_NO_80MHZ;
824 if (!(nvm_flags & NVM_CHANNEL_160MHZ))
825 flags |= NL80211_RRF_NO_160MHZ;
826
af45a900
AN
827 if (!(nvm_flags & NVM_CHANNEL_ACTIVE))
828 flags |= NL80211_RRF_NO_IR;
829
830 if (nvm_flags & NVM_CHANNEL_RADAR)
831 flags |= NL80211_RRF_DFS;
832
833 if (nvm_flags & NVM_CHANNEL_INDOOR_ONLY)
834 flags |= NL80211_RRF_NO_OUTDOOR;
835
836 /* Set the GO concurrent flag only in case that NO_IR is set.
837 * Otherwise it is meaningless
838 */
839 if ((nvm_flags & NVM_CHANNEL_GO_CONCURRENT) &&
840 (flags & NL80211_RRF_NO_IR))
841 flags |= NL80211_RRF_GO_CONCURRENT;
842
843 return flags;
844}
845
77e30e10
HD
846struct regdb_ptrs {
847 struct ieee80211_wmm_rule *rule;
848 u32 token;
849};
850
af45a900 851struct ieee80211_regdomain *
162ee3c9 852iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
77e30e10
HD
853 int num_of_ch, __le32 *channels, u16 fw_mcc,
854 u16 geo_info)
af45a900
AN
855{
856 int ch_idx;
92b0f7b2
EG
857 u16 ch_flags;
858 u32 reg_rule_flags, prev_reg_rule_flags = 0;
44fd09da 859 const u8 *nvm_chan = cfg->nvm_type == IWL_NVM_EXT ?
7042678d 860 iwl_ext_nvm_channels : iwl_nvm_channels;
77e30e10
HD
861 struct ieee80211_regdomain *regd, *copy_rd;
862 int size_of_regd, regd_to_copy, wmms_to_copy;
863 int size_of_wmms = 0;
af45a900 864 struct ieee80211_reg_rule *rule;
77e30e10
HD
865 struct ieee80211_wmm_rule *wmm_rule, *d_wmm, *s_wmm;
866 struct regdb_ptrs *regdb_ptrs;
57fbcce3 867 enum nl80211_band band;
af45a900 868 int center_freq, prev_center_freq = 0;
77e30e10
HD
869 int valid_rules = 0, n_wmms = 0;
870 int i;
af45a900 871 bool new_rule;
44fd09da 872 int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ?
77e30e10 873 IWL_NVM_NUM_CHANNELS_EXT : IWL_NVM_NUM_CHANNELS;
af45a900
AN
874
875 if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES))
876 return ERR_PTR(-EINVAL);
877
4557eaba
AN
878 if (WARN_ON(num_of_ch > max_num_ch))
879 num_of_ch = max_num_ch;
880
af45a900
AN
881 IWL_DEBUG_DEV(dev, IWL_DL_LAR, "building regdom for %d channels\n",
882 num_of_ch);
883
884 /* build a regdomain rule for every valid channel */
885 size_of_regd =
886 sizeof(struct ieee80211_regdomain) +
887 num_of_ch * sizeof(struct ieee80211_reg_rule);
888
77e30e10
HD
889 if (geo_info & GEO_WMM_ETSI_5GHZ_INFO)
890 size_of_wmms =
891 num_of_ch * sizeof(struct ieee80211_wmm_rule);
892
893 regd = kzalloc(size_of_regd + size_of_wmms, GFP_KERNEL);
af45a900
AN
894 if (!regd)
895 return ERR_PTR(-ENOMEM);
896
77e30e10
HD
897 regdb_ptrs = kcalloc(num_of_ch, sizeof(*regdb_ptrs), GFP_KERNEL);
898 if (!regdb_ptrs) {
899 copy_rd = ERR_PTR(-ENOMEM);
900 goto out;
901 }
902
903 /* set alpha2 from FW. */
904 regd->alpha2[0] = fw_mcc >> 8;
905 regd->alpha2[1] = fw_mcc & 0xff;
906
907 wmm_rule = (struct ieee80211_wmm_rule *)((u8 *)regd + size_of_regd);
908
af45a900
AN
909 for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
910 ch_flags = (u16)__le32_to_cpup(channels + ch_idx);
911 band = (ch_idx < NUM_2GHZ_CHANNELS) ?
57fbcce3 912 NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
af45a900
AN
913 center_freq = ieee80211_channel_to_frequency(nvm_chan[ch_idx],
914 band);
915 new_rule = false;
916
917 if (!(ch_flags & NVM_CHANNEL_VALID)) {
d8c73e45
JB
918 iwl_nvm_print_channel_flags(dev, IWL_DL_LAR,
919 nvm_chan[ch_idx], ch_flags);
af45a900
AN
920 continue;
921 }
922
92b0f7b2
EG
923 reg_rule_flags = iwl_nvm_get_regdom_bw_flags(nvm_chan, ch_idx,
924 ch_flags, cfg);
925
af45a900 926 /* we can't continue the same rule */
92b0f7b2 927 if (ch_idx == 0 || prev_reg_rule_flags != reg_rule_flags ||
af45a900
AN
928 center_freq - prev_center_freq > 20) {
929 valid_rules++;
930 new_rule = true;
931 }
932
933 rule = &regd->reg_rules[valid_rules - 1];
934
935 if (new_rule)
936 rule->freq_range.start_freq_khz =
937 MHZ_TO_KHZ(center_freq - 10);
938
939 rule->freq_range.end_freq_khz = MHZ_TO_KHZ(center_freq + 10);
940
941 /* this doesn't matter - not used by FW */
942 rule->power_rule.max_antenna_gain = DBI_TO_MBI(6);
02a50495
EP
943 rule->power_rule.max_eirp =
944 DBM_TO_MBM(IWL_DEFAULT_MAX_TX_POWER);
af45a900 945
92b0f7b2 946 rule->flags = reg_rule_flags;
af45a900
AN
947
948 /* rely on auto-calculation to merge BW of contiguous chans */
949 rule->flags |= NL80211_RRF_AUTO_BW;
950 rule->freq_range.max_bandwidth_khz = 0;
951
af45a900 952 prev_center_freq = center_freq;
92b0f7b2 953 prev_reg_rule_flags = reg_rule_flags;
af45a900 954
d8c73e45
JB
955 iwl_nvm_print_channel_flags(dev, IWL_DL_LAR,
956 nvm_chan[ch_idx], ch_flags);
77e30e10
HD
957
958 if (!(geo_info & GEO_WMM_ETSI_5GHZ_INFO) ||
959 band == NL80211_BAND_2GHZ)
960 continue;
961
962 if (!reg_query_regdb_wmm(regd->alpha2, center_freq,
963 &regdb_ptrs[n_wmms].token, wmm_rule)) {
964 /* Add only new rules */
965 for (i = 0; i < n_wmms; i++) {
966 if (regdb_ptrs[i].token ==
967 regdb_ptrs[n_wmms].token) {
968 rule->wmm_rule = regdb_ptrs[i].rule;
969 break;
970 }
971 }
972 if (i == n_wmms) {
973 rule->wmm_rule = wmm_rule;
974 regdb_ptrs[n_wmms++].rule = wmm_rule;
975 wmm_rule++;
976 }
977 }
af45a900
AN
978 }
979
980 regd->n_reg_rules = valid_rules;
77e30e10 981 regd->n_wmm_rules = n_wmms;
af45a900 982
77e30e10
HD
983 /*
984 * Narrow down regdom for unused regulatory rules to prevent hole
985 * between reg rules to wmm rules.
986 */
987 regd_to_copy = sizeof(struct ieee80211_regdomain) +
988 valid_rules * sizeof(struct ieee80211_reg_rule);
989
990 wmms_to_copy = sizeof(struct ieee80211_wmm_rule) * n_wmms;
991
992 copy_rd = kzalloc(regd_to_copy + wmms_to_copy, GFP_KERNEL);
993 if (!copy_rd) {
994 copy_rd = ERR_PTR(-ENOMEM);
995 goto out;
996 }
997
998 memcpy(copy_rd, regd, regd_to_copy);
999 memcpy((u8 *)copy_rd + regd_to_copy, (u8 *)regd + size_of_regd,
1000 wmms_to_copy);
1001
1002 d_wmm = (struct ieee80211_wmm_rule *)((u8 *)copy_rd + regd_to_copy);
1003 s_wmm = (struct ieee80211_wmm_rule *)((u8 *)regd + size_of_regd);
1004
1005 for (i = 0; i < regd->n_reg_rules; i++) {
1006 if (!regd->reg_rules[i].wmm_rule)
1007 continue;
1008
1009 copy_rd->reg_rules[i].wmm_rule = d_wmm +
1010 (regd->reg_rules[i].wmm_rule - s_wmm) /
1011 sizeof(struct ieee80211_wmm_rule);
1012 }
af45a900 1013
77e30e10
HD
1014out:
1015 kfree(regdb_ptrs);
1016 kfree(regd);
1017 return copy_rd;
af45a900
AN
1018}
1019IWL_EXPORT_SYMBOL(iwl_parse_nvm_mcc_info);