diff options
32 files changed, 1854 insertions, 1996 deletions
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 7ba6b8dc1cbd..98c8f6449649 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -8,6 +8,7 @@ iwlwifi-objs += iwl-io.o | |||
8 | iwlwifi-objs += iwl-drv.o | 8 | iwlwifi-objs += iwl-drv.o |
9 | iwlwifi-objs += iwl-debug.o | 9 | iwlwifi-objs += iwl-debug.o |
10 | iwlwifi-objs += iwl-notif-wait.o | 10 | iwlwifi-objs += iwl-notif-wait.o |
11 | iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o | ||
11 | iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o | 12 | iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o |
12 | iwlwifi-objs += pcie/1000.o pcie/2000.o pcie/5000.o pcie/6000.o | 13 | iwlwifi-objs += pcie/1000.o pcie/2000.o pcie/5000.o pcie/6000.o |
13 | 14 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/Makefile b/drivers/net/wireless/iwlwifi/dvm/Makefile index 13f8282f4d0e..5ff76b204141 100644 --- a/drivers/net/wireless/iwlwifi/dvm/Makefile +++ b/drivers/net/wireless/iwlwifi/dvm/Makefile | |||
@@ -3,7 +3,7 @@ obj-$(CONFIG_IWLDVM) += iwldvm.o | |||
3 | iwldvm-objs += main.o rs.o mac80211.o ucode.o tx.o | 3 | iwldvm-objs += main.o rs.o mac80211.o ucode.o tx.o |
4 | iwldvm-objs += lib.o calib.o tt.o sta.o rx.o | 4 | iwldvm-objs += lib.o calib.o tt.o sta.o rx.o |
5 | 5 | ||
6 | iwldvm-objs += eeprom.o power.o | 6 | iwldvm-objs += power.o |
7 | iwldvm-objs += scan.o led.o | 7 | iwldvm-objs += scan.o led.o |
8 | iwldvm-objs += rxon.o devices.o | 8 | iwldvm-objs += rxon.o devices.o |
9 | 9 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index 9a8dd1a579d0..2ae3608472a6 100644 --- a/drivers/net/wireless/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h | |||
@@ -92,7 +92,6 @@ extern struct iwl_lib_ops iwl6030_lib; | |||
92 | #define STATUS_CT_KILL 1 | 92 | #define STATUS_CT_KILL 1 |
93 | #define STATUS_ALIVE 2 | 93 | #define STATUS_ALIVE 2 |
94 | #define STATUS_READY 3 | 94 | #define STATUS_READY 3 |
95 | #define STATUS_GEO_CONFIGURED 4 | ||
96 | #define STATUS_EXIT_PENDING 5 | 95 | #define STATUS_EXIT_PENDING 5 |
97 | #define STATUS_STATISTICS 6 | 96 | #define STATUS_STATISTICS 6 |
98 | #define STATUS_SCANNING 7 | 97 | #define STATUS_SCANNING 7 |
@@ -443,10 +442,8 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, | |||
443 | 442 | ||
444 | static inline int iwl_is_ready(struct iwl_priv *priv) | 443 | static inline int iwl_is_ready(struct iwl_priv *priv) |
445 | { | 444 | { |
446 | /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are | 445 | /* The adapter is 'ready' if READY EXIT_PENDING is not set */ |
447 | * set but EXIT_PENDING is not */ | ||
448 | return test_bit(STATUS_READY, &priv->status) && | 446 | return test_bit(STATUS_READY, &priv->status) && |
449 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) && | ||
450 | !test_bit(STATUS_EXIT_PENDING, &priv->status); | 447 | !test_bit(STATUS_EXIT_PENDING, &priv->status); |
451 | } | 448 | } |
452 | 449 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.c b/drivers/net/wireless/iwlwifi/dvm/calib.c index 7eb3fa3df7c4..f2dd671d7dc8 100644 --- a/drivers/net/wireless/iwlwifi/dvm/calib.c +++ b/drivers/net/wireless/iwlwifi/dvm/calib.c | |||
@@ -833,14 +833,14 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | |||
833 | * To be safe, simply mask out any chains that we know | 833 | * To be safe, simply mask out any chains that we know |
834 | * are not on the device. | 834 | * are not on the device. |
835 | */ | 835 | */ |
836 | active_chains &= priv->hw_params.valid_rx_ant; | 836 | active_chains &= priv->eeprom_data->valid_rx_ant; |
837 | 837 | ||
838 | num_tx_chains = 0; | 838 | num_tx_chains = 0; |
839 | for (i = 0; i < NUM_RX_CHAINS; i++) { | 839 | for (i = 0; i < NUM_RX_CHAINS; i++) { |
840 | /* loops on all the bits of | 840 | /* loops on all the bits of |
841 | * priv->hw_setting.valid_tx_ant */ | 841 | * priv->hw_setting.valid_tx_ant */ |
842 | u8 ant_msk = (1 << i); | 842 | u8 ant_msk = (1 << i); |
843 | if (!(priv->hw_params.valid_tx_ant & ant_msk)) | 843 | if (!(priv->eeprom_data->valid_tx_ant & ant_msk)) |
844 | continue; | 844 | continue; |
845 | 845 | ||
846 | num_tx_chains++; | 846 | num_tx_chains++; |
@@ -854,7 +854,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | |||
854 | * connect the first valid tx chain | 854 | * connect the first valid tx chain |
855 | */ | 855 | */ |
856 | first_chain = | 856 | first_chain = |
857 | find_first_chain(priv->hw_params.valid_tx_ant); | 857 | find_first_chain(priv->eeprom_data->valid_tx_ant); |
858 | data->disconn_array[first_chain] = 0; | 858 | data->disconn_array[first_chain] = 0; |
859 | active_chains |= BIT(first_chain); | 859 | active_chains |= BIT(first_chain); |
860 | IWL_DEBUG_CALIB(priv, | 860 | IWL_DEBUG_CALIB(priv, |
@@ -864,13 +864,13 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | |||
864 | } | 864 | } |
865 | } | 865 | } |
866 | 866 | ||
867 | if (active_chains != priv->hw_params.valid_rx_ant && | 867 | if (active_chains != priv->eeprom_data->valid_rx_ant && |
868 | active_chains != priv->chain_noise_data.active_chains) | 868 | active_chains != priv->chain_noise_data.active_chains) |
869 | IWL_DEBUG_CALIB(priv, | 869 | IWL_DEBUG_CALIB(priv, |
870 | "Detected that not all antennas are connected! " | 870 | "Detected that not all antennas are connected! " |
871 | "Connected: %#x, valid: %#x.\n", | 871 | "Connected: %#x, valid: %#x.\n", |
872 | active_chains, | 872 | active_chains, |
873 | priv->hw_params.valid_rx_ant); | 873 | priv->eeprom_data->valid_rx_ant); |
874 | 874 | ||
875 | /* Save for use within RXON, TX, SCAN commands, etc. */ | 875 | /* Save for use within RXON, TX, SCAN commands, etc. */ |
876 | data->active_chains = active_chains; | 876 | data->active_chains = active_chains; |
@@ -1055,7 +1055,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | |||
1055 | priv->cfg->bt_params->advanced_bt_coexist) { | 1055 | priv->cfg->bt_params->advanced_bt_coexist) { |
1056 | /* Disable disconnected antenna algorithm for advanced | 1056 | /* Disable disconnected antenna algorithm for advanced |
1057 | bt coex, assuming valid antennas are connected */ | 1057 | bt coex, assuming valid antennas are connected */ |
1058 | data->active_chains = priv->hw_params.valid_rx_ant; | 1058 | data->active_chains = priv->eeprom_data->valid_rx_ant; |
1059 | for (i = 0; i < NUM_RX_CHAINS; i++) | 1059 | for (i = 0; i < NUM_RX_CHAINS; i++) |
1060 | if (!(data->active_chains & (1<<i))) | 1060 | if (!(data->active_chains & (1<<i))) |
1061 | data->disconn_array[i] = 1; | 1061 | data->disconn_array[i] = 1; |
@@ -1084,8 +1084,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | |||
1084 | IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n", | 1084 | IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n", |
1085 | min_average_noise, min_average_noise_antenna_i); | 1085 | min_average_noise, min_average_noise_antenna_i); |
1086 | 1086 | ||
1087 | iwlagn_gain_computation(priv, average_noise, | 1087 | iwlagn_gain_computation( |
1088 | find_first_chain(priv->hw_params.valid_rx_ant)); | 1088 | priv, average_noise, |
1089 | find_first_chain(priv->eeprom_data->valid_rx_ant)); | ||
1089 | 1090 | ||
1090 | /* Some power changes may have been made during the calibration. | 1091 | /* Some power changes may have been made during the calibration. |
1091 | * Update and commit the RXON | 1092 | * Update and commit the RXON |
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c index 2268adddf4c0..8a2d9e643b14 100644 --- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c | |||
@@ -303,13 +303,13 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
303 | const u8 *ptr; | 303 | const u8 *ptr; |
304 | char *buf; | 304 | char *buf; |
305 | u16 eeprom_ver; | 305 | u16 eeprom_ver; |
306 | size_t eeprom_len = priv->cfg->base_params->eeprom_size; | 306 | size_t eeprom_len = priv->eeprom_blob_size; |
307 | buf_size = 4 * eeprom_len + 256; | 307 | buf_size = 4 * eeprom_len + 256; |
308 | 308 | ||
309 | if (eeprom_len % 16) | 309 | if (eeprom_len % 16) |
310 | return -ENODATA; | 310 | return -ENODATA; |
311 | 311 | ||
312 | ptr = priv->eeprom; | 312 | ptr = priv->eeprom_blob; |
313 | if (!ptr) | 313 | if (!ptr) |
314 | return -ENOMEM; | 314 | return -ENOMEM; |
315 | 315 | ||
@@ -318,11 +318,9 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
318 | if (!buf) | 318 | if (!buf) |
319 | return -ENOMEM; | 319 | return -ENOMEM; |
320 | 320 | ||
321 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | 321 | eeprom_ver = priv->eeprom_data->eeprom_version; |
322 | pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, " | 322 | pos += scnprintf(buf + pos, buf_size - pos, |
323 | "version: 0x%x\n", | 323 | "NVM version: 0x%x\n", eeprom_ver); |
324 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
325 | ? "OTP" : "EEPROM", eeprom_ver); | ||
326 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { | 324 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { |
327 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); | 325 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); |
328 | hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, | 326 | hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, |
@@ -347,9 +345,6 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, | |||
347 | char *buf; | 345 | char *buf; |
348 | ssize_t ret; | 346 | ssize_t ret; |
349 | 347 | ||
350 | if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status)) | ||
351 | return -EAGAIN; | ||
352 | |||
353 | buf = kzalloc(bufsz, GFP_KERNEL); | 348 | buf = kzalloc(bufsz, GFP_KERNEL); |
354 | if (!buf) | 349 | if (!buf) |
355 | return -ENOMEM; | 350 | return -ENOMEM; |
@@ -422,8 +417,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, | |||
422 | test_bit(STATUS_ALIVE, &priv->status)); | 417 | test_bit(STATUS_ALIVE, &priv->status)); |
423 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", | 418 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", |
424 | test_bit(STATUS_READY, &priv->status)); | 419 | test_bit(STATUS_READY, &priv->status)); |
425 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", | ||
426 | test_bit(STATUS_GEO_CONFIGURED, &priv->status)); | ||
427 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", | 420 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", |
428 | test_bit(STATUS_EXIT_PENDING, &priv->status)); | 421 | test_bit(STATUS_EXIT_PENDING, &priv->status)); |
429 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", | 422 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", |
@@ -1337,17 +1330,17 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | |||
1337 | if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { | 1330 | if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { |
1338 | pos += scnprintf(buf + pos, bufsz - pos, | 1331 | pos += scnprintf(buf + pos, bufsz - pos, |
1339 | "tx power: (1/2 dB step)\n"); | 1332 | "tx power: (1/2 dB step)\n"); |
1340 | if ((priv->hw_params.valid_tx_ant & ANT_A) && | 1333 | if ((priv->eeprom_data->valid_tx_ant & ANT_A) && |
1341 | tx->tx_power.ant_a) | 1334 | tx->tx_power.ant_a) |
1342 | pos += scnprintf(buf + pos, bufsz - pos, | 1335 | pos += scnprintf(buf + pos, bufsz - pos, |
1343 | fmt_hex, "antenna A:", | 1336 | fmt_hex, "antenna A:", |
1344 | tx->tx_power.ant_a); | 1337 | tx->tx_power.ant_a); |
1345 | if ((priv->hw_params.valid_tx_ant & ANT_B) && | 1338 | if ((priv->eeprom_data->valid_tx_ant & ANT_B) && |
1346 | tx->tx_power.ant_b) | 1339 | tx->tx_power.ant_b) |
1347 | pos += scnprintf(buf + pos, bufsz - pos, | 1340 | pos += scnprintf(buf + pos, bufsz - pos, |
1348 | fmt_hex, "antenna B:", | 1341 | fmt_hex, "antenna B:", |
1349 | tx->tx_power.ant_b); | 1342 | tx->tx_power.ant_b); |
1350 | if ((priv->hw_params.valid_tx_ant & ANT_C) && | 1343 | if ((priv->eeprom_data->valid_tx_ant & ANT_C) && |
1351 | tx->tx_power.ant_c) | 1344 | tx->tx_power.ant_c) |
1352 | pos += scnprintf(buf + pos, bufsz - pos, | 1345 | pos += scnprintf(buf + pos, bufsz - pos, |
1353 | fmt_hex, "antenna C:", | 1346 | fmt_hex, "antenna C:", |
diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h index c29e6378a11d..89f2e1040e7f 100644 --- a/drivers/net/wireless/iwlwifi/dvm/dev.h +++ b/drivers/net/wireless/iwlwifi/dvm/dev.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/mutex.h> | 39 | #include <linux/mutex.h> |
40 | 40 | ||
41 | #include "iwl-fw.h" | 41 | #include "iwl-fw.h" |
42 | #include "iwl-eeprom-parse.h" | ||
42 | #include "iwl-csr.h" | 43 | #include "iwl-csr.h" |
43 | #include "iwl-debug.h" | 44 | #include "iwl-debug.h" |
44 | #include "iwl-agn-hw.h" | 45 | #include "iwl-agn-hw.h" |
@@ -46,7 +47,6 @@ | |||
46 | #include "iwl-notif-wait.h" | 47 | #include "iwl-notif-wait.h" |
47 | #include "iwl-trans.h" | 48 | #include "iwl-trans.h" |
48 | 49 | ||
49 | #include "eeprom.h" | ||
50 | #include "led.h" | 50 | #include "led.h" |
51 | #include "power.h" | 51 | #include "power.h" |
52 | #include "rs.h" | 52 | #include "rs.h" |
@@ -89,33 +89,6 @@ | |||
89 | #define IWL_NUM_SCAN_RATES (2) | 89 | #define IWL_NUM_SCAN_RATES (2) |
90 | 90 | ||
91 | /* | 91 | /* |
92 | * One for each channel, holds all channel setup data | ||
93 | * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant | ||
94 | * with one another! | ||
95 | */ | ||
96 | struct iwl_channel_info { | ||
97 | struct iwl_eeprom_channel eeprom; /* EEPROM regulatory limit */ | ||
98 | struct iwl_eeprom_channel ht40_eeprom; /* EEPROM regulatory limit for | ||
99 | * HT40 channel */ | ||
100 | |||
101 | u8 channel; /* channel number */ | ||
102 | u8 flags; /* flags copied from EEPROM */ | ||
103 | s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ | ||
104 | s8 curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) limit */ | ||
105 | s8 min_power; /* always 0 */ | ||
106 | s8 scan_power; /* (dBm) regul. eeprom, direct scans, any rate */ | ||
107 | |||
108 | u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */ | ||
109 | u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */ | ||
110 | enum ieee80211_band band; | ||
111 | |||
112 | /* HT40 channel info */ | ||
113 | s8 ht40_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ | ||
114 | u8 ht40_flags; /* flags copied from EEPROM */ | ||
115 | u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */ | ||
116 | }; | ||
117 | |||
118 | /* | ||
119 | * Minimum number of queues. MAX_NUM is defined in hw specific files. | 92 | * Minimum number of queues. MAX_NUM is defined in hw specific files. |
120 | * Set the minimum to accommodate | 93 | * Set the minimum to accommodate |
121 | * - 4 standard TX queues | 94 | * - 4 standard TX queues |
@@ -154,29 +127,6 @@ union iwl_ht_rate_supp { | |||
154 | }; | 127 | }; |
155 | }; | 128 | }; |
156 | 129 | ||
157 | #define CFG_HT_RX_AMPDU_FACTOR_8K (0x0) | ||
158 | #define CFG_HT_RX_AMPDU_FACTOR_16K (0x1) | ||
159 | #define CFG_HT_RX_AMPDU_FACTOR_32K (0x2) | ||
160 | #define CFG_HT_RX_AMPDU_FACTOR_64K (0x3) | ||
161 | #define CFG_HT_RX_AMPDU_FACTOR_DEF CFG_HT_RX_AMPDU_FACTOR_64K | ||
162 | #define CFG_HT_RX_AMPDU_FACTOR_MAX CFG_HT_RX_AMPDU_FACTOR_64K | ||
163 | #define CFG_HT_RX_AMPDU_FACTOR_MIN CFG_HT_RX_AMPDU_FACTOR_8K | ||
164 | |||
165 | /* | ||
166 | * Maximal MPDU density for TX aggregation | ||
167 | * 4 - 2us density | ||
168 | * 5 - 4us density | ||
169 | * 6 - 8us density | ||
170 | * 7 - 16us density | ||
171 | */ | ||
172 | #define CFG_HT_MPDU_DENSITY_2USEC (0x4) | ||
173 | #define CFG_HT_MPDU_DENSITY_4USEC (0x5) | ||
174 | #define CFG_HT_MPDU_DENSITY_8USEC (0x6) | ||
175 | #define CFG_HT_MPDU_DENSITY_16USEC (0x7) | ||
176 | #define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC | ||
177 | #define CFG_HT_MPDU_DENSITY_MAX CFG_HT_MPDU_DENSITY_16USEC | ||
178 | #define CFG_HT_MPDU_DENSITY_MIN (0x1) | ||
179 | |||
180 | struct iwl_ht_config { | 130 | struct iwl_ht_config { |
181 | bool single_chain_sufficient; | 131 | bool single_chain_sufficient; |
182 | enum ieee80211_smps_mode smps; /* current smps mode */ | 132 | enum ieee80211_smps_mode smps; /* current smps mode */ |
@@ -446,23 +396,6 @@ enum { | |||
446 | MEASUREMENT_ACTIVE = (1 << 1), | 396 | MEASUREMENT_ACTIVE = (1 << 1), |
447 | }; | 397 | }; |
448 | 398 | ||
449 | enum iwl_nvm_type { | ||
450 | NVM_DEVICE_TYPE_EEPROM = 0, | ||
451 | NVM_DEVICE_TYPE_OTP, | ||
452 | }; | ||
453 | |||
454 | /* | ||
455 | * Two types of OTP memory access modes | ||
456 | * IWL_OTP_ACCESS_ABSOLUTE - absolute address mode, | ||
457 | * based on physical memory addressing | ||
458 | * IWL_OTP_ACCESS_RELATIVE - relative address mode, | ||
459 | * based on logical memory addressing | ||
460 | */ | ||
461 | enum iwl_access_mode { | ||
462 | IWL_OTP_ACCESS_ABSOLUTE, | ||
463 | IWL_OTP_ACCESS_RELATIVE, | ||
464 | }; | ||
465 | |||
466 | /* reply_tx_statistics (for _agn devices) */ | 399 | /* reply_tx_statistics (for _agn devices) */ |
467 | struct reply_tx_error_statistics { | 400 | struct reply_tx_error_statistics { |
468 | u32 pp_delay; | 401 | u32 pp_delay; |
@@ -633,8 +566,6 @@ enum iwl_scan_type { | |||
633 | * | 566 | * |
634 | * @tx_chains_num: Number of TX chains | 567 | * @tx_chains_num: Number of TX chains |
635 | * @rx_chains_num: Number of RX chains | 568 | * @rx_chains_num: Number of RX chains |
636 | * @valid_tx_ant: usable antennas for TX | ||
637 | * @valid_rx_ant: usable antennas for RX | ||
638 | * @sku: sku read from EEPROM | 569 | * @sku: sku read from EEPROM |
639 | * @ct_kill_threshold: temperature threshold - in hw dependent unit | 570 | * @ct_kill_threshold: temperature threshold - in hw dependent unit |
640 | * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit | 571 | * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit |
@@ -645,8 +576,6 @@ enum iwl_scan_type { | |||
645 | struct iwl_hw_params { | 576 | struct iwl_hw_params { |
646 | u8 tx_chains_num; | 577 | u8 tx_chains_num; |
647 | u8 rx_chains_num; | 578 | u8 rx_chains_num; |
648 | u8 valid_tx_ant; | ||
649 | u8 valid_rx_ant; | ||
650 | bool use_rts_for_aggregation; | 579 | bool use_rts_for_aggregation; |
651 | u16 sku; | 580 | u16 sku; |
652 | u32 ct_kill_threshold; | 581 | u32 ct_kill_threshold; |
@@ -663,9 +592,6 @@ struct iwl_lib_ops { | |||
663 | /* device specific configuration */ | 592 | /* device specific configuration */ |
664 | void (*nic_config)(struct iwl_priv *priv); | 593 | void (*nic_config)(struct iwl_priv *priv); |
665 | 594 | ||
666 | /* eeprom operations (as defined in eeprom.h) */ | ||
667 | struct iwl_eeprom_ops eeprom_ops; | ||
668 | |||
669 | /* temperature */ | 595 | /* temperature */ |
670 | void (*temperature)(struct iwl_priv *priv); | 596 | void (*temperature)(struct iwl_priv *priv); |
671 | }; | 597 | }; |
@@ -734,8 +660,6 @@ struct iwl_priv { | |||
734 | 660 | ||
735 | /* ieee device used by generic ieee processing code */ | 661 | /* ieee device used by generic ieee processing code */ |
736 | struct ieee80211_hw *hw; | 662 | struct ieee80211_hw *hw; |
737 | struct ieee80211_channel *ieee_channels; | ||
738 | struct ieee80211_rate *ieee_rates; | ||
739 | 663 | ||
740 | struct list_head calib_results; | 664 | struct list_head calib_results; |
741 | 665 | ||
@@ -754,8 +678,6 @@ struct iwl_priv { | |||
754 | 678 | ||
755 | struct iwl_notif_wait_data notif_wait; | 679 | struct iwl_notif_wait_data notif_wait; |
756 | 680 | ||
757 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | ||
758 | |||
759 | /* spectrum measurement report caching */ | 681 | /* spectrum measurement report caching */ |
760 | struct iwl_spectrum_notification measure_report; | 682 | struct iwl_spectrum_notification measure_report; |
761 | u8 measurement_status; | 683 | u8 measurement_status; |
@@ -786,11 +708,6 @@ struct iwl_priv { | |||
786 | bool ucode_loaded; | 708 | bool ucode_loaded; |
787 | bool init_ucode_run; /* Don't run init uCode again */ | 709 | bool init_ucode_run; /* Don't run init uCode again */ |
788 | 710 | ||
789 | /* we allocate array of iwl_channel_info for NIC's valid channels. | ||
790 | * Access via channel # using indirect index array */ | ||
791 | struct iwl_channel_info *channel_info; /* channel info array */ | ||
792 | u8 channel_count; /* # of channels */ | ||
793 | |||
794 | u8 plcp_delta_threshold; | 711 | u8 plcp_delta_threshold; |
795 | 712 | ||
796 | /* thermal calibration */ | 713 | /* thermal calibration */ |
@@ -950,10 +867,8 @@ struct iwl_priv { | |||
950 | 867 | ||
951 | struct delayed_work scan_check; | 868 | struct delayed_work scan_check; |
952 | 869 | ||
953 | /* TX Power */ | 870 | /* TX Power settings */ |
954 | s8 tx_power_user_lmt; | 871 | s8 tx_power_user_lmt; |
955 | s8 tx_power_device_lmt; | ||
956 | s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */ | ||
957 | s8 tx_power_next; | 872 | s8 tx_power_next; |
958 | 873 | ||
959 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 874 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
@@ -964,9 +879,10 @@ struct iwl_priv { | |||
964 | void *wowlan_sram; | 879 | void *wowlan_sram; |
965 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 880 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
966 | 881 | ||
967 | /* eeprom -- this is in the card's little endian byte order */ | 882 | struct iwl_eeprom_data *eeprom_data; |
968 | u8 *eeprom; | 883 | /* eeprom blob for debugfs/testmode */ |
969 | enum iwl_nvm_type nvm_device_type; | 884 | u8 *eeprom_blob; |
885 | size_t eeprom_blob_size; | ||
970 | 886 | ||
971 | struct work_struct txpower_work; | 887 | struct work_struct txpower_work; |
972 | u32 calib_disabled; | 888 | u32 calib_disabled; |
@@ -1034,36 +950,4 @@ static inline int iwl_is_any_associated(struct iwl_priv *priv) | |||
1034 | return false; | 950 | return false; |
1035 | } | 951 | } |
1036 | 952 | ||
1037 | static inline int is_channel_valid(const struct iwl_channel_info *ch_info) | ||
1038 | { | ||
1039 | if (ch_info == NULL) | ||
1040 | return 0; | ||
1041 | return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0; | ||
1042 | } | ||
1043 | |||
1044 | static inline int is_channel_radar(const struct iwl_channel_info *ch_info) | ||
1045 | { | ||
1046 | return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0; | ||
1047 | } | ||
1048 | |||
1049 | static inline u8 is_channel_a_band(const struct iwl_channel_info *ch_info) | ||
1050 | { | ||
1051 | return ch_info->band == IEEE80211_BAND_5GHZ; | ||
1052 | } | ||
1053 | |||
1054 | static inline u8 is_channel_bg_band(const struct iwl_channel_info *ch_info) | ||
1055 | { | ||
1056 | return ch_info->band == IEEE80211_BAND_2GHZ; | ||
1057 | } | ||
1058 | |||
1059 | static inline int is_channel_passive(const struct iwl_channel_info *ch) | ||
1060 | { | ||
1061 | return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0; | ||
1062 | } | ||
1063 | |||
1064 | static inline int is_channel_ibss(const struct iwl_channel_info *ch) | ||
1065 | { | ||
1066 | return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; | ||
1067 | } | ||
1068 | |||
1069 | #endif /* __iwl_dev_h__ */ | 953 | #endif /* __iwl_dev_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c index ddf053c5713d..747e576950f4 100644 --- a/drivers/net/wireless/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/iwlwifi/dvm/devices.c | |||
@@ -29,11 +29,48 @@ | |||
29 | */ | 29 | */ |
30 | #include "iwl-io.h" | 30 | #include "iwl-io.h" |
31 | #include "iwl-prph.h" | 31 | #include "iwl-prph.h" |
32 | #include "iwl-eeprom-parse.h" | ||
32 | 33 | ||
33 | #include "agn.h" | 34 | #include "agn.h" |
34 | #include "dev.h" | 35 | #include "dev.h" |
35 | #include "commands.h" | 36 | #include "commands.h" |
36 | 37 | ||
38 | |||
39 | #define EEPROM_RF_CONFIG_TYPE_MAX 0x3 | ||
40 | |||
41 | static void iwl_rf_config(struct iwl_priv *priv) | ||
42 | { | ||
43 | u16 radio_cfg = priv->eeprom_data->radio_cfg; | ||
44 | |||
45 | /* write radio config values to register */ | ||
46 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { | ||
47 | u32 reg_val = | ||
48 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) << | ||
49 | CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE | | ||
50 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) << | ||
51 | CSR_HW_IF_CONFIG_REG_POS_PHY_STEP | | ||
52 | EEPROM_RF_CFG_DASH_MSK(radio_cfg) << | ||
53 | CSR_HW_IF_CONFIG_REG_POS_PHY_DASH; | ||
54 | |||
55 | iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG, | ||
56 | CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE | | ||
57 | CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP | | ||
58 | CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH, reg_val); | ||
59 | |||
60 | IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n", | ||
61 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg), | ||
62 | EEPROM_RF_CFG_STEP_MSK(radio_cfg), | ||
63 | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); | ||
64 | } else { | ||
65 | WARN_ON(1); | ||
66 | } | ||
67 | |||
68 | /* set CSR_HW_CONFIG_REG for uCode use */ | ||
69 | iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG, | ||
70 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||
71 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||
72 | } | ||
73 | |||
37 | /* | 74 | /* |
38 | * 1000 series | 75 | * 1000 series |
39 | * =========== | 76 | * =========== |
@@ -180,17 +217,6 @@ static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
180 | struct iwl_lib_ops iwl1000_lib = { | 217 | struct iwl_lib_ops iwl1000_lib = { |
181 | .set_hw_params = iwl1000_hw_set_hw_params, | 218 | .set_hw_params = iwl1000_hw_set_hw_params, |
182 | .nic_config = iwl1000_nic_config, | 219 | .nic_config = iwl1000_nic_config, |
183 | .eeprom_ops = { | ||
184 | .regulatory_bands = { | ||
185 | EEPROM_REG_BAND_1_CHANNELS, | ||
186 | EEPROM_REG_BAND_2_CHANNELS, | ||
187 | EEPROM_REG_BAND_3_CHANNELS, | ||
188 | EEPROM_REG_BAND_4_CHANNELS, | ||
189 | EEPROM_REG_BAND_5_CHANNELS, | ||
190 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
191 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
192 | }, | ||
193 | }, | ||
194 | .temperature = iwlagn_temperature, | 220 | .temperature = iwlagn_temperature, |
195 | }; | 221 | }; |
196 | 222 | ||
@@ -251,36 +277,12 @@ static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) | |||
251 | struct iwl_lib_ops iwl2000_lib = { | 277 | struct iwl_lib_ops iwl2000_lib = { |
252 | .set_hw_params = iwl2000_hw_set_hw_params, | 278 | .set_hw_params = iwl2000_hw_set_hw_params, |
253 | .nic_config = iwl2000_nic_config, | 279 | .nic_config = iwl2000_nic_config, |
254 | .eeprom_ops = { | ||
255 | .regulatory_bands = { | ||
256 | EEPROM_REG_BAND_1_CHANNELS, | ||
257 | EEPROM_REG_BAND_2_CHANNELS, | ||
258 | EEPROM_REG_BAND_3_CHANNELS, | ||
259 | EEPROM_REG_BAND_4_CHANNELS, | ||
260 | EEPROM_REG_BAND_5_CHANNELS, | ||
261 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
262 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
263 | }, | ||
264 | .enhanced_txpower = true, | ||
265 | }, | ||
266 | .temperature = iwlagn_temperature, | 280 | .temperature = iwlagn_temperature, |
267 | }; | 281 | }; |
268 | 282 | ||
269 | struct iwl_lib_ops iwl2030_lib = { | 283 | struct iwl_lib_ops iwl2030_lib = { |
270 | .set_hw_params = iwl2000_hw_set_hw_params, | 284 | .set_hw_params = iwl2000_hw_set_hw_params, |
271 | .nic_config = iwl2000_nic_config, | 285 | .nic_config = iwl2000_nic_config, |
272 | .eeprom_ops = { | ||
273 | .regulatory_bands = { | ||
274 | EEPROM_REG_BAND_1_CHANNELS, | ||
275 | EEPROM_REG_BAND_2_CHANNELS, | ||
276 | EEPROM_REG_BAND_3_CHANNELS, | ||
277 | EEPROM_REG_BAND_4_CHANNELS, | ||
278 | EEPROM_REG_BAND_5_CHANNELS, | ||
279 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
280 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
281 | }, | ||
282 | .enhanced_txpower = true, | ||
283 | }, | ||
284 | .temperature = iwlagn_temperature, | 286 | .temperature = iwlagn_temperature, |
285 | }; | 287 | }; |
286 | 288 | ||
@@ -357,11 +359,9 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = { | |||
357 | static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) | 359 | static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) |
358 | { | 360 | { |
359 | u16 temperature, voltage; | 361 | u16 temperature, voltage; |
360 | __le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(priv, | ||
361 | EEPROM_KELVIN_TEMPERATURE); | ||
362 | 362 | ||
363 | temperature = le16_to_cpu(temp_calib[0]); | 363 | temperature = le16_to_cpu(priv->eeprom_data->kelvin_temperature); |
364 | voltage = le16_to_cpu(temp_calib[1]); | 364 | voltage = le16_to_cpu(priv->eeprom_data->kelvin_voltage); |
365 | 365 | ||
366 | /* offset = temp - volt / coeff */ | 366 | /* offset = temp - volt / coeff */ |
367 | return (s32)(temperature - | 367 | return (s32)(temperature - |
@@ -478,17 +478,6 @@ struct iwl_lib_ops iwl5000_lib = { | |||
478 | .set_hw_params = iwl5000_hw_set_hw_params, | 478 | .set_hw_params = iwl5000_hw_set_hw_params, |
479 | .set_channel_switch = iwl5000_hw_channel_switch, | 479 | .set_channel_switch = iwl5000_hw_channel_switch, |
480 | .nic_config = iwl5000_nic_config, | 480 | .nic_config = iwl5000_nic_config, |
481 | .eeprom_ops = { | ||
482 | .regulatory_bands = { | ||
483 | EEPROM_REG_BAND_1_CHANNELS, | ||
484 | EEPROM_REG_BAND_2_CHANNELS, | ||
485 | EEPROM_REG_BAND_3_CHANNELS, | ||
486 | EEPROM_REG_BAND_4_CHANNELS, | ||
487 | EEPROM_REG_BAND_5_CHANNELS, | ||
488 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
489 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
490 | }, | ||
491 | }, | ||
492 | .temperature = iwlagn_temperature, | 481 | .temperature = iwlagn_temperature, |
493 | }; | 482 | }; |
494 | 483 | ||
@@ -496,17 +485,6 @@ struct iwl_lib_ops iwl5150_lib = { | |||
496 | .set_hw_params = iwl5150_hw_set_hw_params, | 485 | .set_hw_params = iwl5150_hw_set_hw_params, |
497 | .set_channel_switch = iwl5000_hw_channel_switch, | 486 | .set_channel_switch = iwl5000_hw_channel_switch, |
498 | .nic_config = iwl5000_nic_config, | 487 | .nic_config = iwl5000_nic_config, |
499 | .eeprom_ops = { | ||
500 | .regulatory_bands = { | ||
501 | EEPROM_REG_BAND_1_CHANNELS, | ||
502 | EEPROM_REG_BAND_2_CHANNELS, | ||
503 | EEPROM_REG_BAND_3_CHANNELS, | ||
504 | EEPROM_REG_BAND_4_CHANNELS, | ||
505 | EEPROM_REG_BAND_5_CHANNELS, | ||
506 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
507 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
508 | }, | ||
509 | }, | ||
510 | .temperature = iwl5150_temperature, | 488 | .temperature = iwl5150_temperature, |
511 | }; | 489 | }; |
512 | 490 | ||
@@ -541,13 +519,13 @@ static void iwl6000_nic_config(struct iwl_priv *priv) | |||
541 | break; | 519 | break; |
542 | case IWL_DEVICE_FAMILY_6050: | 520 | case IWL_DEVICE_FAMILY_6050: |
543 | /* Indicate calibration version to uCode. */ | 521 | /* Indicate calibration version to uCode. */ |
544 | if (iwl_eeprom_calib_version(priv) >= 6) | 522 | if (priv->eeprom_data->calib_version >= 6) |
545 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | 523 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, |
546 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | 524 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); |
547 | break; | 525 | break; |
548 | case IWL_DEVICE_FAMILY_6150: | 526 | case IWL_DEVICE_FAMILY_6150: |
549 | /* Indicate calibration version to uCode. */ | 527 | /* Indicate calibration version to uCode. */ |
550 | if (iwl_eeprom_calib_version(priv) >= 6) | 528 | if (priv->eeprom_data->calib_version >= 6) |
551 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | 529 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, |
552 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | 530 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); |
553 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | 531 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, |
@@ -658,18 +636,6 @@ struct iwl_lib_ops iwl6000_lib = { | |||
658 | .set_hw_params = iwl6000_hw_set_hw_params, | 636 | .set_hw_params = iwl6000_hw_set_hw_params, |
659 | .set_channel_switch = iwl6000_hw_channel_switch, | 637 | .set_channel_switch = iwl6000_hw_channel_switch, |
660 | .nic_config = iwl6000_nic_config, | 638 | .nic_config = iwl6000_nic_config, |
661 | .eeprom_ops = { | ||
662 | .regulatory_bands = { | ||
663 | EEPROM_REG_BAND_1_CHANNELS, | ||
664 | EEPROM_REG_BAND_2_CHANNELS, | ||
665 | EEPROM_REG_BAND_3_CHANNELS, | ||
666 | EEPROM_REG_BAND_4_CHANNELS, | ||
667 | EEPROM_REG_BAND_5_CHANNELS, | ||
668 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
669 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
670 | }, | ||
671 | .enhanced_txpower = true, | ||
672 | }, | ||
673 | .temperature = iwlagn_temperature, | 639 | .temperature = iwlagn_temperature, |
674 | }; | 640 | }; |
675 | 641 | ||
@@ -677,17 +643,5 @@ struct iwl_lib_ops iwl6030_lib = { | |||
677 | .set_hw_params = iwl6000_hw_set_hw_params, | 643 | .set_hw_params = iwl6000_hw_set_hw_params, |
678 | .set_channel_switch = iwl6000_hw_channel_switch, | 644 | .set_channel_switch = iwl6000_hw_channel_switch, |
679 | .nic_config = iwl6000_nic_config, | 645 | .nic_config = iwl6000_nic_config, |
680 | .eeprom_ops = { | ||
681 | .regulatory_bands = { | ||
682 | EEPROM_REG_BAND_1_CHANNELS, | ||
683 | EEPROM_REG_BAND_2_CHANNELS, | ||
684 | EEPROM_REG_BAND_3_CHANNELS, | ||
685 | EEPROM_REG_BAND_4_CHANNELS, | ||
686 | EEPROM_REG_BAND_5_CHANNELS, | ||
687 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
688 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
689 | }, | ||
690 | .enhanced_txpower = true, | ||
691 | }, | ||
692 | .temperature = iwlagn_temperature, | 646 | .temperature = iwlagn_temperature, |
693 | }; | 647 | }; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/eeprom.c b/drivers/net/wireless/iwlwifi/dvm/eeprom.c deleted file mode 100644 index b382b16b89d7..000000000000 --- a/drivers/net/wireless/iwlwifi/dvm/eeprom.c +++ /dev/null | |||
@@ -1,1163 +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 - 2012 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 - 2012 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 | #include <net/mac80211.h> | ||
69 | #include "iwl-io.h" | ||
70 | #include "iwl-prph.h" | ||
71 | #include "iwl-debug.h" | ||
72 | #include "dev.h" | ||
73 | #include "agn.h" | ||
74 | #include "eeprom.h" | ||
75 | |||
76 | /************************** EEPROM BANDS **************************** | ||
77 | * | ||
78 | * The iwl_eeprom_band definitions below provide the mapping from the | ||
79 | * EEPROM contents to the specific channel number supported for each | ||
80 | * band. | ||
81 | * | ||
82 | * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3 | ||
83 | * definition below maps to physical channel 42 in the 5.2GHz spectrum. | ||
84 | * The specific geography and calibration information for that channel | ||
85 | * is contained in the eeprom map itself. | ||
86 | * | ||
87 | * During init, we copy the eeprom information and channel map | ||
88 | * information into priv->channel_info_24/52 and priv->channel_map_24/52 | ||
89 | * | ||
90 | * channel_map_24/52 provides the index in the channel_info array for a | ||
91 | * given channel. We have to have two separate maps as there is channel | ||
92 | * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and | ||
93 | * band_2 | ||
94 | * | ||
95 | * A value of 0xff stored in the channel_map indicates that the channel | ||
96 | * is not supported by the hardware at all. | ||
97 | * | ||
98 | * A value of 0xfe in the channel_map indicates that the channel is not | ||
99 | * valid for Tx with the current hardware. This means that | ||
100 | * while the system can tune and receive on a given channel, it may not | ||
101 | * be able to associate or transmit any frames on that | ||
102 | * channel. There is no corresponding channel information for that | ||
103 | * entry. | ||
104 | * | ||
105 | *********************************************************************/ | ||
106 | |||
107 | /* 2.4 GHz */ | ||
108 | const u8 iwl_eeprom_band_1[14] = { | ||
109 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 | ||
110 | }; | ||
111 | |||
112 | /* 5.2 GHz bands */ | ||
113 | static const u8 iwl_eeprom_band_2[] = { /* 4915-5080MHz */ | ||
114 | 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 | ||
115 | }; | ||
116 | |||
117 | static const u8 iwl_eeprom_band_3[] = { /* 5170-5320MHz */ | ||
118 | 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 | ||
119 | }; | ||
120 | |||
121 | static const u8 iwl_eeprom_band_4[] = { /* 5500-5700MHz */ | ||
122 | 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 | ||
123 | }; | ||
124 | |||
125 | static const u8 iwl_eeprom_band_5[] = { /* 5725-5825MHz */ | ||
126 | 145, 149, 153, 157, 161, 165 | ||
127 | }; | ||
128 | |||
129 | static const u8 iwl_eeprom_band_6[] = { /* 2.4 ht40 channel */ | ||
130 | 1, 2, 3, 4, 5, 6, 7 | ||
131 | }; | ||
132 | |||
133 | static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */ | ||
134 | 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 | ||
135 | }; | ||
136 | |||
137 | /****************************************************************************** | ||
138 | * | ||
139 | * generic NVM functions | ||
140 | * | ||
141 | ******************************************************************************/ | ||
142 | |||
143 | /* | ||
144 | * The device's EEPROM semaphore prevents conflicts between driver and uCode | ||
145 | * when accessing the EEPROM; each access is a series of pulses to/from the | ||
146 | * EEPROM chip, not a single event, so even reads could conflict if they | ||
147 | * weren't arbitrated by the semaphore. | ||
148 | */ | ||
149 | |||
150 | #define EEPROM_SEM_TIMEOUT 10 /* milliseconds */ | ||
151 | #define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ | ||
152 | |||
153 | static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans) | ||
154 | { | ||
155 | u16 count; | ||
156 | int ret; | ||
157 | |||
158 | for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { | ||
159 | /* Request semaphore */ | ||
160 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
161 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
162 | |||
163 | /* See if we got it */ | ||
164 | ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
165 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
166 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
167 | EEPROM_SEM_TIMEOUT); | ||
168 | if (ret >= 0) { | ||
169 | IWL_DEBUG_EEPROM(trans, | ||
170 | "Acquired semaphore after %d tries.\n", | ||
171 | count+1); | ||
172 | return ret; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | static void iwl_eeprom_release_semaphore(struct iwl_trans *trans) | ||
180 | { | ||
181 | iwl_clear_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
182 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
183 | |||
184 | } | ||
185 | |||
186 | static int iwl_eeprom_verify_signature(struct iwl_priv *priv) | ||
187 | { | ||
188 | u32 gp = iwl_read32(priv->trans, CSR_EEPROM_GP) & | ||
189 | CSR_EEPROM_GP_VALID_MSK; | ||
190 | int ret = 0; | ||
191 | |||
192 | IWL_DEBUG_EEPROM(priv, "EEPROM signature=0x%08x\n", gp); | ||
193 | switch (gp) { | ||
194 | case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP: | ||
195 | if (priv->nvm_device_type != NVM_DEVICE_TYPE_OTP) { | ||
196 | IWL_ERR(priv, "EEPROM with bad signature: 0x%08x\n", | ||
197 | gp); | ||
198 | ret = -ENOENT; | ||
199 | } | ||
200 | break; | ||
201 | case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K: | ||
202 | case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K: | ||
203 | if (priv->nvm_device_type != NVM_DEVICE_TYPE_EEPROM) { | ||
204 | IWL_ERR(priv, "OTP with bad signature: 0x%08x\n", gp); | ||
205 | ret = -ENOENT; | ||
206 | } | ||
207 | break; | ||
208 | case CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP: | ||
209 | default: | ||
210 | IWL_ERR(priv, "bad EEPROM/OTP signature, type=%s, " | ||
211 | "EEPROM_GP=0x%08x\n", | ||
212 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
213 | ? "OTP" : "EEPROM", gp); | ||
214 | ret = -ENOENT; | ||
215 | break; | ||
216 | } | ||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | u16 iwl_eeprom_query16(struct iwl_priv *priv, size_t offset) | ||
221 | { | ||
222 | if (!priv->eeprom) | ||
223 | return 0; | ||
224 | return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); | ||
225 | } | ||
226 | |||
227 | int iwl_eeprom_check_version(struct iwl_priv *priv) | ||
228 | { | ||
229 | u16 eeprom_ver; | ||
230 | u16 calib_ver; | ||
231 | |||
232 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | ||
233 | calib_ver = iwl_eeprom_calib_version(priv); | ||
234 | |||
235 | if (eeprom_ver < priv->cfg->eeprom_ver || | ||
236 | calib_ver < priv->cfg->eeprom_calib_ver) | ||
237 | goto err; | ||
238 | |||
239 | IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n", | ||
240 | eeprom_ver, calib_ver); | ||
241 | |||
242 | return 0; | ||
243 | err: | ||
244 | IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x " | ||
245 | "CALIB=0x%x < 0x%x\n", | ||
246 | eeprom_ver, priv->cfg->eeprom_ver, | ||
247 | calib_ver, priv->cfg->eeprom_calib_ver); | ||
248 | return -EINVAL; | ||
249 | |||
250 | } | ||
251 | |||
252 | int iwl_eeprom_init_hw_params(struct iwl_priv *priv) | ||
253 | { | ||
254 | u16 radio_cfg; | ||
255 | |||
256 | priv->hw_params.sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP); | ||
257 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE && | ||
258 | !priv->cfg->ht_params) { | ||
259 | IWL_ERR(priv, "Invalid 11n configuration\n"); | ||
260 | return -EINVAL; | ||
261 | } | ||
262 | |||
263 | if (!priv->hw_params.sku) { | ||
264 | IWL_ERR(priv, "Invalid device sku\n"); | ||
265 | return -EINVAL; | ||
266 | } | ||
267 | |||
268 | IWL_INFO(priv, "Device SKU: 0x%X\n", priv->hw_params.sku); | ||
269 | |||
270 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | ||
271 | |||
272 | priv->hw_params.valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); | ||
273 | priv->hw_params.valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg); | ||
274 | |||
275 | /* check overrides (some devices have wrong EEPROM) */ | ||
276 | if (priv->cfg->valid_tx_ant) | ||
277 | priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; | ||
278 | if (priv->cfg->valid_rx_ant) | ||
279 | priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; | ||
280 | |||
281 | if (!priv->hw_params.valid_tx_ant || !priv->hw_params.valid_rx_ant) { | ||
282 | IWL_ERR(priv, "Invalid chain (0x%X, 0x%X)\n", | ||
283 | priv->hw_params.valid_tx_ant, | ||
284 | priv->hw_params.valid_rx_ant); | ||
285 | return -EINVAL; | ||
286 | } | ||
287 | |||
288 | priv->hw_params.tx_chains_num = | ||
289 | num_of_ant(priv->hw_params.valid_tx_ant); | ||
290 | if (priv->cfg->rx_with_siso_diversity) | ||
291 | priv->hw_params.rx_chains_num = 1; | ||
292 | else | ||
293 | priv->hw_params.rx_chains_num = | ||
294 | num_of_ant(priv->hw_params.valid_rx_ant); | ||
295 | |||
296 | IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n", | ||
297 | priv->hw_params.valid_tx_ant, priv->hw_params.valid_rx_ant); | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | u16 iwl_eeprom_calib_version(struct iwl_priv *priv) | ||
303 | { | ||
304 | struct iwl_eeprom_calib_hdr *hdr; | ||
305 | |||
306 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | ||
307 | EEPROM_CALIB_ALL); | ||
308 | return hdr->version; | ||
309 | } | ||
310 | |||
311 | static u32 eeprom_indirect_address(struct iwl_priv *priv, u32 address) | ||
312 | { | ||
313 | u16 offset = 0; | ||
314 | |||
315 | if ((address & INDIRECT_ADDRESS) == 0) | ||
316 | return address; | ||
317 | |||
318 | switch (address & INDIRECT_TYPE_MSK) { | ||
319 | case INDIRECT_HOST: | ||
320 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_HOST); | ||
321 | break; | ||
322 | case INDIRECT_GENERAL: | ||
323 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_GENERAL); | ||
324 | break; | ||
325 | case INDIRECT_REGULATORY: | ||
326 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY); | ||
327 | break; | ||
328 | case INDIRECT_TXP_LIMIT: | ||
329 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT); | ||
330 | break; | ||
331 | case INDIRECT_TXP_LIMIT_SIZE: | ||
332 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT_SIZE); | ||
333 | break; | ||
334 | case INDIRECT_CALIBRATION: | ||
335 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION); | ||
336 | break; | ||
337 | case INDIRECT_PROCESS_ADJST: | ||
338 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_PROCESS_ADJST); | ||
339 | break; | ||
340 | case INDIRECT_OTHERS: | ||
341 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_OTHERS); | ||
342 | break; | ||
343 | default: | ||
344 | IWL_ERR(priv, "illegal indirect type: 0x%X\n", | ||
345 | address & INDIRECT_TYPE_MSK); | ||
346 | break; | ||
347 | } | ||
348 | |||
349 | /* translate the offset from words to byte */ | ||
350 | return (address & ADDRESS_MSK) + (offset << 1); | ||
351 | } | ||
352 | |||
353 | const u8 *iwl_eeprom_query_addr(struct iwl_priv *priv, size_t offset) | ||
354 | { | ||
355 | u32 address = eeprom_indirect_address(priv, offset); | ||
356 | BUG_ON(address >= priv->cfg->base_params->eeprom_size); | ||
357 | return &priv->eeprom[address]; | ||
358 | } | ||
359 | |||
360 | void iwl_eeprom_get_mac(struct iwl_priv *priv, u8 *mac) | ||
361 | { | ||
362 | const u8 *addr = iwl_eeprom_query_addr(priv, | ||
363 | EEPROM_MAC_ADDRESS); | ||
364 | memcpy(mac, addr, ETH_ALEN); | ||
365 | } | ||
366 | |||
367 | /****************************************************************************** | ||
368 | * | ||
369 | * OTP related functions | ||
370 | * | ||
371 | ******************************************************************************/ | ||
372 | |||
373 | static void iwl_set_otp_access(struct iwl_trans *trans, | ||
374 | enum iwl_access_mode mode) | ||
375 | { | ||
376 | iwl_read32(trans, CSR_OTP_GP_REG); | ||
377 | |||
378 | if (mode == IWL_OTP_ACCESS_ABSOLUTE) | ||
379 | iwl_clear_bit(trans, CSR_OTP_GP_REG, | ||
380 | CSR_OTP_GP_REG_OTP_ACCESS_MODE); | ||
381 | else | ||
382 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
383 | CSR_OTP_GP_REG_OTP_ACCESS_MODE); | ||
384 | } | ||
385 | |||
386 | static int iwl_get_nvm_type(struct iwl_trans *trans, u32 hw_rev) | ||
387 | { | ||
388 | u32 otpgp; | ||
389 | int nvm_type; | ||
390 | |||
391 | /* OTP only valid for CP/PP and after */ | ||
392 | switch (hw_rev & CSR_HW_REV_TYPE_MSK) { | ||
393 | case CSR_HW_REV_TYPE_NONE: | ||
394 | IWL_ERR(trans, "Unknown hardware type\n"); | ||
395 | return -ENOENT; | ||
396 | case CSR_HW_REV_TYPE_5300: | ||
397 | case CSR_HW_REV_TYPE_5350: | ||
398 | case CSR_HW_REV_TYPE_5100: | ||
399 | case CSR_HW_REV_TYPE_5150: | ||
400 | nvm_type = NVM_DEVICE_TYPE_EEPROM; | ||
401 | break; | ||
402 | default: | ||
403 | otpgp = iwl_read32(trans, CSR_OTP_GP_REG); | ||
404 | if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) | ||
405 | nvm_type = NVM_DEVICE_TYPE_OTP; | ||
406 | else | ||
407 | nvm_type = NVM_DEVICE_TYPE_EEPROM; | ||
408 | break; | ||
409 | } | ||
410 | return nvm_type; | ||
411 | } | ||
412 | |||
413 | static int iwl_init_otp_access(struct iwl_trans *trans) | ||
414 | { | ||
415 | int ret; | ||
416 | |||
417 | /* Enable 40MHz radio clock */ | ||
418 | iwl_write32(trans, CSR_GP_CNTRL, | ||
419 | iwl_read32(trans, CSR_GP_CNTRL) | | ||
420 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
421 | |||
422 | /* wait for clock to be ready */ | ||
423 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
424 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
425 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
426 | 25000); | ||
427 | if (ret < 0) | ||
428 | IWL_ERR(trans, "Time out access OTP\n"); | ||
429 | else { | ||
430 | iwl_set_bits_prph(trans, APMG_PS_CTRL_REG, | ||
431 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
432 | udelay(5); | ||
433 | iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG, | ||
434 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
435 | |||
436 | /* | ||
437 | * CSR auto clock gate disable bit - | ||
438 | * this is only applicable for HW with OTP shadow RAM | ||
439 | */ | ||
440 | if (trans->cfg->base_params->shadow_ram_support) | ||
441 | iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, | ||
442 | CSR_RESET_LINK_PWR_MGMT_DISABLED); | ||
443 | } | ||
444 | return ret; | ||
445 | } | ||
446 | |||
447 | static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr, | ||
448 | __le16 *eeprom_data) | ||
449 | { | ||
450 | int ret = 0; | ||
451 | u32 r; | ||
452 | u32 otpgp; | ||
453 | |||
454 | iwl_write32(trans, CSR_EEPROM_REG, | ||
455 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||
456 | ret = iwl_poll_bit(trans, CSR_EEPROM_REG, | ||
457 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
458 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
459 | IWL_EEPROM_ACCESS_TIMEOUT); | ||
460 | if (ret < 0) { | ||
461 | IWL_ERR(trans, "Time out reading OTP[%d]\n", addr); | ||
462 | return ret; | ||
463 | } | ||
464 | r = iwl_read32(trans, CSR_EEPROM_REG); | ||
465 | /* check for ECC errors: */ | ||
466 | otpgp = iwl_read32(trans, CSR_OTP_GP_REG); | ||
467 | if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { | ||
468 | /* stop in this case */ | ||
469 | /* set the uncorrectable OTP ECC bit for acknowledgement */ | ||
470 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
471 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | ||
472 | IWL_ERR(trans, "Uncorrectable OTP ECC error, abort OTP read\n"); | ||
473 | return -EINVAL; | ||
474 | } | ||
475 | if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { | ||
476 | /* continue in this case */ | ||
477 | /* set the correctable OTP ECC bit for acknowledgement */ | ||
478 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
479 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); | ||
480 | IWL_ERR(trans, "Correctable OTP ECC error, continue read\n"); | ||
481 | } | ||
482 | *eeprom_data = cpu_to_le16(r >> 16); | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | /* | ||
487 | * iwl_is_otp_empty: check for empty OTP | ||
488 | */ | ||
489 | static bool iwl_is_otp_empty(struct iwl_trans *trans) | ||
490 | { | ||
491 | u16 next_link_addr = 0; | ||
492 | __le16 link_value; | ||
493 | bool is_empty = false; | ||
494 | |||
495 | /* locate the beginning of OTP link list */ | ||
496 | if (!iwl_read_otp_word(trans, next_link_addr, &link_value)) { | ||
497 | if (!link_value) { | ||
498 | IWL_ERR(trans, "OTP is empty\n"); | ||
499 | is_empty = true; | ||
500 | } | ||
501 | } else { | ||
502 | IWL_ERR(trans, "Unable to read first block of OTP list.\n"); | ||
503 | is_empty = true; | ||
504 | } | ||
505 | |||
506 | return is_empty; | ||
507 | } | ||
508 | |||
509 | |||
510 | /* | ||
511 | * iwl_find_otp_image: find EEPROM image in OTP | ||
512 | * finding the OTP block that contains the EEPROM image. | ||
513 | * the last valid block on the link list (the block _before_ the last block) | ||
514 | * is the block we should read and used to configure the device. | ||
515 | * If all the available OTP blocks are full, the last block will be the block | ||
516 | * we should read and used to configure the device. | ||
517 | * only perform this operation if shadow RAM is disabled | ||
518 | */ | ||
519 | static int iwl_find_otp_image(struct iwl_trans *trans, | ||
520 | u16 *validblockaddr) | ||
521 | { | ||
522 | u16 next_link_addr = 0, valid_addr; | ||
523 | __le16 link_value = 0; | ||
524 | int usedblocks = 0; | ||
525 | |||
526 | /* set addressing mode to absolute to traverse the link list */ | ||
527 | iwl_set_otp_access(trans, IWL_OTP_ACCESS_ABSOLUTE); | ||
528 | |||
529 | /* checking for empty OTP or error */ | ||
530 | if (iwl_is_otp_empty(trans)) | ||
531 | return -EINVAL; | ||
532 | |||
533 | /* | ||
534 | * start traverse link list | ||
535 | * until reach the max number of OTP blocks | ||
536 | * different devices have different number of OTP blocks | ||
537 | */ | ||
538 | do { | ||
539 | /* save current valid block address | ||
540 | * check for more block on the link list | ||
541 | */ | ||
542 | valid_addr = next_link_addr; | ||
543 | next_link_addr = le16_to_cpu(link_value) * sizeof(u16); | ||
544 | IWL_DEBUG_EEPROM(trans, "OTP blocks %d addr 0x%x\n", | ||
545 | usedblocks, next_link_addr); | ||
546 | if (iwl_read_otp_word(trans, next_link_addr, &link_value)) | ||
547 | return -EINVAL; | ||
548 | if (!link_value) { | ||
549 | /* | ||
550 | * reach the end of link list, return success and | ||
551 | * set address point to the starting address | ||
552 | * of the image | ||
553 | */ | ||
554 | *validblockaddr = valid_addr; | ||
555 | /* skip first 2 bytes (link list pointer) */ | ||
556 | *validblockaddr += 2; | ||
557 | return 0; | ||
558 | } | ||
559 | /* more in the link list, continue */ | ||
560 | usedblocks++; | ||
561 | } while (usedblocks <= trans->cfg->base_params->max_ll_items); | ||
562 | |||
563 | /* OTP has no valid blocks */ | ||
564 | IWL_DEBUG_EEPROM(trans, "OTP has no valid blocks\n"); | ||
565 | return -EINVAL; | ||
566 | } | ||
567 | |||
568 | /****************************************************************************** | ||
569 | * | ||
570 | * Tx Power related functions | ||
571 | * | ||
572 | ******************************************************************************/ | ||
573 | /** | ||
574 | * iwl_get_max_txpower_avg - get the highest tx power from all chains. | ||
575 | * find the highest tx power from all chains for the channel | ||
576 | */ | ||
577 | static s8 iwl_get_max_txpower_avg(const struct iwl_cfg *cfg, | ||
578 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, | ||
579 | int element, s8 *max_txpower_in_half_dbm) | ||
580 | { | ||
581 | s8 max_txpower_avg = 0; /* (dBm) */ | ||
582 | |||
583 | /* Take the highest tx power from any valid chains */ | ||
584 | if ((cfg->valid_tx_ant & ANT_A) && | ||
585 | (enhanced_txpower[element].chain_a_max > max_txpower_avg)) | ||
586 | max_txpower_avg = enhanced_txpower[element].chain_a_max; | ||
587 | if ((cfg->valid_tx_ant & ANT_B) && | ||
588 | (enhanced_txpower[element].chain_b_max > max_txpower_avg)) | ||
589 | max_txpower_avg = enhanced_txpower[element].chain_b_max; | ||
590 | if ((cfg->valid_tx_ant & ANT_C) && | ||
591 | (enhanced_txpower[element].chain_c_max > max_txpower_avg)) | ||
592 | max_txpower_avg = enhanced_txpower[element].chain_c_max; | ||
593 | if (((cfg->valid_tx_ant == ANT_AB) | | ||
594 | (cfg->valid_tx_ant == ANT_BC) | | ||
595 | (cfg->valid_tx_ant == ANT_AC)) && | ||
596 | (enhanced_txpower[element].mimo2_max > max_txpower_avg)) | ||
597 | max_txpower_avg = enhanced_txpower[element].mimo2_max; | ||
598 | if ((cfg->valid_tx_ant == ANT_ABC) && | ||
599 | (enhanced_txpower[element].mimo3_max > max_txpower_avg)) | ||
600 | max_txpower_avg = enhanced_txpower[element].mimo3_max; | ||
601 | |||
602 | /* | ||
603 | * max. tx power in EEPROM is in 1/2 dBm format | ||
604 | * convert from 1/2 dBm to dBm (round-up convert) | ||
605 | * but we also do not want to loss 1/2 dBm resolution which | ||
606 | * will impact performance | ||
607 | */ | ||
608 | *max_txpower_in_half_dbm = max_txpower_avg; | ||
609 | return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1); | ||
610 | } | ||
611 | |||
612 | static void | ||
613 | iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv, | ||
614 | struct iwl_eeprom_enhanced_txpwr *txp, | ||
615 | s8 max_txpower_avg) | ||
616 | { | ||
617 | int ch_idx; | ||
618 | bool is_ht40 = txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ; | ||
619 | enum ieee80211_band band; | ||
620 | |||
621 | band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ? | ||
622 | IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; | ||
623 | |||
624 | for (ch_idx = 0; ch_idx < priv->channel_count; ch_idx++) { | ||
625 | struct iwl_channel_info *ch_info = &priv->channel_info[ch_idx]; | ||
626 | |||
627 | /* update matching channel or from common data only */ | ||
628 | if (txp->channel != 0 && ch_info->channel != txp->channel) | ||
629 | continue; | ||
630 | |||
631 | /* update matching band only */ | ||
632 | if (band != ch_info->band) | ||
633 | continue; | ||
634 | |||
635 | if (ch_info->max_power_avg < max_txpower_avg && !is_ht40) { | ||
636 | ch_info->max_power_avg = max_txpower_avg; | ||
637 | ch_info->curr_txpow = max_txpower_avg; | ||
638 | ch_info->scan_power = max_txpower_avg; | ||
639 | } | ||
640 | |||
641 | if (is_ht40 && ch_info->ht40_max_power_avg < max_txpower_avg) | ||
642 | ch_info->ht40_max_power_avg = max_txpower_avg; | ||
643 | } | ||
644 | } | ||
645 | |||
646 | #define EEPROM_TXP_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT) | ||
647 | #define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr) | ||
648 | #define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE) | ||
649 | |||
650 | #define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \ | ||
651 | ? # x " " : "") | ||
652 | |||
653 | static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) | ||
654 | { | ||
655 | struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; | ||
656 | int idx, entries; | ||
657 | __le16 *txp_len; | ||
658 | s8 max_txp_avg, max_txp_avg_halfdbm; | ||
659 | |||
660 | BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8); | ||
661 | |||
662 | /* the length is in 16-bit words, but we want entries */ | ||
663 | txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS); | ||
664 | entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN; | ||
665 | |||
666 | txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS); | ||
667 | |||
668 | for (idx = 0; idx < entries; idx++) { | ||
669 | txp = &txp_array[idx]; | ||
670 | /* skip invalid entries */ | ||
671 | if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID)) | ||
672 | continue; | ||
673 | |||
674 | IWL_DEBUG_EEPROM(priv, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n", | ||
675 | (txp->channel && (txp->flags & | ||
676 | IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ? | ||
677 | "Common " : (txp->channel) ? | ||
678 | "Channel" : "Common", | ||
679 | (txp->channel), | ||
680 | TXP_CHECK_AND_PRINT(VALID), | ||
681 | TXP_CHECK_AND_PRINT(BAND_52G), | ||
682 | TXP_CHECK_AND_PRINT(OFDM), | ||
683 | TXP_CHECK_AND_PRINT(40MHZ), | ||
684 | TXP_CHECK_AND_PRINT(HT_AP), | ||
685 | TXP_CHECK_AND_PRINT(RES1), | ||
686 | TXP_CHECK_AND_PRINT(RES2), | ||
687 | TXP_CHECK_AND_PRINT(COMMON_TYPE), | ||
688 | txp->flags); | ||
689 | IWL_DEBUG_EEPROM(priv, "\t\t chain_A: 0x%02x " | ||
690 | "chain_B: 0X%02x chain_C: 0X%02x\n", | ||
691 | txp->chain_a_max, txp->chain_b_max, | ||
692 | txp->chain_c_max); | ||
693 | IWL_DEBUG_EEPROM(priv, "\t\t MIMO2: 0x%02x " | ||
694 | "MIMO3: 0x%02x High 20_on_40: 0x%02x " | ||
695 | "Low 20_on_40: 0x%02x\n", | ||
696 | txp->mimo2_max, txp->mimo3_max, | ||
697 | ((txp->delta_20_in_40 & 0xf0) >> 4), | ||
698 | (txp->delta_20_in_40 & 0x0f)); | ||
699 | |||
700 | max_txp_avg = iwl_get_max_txpower_avg(priv->cfg, txp_array, idx, | ||
701 | &max_txp_avg_halfdbm); | ||
702 | |||
703 | /* | ||
704 | * Update the user limit values values to the highest | ||
705 | * power supported by any channel | ||
706 | */ | ||
707 | if (max_txp_avg > priv->tx_power_user_lmt) | ||
708 | priv->tx_power_user_lmt = max_txp_avg; | ||
709 | if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm) | ||
710 | priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm; | ||
711 | |||
712 | iwl_eeprom_enh_txp_read_element(priv, txp, max_txp_avg); | ||
713 | } | ||
714 | } | ||
715 | |||
716 | /** | ||
717 | * iwl_eeprom_init - read EEPROM contents | ||
718 | * | ||
719 | * Load the EEPROM contents from adapter into priv->eeprom | ||
720 | * | ||
721 | * NOTE: This routine uses the non-debug IO access functions. | ||
722 | */ | ||
723 | int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) | ||
724 | { | ||
725 | __le16 *e; | ||
726 | u32 gp = iwl_read32(priv->trans, CSR_EEPROM_GP); | ||
727 | int sz; | ||
728 | int ret; | ||
729 | u16 addr; | ||
730 | u16 validblockaddr = 0; | ||
731 | u16 cache_addr = 0; | ||
732 | |||
733 | priv->nvm_device_type = iwl_get_nvm_type(priv->trans, hw_rev); | ||
734 | if (priv->nvm_device_type == -ENOENT) | ||
735 | return -ENOENT; | ||
736 | /* allocate eeprom */ | ||
737 | sz = priv->cfg->base_params->eeprom_size; | ||
738 | IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz); | ||
739 | priv->eeprom = kzalloc(sz, GFP_KERNEL); | ||
740 | if (!priv->eeprom) { | ||
741 | ret = -ENOMEM; | ||
742 | goto alloc_err; | ||
743 | } | ||
744 | e = (__le16 *)priv->eeprom; | ||
745 | |||
746 | ret = iwl_eeprom_verify_signature(priv); | ||
747 | if (ret < 0) { | ||
748 | IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); | ||
749 | ret = -ENOENT; | ||
750 | goto err; | ||
751 | } | ||
752 | |||
753 | /* Make sure driver (instead of uCode) is allowed to read EEPROM */ | ||
754 | ret = iwl_eeprom_acquire_semaphore(priv->trans); | ||
755 | if (ret < 0) { | ||
756 | IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n"); | ||
757 | ret = -ENOENT; | ||
758 | goto err; | ||
759 | } | ||
760 | |||
761 | if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) { | ||
762 | |||
763 | ret = iwl_init_otp_access(priv->trans); | ||
764 | if (ret) { | ||
765 | IWL_ERR(priv, "Failed to initialize OTP access.\n"); | ||
766 | ret = -ENOENT; | ||
767 | goto done; | ||
768 | } | ||
769 | iwl_write32(priv->trans, CSR_EEPROM_GP, | ||
770 | iwl_read32(priv->trans, CSR_EEPROM_GP) & | ||
771 | ~CSR_EEPROM_GP_IF_OWNER_MSK); | ||
772 | |||
773 | iwl_set_bit(priv->trans, CSR_OTP_GP_REG, | ||
774 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | | ||
775 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | ||
776 | /* traversing the linked list if no shadow ram supported */ | ||
777 | if (!priv->cfg->base_params->shadow_ram_support) { | ||
778 | if (iwl_find_otp_image(priv->trans, &validblockaddr)) { | ||
779 | ret = -ENOENT; | ||
780 | goto done; | ||
781 | } | ||
782 | } | ||
783 | for (addr = validblockaddr; addr < validblockaddr + sz; | ||
784 | addr += sizeof(u16)) { | ||
785 | __le16 eeprom_data; | ||
786 | |||
787 | ret = iwl_read_otp_word(priv->trans, addr, | ||
788 | &eeprom_data); | ||
789 | if (ret) | ||
790 | goto done; | ||
791 | e[cache_addr / 2] = eeprom_data; | ||
792 | cache_addr += sizeof(u16); | ||
793 | } | ||
794 | } else { | ||
795 | /* eeprom is an array of 16bit values */ | ||
796 | for (addr = 0; addr < sz; addr += sizeof(u16)) { | ||
797 | u32 r; | ||
798 | |||
799 | iwl_write32(priv->trans, CSR_EEPROM_REG, | ||
800 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||
801 | |||
802 | ret = iwl_poll_bit(priv->trans, CSR_EEPROM_REG, | ||
803 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
804 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
805 | IWL_EEPROM_ACCESS_TIMEOUT); | ||
806 | if (ret < 0) { | ||
807 | IWL_ERR(priv, | ||
808 | "Time out reading EEPROM[%d]\n", addr); | ||
809 | goto done; | ||
810 | } | ||
811 | r = iwl_read32(priv->trans, CSR_EEPROM_REG); | ||
812 | e[addr / 2] = cpu_to_le16(r >> 16); | ||
813 | } | ||
814 | } | ||
815 | |||
816 | IWL_DEBUG_EEPROM(priv, "NVM Type: %s, version: 0x%x\n", | ||
817 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
818 | ? "OTP" : "EEPROM", | ||
819 | iwl_eeprom_query16(priv, EEPROM_VERSION)); | ||
820 | |||
821 | ret = 0; | ||
822 | done: | ||
823 | iwl_eeprom_release_semaphore(priv->trans); | ||
824 | |||
825 | err: | ||
826 | if (ret) | ||
827 | iwl_eeprom_free(priv); | ||
828 | alloc_err: | ||
829 | return ret; | ||
830 | } | ||
831 | |||
832 | void iwl_eeprom_free(struct iwl_priv *priv) | ||
833 | { | ||
834 | kfree(priv->eeprom); | ||
835 | priv->eeprom = NULL; | ||
836 | } | ||
837 | |||
838 | static void iwl_init_band_reference(struct iwl_priv *priv, | ||
839 | int eep_band, int *eeprom_ch_count, | ||
840 | const struct iwl_eeprom_channel **eeprom_ch_info, | ||
841 | const u8 **eeprom_ch_index) | ||
842 | { | ||
843 | u32 offset = priv->lib-> | ||
844 | eeprom_ops.regulatory_bands[eep_band - 1]; | ||
845 | switch (eep_band) { | ||
846 | case 1: /* 2.4GHz band */ | ||
847 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1); | ||
848 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
849 | iwl_eeprom_query_addr(priv, offset); | ||
850 | *eeprom_ch_index = iwl_eeprom_band_1; | ||
851 | break; | ||
852 | case 2: /* 4.9GHz band */ | ||
853 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2); | ||
854 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
855 | iwl_eeprom_query_addr(priv, offset); | ||
856 | *eeprom_ch_index = iwl_eeprom_band_2; | ||
857 | break; | ||
858 | case 3: /* 5.2GHz band */ | ||
859 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3); | ||
860 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
861 | iwl_eeprom_query_addr(priv, offset); | ||
862 | *eeprom_ch_index = iwl_eeprom_band_3; | ||
863 | break; | ||
864 | case 4: /* 5.5GHz band */ | ||
865 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4); | ||
866 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
867 | iwl_eeprom_query_addr(priv, offset); | ||
868 | *eeprom_ch_index = iwl_eeprom_band_4; | ||
869 | break; | ||
870 | case 5: /* 5.7GHz band */ | ||
871 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5); | ||
872 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
873 | iwl_eeprom_query_addr(priv, offset); | ||
874 | *eeprom_ch_index = iwl_eeprom_band_5; | ||
875 | break; | ||
876 | case 6: /* 2.4GHz ht40 channels */ | ||
877 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6); | ||
878 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
879 | iwl_eeprom_query_addr(priv, offset); | ||
880 | *eeprom_ch_index = iwl_eeprom_band_6; | ||
881 | break; | ||
882 | case 7: /* 5 GHz ht40 channels */ | ||
883 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7); | ||
884 | *eeprom_ch_info = (struct iwl_eeprom_channel *) | ||
885 | iwl_eeprom_query_addr(priv, offset); | ||
886 | *eeprom_ch_index = iwl_eeprom_band_7; | ||
887 | break; | ||
888 | default: | ||
889 | BUG(); | ||
890 | return; | ||
891 | } | ||
892 | } | ||
893 | |||
894 | #define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \ | ||
895 | ? # x " " : "") | ||
896 | /** | ||
897 | * iwl_mod_ht40_chan_info - Copy ht40 channel info into driver's priv. | ||
898 | * | ||
899 | * Does not set up a command, or touch hardware. | ||
900 | */ | ||
901 | static int iwl_mod_ht40_chan_info(struct iwl_priv *priv, | ||
902 | enum ieee80211_band band, u16 channel, | ||
903 | const struct iwl_eeprom_channel *eeprom_ch, | ||
904 | u8 clear_ht40_extension_channel) | ||
905 | { | ||
906 | struct iwl_channel_info *ch_info; | ||
907 | |||
908 | ch_info = (struct iwl_channel_info *) | ||
909 | iwl_get_channel_info(priv, band, channel); | ||
910 | |||
911 | if (!is_channel_valid(ch_info)) | ||
912 | return -1; | ||
913 | |||
914 | IWL_DEBUG_EEPROM(priv, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):" | ||
915 | " Ad-Hoc %ssupported\n", | ||
916 | ch_info->channel, | ||
917 | is_channel_a_band(ch_info) ? | ||
918 | "5.2" : "2.4", | ||
919 | CHECK_AND_PRINT(IBSS), | ||
920 | CHECK_AND_PRINT(ACTIVE), | ||
921 | CHECK_AND_PRINT(RADAR), | ||
922 | CHECK_AND_PRINT(WIDE), | ||
923 | CHECK_AND_PRINT(DFS), | ||
924 | eeprom_ch->flags, | ||
925 | eeprom_ch->max_power_avg, | ||
926 | ((eeprom_ch->flags & EEPROM_CHANNEL_IBSS) | ||
927 | && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ? | ||
928 | "" : "not "); | ||
929 | |||
930 | ch_info->ht40_eeprom = *eeprom_ch; | ||
931 | ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg; | ||
932 | ch_info->ht40_flags = eeprom_ch->flags; | ||
933 | if (eeprom_ch->flags & EEPROM_CHANNEL_VALID) | ||
934 | ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; | ||
935 | |||
936 | return 0; | ||
937 | } | ||
938 | |||
939 | #define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \ | ||
940 | ? # x " " : "") | ||
941 | |||
942 | /** | ||
943 | * iwl_init_channel_map - Set up driver's info for all possible channels | ||
944 | */ | ||
945 | int iwl_init_channel_map(struct iwl_priv *priv) | ||
946 | { | ||
947 | int eeprom_ch_count = 0; | ||
948 | const u8 *eeprom_ch_index = NULL; | ||
949 | const struct iwl_eeprom_channel *eeprom_ch_info = NULL; | ||
950 | int band, ch; | ||
951 | struct iwl_channel_info *ch_info; | ||
952 | |||
953 | if (priv->channel_count) { | ||
954 | IWL_DEBUG_EEPROM(priv, "Channel map already initialized.\n"); | ||
955 | return 0; | ||
956 | } | ||
957 | |||
958 | IWL_DEBUG_EEPROM(priv, "Initializing regulatory info from EEPROM\n"); | ||
959 | |||
960 | priv->channel_count = | ||
961 | ARRAY_SIZE(iwl_eeprom_band_1) + | ||
962 | ARRAY_SIZE(iwl_eeprom_band_2) + | ||
963 | ARRAY_SIZE(iwl_eeprom_band_3) + | ||
964 | ARRAY_SIZE(iwl_eeprom_band_4) + | ||
965 | ARRAY_SIZE(iwl_eeprom_band_5); | ||
966 | |||
967 | IWL_DEBUG_EEPROM(priv, "Parsing data for %d channels.\n", | ||
968 | priv->channel_count); | ||
969 | |||
970 | priv->channel_info = kcalloc(priv->channel_count, | ||
971 | sizeof(struct iwl_channel_info), | ||
972 | GFP_KERNEL); | ||
973 | if (!priv->channel_info) { | ||
974 | IWL_ERR(priv, "Could not allocate channel_info\n"); | ||
975 | priv->channel_count = 0; | ||
976 | return -ENOMEM; | ||
977 | } | ||
978 | |||
979 | ch_info = priv->channel_info; | ||
980 | |||
981 | /* Loop through the 5 EEPROM bands adding them in order to the | ||
982 | * channel map we maintain (that contains additional information than | ||
983 | * what just in the EEPROM) */ | ||
984 | for (band = 1; band <= 5; band++) { | ||
985 | |||
986 | iwl_init_band_reference(priv, band, &eeprom_ch_count, | ||
987 | &eeprom_ch_info, &eeprom_ch_index); | ||
988 | |||
989 | /* Loop through each band adding each of the channels */ | ||
990 | for (ch = 0; ch < eeprom_ch_count; ch++) { | ||
991 | ch_info->channel = eeprom_ch_index[ch]; | ||
992 | ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ : | ||
993 | IEEE80211_BAND_5GHZ; | ||
994 | |||
995 | /* permanently store EEPROM's channel regulatory flags | ||
996 | * and max power in channel info database. */ | ||
997 | ch_info->eeprom = eeprom_ch_info[ch]; | ||
998 | |||
999 | /* Copy the run-time flags so they are there even on | ||
1000 | * invalid channels */ | ||
1001 | ch_info->flags = eeprom_ch_info[ch].flags; | ||
1002 | /* First write that ht40 is not enabled, and then enable | ||
1003 | * one by one */ | ||
1004 | ch_info->ht40_extension_channel = | ||
1005 | IEEE80211_CHAN_NO_HT40; | ||
1006 | |||
1007 | if (!(is_channel_valid(ch_info))) { | ||
1008 | IWL_DEBUG_EEPROM(priv, | ||
1009 | "Ch. %d Flags %x [%sGHz] - " | ||
1010 | "No traffic\n", | ||
1011 | ch_info->channel, | ||
1012 | ch_info->flags, | ||
1013 | is_channel_a_band(ch_info) ? | ||
1014 | "5.2" : "2.4"); | ||
1015 | ch_info++; | ||
1016 | continue; | ||
1017 | } | ||
1018 | |||
1019 | /* Initialize regulatory-based run-time data */ | ||
1020 | ch_info->max_power_avg = ch_info->curr_txpow = | ||
1021 | eeprom_ch_info[ch].max_power_avg; | ||
1022 | ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; | ||
1023 | ch_info->min_power = 0; | ||
1024 | |||
1025 | IWL_DEBUG_EEPROM(priv, "Ch. %d [%sGHz] " | ||
1026 | "%s%s%s%s%s%s(0x%02x %ddBm):" | ||
1027 | " Ad-Hoc %ssupported\n", | ||
1028 | ch_info->channel, | ||
1029 | is_channel_a_band(ch_info) ? | ||
1030 | "5.2" : "2.4", | ||
1031 | CHECK_AND_PRINT_I(VALID), | ||
1032 | CHECK_AND_PRINT_I(IBSS), | ||
1033 | CHECK_AND_PRINT_I(ACTIVE), | ||
1034 | CHECK_AND_PRINT_I(RADAR), | ||
1035 | CHECK_AND_PRINT_I(WIDE), | ||
1036 | CHECK_AND_PRINT_I(DFS), | ||
1037 | eeprom_ch_info[ch].flags, | ||
1038 | eeprom_ch_info[ch].max_power_avg, | ||
1039 | ((eeprom_ch_info[ch]. | ||
1040 | flags & EEPROM_CHANNEL_IBSS) | ||
1041 | && !(eeprom_ch_info[ch]. | ||
1042 | flags & EEPROM_CHANNEL_RADAR)) | ||
1043 | ? "" : "not "); | ||
1044 | |||
1045 | ch_info++; | ||
1046 | } | ||
1047 | } | ||
1048 | |||
1049 | /* Check if we do have HT40 channels */ | ||
1050 | if (priv->lib->eeprom_ops.regulatory_bands[5] == | ||
1051 | EEPROM_REGULATORY_BAND_NO_HT40 && | ||
1052 | priv->lib->eeprom_ops.regulatory_bands[6] == | ||
1053 | EEPROM_REGULATORY_BAND_NO_HT40) | ||
1054 | return 0; | ||
1055 | |||
1056 | /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */ | ||
1057 | for (band = 6; band <= 7; band++) { | ||
1058 | enum ieee80211_band ieeeband; | ||
1059 | |||
1060 | iwl_init_band_reference(priv, band, &eeprom_ch_count, | ||
1061 | &eeprom_ch_info, &eeprom_ch_index); | ||
1062 | |||
1063 | /* EEPROM band 6 is 2.4, band 7 is 5 GHz */ | ||
1064 | ieeeband = | ||
1065 | (band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
1066 | |||
1067 | /* Loop through each band adding each of the channels */ | ||
1068 | for (ch = 0; ch < eeprom_ch_count; ch++) { | ||
1069 | /* Set up driver's info for lower half */ | ||
1070 | iwl_mod_ht40_chan_info(priv, ieeeband, | ||
1071 | eeprom_ch_index[ch], | ||
1072 | &eeprom_ch_info[ch], | ||
1073 | IEEE80211_CHAN_NO_HT40PLUS); | ||
1074 | |||
1075 | /* Set up driver's info for upper half */ | ||
1076 | iwl_mod_ht40_chan_info(priv, ieeeband, | ||
1077 | eeprom_ch_index[ch] + 4, | ||
1078 | &eeprom_ch_info[ch], | ||
1079 | IEEE80211_CHAN_NO_HT40MINUS); | ||
1080 | } | ||
1081 | } | ||
1082 | |||
1083 | /* for newer device (6000 series and up) | ||
1084 | * EEPROM contain enhanced tx power information | ||
1085 | * driver need to process addition information | ||
1086 | * to determine the max channel tx power limits | ||
1087 | */ | ||
1088 | if (priv->lib->eeprom_ops.enhanced_txpower) | ||
1089 | iwl_eeprom_enhanced_txpower(priv); | ||
1090 | |||
1091 | return 0; | ||
1092 | } | ||
1093 | |||
1094 | /* | ||
1095 | * iwl_free_channel_map - undo allocations in iwl_init_channel_map | ||
1096 | */ | ||
1097 | void iwl_free_channel_map(struct iwl_priv *priv) | ||
1098 | { | ||
1099 | kfree(priv->channel_info); | ||
1100 | priv->channel_count = 0; | ||
1101 | } | ||
1102 | |||
1103 | /** | ||
1104 | * iwl_get_channel_info - Find driver's private channel info | ||
1105 | * | ||
1106 | * Based on band and channel number. | ||
1107 | */ | ||
1108 | const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv, | ||
1109 | enum ieee80211_band band, u16 channel) | ||
1110 | { | ||
1111 | int i; | ||
1112 | |||
1113 | switch (band) { | ||
1114 | case IEEE80211_BAND_5GHZ: | ||
1115 | for (i = 14; i < priv->channel_count; i++) { | ||
1116 | if (priv->channel_info[i].channel == channel) | ||
1117 | return &priv->channel_info[i]; | ||
1118 | } | ||
1119 | break; | ||
1120 | case IEEE80211_BAND_2GHZ: | ||
1121 | if (channel >= 1 && channel <= 14) | ||
1122 | return &priv->channel_info[channel - 1]; | ||
1123 | break; | ||
1124 | default: | ||
1125 | BUG(); | ||
1126 | } | ||
1127 | |||
1128 | return NULL; | ||
1129 | } | ||
1130 | |||
1131 | void iwl_rf_config(struct iwl_priv *priv) | ||
1132 | { | ||
1133 | u16 radio_cfg; | ||
1134 | |||
1135 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | ||
1136 | |||
1137 | /* write radio config values to register */ | ||
1138 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { | ||
1139 | u32 reg_val = | ||
1140 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) << | ||
1141 | CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE | | ||
1142 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) << | ||
1143 | CSR_HW_IF_CONFIG_REG_POS_PHY_STEP | | ||
1144 | EEPROM_RF_CFG_DASH_MSK(radio_cfg) << | ||
1145 | CSR_HW_IF_CONFIG_REG_POS_PHY_DASH; | ||
1146 | |||
1147 | iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG, | ||
1148 | CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE | | ||
1149 | CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP | | ||
1150 | CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH, reg_val); | ||
1151 | |||
1152 | IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n", | ||
1153 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg), | ||
1154 | EEPROM_RF_CFG_STEP_MSK(radio_cfg), | ||
1155 | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); | ||
1156 | } else | ||
1157 | WARN_ON(1); | ||
1158 | |||
1159 | /* set CSR_HW_CONFIG_REG for uCode use */ | ||
1160 | iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG, | ||
1161 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||
1162 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||
1163 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/eeprom.h b/drivers/net/wireless/iwlwifi/dvm/eeprom.h deleted file mode 100644 index 64bfd947caeb..000000000000 --- a/drivers/net/wireless/iwlwifi/dvm/eeprom.h +++ /dev/null | |||
@@ -1,269 +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 - 2012 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 - 2012 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_eeprom_h__ | ||
64 | #define __iwl_eeprom_h__ | ||
65 | |||
66 | #include <net/mac80211.h> | ||
67 | |||
68 | struct iwl_priv; | ||
69 | |||
70 | /* | ||
71 | * EEPROM access time values: | ||
72 | * | ||
73 | * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG. | ||
74 | * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1). | ||
75 | * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec. | ||
76 | * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG. | ||
77 | */ | ||
78 | #define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */ | ||
79 | |||
80 | #define IWL_EEPROM_SEM_TIMEOUT 10 /* microseconds */ | ||
81 | #define IWL_EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ | ||
82 | |||
83 | |||
84 | /* | ||
85 | * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags. | ||
86 | * | ||
87 | * IBSS and/or AP operation is allowed *only* on those channels with | ||
88 | * (VALID && IBSS && ACTIVE && !RADAR). This restriction is in place because | ||
89 | * RADAR detection is not supported by the 4965 driver, but is a | ||
90 | * requirement for establishing a new network for legal operation on channels | ||
91 | * requiring RADAR detection or restricting ACTIVE scanning. | ||
92 | * | ||
93 | * NOTE: "WIDE" flag does not indicate anything about "HT40" 40 MHz channels. | ||
94 | * It only indicates that 20 MHz channel use is supported; HT40 channel | ||
95 | * usage is indicated by a separate set of regulatory flags for each | ||
96 | * HT40 channel pair. | ||
97 | * | ||
98 | * NOTE: Using a channel inappropriately will result in a uCode error! | ||
99 | */ | ||
100 | #define IWL_NUM_TX_CALIB_GROUPS 5 | ||
101 | enum { | ||
102 | EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */ | ||
103 | EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */ | ||
104 | /* Bit 2 Reserved */ | ||
105 | EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */ | ||
106 | EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */ | ||
107 | EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */ | ||
108 | /* Bit 6 Reserved (was Narrow Channel) */ | ||
109 | EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */ | ||
110 | }; | ||
111 | |||
112 | /* SKU Capabilities */ | ||
113 | #define EEPROM_SKU_CAP_BAND_24GHZ (1 << 4) | ||
114 | #define EEPROM_SKU_CAP_BAND_52GHZ (1 << 5) | ||
115 | #define EEPROM_SKU_CAP_11N_ENABLE (1 << 6) | ||
116 | #define EEPROM_SKU_CAP_AMT_ENABLE (1 << 7) | ||
117 | #define EEPROM_SKU_CAP_IPAN_ENABLE (1 << 8) | ||
118 | |||
119 | /* *regulatory* channel data format in eeprom, one for each channel. | ||
120 | * There are separate entries for HT40 (40 MHz) vs. normal (20 MHz) channels. */ | ||
121 | struct iwl_eeprom_channel { | ||
122 | u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */ | ||
123 | s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */ | ||
124 | } __packed; | ||
125 | |||
126 | enum iwl_eeprom_enhanced_txpwr_flags { | ||
127 | IWL_EEPROM_ENH_TXP_FL_VALID = BIT(0), | ||
128 | IWL_EEPROM_ENH_TXP_FL_BAND_52G = BIT(1), | ||
129 | IWL_EEPROM_ENH_TXP_FL_OFDM = BIT(2), | ||
130 | IWL_EEPROM_ENH_TXP_FL_40MHZ = BIT(3), | ||
131 | IWL_EEPROM_ENH_TXP_FL_HT_AP = BIT(4), | ||
132 | IWL_EEPROM_ENH_TXP_FL_RES1 = BIT(5), | ||
133 | IWL_EEPROM_ENH_TXP_FL_RES2 = BIT(6), | ||
134 | IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE = BIT(7), | ||
135 | }; | ||
136 | |||
137 | /** | ||
138 | * iwl_eeprom_enhanced_txpwr structure | ||
139 | * This structure presents the enhanced regulatory tx power limit layout | ||
140 | * in eeprom image | ||
141 | * Enhanced regulatory tx power portion of eeprom image can be broken down | ||
142 | * into individual structures; each one is 8 bytes in size and contain the | ||
143 | * following information | ||
144 | * @flags: entry flags | ||
145 | * @channel: channel number | ||
146 | * @chain_a_max_pwr: chain a max power in 1/2 dBm | ||
147 | * @chain_b_max_pwr: chain b max power in 1/2 dBm | ||
148 | * @chain_c_max_pwr: chain c max power in 1/2 dBm | ||
149 | * @delta_20_in_40: 20-in-40 deltas (hi/lo) | ||
150 | * @mimo2_max_pwr: mimo2 max power in 1/2 dBm | ||
151 | * @mimo3_max_pwr: mimo3 max power in 1/2 dBm | ||
152 | * | ||
153 | */ | ||
154 | struct iwl_eeprom_enhanced_txpwr { | ||
155 | u8 flags; | ||
156 | u8 channel; | ||
157 | s8 chain_a_max; | ||
158 | s8 chain_b_max; | ||
159 | s8 chain_c_max; | ||
160 | u8 delta_20_in_40; | ||
161 | s8 mimo2_max; | ||
162 | s8 mimo3_max; | ||
163 | } __packed; | ||
164 | |||
165 | /* calibration */ | ||
166 | struct iwl_eeprom_calib_hdr { | ||
167 | u8 version; | ||
168 | u8 pa_type; | ||
169 | __le16 voltage; | ||
170 | } __packed; | ||
171 | |||
172 | #define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION) | ||
173 | #define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL) | ||
174 | |||
175 | /* temperature */ | ||
176 | #define EEPROM_KELVIN_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL) | ||
177 | #define EEPROM_RAW_TEMPERATURE ((2*0x12B) | EEPROM_CALIB_ALL) | ||
178 | |||
179 | |||
180 | /* agn links */ | ||
181 | #define EEPROM_LINK_HOST (2*0x64) | ||
182 | #define EEPROM_LINK_GENERAL (2*0x65) | ||
183 | #define EEPROM_LINK_REGULATORY (2*0x66) | ||
184 | #define EEPROM_LINK_CALIBRATION (2*0x67) | ||
185 | #define EEPROM_LINK_PROCESS_ADJST (2*0x68) | ||
186 | #define EEPROM_LINK_OTHERS (2*0x69) | ||
187 | #define EEPROM_LINK_TXP_LIMIT (2*0x6a) | ||
188 | #define EEPROM_LINK_TXP_LIMIT_SIZE (2*0x6b) | ||
189 | |||
190 | /* agn regulatory - indirect access */ | ||
191 | #define EEPROM_REG_BAND_1_CHANNELS ((0x08)\ | ||
192 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 28 bytes */ | ||
193 | #define EEPROM_REG_BAND_2_CHANNELS ((0x26)\ | ||
194 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 26 bytes */ | ||
195 | #define EEPROM_REG_BAND_3_CHANNELS ((0x42)\ | ||
196 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ | ||
197 | #define EEPROM_REG_BAND_4_CHANNELS ((0x5C)\ | ||
198 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ | ||
199 | #define EEPROM_REG_BAND_5_CHANNELS ((0x74)\ | ||
200 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 12 bytes */ | ||
201 | #define EEPROM_REG_BAND_24_HT40_CHANNELS ((0x82)\ | ||
202 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ | ||
203 | #define EEPROM_REG_BAND_52_HT40_CHANNELS ((0x92)\ | ||
204 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ | ||
205 | |||
206 | /* 6000 regulatory - indirect access */ | ||
207 | #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS ((0x80)\ | ||
208 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ | ||
209 | /* 2.4 GHz */ | ||
210 | extern const u8 iwl_eeprom_band_1[14]; | ||
211 | |||
212 | #define ADDRESS_MSK 0x0000FFFF | ||
213 | #define INDIRECT_TYPE_MSK 0x000F0000 | ||
214 | #define INDIRECT_HOST 0x00010000 | ||
215 | #define INDIRECT_GENERAL 0x00020000 | ||
216 | #define INDIRECT_REGULATORY 0x00030000 | ||
217 | #define INDIRECT_CALIBRATION 0x00040000 | ||
218 | #define INDIRECT_PROCESS_ADJST 0x00050000 | ||
219 | #define INDIRECT_OTHERS 0x00060000 | ||
220 | #define INDIRECT_TXP_LIMIT 0x00070000 | ||
221 | #define INDIRECT_TXP_LIMIT_SIZE 0x00080000 | ||
222 | #define INDIRECT_ADDRESS 0x00100000 | ||
223 | |||
224 | /* General */ | ||
225 | #define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */ | ||
226 | #define EEPROM_SUBSYSTEM_ID (2*0x0A) /* 2 bytes */ | ||
227 | #define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */ | ||
228 | #define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */ | ||
229 | #define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ | ||
230 | #define EEPROM_VERSION (2*0x44) /* 2 bytes */ | ||
231 | #define EEPROM_SKU_CAP (2*0x45) /* 2 bytes */ | ||
232 | #define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ | ||
233 | #define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */ | ||
234 | #define EEPROM_NUM_MAC_ADDRESS (2*0x4C) /* 2 bytes */ | ||
235 | |||
236 | /* The following masks are to be applied on EEPROM_RADIO_CONFIG */ | ||
237 | #define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */ | ||
238 | #define EEPROM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */ | ||
239 | #define EEPROM_RF_CFG_DASH_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */ | ||
240 | #define EEPROM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */ | ||
241 | #define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */ | ||
242 | #define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */ | ||
243 | |||
244 | #define EEPROM_RF_CONFIG_TYPE_MAX 0x3 | ||
245 | |||
246 | #define EEPROM_REGULATORY_BAND_NO_HT40 (0) | ||
247 | |||
248 | struct iwl_eeprom_ops { | ||
249 | const u32 regulatory_bands[7]; | ||
250 | bool enhanced_txpower; | ||
251 | }; | ||
252 | |||
253 | |||
254 | int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev); | ||
255 | void iwl_eeprom_free(struct iwl_priv *priv); | ||
256 | int iwl_eeprom_check_version(struct iwl_priv *priv); | ||
257 | int iwl_eeprom_init_hw_params(struct iwl_priv *priv); | ||
258 | u16 iwl_eeprom_calib_version(struct iwl_priv *priv); | ||
259 | const u8 *iwl_eeprom_query_addr(struct iwl_priv *priv, size_t offset); | ||
260 | u16 iwl_eeprom_query16(struct iwl_priv *priv, size_t offset); | ||
261 | void iwl_eeprom_get_mac(struct iwl_priv *priv, u8 *mac); | ||
262 | int iwl_init_channel_map(struct iwl_priv *priv); | ||
263 | void iwl_free_channel_map(struct iwl_priv *priv); | ||
264 | const struct iwl_channel_info *iwl_get_channel_info( | ||
265 | const struct iwl_priv *priv, | ||
266 | enum ieee80211_band band, u16 channel); | ||
267 | void iwl_rf_config(struct iwl_priv *priv); | ||
268 | |||
269 | #endif /* __iwl_eeprom_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index 4ac9af7eb853..cb1ca7a25dd5 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c | |||
@@ -59,8 +59,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) | |||
59 | /* half dBm need to multiply */ | 59 | /* half dBm need to multiply */ |
60 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); | 60 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); |
61 | 61 | ||
62 | if (priv->tx_power_lmt_in_half_dbm && | 62 | if (tx_power_cmd.global_lmt > priv->eeprom_data->max_tx_pwr_half_dbm) { |
63 | priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) { | ||
64 | /* | 63 | /* |
65 | * For the newer devices which using enhanced/extend tx power | 64 | * For the newer devices which using enhanced/extend tx power |
66 | * table in EEPROM, the format is in half dBm. driver need to | 65 | * table in EEPROM, the format is in half dBm. driver need to |
@@ -72,7 +71,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) | |||
72 | * "tx_power_user_lmt" is higher than EEPROM value (in | 71 | * "tx_power_user_lmt" is higher than EEPROM value (in |
73 | * half-dBm format), lower the tx power based on EEPROM | 72 | * half-dBm format), lower the tx power based on EEPROM |
74 | */ | 73 | */ |
75 | tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm; | 74 | tx_power_cmd.global_lmt = |
75 | priv->eeprom_data->max_tx_pwr_half_dbm; | ||
76 | } | 76 | } |
77 | tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED; | 77 | tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED; |
78 | tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO; | 78 | tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO; |
@@ -824,7 +824,7 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
824 | if (priv->chain_noise_data.active_chains) | 824 | if (priv->chain_noise_data.active_chains) |
825 | active_chains = priv->chain_noise_data.active_chains; | 825 | active_chains = priv->chain_noise_data.active_chains; |
826 | else | 826 | else |
827 | active_chains = priv->hw_params.valid_rx_ant; | 827 | active_chains = priv->eeprom_data->valid_rx_ant; |
828 | 828 | ||
829 | if (priv->cfg->bt_params && | 829 | if (priv->cfg->bt_params && |
830 | priv->cfg->bt_params->advanced_bt_coexist && | 830 | priv->cfg->bt_params->advanced_bt_coexist && |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 32a823d7497f..f60be3993e81 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -48,7 +48,6 @@ | |||
48 | #include "iwl-op-mode.h" | 48 | #include "iwl-op-mode.h" |
49 | #include "iwl-modparams.h" | 49 | #include "iwl-modparams.h" |
50 | 50 | ||
51 | #include "eeprom.h" | ||
52 | #include "dev.h" | 51 | #include "dev.h" |
53 | #include "calib.h" | 52 | #include "calib.h" |
54 | #include "agn.h" | 53 | #include "agn.h" |
@@ -238,12 +237,12 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
238 | 237 | ||
239 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; | 238 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; |
240 | 239 | ||
241 | if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) | 240 | if (priv->eeprom_data->bands[IEEE80211_BAND_2GHZ].n_channels) |
242 | priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | 241 | priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = |
243 | &priv->bands[IEEE80211_BAND_2GHZ]; | 242 | &priv->eeprom_data->bands[IEEE80211_BAND_2GHZ]; |
244 | if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) | 243 | if (priv->eeprom_data->bands[IEEE80211_BAND_5GHZ].n_channels) |
245 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 244 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = |
246 | &priv->bands[IEEE80211_BAND_5GHZ]; | 245 | &priv->eeprom_data->bands[IEEE80211_BAND_5GHZ]; |
247 | 246 | ||
248 | hw->wiphy->hw_version = priv->trans->hw_id; | 247 | hw->wiphy->hw_version = priv->trans->hw_id; |
249 | 248 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 10a2800687bc..ebdc8b93bc04 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
@@ -44,13 +44,14 @@ | |||
44 | 44 | ||
45 | #include <asm/div64.h> | 45 | #include <asm/div64.h> |
46 | 46 | ||
47 | #include "iwl-eeprom-read.h" | ||
48 | #include "iwl-eeprom-parse.h" | ||
47 | #include "iwl-io.h" | 49 | #include "iwl-io.h" |
48 | #include "iwl-trans.h" | 50 | #include "iwl-trans.h" |
49 | #include "iwl-op-mode.h" | 51 | #include "iwl-op-mode.h" |
50 | #include "iwl-drv.h" | 52 | #include "iwl-drv.h" |
51 | #include "iwl-modparams.h" | 53 | #include "iwl-modparams.h" |
52 | 54 | ||
53 | #include "eeprom.h" | ||
54 | #include "dev.h" | 55 | #include "dev.h" |
55 | #include "calib.h" | 56 | #include "calib.h" |
56 | #include "agn.h" | 57 | #include "agn.h" |
@@ -180,7 +181,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) | |||
180 | rate = info->control.rates[0].idx; | 181 | rate = info->control.rates[0].idx; |
181 | 182 | ||
182 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 183 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
183 | priv->hw_params.valid_tx_ant); | 184 | priv->eeprom_data->valid_tx_ant); |
184 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 185 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); |
185 | 186 | ||
186 | /* In mac80211, rates for 5 GHz start at 0 */ | 187 | /* In mac80211, rates for 5 GHz start at 0 */ |
@@ -814,7 +815,7 @@ int iwl_alive_start(struct iwl_priv *priv) | |||
814 | ieee80211_wake_queues(priv->hw); | 815 | ieee80211_wake_queues(priv->hw); |
815 | 816 | ||
816 | /* Configure Tx antenna selection based on H/W config */ | 817 | /* Configure Tx antenna selection based on H/W config */ |
817 | iwlagn_send_tx_ant_config(priv, priv->hw_params.valid_tx_ant); | 818 | iwlagn_send_tx_ant_config(priv, priv->eeprom_data->valid_tx_ant); |
818 | 819 | ||
819 | if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { | 820 | if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { |
820 | struct iwl_rxon_cmd *active_rxon = | 821 | struct iwl_rxon_cmd *active_rxon = |
@@ -938,8 +939,6 @@ void iwl_down(struct iwl_priv *priv) | |||
938 | /* Clear out all status bits but a few that are stable across reset */ | 939 | /* Clear out all status bits but a few that are stable across reset */ |
939 | priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << | 940 | priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << |
940 | STATUS_RF_KILL_HW | | 941 | STATUS_RF_KILL_HW | |
941 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << | ||
942 | STATUS_GEO_CONFIGURED | | ||
943 | test_bit(STATUS_FW_ERROR, &priv->status) << | 942 | test_bit(STATUS_FW_ERROR, &priv->status) << |
944 | STATUS_FW_ERROR | | 943 | STATUS_FW_ERROR | |
945 | test_bit(STATUS_EXIT_PENDING, &priv->status) << | 944 | test_bit(STATUS_EXIT_PENDING, &priv->status) << |
@@ -1126,227 +1125,14 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
1126 | del_timer_sync(&priv->ucode_trace); | 1125 | del_timer_sync(&priv->ucode_trace); |
1127 | } | 1126 | } |
1128 | 1127 | ||
1129 | static void iwl_init_hw_rates(struct ieee80211_rate *rates) | ||
1130 | { | ||
1131 | int i; | ||
1132 | |||
1133 | for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) { | ||
1134 | rates[i].bitrate = iwl_rates[i].ieee * 5; | ||
1135 | rates[i].hw_value = i; /* Rate scaling will work on indexes */ | ||
1136 | rates[i].hw_value_short = i; | ||
1137 | rates[i].flags = 0; | ||
1138 | if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) { | ||
1139 | /* | ||
1140 | * If CCK != 1M then set short preamble rate flag. | ||
1141 | */ | ||
1142 | rates[i].flags |= | ||
1143 | (iwl_rates[i].plcp == IWL_RATE_1M_PLCP) ? | ||
1144 | 0 : IEEE80211_RATE_SHORT_PREAMBLE; | ||
1145 | } | ||
1146 | } | ||
1147 | } | ||
1148 | |||
1149 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ | ||
1150 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ | ||
1151 | static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, | ||
1152 | struct ieee80211_sta_ht_cap *ht_info, | ||
1153 | enum ieee80211_band band) | ||
1154 | { | ||
1155 | u16 max_bit_rate = 0; | ||
1156 | u8 rx_chains_num = priv->hw_params.rx_chains_num; | ||
1157 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | ||
1158 | |||
1159 | ht_info->cap = 0; | ||
1160 | ht_info->ht_supported = false; | ||
1161 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); | ||
1162 | |||
1163 | if (!priv->cfg->ht_params) | ||
1164 | return; | ||
1165 | |||
1166 | ht_info->ht_supported = true; | ||
1167 | |||
1168 | if (priv->cfg->ht_params->ht_greenfield_support) | ||
1169 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | ||
1170 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | ||
1171 | max_bit_rate = MAX_BIT_RATE_20_MHZ; | ||
1172 | if (priv->cfg->ht_params->ht40_bands & BIT(band)) { | ||
1173 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
1174 | ht_info->cap |= IEEE80211_HT_CAP_SGI_40; | ||
1175 | ht_info->mcs.rx_mask[4] = 0x01; | ||
1176 | max_bit_rate = MAX_BIT_RATE_40_MHZ; | ||
1177 | } | ||
1178 | |||
1179 | if (iwlwifi_mod_params.amsdu_size_8K) | ||
1180 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | ||
1181 | |||
1182 | ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; | ||
1183 | ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; | ||
1184 | |||
1185 | ht_info->mcs.rx_mask[0] = 0xFF; | ||
1186 | if (rx_chains_num >= 2) | ||
1187 | ht_info->mcs.rx_mask[1] = 0xFF; | ||
1188 | if (rx_chains_num >= 3) | ||
1189 | ht_info->mcs.rx_mask[2] = 0xFF; | ||
1190 | |||
1191 | /* Highest supported Rx data rate */ | ||
1192 | max_bit_rate *= rx_chains_num; | ||
1193 | WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK); | ||
1194 | ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate); | ||
1195 | |||
1196 | /* Tx MCS capabilities */ | ||
1197 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
1198 | if (tx_chains_num != rx_chains_num) { | ||
1199 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | ||
1200 | ht_info->mcs.tx_params |= ((tx_chains_num - 1) << | ||
1201 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | ||
1202 | } | ||
1203 | } | ||
1204 | |||
1205 | /** | ||
1206 | * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom | ||
1207 | */ | ||
1208 | static int iwl_init_geos(struct iwl_priv *priv) | ||
1209 | { | ||
1210 | struct iwl_channel_info *ch; | ||
1211 | struct ieee80211_supported_band *sband; | ||
1212 | struct ieee80211_channel *channels; | ||
1213 | struct ieee80211_channel *geo_ch; | ||
1214 | struct ieee80211_rate *rates; | ||
1215 | int i = 0; | ||
1216 | s8 max_tx_power = IWLAGN_TX_POWER_TARGET_POWER_MIN; | ||
1217 | |||
1218 | if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || | ||
1219 | priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { | ||
1220 | IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n"); | ||
1221 | set_bit(STATUS_GEO_CONFIGURED, &priv->status); | ||
1222 | return 0; | ||
1223 | } | ||
1224 | |||
1225 | channels = kcalloc(priv->channel_count, | ||
1226 | sizeof(struct ieee80211_channel), GFP_KERNEL); | ||
1227 | if (!channels) | ||
1228 | return -ENOMEM; | ||
1229 | |||
1230 | rates = kcalloc(IWL_RATE_COUNT_LEGACY, sizeof(struct ieee80211_rate), | ||
1231 | GFP_KERNEL); | ||
1232 | if (!rates) { | ||
1233 | kfree(channels); | ||
1234 | return -ENOMEM; | ||
1235 | } | ||
1236 | |||
1237 | /* 5.2GHz channels start after the 2.4GHz channels */ | ||
1238 | sband = &priv->bands[IEEE80211_BAND_5GHZ]; | ||
1239 | sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)]; | ||
1240 | /* just OFDM */ | ||
1241 | sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; | ||
1242 | sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE; | ||
1243 | |||
1244 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE) | ||
1245 | iwl_init_ht_hw_capab(priv, &sband->ht_cap, | ||
1246 | IEEE80211_BAND_5GHZ); | ||
1247 | |||
1248 | sband = &priv->bands[IEEE80211_BAND_2GHZ]; | ||
1249 | sband->channels = channels; | ||
1250 | /* OFDM & CCK */ | ||
1251 | sband->bitrates = rates; | ||
1252 | sband->n_bitrates = IWL_RATE_COUNT_LEGACY; | ||
1253 | |||
1254 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE) | ||
1255 | iwl_init_ht_hw_capab(priv, &sband->ht_cap, | ||
1256 | IEEE80211_BAND_2GHZ); | ||
1257 | |||
1258 | priv->ieee_channels = channels; | ||
1259 | priv->ieee_rates = rates; | ||
1260 | |||
1261 | for (i = 0; i < priv->channel_count; i++) { | ||
1262 | ch = &priv->channel_info[i]; | ||
1263 | |||
1264 | /* FIXME: might be removed if scan is OK */ | ||
1265 | if (!is_channel_valid(ch)) | ||
1266 | continue; | ||
1267 | |||
1268 | sband = &priv->bands[ch->band]; | ||
1269 | |||
1270 | geo_ch = &sband->channels[sband->n_channels++]; | ||
1271 | |||
1272 | geo_ch->center_freq = | ||
1273 | ieee80211_channel_to_frequency(ch->channel, ch->band); | ||
1274 | geo_ch->max_power = ch->max_power_avg; | ||
1275 | geo_ch->max_antenna_gain = 0xff; | ||
1276 | geo_ch->hw_value = ch->channel; | ||
1277 | |||
1278 | if (is_channel_valid(ch)) { | ||
1279 | if (!(ch->flags & EEPROM_CHANNEL_IBSS)) | ||
1280 | geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; | ||
1281 | |||
1282 | if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) | ||
1283 | geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; | ||
1284 | |||
1285 | if (ch->flags & EEPROM_CHANNEL_RADAR) | ||
1286 | geo_ch->flags |= IEEE80211_CHAN_RADAR; | ||
1287 | |||
1288 | geo_ch->flags |= ch->ht40_extension_channel; | ||
1289 | |||
1290 | if (ch->max_power_avg > max_tx_power) | ||
1291 | max_tx_power = ch->max_power_avg; | ||
1292 | } else { | ||
1293 | geo_ch->flags |= IEEE80211_CHAN_DISABLED; | ||
1294 | } | ||
1295 | |||
1296 | IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n", | ||
1297 | ch->channel, geo_ch->center_freq, | ||
1298 | is_channel_a_band(ch) ? "5.2" : "2.4", | ||
1299 | geo_ch->flags & IEEE80211_CHAN_DISABLED ? | ||
1300 | "restricted" : "valid", | ||
1301 | geo_ch->flags); | ||
1302 | } | ||
1303 | |||
1304 | priv->tx_power_device_lmt = max_tx_power; | ||
1305 | priv->tx_power_user_lmt = max_tx_power; | ||
1306 | priv->tx_power_next = max_tx_power; | ||
1307 | |||
1308 | if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && | ||
1309 | priv->hw_params.sku & EEPROM_SKU_CAP_BAND_52GHZ) { | ||
1310 | IWL_INFO(priv, "Incorrectly detected BG card as ABG. " | ||
1311 | "Please send your %s to maintainer.\n", | ||
1312 | priv->trans->hw_id_str); | ||
1313 | priv->hw_params.sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; | ||
1314 | } | ||
1315 | |||
1316 | if (iwlwifi_mod_params.disable_5ghz) | ||
1317 | priv->bands[IEEE80211_BAND_5GHZ].n_channels = 0; | ||
1318 | |||
1319 | IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n", | ||
1320 | priv->bands[IEEE80211_BAND_2GHZ].n_channels, | ||
1321 | priv->bands[IEEE80211_BAND_5GHZ].n_channels); | ||
1322 | |||
1323 | set_bit(STATUS_GEO_CONFIGURED, &priv->status); | ||
1324 | |||
1325 | return 0; | ||
1326 | } | ||
1327 | |||
1328 | /* | ||
1329 | * iwl_free_geos - undo allocations in iwl_init_geos | ||
1330 | */ | ||
1331 | static void iwl_free_geos(struct iwl_priv *priv) | ||
1332 | { | ||
1333 | kfree(priv->ieee_channels); | ||
1334 | kfree(priv->ieee_rates); | ||
1335 | clear_bit(STATUS_GEO_CONFIGURED, &priv->status); | ||
1336 | } | ||
1337 | |||
1338 | static int iwl_init_drv(struct iwl_priv *priv) | 1128 | static int iwl_init_drv(struct iwl_priv *priv) |
1339 | { | 1129 | { |
1340 | int ret; | ||
1341 | |||
1342 | spin_lock_init(&priv->sta_lock); | 1130 | spin_lock_init(&priv->sta_lock); |
1343 | 1131 | ||
1344 | mutex_init(&priv->mutex); | 1132 | mutex_init(&priv->mutex); |
1345 | 1133 | ||
1346 | INIT_LIST_HEAD(&priv->calib_results); | 1134 | INIT_LIST_HEAD(&priv->calib_results); |
1347 | 1135 | ||
1348 | priv->ieee_channels = NULL; | ||
1349 | priv->ieee_rates = NULL; | ||
1350 | priv->band = IEEE80211_BAND_2GHZ; | 1136 | priv->band = IEEE80211_BAND_2GHZ; |
1351 | 1137 | ||
1352 | priv->plcp_delta_threshold = | 1138 | priv->plcp_delta_threshold = |
@@ -1377,31 +1163,11 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
1377 | priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; | 1163 | priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; |
1378 | } | 1164 | } |
1379 | 1165 | ||
1380 | ret = iwl_init_channel_map(priv); | ||
1381 | if (ret) { | ||
1382 | IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); | ||
1383 | goto err; | ||
1384 | } | ||
1385 | |||
1386 | ret = iwl_init_geos(priv); | ||
1387 | if (ret) { | ||
1388 | IWL_ERR(priv, "initializing geos failed: %d\n", ret); | ||
1389 | goto err_free_channel_map; | ||
1390 | } | ||
1391 | iwl_init_hw_rates(priv->ieee_rates); | ||
1392 | |||
1393 | return 0; | 1166 | return 0; |
1394 | |||
1395 | err_free_channel_map: | ||
1396 | iwl_free_channel_map(priv); | ||
1397 | err: | ||
1398 | return ret; | ||
1399 | } | 1167 | } |
1400 | 1168 | ||
1401 | static void iwl_uninit_drv(struct iwl_priv *priv) | 1169 | static void iwl_uninit_drv(struct iwl_priv *priv) |
1402 | { | 1170 | { |
1403 | iwl_free_geos(priv); | ||
1404 | iwl_free_channel_map(priv); | ||
1405 | kfree(priv->scan_cmd); | 1171 | kfree(priv->scan_cmd); |
1406 | kfree(priv->beacon_cmd); | 1172 | kfree(priv->beacon_cmd); |
1407 | kfree(rcu_dereference_raw(priv->noa_data)); | 1173 | kfree(rcu_dereference_raw(priv->noa_data)); |
@@ -1460,6 +1226,42 @@ static void iwl_option_config(struct iwl_priv *priv) | |||
1460 | #endif | 1226 | #endif |
1461 | } | 1227 | } |
1462 | 1228 | ||
1229 | static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) | ||
1230 | { | ||
1231 | u16 radio_cfg; | ||
1232 | |||
1233 | priv->hw_params.sku = priv->eeprom_data->sku; | ||
1234 | |||
1235 | if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE && | ||
1236 | !priv->cfg->ht_params) { | ||
1237 | IWL_ERR(priv, "Invalid 11n configuration\n"); | ||
1238 | return -EINVAL; | ||
1239 | } | ||
1240 | |||
1241 | if (!priv->hw_params.sku) { | ||
1242 | IWL_ERR(priv, "Invalid device sku\n"); | ||
1243 | return -EINVAL; | ||
1244 | } | ||
1245 | |||
1246 | IWL_INFO(priv, "Device SKU: 0x%X\n", priv->hw_params.sku); | ||
1247 | |||
1248 | radio_cfg = priv->eeprom_data->radio_cfg; | ||
1249 | |||
1250 | priv->hw_params.tx_chains_num = | ||
1251 | num_of_ant(priv->eeprom_data->valid_tx_ant); | ||
1252 | if (priv->cfg->rx_with_siso_diversity) | ||
1253 | priv->hw_params.rx_chains_num = 1; | ||
1254 | else | ||
1255 | priv->hw_params.rx_chains_num = | ||
1256 | num_of_ant(priv->eeprom_data->valid_rx_ant); | ||
1257 | |||
1258 | IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n", | ||
1259 | priv->eeprom_data->valid_tx_ant, | ||
1260 | priv->eeprom_data->valid_rx_ant); | ||
1261 | |||
1262 | return 0; | ||
1263 | } | ||
1264 | |||
1463 | static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | 1265 | static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, |
1464 | const struct iwl_cfg *cfg, | 1266 | const struct iwl_cfg *cfg, |
1465 | const struct iwl_fw *fw) | 1267 | const struct iwl_fw *fw) |
@@ -1605,25 +1407,33 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1605 | goto out_free_hw; | 1407 | goto out_free_hw; |
1606 | 1408 | ||
1607 | /* Read the EEPROM */ | 1409 | /* Read the EEPROM */ |
1608 | if (iwl_eeprom_init(priv, priv->trans->hw_rev)) { | 1410 | if (iwl_read_eeprom(priv->trans, &priv->eeprom_blob, |
1411 | &priv->eeprom_blob_size)) { | ||
1609 | IWL_ERR(priv, "Unable to init EEPROM\n"); | 1412 | IWL_ERR(priv, "Unable to init EEPROM\n"); |
1610 | goto out_free_hw; | 1413 | goto out_free_hw; |
1611 | } | 1414 | } |
1415 | |||
1612 | /* Reset chip to save power until we load uCode during "up". */ | 1416 | /* Reset chip to save power until we load uCode during "up". */ |
1613 | iwl_trans_stop_hw(priv->trans, false); | 1417 | iwl_trans_stop_hw(priv->trans, false); |
1614 | 1418 | ||
1615 | if (iwl_eeprom_check_version(priv)) | 1419 | priv->eeprom_data = iwl_parse_eeprom_data(priv->trans->dev, priv->cfg, |
1420 | priv->eeprom_blob, | ||
1421 | priv->eeprom_blob_size); | ||
1422 | if (!priv->eeprom_data) | ||
1423 | goto out_free_eeprom_blob; | ||
1424 | |||
1425 | if (iwl_eeprom_check_version(priv->eeprom_data, priv->trans)) | ||
1616 | goto out_free_eeprom; | 1426 | goto out_free_eeprom; |
1617 | 1427 | ||
1618 | if (iwl_eeprom_init_hw_params(priv)) | 1428 | if (iwl_eeprom_init_hw_params(priv)) |
1619 | goto out_free_eeprom; | 1429 | goto out_free_eeprom; |
1620 | 1430 | ||
1621 | /* extract MAC Address */ | 1431 | /* extract MAC Address */ |
1622 | iwl_eeprom_get_mac(priv, priv->addresses[0].addr); | 1432 | memcpy(priv->addresses[0].addr, priv->eeprom_data->hw_addr, ETH_ALEN); |
1623 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr); | 1433 | IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr); |
1624 | priv->hw->wiphy->addresses = priv->addresses; | 1434 | priv->hw->wiphy->addresses = priv->addresses; |
1625 | priv->hw->wiphy->n_addresses = 1; | 1435 | priv->hw->wiphy->n_addresses = 1; |
1626 | num_mac = iwl_eeprom_query16(priv, EEPROM_NUM_MAC_ADDRESS); | 1436 | num_mac = priv->eeprom_data->n_hw_addrs; |
1627 | if (num_mac > 1) { | 1437 | if (num_mac > 1) { |
1628 | memcpy(priv->addresses[1].addr, priv->addresses[0].addr, | 1438 | memcpy(priv->addresses[1].addr, priv->addresses[0].addr, |
1629 | ETH_ALEN); | 1439 | ETH_ALEN); |
@@ -1717,8 +1527,10 @@ out_destroy_workqueue: | |||
1717 | destroy_workqueue(priv->workqueue); | 1527 | destroy_workqueue(priv->workqueue); |
1718 | priv->workqueue = NULL; | 1528 | priv->workqueue = NULL; |
1719 | iwl_uninit_drv(priv); | 1529 | iwl_uninit_drv(priv); |
1530 | out_free_eeprom_blob: | ||
1531 | kfree(priv->eeprom_blob); | ||
1720 | out_free_eeprom: | 1532 | out_free_eeprom: |
1721 | iwl_eeprom_free(priv); | 1533 | iwl_free_eeprom_data(priv->eeprom_data); |
1722 | out_free_hw: | 1534 | out_free_hw: |
1723 | ieee80211_free_hw(priv->hw); | 1535 | ieee80211_free_hw(priv->hw); |
1724 | out: | 1536 | out: |
@@ -1743,7 +1555,8 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) | |||
1743 | priv->ucode_loaded = false; | 1555 | priv->ucode_loaded = false; |
1744 | iwl_trans_stop_device(priv->trans); | 1556 | iwl_trans_stop_device(priv->trans); |
1745 | 1557 | ||
1746 | iwl_eeprom_free(priv); | 1558 | kfree(priv->eeprom_blob); |
1559 | iwl_free_eeprom_data(priv->eeprom_data); | ||
1747 | 1560 | ||
1748 | /*netif_stop_queue(dev); */ | 1561 | /*netif_stop_queue(dev); */ |
1749 | flush_workqueue(priv->workqueue); | 1562 | flush_workqueue(priv->workqueue); |
diff --git a/drivers/net/wireless/iwlwifi/dvm/power.c b/drivers/net/wireless/iwlwifi/dvm/power.c index 72c940759ac7..518cf3715809 100644 --- a/drivers/net/wireless/iwlwifi/dvm/power.c +++ b/drivers/net/wireless/iwlwifi/dvm/power.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include "iwl-debug.h" | 36 | #include "iwl-debug.h" |
37 | #include "iwl-trans.h" | 37 | #include "iwl-trans.h" |
38 | #include "iwl-modparams.h" | 38 | #include "iwl-modparams.h" |
39 | #include "eeprom.h" | ||
40 | #include "dev.h" | 39 | #include "dev.h" |
41 | #include "agn.h" | 40 | #include "agn.h" |
42 | #include "commands.h" | 41 | #include "commands.h" |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c index af102910e689..6fddd2785e6e 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/iwlwifi/dvm/rs.c | |||
@@ -817,7 +817,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, | |||
817 | 817 | ||
818 | if (num_of_ant(tbl->ant_type) > 1) | 818 | if (num_of_ant(tbl->ant_type) > 1) |
819 | tbl->ant_type = | 819 | tbl->ant_type = |
820 | first_antenna(priv->hw_params.valid_tx_ant); | 820 | first_antenna(priv->eeprom_data->valid_tx_ant); |
821 | 821 | ||
822 | tbl->is_ht40 = 0; | 822 | tbl->is_ht40 = 0; |
823 | tbl->is_SGI = 0; | 823 | tbl->is_SGI = 0; |
@@ -1445,7 +1445,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1445 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1445 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1446 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1446 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1447 | u8 start_action; | 1447 | u8 start_action; |
1448 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1448 | u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
1449 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1449 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1450 | int ret = 0; | 1450 | int ret = 0; |
1451 | u8 update_search_tbl_counter = 0; | 1451 | u8 update_search_tbl_counter = 0; |
@@ -1463,7 +1463,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1463 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | 1463 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: |
1464 | /* avoid antenna B and MIMO */ | 1464 | /* avoid antenna B and MIMO */ |
1465 | valid_tx_ant = | 1465 | valid_tx_ant = |
1466 | first_antenna(priv->hw_params.valid_tx_ant); | 1466 | first_antenna(priv->eeprom_data->valid_tx_ant); |
1467 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && | 1467 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && |
1468 | tbl->action != IWL_LEGACY_SWITCH_SISO) | 1468 | tbl->action != IWL_LEGACY_SWITCH_SISO) |
1469 | tbl->action = IWL_LEGACY_SWITCH_SISO; | 1469 | tbl->action = IWL_LEGACY_SWITCH_SISO; |
@@ -1487,7 +1487,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1487 | else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) | 1487 | else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) |
1488 | tbl->action = IWL_LEGACY_SWITCH_SISO; | 1488 | tbl->action = IWL_LEGACY_SWITCH_SISO; |
1489 | valid_tx_ant = | 1489 | valid_tx_ant = |
1490 | first_antenna(priv->hw_params.valid_tx_ant); | 1490 | first_antenna(priv->eeprom_data->valid_tx_ant); |
1491 | } | 1491 | } |
1492 | 1492 | ||
1493 | start_action = tbl->action; | 1493 | start_action = tbl->action; |
@@ -1621,7 +1621,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1621 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1621 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1622 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1622 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1623 | u8 start_action; | 1623 | u8 start_action; |
1624 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1624 | u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
1625 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1625 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1626 | u8 update_search_tbl_counter = 0; | 1626 | u8 update_search_tbl_counter = 0; |
1627 | int ret; | 1627 | int ret; |
@@ -1639,7 +1639,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1639 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | 1639 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: |
1640 | /* avoid antenna B and MIMO */ | 1640 | /* avoid antenna B and MIMO */ |
1641 | valid_tx_ant = | 1641 | valid_tx_ant = |
1642 | first_antenna(priv->hw_params.valid_tx_ant); | 1642 | first_antenna(priv->eeprom_data->valid_tx_ant); |
1643 | if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) | 1643 | if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) |
1644 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1644 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
1645 | break; | 1645 | break; |
@@ -1657,7 +1657,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1657 | /* configure as 1x1 if bt full concurrency */ | 1657 | /* configure as 1x1 if bt full concurrency */ |
1658 | if (priv->bt_full_concurrent) { | 1658 | if (priv->bt_full_concurrent) { |
1659 | valid_tx_ant = | 1659 | valid_tx_ant = |
1660 | first_antenna(priv->hw_params.valid_tx_ant); | 1660 | first_antenna(priv->eeprom_data->valid_tx_ant); |
1661 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) | 1661 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) |
1662 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1662 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
1663 | } | 1663 | } |
@@ -1793,7 +1793,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | |||
1793 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1793 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1794 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1794 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1795 | u8 start_action; | 1795 | u8 start_action; |
1796 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1796 | u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
1797 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1797 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1798 | u8 update_search_tbl_counter = 0; | 1798 | u8 update_search_tbl_counter = 0; |
1799 | int ret; | 1799 | int ret; |
@@ -1963,7 +1963,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | |||
1963 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1963 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1964 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1964 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1965 | u8 start_action; | 1965 | u8 start_action; |
1966 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1966 | u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
1967 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1967 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1968 | int ret; | 1968 | int ret; |
1969 | u8 update_search_tbl_counter = 0; | 1969 | u8 update_search_tbl_counter = 0; |
@@ -2697,7 +2697,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2697 | 2697 | ||
2698 | i = lq_sta->last_txrate_idx; | 2698 | i = lq_sta->last_txrate_idx; |
2699 | 2699 | ||
2700 | valid_tx_ant = priv->hw_params.valid_tx_ant; | 2700 | valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
2701 | 2701 | ||
2702 | if (!lq_sta->search_better_tbl) | 2702 | if (!lq_sta->search_better_tbl) |
2703 | active_tbl = lq_sta->active_tbl; | 2703 | active_tbl = lq_sta->active_tbl; |
@@ -2891,15 +2891,15 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i | |||
2891 | 2891 | ||
2892 | /* These values will be overridden later */ | 2892 | /* These values will be overridden later */ |
2893 | lq_sta->lq.general_params.single_stream_ant_msk = | 2893 | lq_sta->lq.general_params.single_stream_ant_msk = |
2894 | first_antenna(priv->hw_params.valid_tx_ant); | 2894 | first_antenna(priv->eeprom_data->valid_tx_ant); |
2895 | lq_sta->lq.general_params.dual_stream_ant_msk = | 2895 | lq_sta->lq.general_params.dual_stream_ant_msk = |
2896 | priv->hw_params.valid_tx_ant & | 2896 | priv->eeprom_data->valid_tx_ant & |
2897 | ~first_antenna(priv->hw_params.valid_tx_ant); | 2897 | ~first_antenna(priv->eeprom_data->valid_tx_ant); |
2898 | if (!lq_sta->lq.general_params.dual_stream_ant_msk) { | 2898 | if (!lq_sta->lq.general_params.dual_stream_ant_msk) { |
2899 | lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; | 2899 | lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; |
2900 | } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { | 2900 | } else if (num_of_ant(priv->eeprom_data->valid_tx_ant) == 2) { |
2901 | lq_sta->lq.general_params.dual_stream_ant_msk = | 2901 | lq_sta->lq.general_params.dual_stream_ant_msk = |
2902 | priv->hw_params.valid_tx_ant; | 2902 | priv->eeprom_data->valid_tx_ant; |
2903 | } | 2903 | } |
2904 | 2904 | ||
2905 | /* as default allow aggregation for all tids */ | 2905 | /* as default allow aggregation for all tids */ |
@@ -2945,7 +2945,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2945 | if (priv && priv->bt_full_concurrent) { | 2945 | if (priv && priv->bt_full_concurrent) { |
2946 | /* 1x1 only */ | 2946 | /* 1x1 only */ |
2947 | tbl_type.ant_type = | 2947 | tbl_type.ant_type = |
2948 | first_antenna(priv->hw_params.valid_tx_ant); | 2948 | first_antenna(priv->eeprom_data->valid_tx_ant); |
2949 | } | 2949 | } |
2950 | 2950 | ||
2951 | /* How many times should we repeat the initial rate? */ | 2951 | /* How many times should we repeat the initial rate? */ |
@@ -2977,7 +2977,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2977 | if (priv->bt_full_concurrent) | 2977 | if (priv->bt_full_concurrent) |
2978 | valid_tx_ant = ANT_A; | 2978 | valid_tx_ant = ANT_A; |
2979 | else | 2979 | else |
2980 | valid_tx_ant = priv->hw_params.valid_tx_ant; | 2980 | valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
2981 | } | 2981 | } |
2982 | 2982 | ||
2983 | /* Fill rest of rate table */ | 2983 | /* Fill rest of rate table */ |
@@ -3011,7 +3011,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
3011 | if (priv && priv->bt_full_concurrent) { | 3011 | if (priv && priv->bt_full_concurrent) { |
3012 | /* 1x1 only */ | 3012 | /* 1x1 only */ |
3013 | tbl_type.ant_type = | 3013 | tbl_type.ant_type = |
3014 | first_antenna(priv->hw_params.valid_tx_ant); | 3014 | first_antenna(priv->eeprom_data->valid_tx_ant); |
3015 | } | 3015 | } |
3016 | 3016 | ||
3017 | /* Indicate to uCode which entries might be MIMO. | 3017 | /* Indicate to uCode which entries might be MIMO. |
@@ -3098,7 +3098,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | |||
3098 | u8 ant_sel_tx; | 3098 | u8 ant_sel_tx; |
3099 | 3099 | ||
3100 | priv = lq_sta->drv; | 3100 | priv = lq_sta->drv; |
3101 | valid_tx_ant = priv->hw_params.valid_tx_ant; | 3101 | valid_tx_ant = priv->eeprom_data->valid_tx_ant; |
3102 | if (lq_sta->dbg_fixed_rate) { | 3102 | if (lq_sta->dbg_fixed_rate) { |
3103 | ant_sel_tx = | 3103 | ant_sel_tx = |
3104 | ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) | 3104 | ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) |
@@ -3169,9 +3169,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
3169 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", | 3169 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", |
3170 | lq_sta->dbg_fixed_rate); | 3170 | lq_sta->dbg_fixed_rate); |
3171 | desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", | 3171 | desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", |
3172 | (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "", | 3172 | (priv->eeprom_data->valid_tx_ant & ANT_A) ? "ANT_A," : "", |
3173 | (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", | 3173 | (priv->eeprom_data->valid_tx_ant & ANT_B) ? "ANT_B," : "", |
3174 | (priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : ""); | 3174 | (priv->eeprom_data->valid_tx_ant & ANT_C) ? "ANT_C" : ""); |
3175 | desc += sprintf(buff+desc, "lq type %s\n", | 3175 | desc += sprintf(buff+desc, "lq type %s\n", |
3176 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); | 3176 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); |
3177 | if (is_Ht(tbl->lq_type)) { | 3177 | if (is_Ht(tbl->lq_type)) { |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c index d61980248408..0ed90bb8b56a 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/iwlwifi/dvm/rx.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <net/mac80211.h> | 33 | #include <net/mac80211.h> |
34 | #include <asm/unaligned.h> | 34 | #include <asm/unaligned.h> |
35 | #include "iwl-io.h" | 35 | #include "iwl-io.h" |
36 | #include "eeprom.h" | ||
37 | #include "dev.h" | 36 | #include "dev.h" |
38 | #include "calib.h" | 37 | #include "calib.h" |
39 | #include "agn.h" | 38 | #include "agn.h" |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c index 4f55689ac6a7..6ee940f497f9 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rxon.c +++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c | |||
@@ -420,10 +420,10 @@ static int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | |||
420 | return -EINVAL; | 420 | return -EINVAL; |
421 | } | 421 | } |
422 | 422 | ||
423 | if (tx_power > priv->tx_power_device_lmt) { | 423 | if (tx_power > DIV_ROUND_UP(priv->eeprom_data->max_tx_pwr_half_dbm, 2)) { |
424 | IWL_WARN(priv, | 424 | IWL_WARN(priv, |
425 | "Requested user TXPOWER %d above upper limit %d.\n", | 425 | "Requested user TXPOWER %d above upper limit %d.\n", |
426 | tx_power, priv->tx_power_device_lmt); | 426 | tx_power, priv->eeprom_data->max_tx_pwr_half_dbm); |
427 | return -EINVAL; | 427 | return -EINVAL; |
428 | } | 428 | } |
429 | 429 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c index 7ee7f32b0fab..2f271c96ed39 100644 --- a/drivers/net/wireless/iwlwifi/dvm/scan.c +++ b/drivers/net/wireless/iwlwifi/dvm/scan.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/etherdevice.h> | 30 | #include <linux/etherdevice.h> |
31 | #include <net/mac80211.h> | 31 | #include <net/mac80211.h> |
32 | 32 | ||
33 | #include "eeprom.h" | ||
34 | #include "dev.h" | 33 | #include "dev.h" |
35 | #include "agn.h" | 34 | #include "agn.h" |
36 | 35 | ||
@@ -65,7 +64,6 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) | |||
65 | * to receive scan abort command or it does not perform | 64 | * to receive scan abort command or it does not perform |
66 | * hardware scan currently */ | 65 | * hardware scan currently */ |
67 | if (!test_bit(STATUS_READY, &priv->status) || | 66 | if (!test_bit(STATUS_READY, &priv->status) || |
68 | !test_bit(STATUS_GEO_CONFIGURED, &priv->status) || | ||
69 | !test_bit(STATUS_SCAN_HW, &priv->status) || | 67 | !test_bit(STATUS_SCAN_HW, &priv->status) || |
70 | test_bit(STATUS_FW_ERROR, &priv->status)) | 68 | test_bit(STATUS_FW_ERROR, &priv->status)) |
71 | return -EIO; | 69 | return -EIO; |
@@ -648,12 +646,12 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
648 | u16 rx_chain = 0; | 646 | u16 rx_chain = 0; |
649 | enum ieee80211_band band; | 647 | enum ieee80211_band band; |
650 | u8 n_probes = 0; | 648 | u8 n_probes = 0; |
651 | u8 rx_ant = priv->hw_params.valid_rx_ant; | 649 | u8 rx_ant = priv->eeprom_data->valid_rx_ant; |
652 | u8 rate; | 650 | u8 rate; |
653 | bool is_active = false; | 651 | bool is_active = false; |
654 | int chan_mod; | 652 | int chan_mod; |
655 | u8 active_chains; | 653 | u8 active_chains; |
656 | u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; | 654 | u8 scan_tx_antennas = priv->eeprom_data->valid_tx_ant; |
657 | int ret; | 655 | int ret; |
658 | int scan_cmd_size = sizeof(struct iwl_scan_cmd) + | 656 | int scan_cmd_size = sizeof(struct iwl_scan_cmd) + |
659 | MAX_SCAN_CHANNEL * sizeof(struct iwl_scan_channel) + | 657 | MAX_SCAN_CHANNEL * sizeof(struct iwl_scan_channel) + |
@@ -863,7 +861,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
863 | 861 | ||
864 | /* MIMO is not used here, but value is required */ | 862 | /* MIMO is not used here, but value is required */ |
865 | rx_chain |= | 863 | rx_chain |= |
866 | priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; | 864 | priv->eeprom_data->valid_rx_ant << RXON_RX_CHAIN_VALID_POS; |
867 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | 865 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; |
868 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; | 866 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; |
869 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; | 867 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; |
@@ -980,7 +978,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
980 | 978 | ||
981 | void iwl_init_scan_params(struct iwl_priv *priv) | 979 | void iwl_init_scan_params(struct iwl_priv *priv) |
982 | { | 980 | { |
983 | u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1; | 981 | u8 ant_idx = fls(priv->eeprom_data->valid_tx_ant) - 1; |
984 | if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) | 982 | if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) |
985 | priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; | 983 | priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; |
986 | if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) | 984 | if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) |
diff --git a/drivers/net/wireless/iwlwifi/dvm/sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c index c6b343fdf5f9..286ce4e18068 100644 --- a/drivers/net/wireless/iwlwifi/dvm/sta.c +++ b/drivers/net/wireless/iwlwifi/dvm/sta.c | |||
@@ -177,17 +177,23 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | |||
177 | if (!ctx->ht.enabled || !ctx->ht.is_40mhz) | 177 | if (!ctx->ht.enabled || !ctx->ht.is_40mhz) |
178 | return false; | 178 | return false; |
179 | 179 | ||
180 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
181 | if (priv->disable_ht40) | ||
182 | return false; | ||
183 | #endif | ||
184 | |||
180 | /* | 185 | /* |
181 | * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 186 | * Remainder of this function checks ht_cap, but if it's |
182 | * the bit will not set if it is pure 40MHz case | 187 | * NULL then we can do HT40 (special case for RXON) |
183 | */ | 188 | */ |
184 | if (ht_cap && !ht_cap->ht_supported) | 189 | if (!ht_cap) |
190 | return true; | ||
191 | |||
192 | if (!ht_cap->ht_supported) | ||
185 | return false; | 193 | return false; |
186 | 194 | ||
187 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 195 | if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) |
188 | if (priv->disable_ht40) | ||
189 | return false; | 196 | return false; |
190 | #endif | ||
191 | 197 | ||
192 | return true; | 198 | return true; |
193 | } | 199 | } |
@@ -627,23 +633,23 @@ static void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | |||
627 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) | 633 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) |
628 | rate_flags |= RATE_MCS_CCK_MSK; | 634 | rate_flags |= RATE_MCS_CCK_MSK; |
629 | 635 | ||
630 | rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << | 636 | rate_flags |= first_antenna(priv->eeprom_data->valid_tx_ant) << |
631 | RATE_MCS_ANT_POS; | 637 | RATE_MCS_ANT_POS; |
632 | rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | 638 | rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); |
633 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) | 639 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) |
634 | link_cmd->rs_table[i].rate_n_flags = rate_n_flags; | 640 | link_cmd->rs_table[i].rate_n_flags = rate_n_flags; |
635 | 641 | ||
636 | link_cmd->general_params.single_stream_ant_msk = | 642 | link_cmd->general_params.single_stream_ant_msk = |
637 | first_antenna(priv->hw_params.valid_tx_ant); | 643 | first_antenna(priv->eeprom_data->valid_tx_ant); |
638 | 644 | ||
639 | link_cmd->general_params.dual_stream_ant_msk = | 645 | link_cmd->general_params.dual_stream_ant_msk = |
640 | priv->hw_params.valid_tx_ant & | 646 | priv->eeprom_data->valid_tx_ant & |
641 | ~first_antenna(priv->hw_params.valid_tx_ant); | 647 | ~first_antenna(priv->eeprom_data->valid_tx_ant); |
642 | if (!link_cmd->general_params.dual_stream_ant_msk) { | 648 | if (!link_cmd->general_params.dual_stream_ant_msk) { |
643 | link_cmd->general_params.dual_stream_ant_msk = ANT_AB; | 649 | link_cmd->general_params.dual_stream_ant_msk = ANT_AB; |
644 | } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { | 650 | } else if (num_of_ant(priv->eeprom_data->valid_tx_ant) == 2) { |
645 | link_cmd->general_params.dual_stream_ant_msk = | 651 | link_cmd->general_params.dual_stream_ant_msk = |
646 | priv->hw_params.valid_tx_ant; | 652 | priv->eeprom_data->valid_tx_ant; |
647 | } | 653 | } |
648 | 654 | ||
649 | link_cmd->agg_params.agg_dis_start_th = | 655 | link_cmd->agg_params.agg_dis_start_th = |
diff --git a/drivers/net/wireless/iwlwifi/dvm/testmode.c b/drivers/net/wireless/iwlwifi/dvm/testmode.c index 59cfe9a8eea5..a7b59590bb53 100644 --- a/drivers/net/wireless/iwlwifi/dvm/testmode.c +++ b/drivers/net/wireless/iwlwifi/dvm/testmode.c | |||
@@ -534,9 +534,9 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | |||
534 | break; | 534 | break; |
535 | 535 | ||
536 | case IWL_TM_CMD_APP2DEV_GET_EEPROM: | 536 | case IWL_TM_CMD_APP2DEV_GET_EEPROM: |
537 | if (priv->eeprom) { | 537 | if (priv->eeprom_blob) { |
538 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, | 538 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, |
539 | priv->cfg->base_params->eeprom_size + 20); | 539 | priv->eeprom_blob_size + 20); |
540 | if (!skb) { | 540 | if (!skb) { |
541 | IWL_ERR(priv, "Memory allocation fail\n"); | 541 | IWL_ERR(priv, "Memory allocation fail\n"); |
542 | return -ENOMEM; | 542 | return -ENOMEM; |
@@ -544,15 +544,15 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | |||
544 | if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, | 544 | if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, |
545 | IWL_TM_CMD_DEV2APP_EEPROM_RSP) || | 545 | IWL_TM_CMD_DEV2APP_EEPROM_RSP) || |
546 | nla_put(skb, IWL_TM_ATTR_EEPROM, | 546 | nla_put(skb, IWL_TM_ATTR_EEPROM, |
547 | priv->cfg->base_params->eeprom_size, | 547 | priv->eeprom_blob_size, |
548 | priv->eeprom)) | 548 | priv->eeprom_blob)) |
549 | goto nla_put_failure; | 549 | goto nla_put_failure; |
550 | status = cfg80211_testmode_reply(skb); | 550 | status = cfg80211_testmode_reply(skb); |
551 | if (status < 0) | 551 | if (status < 0) |
552 | IWL_ERR(priv, "Error sending msg : %d\n", | 552 | IWL_ERR(priv, "Error sending msg : %d\n", |
553 | status); | 553 | status); |
554 | } else | 554 | } else |
555 | return -EFAULT; | 555 | return -ENODATA; |
556 | break; | 556 | break; |
557 | 557 | ||
558 | case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: | 558 | case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tt.c b/drivers/net/wireless/iwlwifi/dvm/tt.c index 55418899bc4e..eb864433e59d 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tt.c +++ b/drivers/net/wireless/iwlwifi/dvm/tt.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include "iwl-modparams.h" | 36 | #include "iwl-modparams.h" |
37 | #include "iwl-debug.h" | 37 | #include "iwl-debug.h" |
38 | #include "agn.h" | 38 | #include "agn.h" |
39 | #include "eeprom.h" | ||
40 | #include "dev.h" | 39 | #include "dev.h" |
41 | #include "commands.h" | 40 | #include "commands.h" |
42 | #include "tt.h" | 41 | #include "tt.h" |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index 7e3bd6281551..0dfaf649b257 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -186,7 +186,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
186 | rate_idx = info->control.rates[0].idx; | 186 | rate_idx = info->control.rates[0].idx; |
187 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || | 187 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || |
188 | (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) | 188 | (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) |
189 | rate_idx = rate_lowest_index(&priv->bands[info->band], | 189 | rate_idx = rate_lowest_index( |
190 | &priv->eeprom_data->bands[info->band], | ||
190 | info->control.sta); | 191 | info->control.sta); |
191 | /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ | 192 | /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ |
192 | if (info->band == IEEE80211_BAND_5GHZ) | 193 | if (info->band == IEEE80211_BAND_5GHZ) |
@@ -206,10 +207,11 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
206 | priv->bt_full_concurrent) { | 207 | priv->bt_full_concurrent) { |
207 | /* operated as 1x1 in full concurrency mode */ | 208 | /* operated as 1x1 in full concurrency mode */ |
208 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 209 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
209 | first_antenna(priv->hw_params.valid_tx_ant)); | 210 | first_antenna(priv->eeprom_data->valid_tx_ant)); |
210 | } else | 211 | } else |
211 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 212 | priv->mgmt_tx_ant = iwl_toggle_tx_ant( |
212 | priv->hw_params.valid_tx_ant); | 213 | priv, priv->mgmt_tx_ant, |
214 | priv->eeprom_data->valid_tx_ant); | ||
213 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 215 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); |
214 | 216 | ||
215 | /* Set the rate in the TX cmd */ | 217 | /* Set the rate in the TX cmd */ |
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index 5a2e186c7ded..b3a314ba48c7 100644 --- a/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
@@ -61,8 +61,7 @@ iwl_get_ucode_image(struct iwl_priv *priv, enum iwl_ucode_type ucode_type) | |||
61 | static int iwl_set_Xtal_calib(struct iwl_priv *priv) | 61 | static int iwl_set_Xtal_calib(struct iwl_priv *priv) |
62 | { | 62 | { |
63 | struct iwl_calib_xtal_freq_cmd cmd; | 63 | struct iwl_calib_xtal_freq_cmd cmd; |
64 | __le16 *xtal_calib = | 64 | __le16 *xtal_calib = priv->eeprom_data->xtal_calib; |
65 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL); | ||
66 | 65 | ||
67 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); | 66 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); |
68 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); | 67 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); |
@@ -73,12 +72,10 @@ static int iwl_set_Xtal_calib(struct iwl_priv *priv) | |||
73 | static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) | 72 | static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) |
74 | { | 73 | { |
75 | struct iwl_calib_temperature_offset_cmd cmd; | 74 | struct iwl_calib_temperature_offset_cmd cmd; |
76 | __le16 *offset_calib = | ||
77 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); | ||
78 | 75 | ||
79 | memset(&cmd, 0, sizeof(cmd)); | 76 | memset(&cmd, 0, sizeof(cmd)); |
80 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); | 77 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); |
81 | memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(*offset_calib)); | 78 | cmd.radio_sensor_offset = priv->eeprom_data->raw_temperature; |
82 | if (!(cmd.radio_sensor_offset)) | 79 | if (!(cmd.radio_sensor_offset)) |
83 | cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; | 80 | cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; |
84 | 81 | ||
@@ -90,27 +87,17 @@ static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) | |||
90 | static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) | 87 | static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) |
91 | { | 88 | { |
92 | struct iwl_calib_temperature_offset_v2_cmd cmd; | 89 | struct iwl_calib_temperature_offset_v2_cmd cmd; |
93 | __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv, | ||
94 | EEPROM_KELVIN_TEMPERATURE); | ||
95 | __le16 *offset_calib_low = | ||
96 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); | ||
97 | struct iwl_eeprom_calib_hdr *hdr; | ||
98 | 90 | ||
99 | memset(&cmd, 0, sizeof(cmd)); | 91 | memset(&cmd, 0, sizeof(cmd)); |
100 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); | 92 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); |
101 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | 93 | cmd.radio_sensor_offset_high = priv->eeprom_data->kelvin_temperature; |
102 | EEPROM_CALIB_ALL); | 94 | cmd.radio_sensor_offset_low = priv->eeprom_data->raw_temperature; |
103 | memcpy(&cmd.radio_sensor_offset_high, offset_calib_high, | 95 | if (!cmd.radio_sensor_offset_low) { |
104 | sizeof(*offset_calib_high)); | ||
105 | memcpy(&cmd.radio_sensor_offset_low, offset_calib_low, | ||
106 | sizeof(*offset_calib_low)); | ||
107 | if (!(cmd.radio_sensor_offset_low)) { | ||
108 | IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n"); | 96 | IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n"); |
109 | cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET; | 97 | cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET; |
110 | cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET; | 98 | cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET; |
111 | } | 99 | } |
112 | memcpy(&cmd.burntVoltageRef, &hdr->voltage, | 100 | cmd.burntVoltageRef = priv->eeprom_data->calib_voltage; |
113 | sizeof(hdr->voltage)); | ||
114 | 101 | ||
115 | IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n", | 102 | IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n", |
116 | le16_to_cpu(cmd.radio_sensor_offset_high)); | 103 | le16_to_cpu(cmd.radio_sensor_offset_high)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index af3a46126f01..e9accfccc050 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
@@ -194,6 +194,24 @@ struct iwl_ht_params { | |||
194 | u8 ht40_bands; | 194 | u8 ht40_bands; |
195 | }; | 195 | }; |
196 | 196 | ||
197 | /* | ||
198 | * information on how to parse the EEPROM | ||
199 | */ | ||
200 | #define EEPROM_REG_BAND_1_CHANNELS 0x08 | ||
201 | #define EEPROM_REG_BAND_2_CHANNELS 0x26 | ||
202 | #define EEPROM_REG_BAND_3_CHANNELS 0x42 | ||
203 | #define EEPROM_REG_BAND_4_CHANNELS 0x5C | ||
204 | #define EEPROM_REG_BAND_5_CHANNELS 0x74 | ||
205 | #define EEPROM_REG_BAND_24_HT40_CHANNELS 0x82 | ||
206 | #define EEPROM_REG_BAND_52_HT40_CHANNELS 0x92 | ||
207 | #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS 0x80 | ||
208 | #define EEPROM_REGULATORY_BAND_NO_HT40 0 | ||
209 | |||
210 | struct iwl_eeprom_params { | ||
211 | const u8 regulatory_bands[7]; | ||
212 | bool enhanced_txpower; | ||
213 | }; | ||
214 | |||
197 | /** | 215 | /** |
198 | * struct iwl_cfg | 216 | * struct iwl_cfg |
199 | * @name: Offical name of the device | 217 | * @name: Offical name of the device |
@@ -246,6 +264,7 @@ struct iwl_cfg { | |||
246 | /* params likely to change within a device family */ | 264 | /* params likely to change within a device family */ |
247 | const struct iwl_ht_params *ht_params; | 265 | const struct iwl_ht_params *ht_params; |
248 | const struct iwl_bt_params *bt_params; | 266 | const struct iwl_bt_params *bt_params; |
267 | const struct iwl_eeprom_params *eeprom_params; | ||
249 | const bool need_temp_offset_calib; /* if used set to true */ | 268 | const bool need_temp_offset_calib; /* if used set to true */ |
250 | const bool no_xtal_calib; | 269 | const bool no_xtal_calib; |
251 | enum iwl_led_mode led_mode; | 270 | enum iwl_led_mode led_mode; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index f6bf91c8f773..42b20b0e83bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -45,6 +45,7 @@ void __iwl_crit(struct device *dev, const char *fmt, ...) __printf(2, 3); | |||
45 | 45 | ||
46 | /* No matter what is m (priv, bus, trans), this will work */ | 46 | /* No matter what is m (priv, bus, trans), this will work */ |
47 | #define IWL_ERR(m, f, a...) __iwl_err((m)->dev, false, false, f, ## a) | 47 | #define IWL_ERR(m, f, a...) __iwl_err((m)->dev, false, false, f, ## a) |
48 | #define IWL_ERR_DEV(d, f, a...) __iwl_err((d), false, false, f, ## a) | ||
48 | #define IWL_WARN(m, f, a...) __iwl_warn((m)->dev, f, ## a) | 49 | #define IWL_WARN(m, f, a...) __iwl_warn((m)->dev, f, ## a) |
49 | #define IWL_INFO(m, f, a...) __iwl_info((m)->dev, f, ## a) | 50 | #define IWL_INFO(m, f, a...) __iwl_info((m)->dev, f, ## a) |
50 | #define IWL_CRIT(m, f, a...) __iwl_crit((m)->dev, f, ## a) | 51 | #define IWL_CRIT(m, f, a...) __iwl_crit((m)->dev, f, ## a) |
@@ -69,6 +70,8 @@ do { \ | |||
69 | 70 | ||
70 | #define IWL_DEBUG(m, level, fmt, args...) \ | 71 | #define IWL_DEBUG(m, level, fmt, args...) \ |
71 | __iwl_dbg((m)->dev, level, false, __func__, fmt, ##args) | 72 | __iwl_dbg((m)->dev, level, false, __func__, fmt, ##args) |
73 | #define IWL_DEBUG_DEV(dev, level, fmt, args...) \ | ||
74 | __iwl_dbg((dev), level, false, __func__, fmt, ##args) | ||
72 | #define IWL_DEBUG_LIMIT(m, level, fmt, args...) \ | 75 | #define IWL_DEBUG_LIMIT(m, level, fmt, args...) \ |
73 | __iwl_dbg((m)->dev, level, true, __func__, fmt, ##args) | 76 | __iwl_dbg((m)->dev, level, true, __func__, fmt, ##args) |
74 | 77 | ||
@@ -153,7 +156,7 @@ do { \ | |||
153 | #define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a) | 156 | #define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a) |
154 | #define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a) | 157 | #define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a) |
155 | #define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a) | 158 | #define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a) |
156 | #define IWL_DEBUG_EEPROM(p, f, a...) IWL_DEBUG(p, IWL_DL_EEPROM, f, ## a) | 159 | #define IWL_DEBUG_EEPROM(d, f, a...) IWL_DEBUG_DEV(d, IWL_DL_EEPROM, f, ## a) |
157 | #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) | 160 | #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) |
158 | #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) | 161 | #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) |
159 | #define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) | 162 | #define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c new file mode 100644 index 000000000000..c87a05cbec12 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c | |||
@@ -0,0 +1,900 @@ | |||
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 - 2012 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 - 2012 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 | #include <linux/types.h> | ||
63 | #include <linux/slab.h> | ||
64 | #include <linux/export.h> | ||
65 | #include "iwl-modparams.h" | ||
66 | #include "iwl-eeprom-parse.h" | ||
67 | |||
68 | /* EEPROM offset definitions */ | ||
69 | |||
70 | /* indirect access definitions */ | ||
71 | #define ADDRESS_MSK 0x0000FFFF | ||
72 | #define INDIRECT_TYPE_MSK 0x000F0000 | ||
73 | #define INDIRECT_HOST 0x00010000 | ||
74 | #define INDIRECT_GENERAL 0x00020000 | ||
75 | #define INDIRECT_REGULATORY 0x00030000 | ||
76 | #define INDIRECT_CALIBRATION 0x00040000 | ||
77 | #define INDIRECT_PROCESS_ADJST 0x00050000 | ||
78 | #define INDIRECT_OTHERS 0x00060000 | ||
79 | #define INDIRECT_TXP_LIMIT 0x00070000 | ||
80 | #define INDIRECT_TXP_LIMIT_SIZE 0x00080000 | ||
81 | #define INDIRECT_ADDRESS 0x00100000 | ||
82 | |||
83 | /* corresponding link offsets in EEPROM */ | ||
84 | #define EEPROM_LINK_HOST (2*0x64) | ||
85 | #define EEPROM_LINK_GENERAL (2*0x65) | ||
86 | #define EEPROM_LINK_REGULATORY (2*0x66) | ||
87 | #define EEPROM_LINK_CALIBRATION (2*0x67) | ||
88 | #define EEPROM_LINK_PROCESS_ADJST (2*0x68) | ||
89 | #define EEPROM_LINK_OTHERS (2*0x69) | ||
90 | #define EEPROM_LINK_TXP_LIMIT (2*0x6a) | ||
91 | #define EEPROM_LINK_TXP_LIMIT_SIZE (2*0x6b) | ||
92 | |||
93 | /* General */ | ||
94 | #define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */ | ||
95 | #define EEPROM_SUBSYSTEM_ID (2*0x0A) /* 2 bytes */ | ||
96 | #define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */ | ||
97 | #define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */ | ||
98 | #define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ | ||
99 | #define EEPROM_VERSION (2*0x44) /* 2 bytes */ | ||
100 | #define EEPROM_SKU_CAP (2*0x45) /* 2 bytes */ | ||
101 | #define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ | ||
102 | #define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */ | ||
103 | #define EEPROM_NUM_MAC_ADDRESS (2*0x4C) /* 2 bytes */ | ||
104 | |||
105 | /* calibration */ | ||
106 | struct iwl_eeprom_calib_hdr { | ||
107 | u8 version; | ||
108 | u8 pa_type; | ||
109 | __le16 voltage; | ||
110 | } __packed; | ||
111 | |||
112 | #define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION) | ||
113 | #define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL) | ||
114 | |||
115 | /* temperature */ | ||
116 | #define EEPROM_KELVIN_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL) | ||
117 | #define EEPROM_RAW_TEMPERATURE ((2*0x12B) | EEPROM_CALIB_ALL) | ||
118 | |||
119 | /* | ||
120 | * EEPROM bands | ||
121 | * These are the channel numbers from each band in the order | ||
122 | * that they are stored in the EEPROM band information. Note | ||
123 | * that EEPROM bands aren't the same as mac80211 bands, and | ||
124 | * there are even special "ht40 bands" in the EEPROM. | ||
125 | */ | ||
126 | static const u8 iwl_eeprom_band_1[14] = { /* 2.4 GHz */ | ||
127 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 | ||
128 | }; | ||
129 | |||
130 | static const u8 iwl_eeprom_band_2[] = { /* 4915-5080MHz */ | ||
131 | 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 | ||
132 | }; | ||
133 | |||
134 | static const u8 iwl_eeprom_band_3[] = { /* 5170-5320MHz */ | ||
135 | 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 | ||
136 | }; | ||
137 | |||
138 | static const u8 iwl_eeprom_band_4[] = { /* 5500-5700MHz */ | ||
139 | 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 | ||
140 | }; | ||
141 | |||
142 | static const u8 iwl_eeprom_band_5[] = { /* 5725-5825MHz */ | ||
143 | 145, 149, 153, 157, 161, 165 | ||
144 | }; | ||
145 | |||
146 | static const u8 iwl_eeprom_band_6[] = { /* 2.4 ht40 channel */ | ||
147 | 1, 2, 3, 4, 5, 6, 7 | ||
148 | }; | ||
149 | |||
150 | static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */ | ||
151 | 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 | ||
152 | }; | ||
153 | |||
154 | #define IWL_NUM_CHANNELS (ARRAY_SIZE(iwl_eeprom_band_1) + \ | ||
155 | ARRAY_SIZE(iwl_eeprom_band_2) + \ | ||
156 | ARRAY_SIZE(iwl_eeprom_band_3) + \ | ||
157 | ARRAY_SIZE(iwl_eeprom_band_4) + \ | ||
158 | ARRAY_SIZE(iwl_eeprom_band_5)) | ||
159 | |||
160 | /* rate data (static) */ | ||
161 | static 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 | /* EEPROM reading functions */ | ||
184 | |||
185 | static u16 iwl_eeprom_query16(const u8 *eeprom, size_t eeprom_size, int offset) | ||
186 | { | ||
187 | if (WARN_ON(offset + sizeof(u16) > eeprom_size)) | ||
188 | return 0; | ||
189 | return le16_to_cpup((__le16 *)(eeprom + offset)); | ||
190 | } | ||
191 | |||
192 | static u32 eeprom_indirect_address(const u8 *eeprom, size_t eeprom_size, | ||
193 | u32 address) | ||
194 | { | ||
195 | u16 offset = 0; | ||
196 | |||
197 | if ((address & INDIRECT_ADDRESS) == 0) | ||
198 | return address; | ||
199 | |||
200 | switch (address & INDIRECT_TYPE_MSK) { | ||
201 | case INDIRECT_HOST: | ||
202 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
203 | EEPROM_LINK_HOST); | ||
204 | break; | ||
205 | case INDIRECT_GENERAL: | ||
206 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
207 | EEPROM_LINK_GENERAL); | ||
208 | break; | ||
209 | case INDIRECT_REGULATORY: | ||
210 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
211 | EEPROM_LINK_REGULATORY); | ||
212 | break; | ||
213 | case INDIRECT_TXP_LIMIT: | ||
214 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
215 | EEPROM_LINK_TXP_LIMIT); | ||
216 | break; | ||
217 | case INDIRECT_TXP_LIMIT_SIZE: | ||
218 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
219 | EEPROM_LINK_TXP_LIMIT_SIZE); | ||
220 | break; | ||
221 | case INDIRECT_CALIBRATION: | ||
222 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
223 | EEPROM_LINK_CALIBRATION); | ||
224 | break; | ||
225 | case INDIRECT_PROCESS_ADJST: | ||
226 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
227 | EEPROM_LINK_PROCESS_ADJST); | ||
228 | break; | ||
229 | case INDIRECT_OTHERS: | ||
230 | offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||
231 | EEPROM_LINK_OTHERS); | ||
232 | break; | ||
233 | default: | ||
234 | WARN_ON(1); | ||
235 | break; | ||
236 | } | ||
237 | |||
238 | /* translate the offset from words to byte */ | ||
239 | return (address & ADDRESS_MSK) + (offset << 1); | ||
240 | } | ||
241 | |||
242 | static const u8 *iwl_eeprom_query_addr(const u8 *eeprom, size_t eeprom_size, | ||
243 | u32 offset) | ||
244 | { | ||
245 | u32 address = eeprom_indirect_address(eeprom, eeprom_size, offset); | ||
246 | |||
247 | if (WARN_ON(address >= eeprom_size)) | ||
248 | return NULL; | ||
249 | |||
250 | return &eeprom[address]; | ||
251 | } | ||
252 | |||
253 | static int iwl_eeprom_read_calib(const u8 *eeprom, size_t eeprom_size, | ||
254 | struct iwl_eeprom_data *data) | ||
255 | { | ||
256 | struct iwl_eeprom_calib_hdr *hdr; | ||
257 | |||
258 | hdr = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size, | ||
259 | EEPROM_CALIB_ALL); | ||
260 | if (!hdr) | ||
261 | return -ENODATA; | ||
262 | data->calib_version = hdr->version; | ||
263 | data->calib_voltage = hdr->voltage; | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * enum iwl_eeprom_channel_flags - channel flags in EEPROM | ||
270 | * @EEPROM_CHANNEL_VALID: channel is usable for this SKU/geo | ||
271 | * @EEPROM_CHANNEL_IBSS: usable as an IBSS channel | ||
272 | * @EEPROM_CHANNEL_ACTIVE: active scanning allowed | ||
273 | * @EEPROM_CHANNEL_RADAR: radar detection required | ||
274 | * @EEPROM_CHANNEL_WIDE: 20 MHz channel okay (?) | ||
275 | * @EEPROM_CHANNEL_DFS: dynamic freq selection candidate | ||
276 | */ | ||
277 | enum iwl_eeprom_channel_flags { | ||
278 | EEPROM_CHANNEL_VALID = BIT(0), | ||
279 | EEPROM_CHANNEL_IBSS = BIT(1), | ||
280 | EEPROM_CHANNEL_ACTIVE = BIT(3), | ||
281 | EEPROM_CHANNEL_RADAR = BIT(4), | ||
282 | EEPROM_CHANNEL_WIDE = BIT(5), | ||
283 | EEPROM_CHANNEL_DFS = BIT(7), | ||
284 | }; | ||
285 | |||
286 | /** | ||
287 | * struct iwl_eeprom_channel - EEPROM channel data | ||
288 | * @flags: %EEPROM_CHANNEL_* flags | ||
289 | * @max_power_avg: max power (in dBm) on this channel, at most 31 dBm | ||
290 | */ | ||
291 | struct iwl_eeprom_channel { | ||
292 | u8 flags; | ||
293 | s8 max_power_avg; | ||
294 | } __packed; | ||
295 | |||
296 | |||
297 | enum iwl_eeprom_enhanced_txpwr_flags { | ||
298 | IWL_EEPROM_ENH_TXP_FL_VALID = BIT(0), | ||
299 | IWL_EEPROM_ENH_TXP_FL_BAND_52G = BIT(1), | ||
300 | IWL_EEPROM_ENH_TXP_FL_OFDM = BIT(2), | ||
301 | IWL_EEPROM_ENH_TXP_FL_40MHZ = BIT(3), | ||
302 | IWL_EEPROM_ENH_TXP_FL_HT_AP = BIT(4), | ||
303 | IWL_EEPROM_ENH_TXP_FL_RES1 = BIT(5), | ||
304 | IWL_EEPROM_ENH_TXP_FL_RES2 = BIT(6), | ||
305 | IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE = BIT(7), | ||
306 | }; | ||
307 | |||
308 | /** | ||
309 | * iwl_eeprom_enhanced_txpwr structure | ||
310 | * @flags: entry flags | ||
311 | * @channel: channel number | ||
312 | * @chain_a_max_pwr: chain a max power in 1/2 dBm | ||
313 | * @chain_b_max_pwr: chain b max power in 1/2 dBm | ||
314 | * @chain_c_max_pwr: chain c max power in 1/2 dBm | ||
315 | * @delta_20_in_40: 20-in-40 deltas (hi/lo) | ||
316 | * @mimo2_max_pwr: mimo2 max power in 1/2 dBm | ||
317 | * @mimo3_max_pwr: mimo3 max power in 1/2 dBm | ||
318 | * | ||
319 | * This structure presents the enhanced regulatory tx power limit layout | ||
320 | * in an EEPROM image. | ||
321 | */ | ||
322 | struct iwl_eeprom_enhanced_txpwr { | ||
323 | u8 flags; | ||
324 | u8 channel; | ||
325 | s8 chain_a_max; | ||
326 | s8 chain_b_max; | ||
327 | s8 chain_c_max; | ||
328 | u8 delta_20_in_40; | ||
329 | s8 mimo2_max; | ||
330 | s8 mimo3_max; | ||
331 | } __packed; | ||
332 | |||
333 | static s8 iwl_get_max_txpwr_half_dbm(const struct iwl_eeprom_data *data, | ||
334 | struct iwl_eeprom_enhanced_txpwr *txp) | ||
335 | { | ||
336 | s8 result = 0; /* (.5 dBm) */ | ||
337 | |||
338 | /* Take the highest tx power from any valid chains */ | ||
339 | if (data->valid_tx_ant & ANT_A && txp->chain_a_max > result) | ||
340 | result = txp->chain_a_max; | ||
341 | |||
342 | if (data->valid_tx_ant & ANT_B && txp->chain_b_max > result) | ||
343 | result = txp->chain_b_max; | ||
344 | |||
345 | if (data->valid_tx_ant & ANT_C && txp->chain_c_max > result) | ||
346 | result = txp->chain_c_max; | ||
347 | |||
348 | if ((data->valid_tx_ant == ANT_AB || | ||
349 | data->valid_tx_ant == ANT_BC || | ||
350 | data->valid_tx_ant == ANT_AC) && txp->mimo2_max > result) | ||
351 | result = txp->mimo2_max; | ||
352 | |||
353 | if (data->valid_tx_ant == ANT_ABC && txp->mimo3_max > result) | ||
354 | result = txp->mimo3_max; | ||
355 | |||
356 | return result; | ||
357 | } | ||
358 | |||
359 | #define EEPROM_TXP_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT) | ||
360 | #define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr) | ||
361 | #define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE) | ||
362 | |||
363 | #define TXP_CHECK_AND_PRINT(x) \ | ||
364 | ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) ? # x " " : "") | ||
365 | |||
366 | static void | ||
367 | iwl_eeprom_enh_txp_read_element(struct iwl_eeprom_data *data, | ||
368 | struct iwl_eeprom_enhanced_txpwr *txp, | ||
369 | int n_channels, s8 max_txpower_avg) | ||
370 | { | ||
371 | int ch_idx; | ||
372 | enum ieee80211_band band; | ||
373 | |||
374 | band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ? | ||
375 | IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; | ||
376 | |||
377 | for (ch_idx = 0; ch_idx < n_channels; ch_idx++) { | ||
378 | struct ieee80211_channel *chan = &data->channels[ch_idx]; | ||
379 | |||
380 | /* update matching channel or from common data only */ | ||
381 | if (txp->channel != 0 && chan->hw_value != txp->channel) | ||
382 | continue; | ||
383 | |||
384 | /* update matching band only */ | ||
385 | if (band != chan->band) | ||
386 | continue; | ||
387 | |||
388 | if (chan->max_power < max_txpower_avg && | ||
389 | !(txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ)) | ||
390 | chan->max_power = max_txpower_avg; | ||
391 | } | ||
392 | } | ||
393 | |||
394 | static void iwl_eeprom_enhanced_txpower(struct device *dev, | ||
395 | struct iwl_eeprom_data *data, | ||
396 | const u8 *eeprom, size_t eeprom_size, | ||
397 | int n_channels) | ||
398 | { | ||
399 | struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; | ||
400 | int idx, entries; | ||
401 | __le16 *txp_len; | ||
402 | s8 max_txp_avg_halfdbm; | ||
403 | |||
404 | BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8); | ||
405 | |||
406 | /* the length is in 16-bit words, but we want entries */ | ||
407 | txp_len = (__le16 *)iwl_eeprom_query_addr(eeprom, eeprom_size, | ||
408 | EEPROM_TXP_SZ_OFFS); | ||
409 | entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN; | ||
410 | |||
411 | txp_array = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size, | ||
412 | EEPROM_TXP_OFFS); | ||
413 | |||
414 | for (idx = 0; idx < entries; idx++) { | ||
415 | txp = &txp_array[idx]; | ||
416 | /* skip invalid entries */ | ||
417 | if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID)) | ||
418 | continue; | ||
419 | |||
420 | IWL_DEBUG_EEPROM(dev, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n", | ||
421 | (txp->channel && (txp->flags & | ||
422 | IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ? | ||
423 | "Common " : (txp->channel) ? | ||
424 | "Channel" : "Common", | ||
425 | (txp->channel), | ||
426 | TXP_CHECK_AND_PRINT(VALID), | ||
427 | TXP_CHECK_AND_PRINT(BAND_52G), | ||
428 | TXP_CHECK_AND_PRINT(OFDM), | ||
429 | TXP_CHECK_AND_PRINT(40MHZ), | ||
430 | TXP_CHECK_AND_PRINT(HT_AP), | ||
431 | TXP_CHECK_AND_PRINT(RES1), | ||
432 | TXP_CHECK_AND_PRINT(RES2), | ||
433 | TXP_CHECK_AND_PRINT(COMMON_TYPE), | ||
434 | txp->flags); | ||
435 | IWL_DEBUG_EEPROM(dev, | ||
436 | "\t\t chain_A: 0x%02x chain_B: 0X%02x chain_C: 0X%02x\n", | ||
437 | txp->chain_a_max, txp->chain_b_max, | ||
438 | txp->chain_c_max); | ||
439 | IWL_DEBUG_EEPROM(dev, | ||
440 | "\t\t MIMO2: 0x%02x MIMO3: 0x%02x High 20_on_40: 0x%02x Low 20_on_40: 0x%02x\n", | ||
441 | txp->mimo2_max, txp->mimo3_max, | ||
442 | ((txp->delta_20_in_40 & 0xf0) >> 4), | ||
443 | (txp->delta_20_in_40 & 0x0f)); | ||
444 | |||
445 | max_txp_avg_halfdbm = iwl_get_max_txpwr_half_dbm(data, txp); | ||
446 | |||
447 | iwl_eeprom_enh_txp_read_element(data, txp, n_channels, | ||
448 | DIV_ROUND_UP(max_txp_avg_halfdbm, 2)); | ||
449 | |||
450 | if (max_txp_avg_halfdbm > data->max_tx_pwr_half_dbm) | ||
451 | data->max_tx_pwr_half_dbm = max_txp_avg_halfdbm; | ||
452 | } | ||
453 | } | ||
454 | |||
455 | static void iwl_init_band_reference(const struct iwl_cfg *cfg, | ||
456 | const u8 *eeprom, size_t eeprom_size, | ||
457 | int eeprom_band, int *eeprom_ch_count, | ||
458 | const struct iwl_eeprom_channel **ch_info, | ||
459 | const u8 **eeprom_ch_array) | ||
460 | { | ||
461 | u32 offset = cfg->eeprom_params->regulatory_bands[eeprom_band - 1]; | ||
462 | |||
463 | offset |= INDIRECT_ADDRESS | INDIRECT_REGULATORY; | ||
464 | |||
465 | *ch_info = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size, offset); | ||
466 | |||
467 | switch (eeprom_band) { | ||
468 | case 1: /* 2.4GHz band */ | ||
469 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1); | ||
470 | *eeprom_ch_array = iwl_eeprom_band_1; | ||
471 | break; | ||
472 | case 2: /* 4.9GHz band */ | ||
473 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2); | ||
474 | *eeprom_ch_array = iwl_eeprom_band_2; | ||
475 | break; | ||
476 | case 3: /* 5.2GHz band */ | ||
477 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3); | ||
478 | *eeprom_ch_array = iwl_eeprom_band_3; | ||
479 | break; | ||
480 | case 4: /* 5.5GHz band */ | ||
481 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4); | ||
482 | *eeprom_ch_array = iwl_eeprom_band_4; | ||
483 | break; | ||
484 | case 5: /* 5.7GHz band */ | ||
485 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5); | ||
486 | *eeprom_ch_array = iwl_eeprom_band_5; | ||
487 | break; | ||
488 | case 6: /* 2.4GHz ht40 channels */ | ||
489 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6); | ||
490 | *eeprom_ch_array = iwl_eeprom_band_6; | ||
491 | break; | ||
492 | case 7: /* 5 GHz ht40 channels */ | ||
493 | *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7); | ||
494 | *eeprom_ch_array = iwl_eeprom_band_7; | ||
495 | break; | ||
496 | default: | ||
497 | *eeprom_ch_count = 0; | ||
498 | *eeprom_ch_array = NULL; | ||
499 | WARN_ON(1); | ||
500 | } | ||
501 | } | ||
502 | |||
503 | #define CHECK_AND_PRINT(x) \ | ||
504 | ((eeprom_ch->flags & EEPROM_CHANNEL_##x) ? # x " " : "") | ||
505 | |||
506 | static void iwl_mod_ht40_chan_info(struct device *dev, | ||
507 | struct iwl_eeprom_data *data, int n_channels, | ||
508 | enum ieee80211_band band, u16 channel, | ||
509 | const struct iwl_eeprom_channel *eeprom_ch, | ||
510 | u8 clear_ht40_extension_channel) | ||
511 | { | ||
512 | struct ieee80211_channel *chan = NULL; | ||
513 | int i; | ||
514 | |||
515 | for (i = 0; i < n_channels; i++) { | ||
516 | if (data->channels[i].band != band) | ||
517 | continue; | ||
518 | if (data->channels[i].hw_value != channel) | ||
519 | continue; | ||
520 | chan = &data->channels[i]; | ||
521 | break; | ||
522 | } | ||
523 | |||
524 | if (!chan) | ||
525 | return; | ||
526 | |||
527 | IWL_DEBUG_EEPROM(dev, | ||
528 | "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", | ||
529 | channel, | ||
530 | band == IEEE80211_BAND_5GHZ ? "5.2" : "2.4", | ||
531 | CHECK_AND_PRINT(IBSS), | ||
532 | CHECK_AND_PRINT(ACTIVE), | ||
533 | CHECK_AND_PRINT(RADAR), | ||
534 | CHECK_AND_PRINT(WIDE), | ||
535 | CHECK_AND_PRINT(DFS), | ||
536 | eeprom_ch->flags, | ||
537 | eeprom_ch->max_power_avg, | ||
538 | ((eeprom_ch->flags & EEPROM_CHANNEL_IBSS) && | ||
539 | !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ? "" | ||
540 | : "not "); | ||
541 | |||
542 | if (eeprom_ch->flags & EEPROM_CHANNEL_VALID) | ||
543 | chan->flags &= ~clear_ht40_extension_channel; | ||
544 | } | ||
545 | |||
546 | #define CHECK_AND_PRINT_I(x) \ | ||
547 | ((eeprom_ch_info[ch_idx].flags & EEPROM_CHANNEL_##x) ? # x " " : "") | ||
548 | |||
549 | static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | ||
550 | struct iwl_eeprom_data *data, | ||
551 | const u8 *eeprom, size_t eeprom_size) | ||
552 | { | ||
553 | int band, ch_idx; | ||
554 | const struct iwl_eeprom_channel *eeprom_ch_info; | ||
555 | const u8 *eeprom_ch_array; | ||
556 | int eeprom_ch_count; | ||
557 | int n_channels = 0; | ||
558 | |||
559 | /* | ||
560 | * Loop through the 5 EEPROM bands and add them to the parse list | ||
561 | */ | ||
562 | for (band = 1; band <= 5; band++) { | ||
563 | struct ieee80211_channel *channel; | ||
564 | |||
565 | iwl_init_band_reference(cfg, eeprom, eeprom_size, band, | ||
566 | &eeprom_ch_count, &eeprom_ch_info, | ||
567 | &eeprom_ch_array); | ||
568 | |||
569 | /* Loop through each band adding each of the channels */ | ||
570 | for (ch_idx = 0; ch_idx < eeprom_ch_count; ch_idx++) { | ||
571 | const struct iwl_eeprom_channel *eeprom_ch; | ||
572 | |||
573 | eeprom_ch = &eeprom_ch_info[ch_idx]; | ||
574 | |||
575 | if (!(eeprom_ch->flags & EEPROM_CHANNEL_VALID)) { | ||
576 | IWL_DEBUG_EEPROM(dev, | ||
577 | "Ch. %d Flags %x [%sGHz] - No traffic\n", | ||
578 | eeprom_ch_array[ch_idx], | ||
579 | eeprom_ch_info[ch_idx].flags, | ||
580 | (band != 1) ? "5.2" : "2.4"); | ||
581 | continue; | ||
582 | } | ||
583 | |||
584 | channel = &data->channels[n_channels]; | ||
585 | n_channels++; | ||
586 | |||
587 | channel->hw_value = eeprom_ch_array[ch_idx]; | ||
588 | channel->band = (band == 1) ? IEEE80211_BAND_2GHZ | ||
589 | : IEEE80211_BAND_5GHZ; | ||
590 | channel->center_freq = | ||
591 | ieee80211_channel_to_frequency( | ||
592 | channel->hw_value, channel->band); | ||
593 | |||
594 | /* set no-HT40, will enable as appropriate later */ | ||
595 | channel->flags = IEEE80211_CHAN_NO_HT40; | ||
596 | |||
597 | if (!(eeprom_ch->flags & EEPROM_CHANNEL_IBSS)) | ||
598 | channel->flags |= IEEE80211_CHAN_NO_IBSS; | ||
599 | |||
600 | if (!(eeprom_ch->flags & EEPROM_CHANNEL_ACTIVE)) | ||
601 | channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN; | ||
602 | |||
603 | if (eeprom_ch->flags & EEPROM_CHANNEL_RADAR) | ||
604 | channel->flags |= IEEE80211_CHAN_RADAR; | ||
605 | |||
606 | /* Initialize regulatory-based run-time data */ | ||
607 | channel->max_power = | ||
608 | eeprom_ch_info[ch_idx].max_power_avg; | ||
609 | IWL_DEBUG_EEPROM(dev, | ||
610 | "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", | ||
611 | channel->hw_value, | ||
612 | (band != 1) ? "5.2" : "2.4", | ||
613 | CHECK_AND_PRINT_I(VALID), | ||
614 | CHECK_AND_PRINT_I(IBSS), | ||
615 | CHECK_AND_PRINT_I(ACTIVE), | ||
616 | CHECK_AND_PRINT_I(RADAR), | ||
617 | CHECK_AND_PRINT_I(WIDE), | ||
618 | CHECK_AND_PRINT_I(DFS), | ||
619 | eeprom_ch_info[ch_idx].flags, | ||
620 | eeprom_ch_info[ch_idx].max_power_avg, | ||
621 | ((eeprom_ch_info[ch_idx].flags & | ||
622 | EEPROM_CHANNEL_IBSS) && | ||
623 | !(eeprom_ch_info[ch_idx].flags & | ||
624 | EEPROM_CHANNEL_RADAR)) | ||
625 | ? "" : "not "); | ||
626 | } | ||
627 | } | ||
628 | |||
629 | if (cfg->eeprom_params->enhanced_txpower) { | ||
630 | /* | ||
631 | * for newer device (6000 series and up) | ||
632 | * EEPROM contain enhanced tx power information | ||
633 | * driver need to process addition information | ||
634 | * to determine the max channel tx power limits | ||
635 | */ | ||
636 | iwl_eeprom_enhanced_txpower(dev, data, eeprom, eeprom_size, | ||
637 | n_channels); | ||
638 | } else { | ||
639 | /* All others use data from channel map */ | ||
640 | int i; | ||
641 | |||
642 | data->max_tx_pwr_half_dbm = -128; | ||
643 | |||
644 | for (i = 0; i < n_channels; i++) | ||
645 | data->max_tx_pwr_half_dbm = | ||
646 | max_t(s8, data->max_tx_pwr_half_dbm, | ||
647 | data->channels[i].max_power * 2); | ||
648 | } | ||
649 | |||
650 | /* Check if we do have HT40 channels */ | ||
651 | if (cfg->eeprom_params->regulatory_bands[5] == | ||
652 | EEPROM_REGULATORY_BAND_NO_HT40 && | ||
653 | cfg->eeprom_params->regulatory_bands[6] == | ||
654 | EEPROM_REGULATORY_BAND_NO_HT40) | ||
655 | return n_channels; | ||
656 | |||
657 | /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */ | ||
658 | for (band = 6; band <= 7; band++) { | ||
659 | enum ieee80211_band ieeeband; | ||
660 | |||
661 | iwl_init_band_reference(cfg, eeprom, eeprom_size, band, | ||
662 | &eeprom_ch_count, &eeprom_ch_info, | ||
663 | &eeprom_ch_array); | ||
664 | |||
665 | /* EEPROM band 6 is 2.4, band 7 is 5 GHz */ | ||
666 | ieeeband = (band == 6) ? IEEE80211_BAND_2GHZ | ||
667 | : IEEE80211_BAND_5GHZ; | ||
668 | |||
669 | /* Loop through each band adding each of the channels */ | ||
670 | for (ch_idx = 0; ch_idx < eeprom_ch_count; ch_idx++) { | ||
671 | /* Set up driver's info for lower half */ | ||
672 | iwl_mod_ht40_chan_info(dev, data, n_channels, ieeeband, | ||
673 | eeprom_ch_array[ch_idx], | ||
674 | &eeprom_ch_info[ch_idx], | ||
675 | IEEE80211_CHAN_NO_HT40PLUS); | ||
676 | |||
677 | /* Set up driver's info for upper half */ | ||
678 | iwl_mod_ht40_chan_info(dev, data, n_channels, ieeeband, | ||
679 | eeprom_ch_array[ch_idx] + 4, | ||
680 | &eeprom_ch_info[ch_idx], | ||
681 | IEEE80211_CHAN_NO_HT40MINUS); | ||
682 | } | ||
683 | } | ||
684 | |||
685 | return n_channels; | ||
686 | } | ||
687 | |||
688 | static int iwl_init_sband_channels(struct iwl_eeprom_data *data, | ||
689 | struct ieee80211_supported_band *sband, | ||
690 | int n_channels, enum ieee80211_band band) | ||
691 | { | ||
692 | struct ieee80211_channel *chan = &data->channels[0]; | ||
693 | int n = 0, idx = 0; | ||
694 | |||
695 | while (chan->band != band && idx < n_channels) | ||
696 | chan = &data->channels[++idx]; | ||
697 | |||
698 | sband->channels = &data->channels[idx]; | ||
699 | |||
700 | while (chan->band == band && idx < n_channels) { | ||
701 | chan = &data->channels[++idx]; | ||
702 | n++; | ||
703 | } | ||
704 | |||
705 | sband->n_channels = n; | ||
706 | |||
707 | return n; | ||
708 | } | ||
709 | |||
710 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ | ||
711 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ | ||
712 | |||
713 | static void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, | ||
714 | struct iwl_eeprom_data *data, | ||
715 | struct ieee80211_sta_ht_cap *ht_info, | ||
716 | enum ieee80211_band band) | ||
717 | { | ||
718 | int max_bit_rate = 0; | ||
719 | u8 rx_chains; | ||
720 | u8 tx_chains; | ||
721 | |||
722 | tx_chains = hweight8(data->valid_tx_ant); | ||
723 | if (cfg->rx_with_siso_diversity) | ||
724 | rx_chains = 1; | ||
725 | else | ||
726 | rx_chains = hweight8(data->valid_rx_ant); | ||
727 | |||
728 | if (!(data->sku & EEPROM_SKU_CAP_11N_ENABLE) || !cfg->ht_params) { | ||
729 | ht_info->ht_supported = false; | ||
730 | return; | ||
731 | } | ||
732 | |||
733 | ht_info->ht_supported = true; | ||
734 | ht_info->cap = 0; | ||
735 | |||
736 | if (iwlwifi_mod_params.amsdu_size_8K) | ||
737 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | ||
738 | |||
739 | ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | ||
740 | ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_4; | ||
741 | |||
742 | ht_info->mcs.rx_mask[0] = 0xFF; | ||
743 | if (rx_chains >= 2) | ||
744 | ht_info->mcs.rx_mask[1] = 0xFF; | ||
745 | if (rx_chains >= 3) | ||
746 | ht_info->mcs.rx_mask[2] = 0xFF; | ||
747 | |||
748 | if (cfg->ht_params->ht_greenfield_support) | ||
749 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | ||
750 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | ||
751 | |||
752 | max_bit_rate = MAX_BIT_RATE_20_MHZ; | ||
753 | |||
754 | if (cfg->ht_params->ht40_bands & BIT(band)) { | ||
755 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
756 | ht_info->cap |= IEEE80211_HT_CAP_SGI_40; | ||
757 | ht_info->mcs.rx_mask[4] = 0x01; | ||
758 | max_bit_rate = MAX_BIT_RATE_40_MHZ; | ||
759 | } | ||
760 | |||
761 | /* Highest supported Rx data rate */ | ||
762 | max_bit_rate *= rx_chains; | ||
763 | WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK); | ||
764 | ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate); | ||
765 | |||
766 | /* Tx MCS capabilities */ | ||
767 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
768 | if (tx_chains != rx_chains) { | ||
769 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | ||
770 | ht_info->mcs.tx_params |= ((tx_chains - 1) << | ||
771 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | ||
772 | } | ||
773 | } | ||
774 | |||
775 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | ||
776 | struct iwl_eeprom_data *data, | ||
777 | const u8 *eeprom, size_t eeprom_size) | ||
778 | { | ||
779 | int n_channels = iwl_init_channel_map(dev, cfg, data, | ||
780 | eeprom, eeprom_size); | ||
781 | int n_used = 0; | ||
782 | struct ieee80211_supported_band *sband; | ||
783 | |||
784 | sband = &data->bands[IEEE80211_BAND_2GHZ]; | ||
785 | sband->band = IEEE80211_BAND_2GHZ; | ||
786 | sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; | ||
787 | sband->n_bitrates = N_RATES_24; | ||
788 | n_used += iwl_init_sband_channels(data, sband, n_channels, | ||
789 | IEEE80211_BAND_2GHZ); | ||
790 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ); | ||
791 | |||
792 | sband = &data->bands[IEEE80211_BAND_5GHZ]; | ||
793 | sband->band = IEEE80211_BAND_5GHZ; | ||
794 | sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS]; | ||
795 | sband->n_bitrates = N_RATES_52; | ||
796 | n_used += iwl_init_sband_channels(data, sband, n_channels, | ||
797 | IEEE80211_BAND_5GHZ); | ||
798 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ); | ||
799 | |||
800 | if (n_channels != n_used) | ||
801 | IWL_ERR_DEV(dev, "EEPROM: used only %d of %d channels\n", | ||
802 | n_used, n_channels); | ||
803 | } | ||
804 | |||
805 | /* EEPROM data functions */ | ||
806 | |||
807 | struct iwl_eeprom_data * | ||
808 | iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg, | ||
809 | const u8 *eeprom, size_t eeprom_size) | ||
810 | { | ||
811 | struct iwl_eeprom_data *data; | ||
812 | const void *tmp; | ||
813 | |||
814 | if (WARN_ON(!cfg || !cfg->eeprom_params)) | ||
815 | return NULL; | ||
816 | |||
817 | data = kzalloc(sizeof(*data) + | ||
818 | sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS, | ||
819 | GFP_KERNEL); | ||
820 | if (!data) | ||
821 | return NULL; | ||
822 | |||
823 | /* get MAC address(es) */ | ||
824 | tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_MAC_ADDRESS); | ||
825 | if (!tmp) | ||
826 | goto err_free; | ||
827 | memcpy(data->hw_addr, tmp, ETH_ALEN); | ||
828 | data->n_hw_addrs = iwl_eeprom_query16(eeprom, eeprom_size, | ||
829 | EEPROM_NUM_MAC_ADDRESS); | ||
830 | |||
831 | if (iwl_eeprom_read_calib(eeprom, eeprom_size, data)) | ||
832 | goto err_free; | ||
833 | |||
834 | tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_XTAL); | ||
835 | if (!tmp) | ||
836 | goto err_free; | ||
837 | memcpy(data->xtal_calib, tmp, sizeof(data->xtal_calib)); | ||
838 | |||
839 | tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, | ||
840 | EEPROM_RAW_TEMPERATURE); | ||
841 | if (!tmp) | ||
842 | goto err_free; | ||
843 | data->raw_temperature = *(__le16 *)tmp; | ||
844 | |||
845 | tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, | ||
846 | EEPROM_KELVIN_TEMPERATURE); | ||
847 | if (!tmp) | ||
848 | goto err_free; | ||
849 | data->kelvin_temperature = *(__le16 *)tmp; | ||
850 | data->kelvin_voltage = *((__le16 *)tmp + 1); | ||
851 | |||
852 | data->radio_cfg = iwl_eeprom_query16(eeprom, eeprom_size, | ||
853 | EEPROM_RADIO_CONFIG); | ||
854 | data->sku = iwl_eeprom_query16(eeprom, eeprom_size, | ||
855 | EEPROM_SKU_CAP); | ||
856 | data->eeprom_version = iwl_eeprom_query16(eeprom, eeprom_size, | ||
857 | EEPROM_VERSION); | ||
858 | |||
859 | data->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(data->radio_cfg); | ||
860 | data->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(data->radio_cfg); | ||
861 | |||
862 | /* check overrides (some devices have wrong EEPROM) */ | ||
863 | if (cfg->valid_tx_ant) | ||
864 | data->valid_tx_ant = cfg->valid_tx_ant; | ||
865 | if (cfg->valid_rx_ant) | ||
866 | data->valid_rx_ant = cfg->valid_rx_ant; | ||
867 | |||
868 | if (!data->valid_tx_ant || !data->valid_rx_ant) { | ||
869 | IWL_ERR_DEV(dev, "invalid antennas (0x%x, 0x%x)\n", | ||
870 | data->valid_tx_ant, data->valid_rx_ant); | ||
871 | goto err_free; | ||
872 | } | ||
873 | |||
874 | iwl_init_sbands(dev, cfg, data, eeprom, eeprom_size); | ||
875 | |||
876 | return data; | ||
877 | err_free: | ||
878 | kfree(data); | ||
879 | return NULL; | ||
880 | } | ||
881 | EXPORT_SYMBOL_GPL(iwl_parse_eeprom_data); | ||
882 | |||
883 | /* helper functions */ | ||
884 | int iwl_eeprom_check_version(struct iwl_eeprom_data *data, | ||
885 | struct iwl_trans *trans) | ||
886 | { | ||
887 | if (data->eeprom_version >= trans->cfg->eeprom_ver || | ||
888 | data->calib_version >= trans->cfg->eeprom_calib_ver) { | ||
889 | IWL_INFO(trans, "device EEPROM VER=0x%x, CALIB=0x%x\n", | ||
890 | data->eeprom_version, data->calib_version); | ||
891 | return 0; | ||
892 | } | ||
893 | |||
894 | IWL_ERR(trans, | ||
895 | "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n", | ||
896 | data->eeprom_version, trans->cfg->eeprom_ver, | ||
897 | data->calib_version, trans->cfg->eeprom_calib_ver); | ||
898 | return -EINVAL; | ||
899 | } | ||
900 | EXPORT_SYMBOL_GPL(iwl_eeprom_check_version); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h new file mode 100644 index 000000000000..9c07c670a1ce --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h | |||
@@ -0,0 +1,138 @@ | |||
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 - 2012 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 - 2012 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 | #ifndef __iwl_eeprom_parse_h__ | ||
63 | #define __iwl_eeprom_parse_h__ | ||
64 | |||
65 | #include <linux/types.h> | ||
66 | #include <linux/if_ether.h> | ||
67 | #include "iwl-trans.h" | ||
68 | |||
69 | /* SKU Capabilities (actual values from EEPROM definition) */ | ||
70 | #define EEPROM_SKU_CAP_BAND_24GHZ (1 << 4) | ||
71 | #define EEPROM_SKU_CAP_BAND_52GHZ (1 << 5) | ||
72 | #define EEPROM_SKU_CAP_11N_ENABLE (1 << 6) | ||
73 | #define EEPROM_SKU_CAP_AMT_ENABLE (1 << 7) | ||
74 | #define EEPROM_SKU_CAP_IPAN_ENABLE (1 << 8) | ||
75 | |||
76 | /* radio config bits (actual values from EEPROM definition) */ | ||
77 | #define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */ | ||
78 | #define EEPROM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */ | ||
79 | #define EEPROM_RF_CFG_DASH_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */ | ||
80 | #define EEPROM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */ | ||
81 | #define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */ | ||
82 | #define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */ | ||
83 | |||
84 | struct iwl_eeprom_data { | ||
85 | int n_hw_addrs; | ||
86 | u8 hw_addr[ETH_ALEN]; | ||
87 | |||
88 | u16 radio_config; | ||
89 | |||
90 | u8 calib_version; | ||
91 | __le16 calib_voltage; | ||
92 | |||
93 | __le16 raw_temperature; | ||
94 | __le16 kelvin_temperature; | ||
95 | __le16 kelvin_voltage; | ||
96 | __le16 xtal_calib[2]; | ||
97 | |||
98 | u16 sku; | ||
99 | u16 radio_cfg; | ||
100 | u16 eeprom_version; | ||
101 | s8 max_tx_pwr_half_dbm; | ||
102 | |||
103 | u8 valid_tx_ant, valid_rx_ant; | ||
104 | |||
105 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | ||
106 | struct ieee80211_channel channels[]; | ||
107 | }; | ||
108 | |||
109 | /** | ||
110 | * iwl_parse_eeprom_data - parse EEPROM data and return values | ||
111 | * | ||
112 | * @dev: device pointer we're parsing for, for debug only | ||
113 | * @cfg: device configuration for parsing and overrides | ||
114 | * @eeprom: the EEPROM data | ||
115 | * @eeprom_size: length of the EEPROM data | ||
116 | * | ||
117 | * This function parses all EEPROM values we need and then | ||
118 | * returns a (newly allocated) struct containing all the | ||
119 | * relevant values for driver use. The struct must be freed | ||
120 | * later with iwl_free_eeprom_data(). | ||
121 | */ | ||
122 | struct iwl_eeprom_data * | ||
123 | iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg, | ||
124 | const u8 *eeprom, size_t eeprom_size); | ||
125 | |||
126 | /** | ||
127 | * iwl_free_eeprom_data - free EEPROM data | ||
128 | * @data: the data to free | ||
129 | */ | ||
130 | static inline void iwl_free_eeprom_data(struct iwl_eeprom_data *data) | ||
131 | { | ||
132 | kfree(data); | ||
133 | } | ||
134 | |||
135 | int iwl_eeprom_check_version(struct iwl_eeprom_data *data, | ||
136 | struct iwl_trans *trans); | ||
137 | |||
138 | #endif /* __iwl_eeprom_parse_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c new file mode 100644 index 000000000000..27c7da3c6ed1 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.c | |||
@@ -0,0 +1,463 @@ | |||
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 - 2012 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 - 2012 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 | #include <linux/types.h> | ||
63 | #include <linux/slab.h> | ||
64 | #include <linux/export.h> | ||
65 | |||
66 | #include "iwl-debug.h" | ||
67 | #include "iwl-eeprom-read.h" | ||
68 | #include "iwl-io.h" | ||
69 | #include "iwl-prph.h" | ||
70 | #include "iwl-csr.h" | ||
71 | |||
72 | /* | ||
73 | * EEPROM access time values: | ||
74 | * | ||
75 | * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG. | ||
76 | * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1). | ||
77 | * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec. | ||
78 | * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG. | ||
79 | */ | ||
80 | #define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */ | ||
81 | |||
82 | #define IWL_EEPROM_SEM_TIMEOUT 10 /* microseconds */ | ||
83 | #define IWL_EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ | ||
84 | |||
85 | |||
86 | /* | ||
87 | * The device's EEPROM semaphore prevents conflicts between driver and uCode | ||
88 | * when accessing the EEPROM; each access is a series of pulses to/from the | ||
89 | * EEPROM chip, not a single event, so even reads could conflict if they | ||
90 | * weren't arbitrated by the semaphore. | ||
91 | */ | ||
92 | |||
93 | #define EEPROM_SEM_TIMEOUT 10 /* milliseconds */ | ||
94 | #define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ | ||
95 | |||
96 | static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans) | ||
97 | { | ||
98 | u16 count; | ||
99 | int ret; | ||
100 | |||
101 | for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { | ||
102 | /* Request semaphore */ | ||
103 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
104 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
105 | |||
106 | /* See if we got it */ | ||
107 | ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
108 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
109 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
110 | EEPROM_SEM_TIMEOUT); | ||
111 | if (ret >= 0) { | ||
112 | IWL_DEBUG_EEPROM(trans->dev, | ||
113 | "Acquired semaphore after %d tries.\n", | ||
114 | count+1); | ||
115 | return ret; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | static void iwl_eeprom_release_semaphore(struct iwl_trans *trans) | ||
123 | { | ||
124 | iwl_clear_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
125 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||
126 | } | ||
127 | |||
128 | static int iwl_eeprom_verify_signature(struct iwl_trans *trans, bool nvm_is_otp) | ||
129 | { | ||
130 | u32 gp = iwl_read32(trans, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; | ||
131 | |||
132 | IWL_DEBUG_EEPROM(trans->dev, "EEPROM signature=0x%08x\n", gp); | ||
133 | |||
134 | switch (gp) { | ||
135 | case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP: | ||
136 | if (!nvm_is_otp) { | ||
137 | IWL_ERR(trans, "EEPROM with bad signature: 0x%08x\n", | ||
138 | gp); | ||
139 | return -ENOENT; | ||
140 | } | ||
141 | return 0; | ||
142 | case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K: | ||
143 | case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K: | ||
144 | if (nvm_is_otp) { | ||
145 | IWL_ERR(trans, "OTP with bad signature: 0x%08x\n", gp); | ||
146 | return -ENOENT; | ||
147 | } | ||
148 | return 0; | ||
149 | case CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP: | ||
150 | default: | ||
151 | IWL_ERR(trans, | ||
152 | "bad EEPROM/OTP signature, type=%s, EEPROM_GP=0x%08x\n", | ||
153 | nvm_is_otp ? "OTP" : "EEPROM", gp); | ||
154 | return -ENOENT; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | /****************************************************************************** | ||
159 | * | ||
160 | * OTP related functions | ||
161 | * | ||
162 | ******************************************************************************/ | ||
163 | |||
164 | static void iwl_set_otp_access_absolute(struct iwl_trans *trans) | ||
165 | { | ||
166 | iwl_read32(trans, CSR_OTP_GP_REG); | ||
167 | |||
168 | iwl_clear_bit(trans, CSR_OTP_GP_REG, | ||
169 | CSR_OTP_GP_REG_OTP_ACCESS_MODE); | ||
170 | } | ||
171 | |||
172 | static int iwl_nvm_is_otp(struct iwl_trans *trans) | ||
173 | { | ||
174 | u32 otpgp; | ||
175 | |||
176 | /* OTP only valid for CP/PP and after */ | ||
177 | switch (trans->hw_rev & CSR_HW_REV_TYPE_MSK) { | ||
178 | case CSR_HW_REV_TYPE_NONE: | ||
179 | IWL_ERR(trans, "Unknown hardware type\n"); | ||
180 | return -EIO; | ||
181 | case CSR_HW_REV_TYPE_5300: | ||
182 | case CSR_HW_REV_TYPE_5350: | ||
183 | case CSR_HW_REV_TYPE_5100: | ||
184 | case CSR_HW_REV_TYPE_5150: | ||
185 | return 0; | ||
186 | default: | ||
187 | otpgp = iwl_read32(trans, CSR_OTP_GP_REG); | ||
188 | if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) | ||
189 | return 1; | ||
190 | return 0; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | static int iwl_init_otp_access(struct iwl_trans *trans) | ||
195 | { | ||
196 | int ret; | ||
197 | |||
198 | /* Enable 40MHz radio clock */ | ||
199 | iwl_write32(trans, CSR_GP_CNTRL, | ||
200 | iwl_read32(trans, CSR_GP_CNTRL) | | ||
201 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
202 | |||
203 | /* wait for clock to be ready */ | ||
204 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
205 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
206 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
207 | 25000); | ||
208 | if (ret < 0) { | ||
209 | IWL_ERR(trans, "Time out access OTP\n"); | ||
210 | } else { | ||
211 | iwl_set_bits_prph(trans, APMG_PS_CTRL_REG, | ||
212 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
213 | udelay(5); | ||
214 | iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG, | ||
215 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
216 | |||
217 | /* | ||
218 | * CSR auto clock gate disable bit - | ||
219 | * this is only applicable for HW with OTP shadow RAM | ||
220 | */ | ||
221 | if (trans->cfg->base_params->shadow_ram_support) | ||
222 | iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, | ||
223 | CSR_RESET_LINK_PWR_MGMT_DISABLED); | ||
224 | } | ||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr, | ||
229 | __le16 *eeprom_data) | ||
230 | { | ||
231 | int ret = 0; | ||
232 | u32 r; | ||
233 | u32 otpgp; | ||
234 | |||
235 | iwl_write32(trans, CSR_EEPROM_REG, | ||
236 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||
237 | ret = iwl_poll_bit(trans, CSR_EEPROM_REG, | ||
238 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
239 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
240 | IWL_EEPROM_ACCESS_TIMEOUT); | ||
241 | if (ret < 0) { | ||
242 | IWL_ERR(trans, "Time out reading OTP[%d]\n", addr); | ||
243 | return ret; | ||
244 | } | ||
245 | r = iwl_read32(trans, CSR_EEPROM_REG); | ||
246 | /* check for ECC errors: */ | ||
247 | otpgp = iwl_read32(trans, CSR_OTP_GP_REG); | ||
248 | if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { | ||
249 | /* stop in this case */ | ||
250 | /* set the uncorrectable OTP ECC bit for acknowledgement */ | ||
251 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
252 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | ||
253 | IWL_ERR(trans, "Uncorrectable OTP ECC error, abort OTP read\n"); | ||
254 | return -EINVAL; | ||
255 | } | ||
256 | if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { | ||
257 | /* continue in this case */ | ||
258 | /* set the correctable OTP ECC bit for acknowledgement */ | ||
259 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
260 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); | ||
261 | IWL_ERR(trans, "Correctable OTP ECC error, continue read\n"); | ||
262 | } | ||
263 | *eeprom_data = cpu_to_le16(r >> 16); | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | /* | ||
268 | * iwl_is_otp_empty: check for empty OTP | ||
269 | */ | ||
270 | static bool iwl_is_otp_empty(struct iwl_trans *trans) | ||
271 | { | ||
272 | u16 next_link_addr = 0; | ||
273 | __le16 link_value; | ||
274 | bool is_empty = false; | ||
275 | |||
276 | /* locate the beginning of OTP link list */ | ||
277 | if (!iwl_read_otp_word(trans, next_link_addr, &link_value)) { | ||
278 | if (!link_value) { | ||
279 | IWL_ERR(trans, "OTP is empty\n"); | ||
280 | is_empty = true; | ||
281 | } | ||
282 | } else { | ||
283 | IWL_ERR(trans, "Unable to read first block of OTP list.\n"); | ||
284 | is_empty = true; | ||
285 | } | ||
286 | |||
287 | return is_empty; | ||
288 | } | ||
289 | |||
290 | |||
291 | /* | ||
292 | * iwl_find_otp_image: find EEPROM image in OTP | ||
293 | * finding the OTP block that contains the EEPROM image. | ||
294 | * the last valid block on the link list (the block _before_ the last block) | ||
295 | * is the block we should read and used to configure the device. | ||
296 | * If all the available OTP blocks are full, the last block will be the block | ||
297 | * we should read and used to configure the device. | ||
298 | * only perform this operation if shadow RAM is disabled | ||
299 | */ | ||
300 | static int iwl_find_otp_image(struct iwl_trans *trans, | ||
301 | u16 *validblockaddr) | ||
302 | { | ||
303 | u16 next_link_addr = 0, valid_addr; | ||
304 | __le16 link_value = 0; | ||
305 | int usedblocks = 0; | ||
306 | |||
307 | /* set addressing mode to absolute to traverse the link list */ | ||
308 | iwl_set_otp_access_absolute(trans); | ||
309 | |||
310 | /* checking for empty OTP or error */ | ||
311 | if (iwl_is_otp_empty(trans)) | ||
312 | return -EINVAL; | ||
313 | |||
314 | /* | ||
315 | * start traverse link list | ||
316 | * until reach the max number of OTP blocks | ||
317 | * different devices have different number of OTP blocks | ||
318 | */ | ||
319 | do { | ||
320 | /* save current valid block address | ||
321 | * check for more block on the link list | ||
322 | */ | ||
323 | valid_addr = next_link_addr; | ||
324 | next_link_addr = le16_to_cpu(link_value) * sizeof(u16); | ||
325 | IWL_DEBUG_EEPROM(trans->dev, "OTP blocks %d addr 0x%x\n", | ||
326 | usedblocks, next_link_addr); | ||
327 | if (iwl_read_otp_word(trans, next_link_addr, &link_value)) | ||
328 | return -EINVAL; | ||
329 | if (!link_value) { | ||
330 | /* | ||
331 | * reach the end of link list, return success and | ||
332 | * set address point to the starting address | ||
333 | * of the image | ||
334 | */ | ||
335 | *validblockaddr = valid_addr; | ||
336 | /* skip first 2 bytes (link list pointer) */ | ||
337 | *validblockaddr += 2; | ||
338 | return 0; | ||
339 | } | ||
340 | /* more in the link list, continue */ | ||
341 | usedblocks++; | ||
342 | } while (usedblocks <= trans->cfg->base_params->max_ll_items); | ||
343 | |||
344 | /* OTP has no valid blocks */ | ||
345 | IWL_DEBUG_EEPROM(trans->dev, "OTP has no valid blocks\n"); | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | |||
349 | /** | ||
350 | * iwl_read_eeprom - read EEPROM contents | ||
351 | * | ||
352 | * Load the EEPROM contents from adapter and return it | ||
353 | * and its size. | ||
354 | * | ||
355 | * NOTE: This routine uses the non-debug IO access functions. | ||
356 | */ | ||
357 | int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) | ||
358 | { | ||
359 | __le16 *e; | ||
360 | u32 gp = iwl_read32(trans, CSR_EEPROM_GP); | ||
361 | int sz; | ||
362 | int ret; | ||
363 | u16 addr; | ||
364 | u16 validblockaddr = 0; | ||
365 | u16 cache_addr = 0; | ||
366 | int nvm_is_otp; | ||
367 | |||
368 | if (!eeprom || !eeprom_size) | ||
369 | return -EINVAL; | ||
370 | |||
371 | nvm_is_otp = iwl_nvm_is_otp(trans); | ||
372 | if (nvm_is_otp < 0) | ||
373 | return nvm_is_otp; | ||
374 | |||
375 | sz = trans->cfg->base_params->eeprom_size; | ||
376 | IWL_DEBUG_EEPROM(trans->dev, "NVM size = %d\n", sz); | ||
377 | |||
378 | e = kmalloc(sz, GFP_KERNEL); | ||
379 | if (!e) | ||
380 | return -ENOMEM; | ||
381 | |||
382 | ret = iwl_eeprom_verify_signature(trans, nvm_is_otp); | ||
383 | if (ret < 0) { | ||
384 | IWL_ERR(trans, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); | ||
385 | goto err_free; | ||
386 | } | ||
387 | |||
388 | /* Make sure driver (instead of uCode) is allowed to read EEPROM */ | ||
389 | ret = iwl_eeprom_acquire_semaphore(trans); | ||
390 | if (ret < 0) { | ||
391 | IWL_ERR(trans, "Failed to acquire EEPROM semaphore.\n"); | ||
392 | goto err_free; | ||
393 | } | ||
394 | |||
395 | if (nvm_is_otp) { | ||
396 | ret = iwl_init_otp_access(trans); | ||
397 | if (ret) { | ||
398 | IWL_ERR(trans, "Failed to initialize OTP access.\n"); | ||
399 | goto err_unlock; | ||
400 | } | ||
401 | |||
402 | iwl_write32(trans, CSR_EEPROM_GP, | ||
403 | iwl_read32(trans, CSR_EEPROM_GP) & | ||
404 | ~CSR_EEPROM_GP_IF_OWNER_MSK); | ||
405 | |||
406 | iwl_set_bit(trans, CSR_OTP_GP_REG, | ||
407 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | | ||
408 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | ||
409 | /* traversing the linked list if no shadow ram supported */ | ||
410 | if (!trans->cfg->base_params->shadow_ram_support) { | ||
411 | ret = iwl_find_otp_image(trans, &validblockaddr); | ||
412 | if (ret) | ||
413 | goto err_unlock; | ||
414 | } | ||
415 | for (addr = validblockaddr; addr < validblockaddr + sz; | ||
416 | addr += sizeof(u16)) { | ||
417 | __le16 eeprom_data; | ||
418 | |||
419 | ret = iwl_read_otp_word(trans, addr, &eeprom_data); | ||
420 | if (ret) | ||
421 | goto err_unlock; | ||
422 | e[cache_addr / 2] = eeprom_data; | ||
423 | cache_addr += sizeof(u16); | ||
424 | } | ||
425 | } else { | ||
426 | /* eeprom is an array of 16bit values */ | ||
427 | for (addr = 0; addr < sz; addr += sizeof(u16)) { | ||
428 | u32 r; | ||
429 | |||
430 | iwl_write32(trans, CSR_EEPROM_REG, | ||
431 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||
432 | |||
433 | ret = iwl_poll_bit(trans, CSR_EEPROM_REG, | ||
434 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
435 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
436 | IWL_EEPROM_ACCESS_TIMEOUT); | ||
437 | if (ret < 0) { | ||
438 | IWL_ERR(trans, | ||
439 | "Time out reading EEPROM[%d]\n", addr); | ||
440 | goto err_unlock; | ||
441 | } | ||
442 | r = iwl_read32(trans, CSR_EEPROM_REG); | ||
443 | e[addr / 2] = cpu_to_le16(r >> 16); | ||
444 | } | ||
445 | } | ||
446 | |||
447 | IWL_DEBUG_EEPROM(trans->dev, "NVM Type: %s\n", | ||
448 | nvm_is_otp ? "OTP" : "EEPROM"); | ||
449 | |||
450 | iwl_eeprom_release_semaphore(trans); | ||
451 | |||
452 | *eeprom_size = sz; | ||
453 | *eeprom = (u8 *)e; | ||
454 | return 0; | ||
455 | |||
456 | err_unlock: | ||
457 | iwl_eeprom_release_semaphore(trans); | ||
458 | err_free: | ||
459 | kfree(e); | ||
460 | |||
461 | return ret; | ||
462 | } | ||
463 | EXPORT_SYMBOL_GPL(iwl_read_eeprom); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h new file mode 100644 index 000000000000..1337c9d36fee --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-read.h | |||
@@ -0,0 +1,70 @@ | |||
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 - 2012 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 - 2012 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_eeprom_h__ | ||
64 | #define __iwl_eeprom_h__ | ||
65 | |||
66 | #include "iwl-trans.h" | ||
67 | |||
68 | int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size); | ||
69 | |||
70 | #endif /* __iwl_eeprom_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/1000.c b/drivers/net/wireless/iwlwifi/pcie/1000.c index 174cf5e38962..0269ea6a5c35 100644 --- a/drivers/net/wireless/iwlwifi/pcie/1000.c +++ b/drivers/net/wireless/iwlwifi/pcie/1000.c | |||
@@ -74,6 +74,18 @@ static const struct iwl_ht_params iwl1000_ht_params = { | |||
74 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ), | 74 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ), |
75 | }; | 75 | }; |
76 | 76 | ||
77 | static const struct iwl_eeprom_params iwl1000_eeprom_params = { | ||
78 | .regulatory_bands = { | ||
79 | EEPROM_REG_BAND_1_CHANNELS, | ||
80 | EEPROM_REG_BAND_2_CHANNELS, | ||
81 | EEPROM_REG_BAND_3_CHANNELS, | ||
82 | EEPROM_REG_BAND_4_CHANNELS, | ||
83 | EEPROM_REG_BAND_5_CHANNELS, | ||
84 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
85 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
86 | } | ||
87 | }; | ||
88 | |||
77 | #define IWL_DEVICE_1000 \ | 89 | #define IWL_DEVICE_1000 \ |
78 | .fw_name_pre = IWL1000_FW_PRE, \ | 90 | .fw_name_pre = IWL1000_FW_PRE, \ |
79 | .ucode_api_max = IWL1000_UCODE_API_MAX, \ | 91 | .ucode_api_max = IWL1000_UCODE_API_MAX, \ |
@@ -85,6 +97,7 @@ static const struct iwl_ht_params iwl1000_ht_params = { | |||
85 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ | 97 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ |
86 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ | 98 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ |
87 | .base_params = &iwl1000_base_params, \ | 99 | .base_params = &iwl1000_base_params, \ |
100 | .eeprom_params = &iwl1000_eeprom_params, \ | ||
88 | .led_mode = IWL_LED_BLINK | 101 | .led_mode = IWL_LED_BLINK |
89 | 102 | ||
90 | const struct iwl_cfg iwl1000_bgn_cfg = { | 103 | const struct iwl_cfg iwl1000_bgn_cfg = { |
@@ -109,6 +122,7 @@ const struct iwl_cfg iwl1000_bg_cfg = { | |||
109 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ | 122 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ |
110 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ | 123 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ |
111 | .base_params = &iwl1000_base_params, \ | 124 | .base_params = &iwl1000_base_params, \ |
125 | .eeprom_params = &iwl1000_eeprom_params, \ | ||
112 | .led_mode = IWL_LED_RF_STATE, \ | 126 | .led_mode = IWL_LED_RF_STATE, \ |
113 | .rx_with_siso_diversity = true | 127 | .rx_with_siso_diversity = true |
114 | 128 | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/2000.c b/drivers/net/wireless/iwlwifi/pcie/2000.c index 8d4d7295aa46..fd4e78f56fa6 100644 --- a/drivers/net/wireless/iwlwifi/pcie/2000.c +++ b/drivers/net/wireless/iwlwifi/pcie/2000.c | |||
@@ -117,6 +117,19 @@ static const struct iwl_bt_params iwl2030_bt_params = { | |||
117 | .bt_session_2 = true, | 117 | .bt_session_2 = true, |
118 | }; | 118 | }; |
119 | 119 | ||
120 | static const struct iwl_eeprom_params iwl20x0_eeprom_params = { | ||
121 | .regulatory_bands = { | ||
122 | EEPROM_REG_BAND_1_CHANNELS, | ||
123 | EEPROM_REG_BAND_2_CHANNELS, | ||
124 | EEPROM_REG_BAND_3_CHANNELS, | ||
125 | EEPROM_REG_BAND_4_CHANNELS, | ||
126 | EEPROM_REG_BAND_5_CHANNELS, | ||
127 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
128 | EEPROM_REGULATORY_BAND_NO_HT40, | ||
129 | }, | ||
130 | .enhanced_txpower = true, | ||
131 | }; | ||
132 | |||
120 | #define IWL_DEVICE_2000 \ | 133 | #define IWL_DEVICE_2000 \ |
121 | .fw_name_pre = IWL2000_FW_PRE, \ | 134 | .fw_name_pre = IWL2000_FW_PRE, \ |
122 | .ucode_api_max = IWL2000_UCODE_API_MAX, \ | 135 | .ucode_api_max = IWL2000_UCODE_API_MAX, \ |
@@ -128,6 +141,7 @@ static const struct iwl_bt_params iwl2030_bt_params = { | |||
128 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ | 141 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ |
129 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 142 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
130 | .base_params = &iwl2000_base_params, \ | 143 | .base_params = &iwl2000_base_params, \ |
144 | .eeprom_params = &iwl20x0_eeprom_params, \ | ||
131 | .need_temp_offset_calib = true, \ | 145 | .need_temp_offset_calib = true, \ |
132 | .temp_offset_v2 = true, \ | 146 | .temp_offset_v2 = true, \ |
133 | .led_mode = IWL_LED_RF_STATE | 147 | .led_mode = IWL_LED_RF_STATE |
@@ -156,6 +170,7 @@ const struct iwl_cfg iwl2000_2bgn_d_cfg = { | |||
156 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 170 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
157 | .base_params = &iwl2030_base_params, \ | 171 | .base_params = &iwl2030_base_params, \ |
158 | .bt_params = &iwl2030_bt_params, \ | 172 | .bt_params = &iwl2030_bt_params, \ |
173 | .eeprom_params = &iwl20x0_eeprom_params, \ | ||
159 | .need_temp_offset_calib = true, \ | 174 | .need_temp_offset_calib = true, \ |
160 | .temp_offset_v2 = true, \ | 175 | .temp_offset_v2 = true, \ |
161 | .led_mode = IWL_LED_RF_STATE, \ | 176 | .led_mode = IWL_LED_RF_STATE, \ |
@@ -178,6 +193,7 @@ const struct iwl_cfg iwl2030_2bgn_cfg = { | |||
178 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ | 193 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ |
179 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 194 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
180 | .base_params = &iwl2000_base_params, \ | 195 | .base_params = &iwl2000_base_params, \ |
196 | .eeprom_params = &iwl20x0_eeprom_params, \ | ||
181 | .need_temp_offset_calib = true, \ | 197 | .need_temp_offset_calib = true, \ |
182 | .temp_offset_v2 = true, \ | 198 | .temp_offset_v2 = true, \ |
183 | .led_mode = IWL_LED_RF_STATE, \ | 199 | .led_mode = IWL_LED_RF_STATE, \ |
@@ -208,6 +224,7 @@ const struct iwl_cfg iwl105_bgn_d_cfg = { | |||
208 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 224 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
209 | .base_params = &iwl2030_base_params, \ | 225 | .base_params = &iwl2030_base_params, \ |
210 | .bt_params = &iwl2030_bt_params, \ | 226 | .bt_params = &iwl2030_bt_params, \ |
227 | .eeprom_params = &iwl20x0_eeprom_params, \ | ||
211 | .need_temp_offset_calib = true, \ | 228 | .need_temp_offset_calib = true, \ |
212 | .temp_offset_v2 = true, \ | 229 | .temp_offset_v2 = true, \ |
213 | .led_mode = IWL_LED_RF_STATE, \ | 230 | .led_mode = IWL_LED_RF_STATE, \ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/5000.c b/drivers/net/wireless/iwlwifi/pcie/5000.c index 75d90a9c184a..745a358ab8e8 100644 --- a/drivers/net/wireless/iwlwifi/pcie/5000.c +++ b/drivers/net/wireless/iwlwifi/pcie/5000.c | |||
@@ -72,6 +72,18 @@ static const struct iwl_ht_params iwl5000_ht_params = { | |||
72 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), | 72 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), |
73 | }; | 73 | }; |
74 | 74 | ||
75 | static const struct iwl_eeprom_params iwl5000_eeprom_params = { | ||
76 | .regulatory_bands = { | ||
77 | EEPROM_REG_BAND_1_CHANNELS, | ||
78 | EEPROM_REG_BAND_2_CHANNELS, | ||
79 | EEPROM_REG_BAND_3_CHANNELS, | ||
80 | EEPROM_REG_BAND_4_CHANNELS, | ||
81 | EEPROM_REG_BAND_5_CHANNELS, | ||
82 | EEPROM_REG_BAND_24_HT40_CHANNELS, | ||
83 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
84 | }, | ||
85 | }; | ||
86 | |||
75 | #define IWL_DEVICE_5000 \ | 87 | #define IWL_DEVICE_5000 \ |
76 | .fw_name_pre = IWL5000_FW_PRE, \ | 88 | .fw_name_pre = IWL5000_FW_PRE, \ |
77 | .ucode_api_max = IWL5000_UCODE_API_MAX, \ | 89 | .ucode_api_max = IWL5000_UCODE_API_MAX, \ |
@@ -83,6 +95,7 @@ static const struct iwl_ht_params iwl5000_ht_params = { | |||
83 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, \ | 95 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, \ |
84 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, \ | 96 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, \ |
85 | .base_params = &iwl5000_base_params, \ | 97 | .base_params = &iwl5000_base_params, \ |
98 | .eeprom_params = &iwl5000_eeprom_params, \ | ||
86 | .led_mode = IWL_LED_BLINK | 99 | .led_mode = IWL_LED_BLINK |
87 | 100 | ||
88 | const struct iwl_cfg iwl5300_agn_cfg = { | 101 | const struct iwl_cfg iwl5300_agn_cfg = { |
@@ -129,6 +142,7 @@ const struct iwl_cfg iwl5350_agn_cfg = { | |||
129 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 142 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
130 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 143 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
131 | .base_params = &iwl5000_base_params, | 144 | .base_params = &iwl5000_base_params, |
145 | .eeprom_params = &iwl5000_eeprom_params, | ||
132 | .ht_params = &iwl5000_ht_params, | 146 | .ht_params = &iwl5000_ht_params, |
133 | .led_mode = IWL_LED_BLINK, | 147 | .led_mode = IWL_LED_BLINK, |
134 | .internal_wimax_coex = true, | 148 | .internal_wimax_coex = true, |
@@ -145,6 +159,7 @@ const struct iwl_cfg iwl5350_agn_cfg = { | |||
145 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, \ | 159 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, \ |
146 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ | 160 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ |
147 | .base_params = &iwl5000_base_params, \ | 161 | .base_params = &iwl5000_base_params, \ |
162 | .eeprom_params = &iwl5000_eeprom_params, \ | ||
148 | .no_xtal_calib = true, \ | 163 | .no_xtal_calib = true, \ |
149 | .led_mode = IWL_LED_BLINK, \ | 164 | .led_mode = IWL_LED_BLINK, \ |
150 | .internal_wimax_coex = true | 165 | .internal_wimax_coex = true |
diff --git a/drivers/net/wireless/iwlwifi/pcie/6000.c b/drivers/net/wireless/iwlwifi/pcie/6000.c index 7b9c02cc67e5..8dd8a6fe61e8 100644 --- a/drivers/net/wireless/iwlwifi/pcie/6000.c +++ b/drivers/net/wireless/iwlwifi/pcie/6000.c | |||
@@ -136,6 +136,19 @@ static const struct iwl_bt_params iwl6000_bt_params = { | |||
136 | .bt_sco_disable = true, | 136 | .bt_sco_disable = true, |
137 | }; | 137 | }; |
138 | 138 | ||
139 | static const struct iwl_eeprom_params iwl6000_eeprom_params = { | ||
140 | .regulatory_bands = { | ||
141 | EEPROM_REG_BAND_1_CHANNELS, | ||
142 | EEPROM_REG_BAND_2_CHANNELS, | ||
143 | EEPROM_REG_BAND_3_CHANNELS, | ||
144 | EEPROM_REG_BAND_4_CHANNELS, | ||
145 | EEPROM_REG_BAND_5_CHANNELS, | ||
146 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
147 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
148 | }, | ||
149 | .enhanced_txpower = true, | ||
150 | }; | ||
151 | |||
139 | #define IWL_DEVICE_6005 \ | 152 | #define IWL_DEVICE_6005 \ |
140 | .fw_name_pre = IWL6005_FW_PRE, \ | 153 | .fw_name_pre = IWL6005_FW_PRE, \ |
141 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ | 154 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ |
@@ -147,6 +160,7 @@ static const struct iwl_bt_params iwl6000_bt_params = { | |||
147 | .eeprom_ver = EEPROM_6005_EEPROM_VERSION, \ | 160 | .eeprom_ver = EEPROM_6005_EEPROM_VERSION, \ |
148 | .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ | 161 | .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ |
149 | .base_params = &iwl6000_g2_base_params, \ | 162 | .base_params = &iwl6000_g2_base_params, \ |
163 | .eeprom_params = &iwl6000_eeprom_params, \ | ||
150 | .need_temp_offset_calib = true, \ | 164 | .need_temp_offset_calib = true, \ |
151 | .led_mode = IWL_LED_RF_STATE | 165 | .led_mode = IWL_LED_RF_STATE |
152 | 166 | ||
@@ -202,6 +216,7 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = { | |||
202 | .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ | 216 | .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ |
203 | .base_params = &iwl6000_g2_base_params, \ | 217 | .base_params = &iwl6000_g2_base_params, \ |
204 | .bt_params = &iwl6000_bt_params, \ | 218 | .bt_params = &iwl6000_bt_params, \ |
219 | .eeprom_params = &iwl6000_eeprom_params, \ | ||
205 | .need_temp_offset_calib = true, \ | 220 | .need_temp_offset_calib = true, \ |
206 | .led_mode = IWL_LED_RF_STATE, \ | 221 | .led_mode = IWL_LED_RF_STATE, \ |
207 | .adv_pm = true \ | 222 | .adv_pm = true \ |
@@ -274,6 +289,7 @@ const struct iwl_cfg iwl130_bg_cfg = { | |||
274 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, \ | 289 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, \ |
275 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \ | 290 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \ |
276 | .base_params = &iwl6000_base_params, \ | 291 | .base_params = &iwl6000_base_params, \ |
292 | .eeprom_params = &iwl6000_eeprom_params, \ | ||
277 | .led_mode = IWL_LED_BLINK | 293 | .led_mode = IWL_LED_BLINK |
278 | 294 | ||
279 | const struct iwl_cfg iwl6000i_2agn_cfg = { | 295 | const struct iwl_cfg iwl6000i_2agn_cfg = { |
@@ -304,6 +320,7 @@ const struct iwl_cfg iwl6000i_2bg_cfg = { | |||
304 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, \ | 320 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, \ |
305 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, \ | 321 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, \ |
306 | .base_params = &iwl6050_base_params, \ | 322 | .base_params = &iwl6050_base_params, \ |
323 | .eeprom_params = &iwl6000_eeprom_params, \ | ||
307 | .led_mode = IWL_LED_BLINK, \ | 324 | .led_mode = IWL_LED_BLINK, \ |
308 | .internal_wimax_coex = true | 325 | .internal_wimax_coex = true |
309 | 326 | ||
@@ -328,6 +345,7 @@ const struct iwl_cfg iwl6050_2abg_cfg = { | |||
328 | .eeprom_ver = EEPROM_6150_EEPROM_VERSION, \ | 345 | .eeprom_ver = EEPROM_6150_EEPROM_VERSION, \ |
329 | .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION, \ | 346 | .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION, \ |
330 | .base_params = &iwl6050_base_params, \ | 347 | .base_params = &iwl6050_base_params, \ |
348 | .eeprom_params = &iwl6000_eeprom_params, \ | ||
331 | .led_mode = IWL_LED_BLINK, \ | 349 | .led_mode = IWL_LED_BLINK, \ |
332 | .internal_wimax_coex = true | 350 | .internal_wimax_coex = true |
333 | 351 | ||
@@ -354,6 +372,7 @@ const struct iwl_cfg iwl6000_3agn_cfg = { | |||
354 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 372 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
355 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, | 373 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
356 | .base_params = &iwl6000_base_params, | 374 | .base_params = &iwl6000_base_params, |
375 | .eeprom_params = &iwl6000_eeprom_params, | ||
357 | .ht_params = &iwl6000_ht_params, | 376 | .ht_params = &iwl6000_ht_params, |
358 | .led_mode = IWL_LED_BLINK, | 377 | .led_mode = IWL_LED_BLINK, |
359 | }; | 378 | }; |