aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/dvm/main.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-05-21 05:55:54 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-06-06 07:24:19 -0400
commit26a7ca9a71a3f7e1826de96b1a1e907123e11b07 (patch)
tree7ab52c58fdd876bacf112c1bfceeac865f196704 /drivers/net/wireless/iwlwifi/dvm/main.c
parent08838cdeca65e754af5c755a05f6cdb1c632eda8 (diff)
iwlwifi: refactor EEPROM reading/parsing
The EEPROM reading/parsing code is all mixed in the driver today, and the EEPROM is parsed only when we access data from it. This is problematic because the NVM needs to be parsed and that is independent of reading it. Also, the NVM format for new devices will be different and probably require a new parser. Therefore refactor the reading and parsing and create two independent components. Reading the EEPROM requires direct hardware accesses and therefore access to the transport, but parsing is independent and can be done on an NVM blob. Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/dvm/main.c')
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/main.c301
1 files changed, 57 insertions, 244 deletions
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
1129static 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 */
1151static 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 */
1208static 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 */
1331static 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
1338static int iwl_init_drv(struct iwl_priv *priv) 1128static 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
1395err_free_channel_map:
1396 iwl_free_channel_map(priv);
1397err:
1398 return ret;
1399} 1167}
1400 1168
1401static void iwl_uninit_drv(struct iwl_priv *priv) 1169static 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
1229static 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
1463static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, 1265static 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);
1530out_free_eeprom_blob:
1531 kfree(priv->eeprom_blob);
1720out_free_eeprom: 1532out_free_eeprom:
1721 iwl_eeprom_free(priv); 1533 iwl_free_eeprom_data(priv->eeprom_data);
1722out_free_hw: 1534out_free_hw:
1723 ieee80211_free_hw(priv->hw); 1535 ieee80211_free_hw(priv->hw);
1724out: 1536out:
@@ -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);