Skip to content

Commit

Permalink
iwlwifi: refactor EEPROM reading/parsing
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Johannes Berg committed Jun 6, 2012
1 parent 08838cd commit 26a7ca9
Show file tree
Hide file tree
Showing 32 changed files with 1,854 additions and 1,996 deletions.
1 change: 1 addition & 0 deletions drivers/net/wireless/iwlwifi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ iwlwifi-objs += iwl-io.o
iwlwifi-objs += iwl-drv.o
iwlwifi-objs += iwl-debug.o
iwlwifi-objs += iwl-notif-wait.o
iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o
iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
iwlwifi-objs += pcie/1000.o pcie/2000.o pcie/5000.o pcie/6000.o

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/iwlwifi/dvm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ obj-$(CONFIG_IWLDVM) += iwldvm.o
iwldvm-objs += main.o rs.o mac80211.o ucode.o tx.o
iwldvm-objs += lib.o calib.o tt.o sta.o rx.o

iwldvm-objs += eeprom.o power.o
iwldvm-objs += power.o
iwldvm-objs += scan.o led.o
iwldvm-objs += rxon.o devices.o

Expand Down
5 changes: 1 addition & 4 deletions drivers/net/wireless/iwlwifi/dvm/agn.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ extern struct iwl_lib_ops iwl6030_lib;
#define STATUS_CT_KILL 1
#define STATUS_ALIVE 2
#define STATUS_READY 3
#define STATUS_GEO_CONFIGURED 4
#define STATUS_EXIT_PENDING 5
#define STATUS_STATISTICS 6
#define STATUS_SCANNING 7
Expand Down Expand Up @@ -443,10 +442,8 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,

static inline int iwl_is_ready(struct iwl_priv *priv)
{
/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
* set but EXIT_PENDING is not */
/* The adapter is 'ready' if READY EXIT_PENDING is not set */
return test_bit(STATUS_READY, &priv->status) &&
test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
!test_bit(STATUS_EXIT_PENDING, &priv->status);
}

Expand Down
17 changes: 9 additions & 8 deletions drivers/net/wireless/iwlwifi/dvm/calib.c
Original file line number Diff line number Diff line change
Expand Up @@ -833,14 +833,14 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
* To be safe, simply mask out any chains that we know
* are not on the device.
*/
active_chains &= priv->hw_params.valid_rx_ant;
active_chains &= priv->eeprom_data->valid_rx_ant;

num_tx_chains = 0;
for (i = 0; i < NUM_RX_CHAINS; i++) {
/* loops on all the bits of
* priv->hw_setting.valid_tx_ant */
u8 ant_msk = (1 << i);
if (!(priv->hw_params.valid_tx_ant & ant_msk))
if (!(priv->eeprom_data->valid_tx_ant & ant_msk))
continue;

num_tx_chains++;
Expand All @@ -854,7 +854,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
* connect the first valid tx chain
*/
first_chain =
find_first_chain(priv->hw_params.valid_tx_ant);
find_first_chain(priv->eeprom_data->valid_tx_ant);
data->disconn_array[first_chain] = 0;
active_chains |= BIT(first_chain);
IWL_DEBUG_CALIB(priv,
Expand All @@ -864,13 +864,13 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
}
}

if (active_chains != priv->hw_params.valid_rx_ant &&
if (active_chains != priv->eeprom_data->valid_rx_ant &&
active_chains != priv->chain_noise_data.active_chains)
IWL_DEBUG_CALIB(priv,
"Detected that not all antennas are connected! "
"Connected: %#x, valid: %#x.\n",
active_chains,
priv->hw_params.valid_rx_ant);
priv->eeprom_data->valid_rx_ant);

/* Save for use within RXON, TX, SCAN commands, etc. */
data->active_chains = active_chains;
Expand Down Expand Up @@ -1055,7 +1055,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
priv->cfg->bt_params->advanced_bt_coexist) {
/* Disable disconnected antenna algorithm for advanced
bt coex, assuming valid antennas are connected */
data->active_chains = priv->hw_params.valid_rx_ant;
data->active_chains = priv->eeprom_data->valid_rx_ant;
for (i = 0; i < NUM_RX_CHAINS; i++)
if (!(data->active_chains & (1<<i)))
data->disconn_array[i] = 1;
Expand Down Expand Up @@ -1084,8 +1084,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n",
min_average_noise, min_average_noise_antenna_i);

iwlagn_gain_computation(priv, average_noise,
find_first_chain(priv->hw_params.valid_rx_ant));
iwlagn_gain_computation(
priv, average_noise,
find_first_chain(priv->eeprom_data->valid_rx_ant));

/* Some power changes may have been made during the calibration.
* Update and commit the RXON
Expand Down
23 changes: 8 additions & 15 deletions drivers/net/wireless/iwlwifi/dvm/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,13 +303,13 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
const u8 *ptr;
char *buf;
u16 eeprom_ver;
size_t eeprom_len = priv->cfg->base_params->eeprom_size;
size_t eeprom_len = priv->eeprom_blob_size;
buf_size = 4 * eeprom_len + 256;

if (eeprom_len % 16)
return -ENODATA;

ptr = priv->eeprom;
ptr = priv->eeprom_blob;
if (!ptr)
return -ENOMEM;

Expand All @@ -318,11 +318,9 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
if (!buf)
return -ENOMEM;

eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, "
"version: 0x%x\n",
(priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
? "OTP" : "EEPROM", eeprom_ver);
eeprom_ver = priv->eeprom_data->eeprom_version;
pos += scnprintf(buf + pos, buf_size - pos,
"NVM version: 0x%x\n", eeprom_ver);
for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {
pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
Expand All @@ -347,9 +345,6 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
char *buf;
ssize_t ret;

if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
return -EAGAIN;

buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf)
return -ENOMEM;
Expand Down Expand Up @@ -422,8 +417,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
test_bit(STATUS_ALIVE, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
test_bit(STATUS_READY, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
test_bit(STATUS_GEO_CONFIGURED, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
test_bit(STATUS_EXIT_PENDING, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
Expand Down Expand Up @@ -1337,17 +1330,17 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) {
pos += scnprintf(buf + pos, bufsz - pos,
"tx power: (1/2 dB step)\n");
if ((priv->hw_params.valid_tx_ant & ANT_A) &&
if ((priv->eeprom_data->valid_tx_ant & ANT_A) &&
tx->tx_power.ant_a)
pos += scnprintf(buf + pos, bufsz - pos,
fmt_hex, "antenna A:",
tx->tx_power.ant_a);
if ((priv->hw_params.valid_tx_ant & ANT_B) &&
if ((priv->eeprom_data->valid_tx_ant & ANT_B) &&
tx->tx_power.ant_b)
pos += scnprintf(buf + pos, bufsz - pos,
fmt_hex, "antenna B:",
tx->tx_power.ant_b);
if ((priv->hw_params.valid_tx_ant & ANT_C) &&
if ((priv->eeprom_data->valid_tx_ant & ANT_C) &&
tx->tx_power.ant_c)
pos += scnprintf(buf + pos, bufsz - pos,
fmt_hex, "antenna C:",
Expand Down
128 changes: 6 additions & 122 deletions drivers/net/wireless/iwlwifi/dvm/dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@
#include <linux/mutex.h>

#include "iwl-fw.h"
#include "iwl-eeprom-parse.h"
#include "iwl-csr.h"
#include "iwl-debug.h"
#include "iwl-agn-hw.h"
#include "iwl-op-mode.h"
#include "iwl-notif-wait.h"
#include "iwl-trans.h"

#include "eeprom.h"
#include "led.h"
#include "power.h"
#include "rs.h"
Expand Down Expand Up @@ -88,33 +88,6 @@

#define IWL_NUM_SCAN_RATES (2)

/*
* One for each channel, holds all channel setup data
* Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant
* with one another!
*/
struct iwl_channel_info {
struct iwl_eeprom_channel eeprom; /* EEPROM regulatory limit */
struct iwl_eeprom_channel ht40_eeprom; /* EEPROM regulatory limit for
* HT40 channel */

u8 channel; /* channel number */
u8 flags; /* flags copied from EEPROM */
s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
s8 curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) limit */
s8 min_power; /* always 0 */
s8 scan_power; /* (dBm) regul. eeprom, direct scans, any rate */

u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */
u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */
enum ieee80211_band band;

/* HT40 channel info */
s8 ht40_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
u8 ht40_flags; /* flags copied from EEPROM */
u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */
};

/*
* Minimum number of queues. MAX_NUM is defined in hw specific files.
* Set the minimum to accommodate
Expand Down Expand Up @@ -154,29 +127,6 @@ union iwl_ht_rate_supp {
};
};

#define CFG_HT_RX_AMPDU_FACTOR_8K (0x0)
#define CFG_HT_RX_AMPDU_FACTOR_16K (0x1)
#define CFG_HT_RX_AMPDU_FACTOR_32K (0x2)
#define CFG_HT_RX_AMPDU_FACTOR_64K (0x3)
#define CFG_HT_RX_AMPDU_FACTOR_DEF CFG_HT_RX_AMPDU_FACTOR_64K
#define CFG_HT_RX_AMPDU_FACTOR_MAX CFG_HT_RX_AMPDU_FACTOR_64K
#define CFG_HT_RX_AMPDU_FACTOR_MIN CFG_HT_RX_AMPDU_FACTOR_8K

/*
* Maximal MPDU density for TX aggregation
* 4 - 2us density
* 5 - 4us density
* 6 - 8us density
* 7 - 16us density
*/
#define CFG_HT_MPDU_DENSITY_2USEC (0x4)
#define CFG_HT_MPDU_DENSITY_4USEC (0x5)
#define CFG_HT_MPDU_DENSITY_8USEC (0x6)
#define CFG_HT_MPDU_DENSITY_16USEC (0x7)
#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC
#define CFG_HT_MPDU_DENSITY_MAX CFG_HT_MPDU_DENSITY_16USEC
#define CFG_HT_MPDU_DENSITY_MIN (0x1)

struct iwl_ht_config {
bool single_chain_sufficient;
enum ieee80211_smps_mode smps; /* current smps mode */
Expand Down Expand Up @@ -446,23 +396,6 @@ enum {
MEASUREMENT_ACTIVE = (1 << 1),
};

enum iwl_nvm_type {
NVM_DEVICE_TYPE_EEPROM = 0,
NVM_DEVICE_TYPE_OTP,
};

/*
* Two types of OTP memory access modes
* IWL_OTP_ACCESS_ABSOLUTE - absolute address mode,
* based on physical memory addressing
* IWL_OTP_ACCESS_RELATIVE - relative address mode,
* based on logical memory addressing
*/
enum iwl_access_mode {
IWL_OTP_ACCESS_ABSOLUTE,
IWL_OTP_ACCESS_RELATIVE,
};

/* reply_tx_statistics (for _agn devices) */
struct reply_tx_error_statistics {
u32 pp_delay;
Expand Down Expand Up @@ -633,8 +566,6 @@ enum iwl_scan_type {
*
* @tx_chains_num: Number of TX chains
* @rx_chains_num: Number of RX chains
* @valid_tx_ant: usable antennas for TX
* @valid_rx_ant: usable antennas for RX
* @sku: sku read from EEPROM
* @ct_kill_threshold: temperature threshold - in hw dependent unit
* @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit
Expand All @@ -645,8 +576,6 @@ enum iwl_scan_type {
struct iwl_hw_params {
u8 tx_chains_num;
u8 rx_chains_num;
u8 valid_tx_ant;
u8 valid_rx_ant;
bool use_rts_for_aggregation;
u16 sku;
u32 ct_kill_threshold;
Expand All @@ -663,9 +592,6 @@ struct iwl_lib_ops {
/* device specific configuration */
void (*nic_config)(struct iwl_priv *priv);

/* eeprom operations (as defined in eeprom.h) */
struct iwl_eeprom_ops eeprom_ops;

/* temperature */
void (*temperature)(struct iwl_priv *priv);
};
Expand Down Expand Up @@ -734,8 +660,6 @@ struct iwl_priv {

/* ieee device used by generic ieee processing code */
struct ieee80211_hw *hw;
struct ieee80211_channel *ieee_channels;
struct ieee80211_rate *ieee_rates;

struct list_head calib_results;

Expand All @@ -754,8 +678,6 @@ struct iwl_priv {

struct iwl_notif_wait_data notif_wait;

struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];

/* spectrum measurement report caching */
struct iwl_spectrum_notification measure_report;
u8 measurement_status;
Expand Down Expand Up @@ -786,11 +708,6 @@ struct iwl_priv {
bool ucode_loaded;
bool init_ucode_run; /* Don't run init uCode again */

/* we allocate array of iwl_channel_info for NIC's valid channels.
* Access via channel # using indirect index array */
struct iwl_channel_info *channel_info; /* channel info array */
u8 channel_count; /* # of channels */

u8 plcp_delta_threshold;

/* thermal calibration */
Expand Down Expand Up @@ -950,10 +867,8 @@ struct iwl_priv {

struct delayed_work scan_check;

/* TX Power */
/* TX Power settings */
s8 tx_power_user_lmt;
s8 tx_power_device_lmt;
s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */
s8 tx_power_next;

#ifdef CONFIG_IWLWIFI_DEBUGFS
Expand All @@ -964,9 +879,10 @@ struct iwl_priv {
void *wowlan_sram;
#endif /* CONFIG_IWLWIFI_DEBUGFS */

/* eeprom -- this is in the card's little endian byte order */
u8 *eeprom;
enum iwl_nvm_type nvm_device_type;
struct iwl_eeprom_data *eeprom_data;
/* eeprom blob for debugfs/testmode */
u8 *eeprom_blob;
size_t eeprom_blob_size;

struct work_struct txpower_work;
u32 calib_disabled;
Expand Down Expand Up @@ -1034,36 +950,4 @@ static inline int iwl_is_any_associated(struct iwl_priv *priv)
return false;
}

static inline int is_channel_valid(const struct iwl_channel_info *ch_info)
{
if (ch_info == NULL)
return 0;
return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0;
}

static inline int is_channel_radar(const struct iwl_channel_info *ch_info)
{
return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0;
}

static inline u8 is_channel_a_band(const struct iwl_channel_info *ch_info)
{
return ch_info->band == IEEE80211_BAND_5GHZ;
}

static inline u8 is_channel_bg_band(const struct iwl_channel_info *ch_info)
{
return ch_info->band == IEEE80211_BAND_2GHZ;
}

static inline int is_channel_passive(const struct iwl_channel_info *ch)
{
return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0;
}

static inline int is_channel_ibss(const struct iwl_channel_info *ch)
{
return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
}

#endif /* __iwl_dev_h__ */
Loading

0 comments on commit 26a7ca9

Please sign in to comment.