Commit bf85ea4f authored by Assaf Krauss's avatar Assaf Krauss Committed by John W. Linville

iwlwifi: Probe Flow - Extracting hw and priv init

1. Extracting hw and priv initialization from probe function.
2. Moving some initialization functions to core module.
Signed-off-by: default avatarAssaf Krauss <assaf.krauss@intel.com>
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 1d0a082d
......@@ -105,6 +105,90 @@ static const u16 default_tid_to_tx_fifo[] = {
#endif /*CONFIG_IWL4965_HT */
static int iwl4965_init_drv(struct iwl_priv *priv)
{
int ret;
int i;
priv->antenna = (enum iwl4965_antenna)iwl4965_mod_params.antenna;
priv->retry_rate = 1;
priv->ibss_beacon = NULL;
spin_lock_init(&priv->lock);
spin_lock_init(&priv->power_data.lock);
spin_lock_init(&priv->sta_lock);
spin_lock_init(&priv->hcmd_lock);
spin_lock_init(&priv->lq_mngr.lock);
for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++)
INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
INIT_LIST_HEAD(&priv->free_frames);
mutex_init(&priv->mutex);
/* Clear the driver's (not device's) station table */
iwlcore_clear_stations_table(priv);
priv->data_retry_limit = -1;
priv->ieee_channels = NULL;
priv->ieee_rates = NULL;
priv->band = IEEE80211_BAND_2GHZ;
priv->iw_mode = IEEE80211_IF_TYPE_STA;
priv->use_ant_b_for_management_frame = 1; /* start with ant B */
priv->valid_antenna = 0x7; /* assume all 3 connected */
priv->ps_mode = IWL_MIMO_PS_NONE;
/* Choose which receivers/antennas to use */
iwl4965_set_rxon_chain(priv);
iwlcore_reset_qos(priv);
priv->qos_data.qos_active = 0;
priv->qos_data.qos_cap.val = 0;
iwlcore_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
priv->rates_mask = IWL_RATES_MASK;
/* If power management is turned on, default to AC mode */
priv->power_mode = IWL_POWER_AC;
priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
ret = iwl_init_channel_map(priv);
if (ret) {
IWL_ERROR("initializing regulatory failed: %d\n", ret);
goto err;
}
ret = iwl4965_init_geos(priv);
if (ret) {
IWL_ERROR("initializing geos failed: %d\n", ret);
goto err_free_channel_map;
}
iwl4965_rate_control_register(priv->hw);
ret = ieee80211_register_hw(priv->hw);
if (ret) {
IWL_ERROR("Failed to register network device (error %d)\n",
ret);
goto err_free_geos;
}
priv->hw->conf.beacon_int = 100;
priv->mac80211_registered = 1;
return 0;
err_free_geos:
iwl4965_free_geos(priv);
err_free_channel_map:
iwl_free_channel_map(priv);
err:
return ret;
}
static int is_fat_channel(__le32 rxon_flags)
{
return (rxon_flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) ||
......@@ -391,55 +475,6 @@ static int iwl4965_kw_alloc(struct iwl_priv *priv)
return 0;
}
#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \
? # x " " : "")
/**
* iwl4965_set_fat_chan_info - Copy fat channel info into driver's priv.
*
* Does not set up a command, or touch hardware.
*/
int iwl4965_set_fat_chan_info(struct iwl_priv *priv,
enum ieee80211_band band, u16 channel,
const struct iwl4965_eeprom_channel *eeprom_ch,
u8 fat_extension_channel)
{
struct iwl4965_channel_info *ch_info;
ch_info = (struct iwl4965_channel_info *)
iwl4965_get_channel_info(priv, band, channel);
if (!is_channel_valid(ch_info))
return -1;
IWL_DEBUG_INFO("FAT Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
" %ddBm): Ad-Hoc %ssupported\n",
ch_info->channel,
is_channel_a_band(ch_info) ?
"5.2" : "2.4",
CHECK_AND_PRINT(IBSS),
CHECK_AND_PRINT(ACTIVE),
CHECK_AND_PRINT(RADAR),
CHECK_AND_PRINT(WIDE),
CHECK_AND_PRINT(NARROW),
CHECK_AND_PRINT(DFS),
eeprom_ch->flags,
eeprom_ch->max_power_avg,
((eeprom_ch->flags & EEPROM_CHANNEL_IBSS)
&& !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ?
"" : "not ");
ch_info->fat_eeprom = *eeprom_ch;
ch_info->fat_max_power_avg = eeprom_ch->max_power_avg;
ch_info->fat_curr_txpow = eeprom_ch->max_power_avg;
ch_info->fat_min_power = 0;
ch_info->fat_scan_power = eeprom_ch->max_power_avg;
ch_info->fat_flags = eeprom_ch->flags;
ch_info->fat_extension_channel = fat_extension_channel;
return 0;
}
/**
* iwl4965_kw_free - Free the "keep warm" buffer
*/
......@@ -2015,11 +2050,11 @@ static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage,
return comp;
}
static const struct iwl4965_channel_info *
static const struct iwl_channel_info *
iwl4965_get_channel_txpower_info(struct iwl_priv *priv,
enum ieee80211_band band, u16 channel)
{
const struct iwl4965_channel_info *ch_info;
const struct iwl_channel_info *ch_info;
ch_info = iwl4965_get_channel_info(priv, band, channel);
......@@ -2438,7 +2473,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
s32 txatten_grp = CALIB_CH_GROUP_MAX;
int i;
int c;
const struct iwl4965_channel_info *ch_info = NULL;
const struct iwl_channel_info *ch_info = NULL;
struct iwl4965_eeprom_calib_ch_info ch_eeprom_info;
const struct iwl4965_eeprom_calib_measure *measurement;
s16 voltage;
......@@ -2725,7 +2760,7 @@ int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
u8 is_fat = 0;
u8 ctrl_chan_high = 0;
struct iwl4965_channel_switch_cmd cmd = { 0 };
const struct iwl4965_channel_info *ch_info;
const struct iwl_channel_info *ch_info;
band = priv->band == IEEE80211_BAND_2GHZ;
......@@ -4471,7 +4506,7 @@ static u8 iwl4965_is_channel_extension(struct iwl_priv *priv,
enum ieee80211_band band,
u16 channel, u8 extension_chan_offset)
{
const struct iwl4965_channel_info *ch_info;
const struct iwl_channel_info *ch_info;
ch_info = iwl4965_get_channel_info(priv, band, channel);
if (!is_channel_valid(ch_info))
......@@ -4848,6 +4883,7 @@ void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv)
}
static struct iwl_lib_ops iwl4965_lib = {
.init_drv = iwl4965_init_drv,
.eeprom_ops = {
.verify_signature = iwlcore_eeprom_verify_signature,
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
......
......@@ -197,7 +197,7 @@ enum {
*/
#define IWL4965_MAX_RATE (33)
struct iwl4965_channel_info {
struct iwl_channel_info {
struct iwl4965_channel_tgd_info tgd;
struct iwl4965_channel_tgh_info tgh;
struct iwl4965_eeprom_channel eeprom; /* EEPROM regulatory limit */
......@@ -669,6 +669,8 @@ extern void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *sk
u32 decrypt_res,
struct ieee80211_rx_status *stats);
extern __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr);
int iwl4965_init_geos(struct iwl_priv *priv);
void iwl4965_free_geos(struct iwl_priv *priv);
extern const u8 iwl4965_broadcast_addr[ETH_ALEN];
......@@ -755,11 +757,6 @@ extern void iwl4965_update_rate_scaling(struct iwl_priv *priv, u8 mode);
extern void iwl4965_chain_noise_reset(struct iwl_priv *priv);
extern void iwl4965_init_sensitivity(struct iwl_priv *priv, u8 flags,
u8 force);
extern int iwl4965_set_fat_chan_info(struct iwl_priv *priv,
enum ieee80211_band band,
u16 channel,
const struct iwl4965_eeprom_channel *eeprom_ch,
u8 fat_extension_channel);
extern void iwl4965_rf_kill_ct_config(struct iwl_priv *priv);
extern void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv,
u32 rate_n_flags,
......@@ -995,7 +992,7 @@ struct iwl_priv {
/* we allocate array of iwl4965_channel_info for NIC's valid channels.
* Access via channel # using indirect index array */
struct iwl4965_channel_info *channel_info; /* channel info array */
struct iwl_channel_info *channel_info; /* channel info array */
u8 channel_count; /* # of channels */
/* each calibration channel group in the EEPROM has a derived
......@@ -1229,44 +1226,44 @@ static inline int iwl4965_is_associated(struct iwl_priv *priv)
return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
}
static inline int is_channel_valid(const struct iwl4965_channel_info *ch_info)
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_narrow(const struct iwl4965_channel_info *ch_info)
static inline int is_channel_narrow(const struct iwl_channel_info *ch_info)
{
return (ch_info->flags & EEPROM_CHANNEL_NARROW) ? 1 : 0;
}
static inline int is_channel_radar(const struct iwl4965_channel_info *ch_info)
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 iwl4965_channel_info *ch_info)
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 iwl4965_channel_info *ch_info)
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 iwl4965_channel_info *ch)
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 iwl4965_channel_info *ch)
static inline int is_channel_ibss(const struct iwl_channel_info *ch)
{
return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
}
extern const struct iwl4965_channel_info *iwl4965_get_channel_info(
extern const struct iwl_channel_info *iwl4965_get_channel_info(
const struct iwl_priv *priv, enum ieee80211_band band, u16 channel);
/* Requires full declaration of iwl_priv before including */
......
......@@ -71,3 +71,181 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
}
EXPORT_SYMBOL(iwl_alloc_all);
/**
* iwlcore_clear_stations_table - Clear the driver's station table
*
* NOTE: This does not clear or otherwise alter the device's station table.
*/
void iwlcore_clear_stations_table(struct iwl_priv *priv)
{
unsigned long flags;
spin_lock_irqsave(&priv->sta_lock, flags);
priv->num_stations = 0;
memset(priv->stations, 0, sizeof(priv->stations));
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
EXPORT_SYMBOL(iwlcore_clear_stations_table);
void iwlcore_reset_qos(struct iwl_priv *priv)
{
u16 cw_min = 15;
u16 cw_max = 1023;
u8 aifs = 2;
u8 is_legacy = 0;
unsigned long flags;
int i;
spin_lock_irqsave(&priv->lock, flags);
priv->qos_data.qos_active = 0;
if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) {
if (priv->qos_data.qos_enable)
priv->qos_data.qos_active = 1;
if (!(priv->active_rate & 0xfff0)) {
cw_min = 31;
is_legacy = 1;
}
} else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
if (priv->qos_data.qos_enable)
priv->qos_data.qos_active = 1;
} else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
cw_min = 31;
is_legacy = 1;
}
if (priv->qos_data.qos_active)
aifs = 3;
priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min);
priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max);
priv->qos_data.def_qos_parm.ac[0].aifsn = aifs;
priv->qos_data.def_qos_parm.ac[0].edca_txop = 0;
priv->qos_data.def_qos_parm.ac[0].reserved1 = 0;
if (priv->qos_data.qos_active) {
i = 1;
priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min);
priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max);
priv->qos_data.def_qos_parm.ac[i].aifsn = 7;
priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
i = 2;
priv->qos_data.def_qos_parm.ac[i].cw_min =
cpu_to_le16((cw_min + 1) / 2 - 1);
priv->qos_data.def_qos_parm.ac[i].cw_max =
cpu_to_le16(cw_max);
priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
if (is_legacy)
priv->qos_data.def_qos_parm.ac[i].edca_txop =
cpu_to_le16(6016);
else
priv->qos_data.def_qos_parm.ac[i].edca_txop =
cpu_to_le16(3008);
priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
i = 3;
priv->qos_data.def_qos_parm.ac[i].cw_min =
cpu_to_le16((cw_min + 1) / 4 - 1);
priv->qos_data.def_qos_parm.ac[i].cw_max =
cpu_to_le16((cw_max + 1) / 2 - 1);
priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
if (is_legacy)
priv->qos_data.def_qos_parm.ac[i].edca_txop =
cpu_to_le16(3264);
else
priv->qos_data.def_qos_parm.ac[i].edca_txop =
cpu_to_le16(1504);
} else {
for (i = 1; i < 4; i++) {
priv->qos_data.def_qos_parm.ac[i].cw_min =
cpu_to_le16(cw_min);
priv->qos_data.def_qos_parm.ac[i].cw_max =
cpu_to_le16(cw_max);
priv->qos_data.def_qos_parm.ac[i].aifsn = aifs;
priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
}
}
IWL_DEBUG_QOS("set QoS to default \n");
spin_unlock_irqrestore(&priv->lock, flags);
}
EXPORT_SYMBOL(iwlcore_reset_qos);
/**
* iwlcore_set_rxon_channel - Set the phymode and channel values in staging RXON
* @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
* @channel: Any channel valid for the requested phymode
* In addition to setting the staging RXON, priv->phymode is also set.
*
* NOTE: Does not commit to the hardware; it sets appropriate bit fields
* in the staging RXON flag structure based on the phymode
*/
int iwlcore_set_rxon_channel(struct iwl_priv *priv,
enum ieee80211_band band,
u16 channel)
{
if (!iwl4965_get_channel_info(priv, band, channel)) {
IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
channel, band);
return -EINVAL;
}
if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
(priv->band == band))
return 0;
priv->staging_rxon.channel = cpu_to_le16(channel);
if (band == IEEE80211_BAND_5GHZ)
priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
else
priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
priv->band = band;
IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band);
return 0;
}
EXPORT_SYMBOL(iwlcore_set_rxon_channel);
static void iwlcore_init_hw(struct iwl_priv *priv)
{
struct ieee80211_hw *hw = priv->hw;
hw->rate_control_algorithm = "iwl-4965-rs";
/* Tell mac80211 and its clients (e.g. Wireless Extensions)
* the range of signal quality values that we'll provide.
* Negative values for level/noise indicate that we'll provide dBm.
* For WE, at least, non-0 values here *enable* display of values
* in app (iwconfig). */
hw->max_rssi = -20; /* signal level, negative indicates dBm */
hw->max_noise = -20; /* noise level, negative indicates dBm */
hw->max_signal = 100; /* link quality indication (%) */
/* Tell mac80211 our Tx characteristics */
hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
/* Default value; 4 EDCA QOS priorities */
hw->queues = 4;
#ifdef CONFIG_IWL4965_HT
/* Enhanced value; more queues, to support 11n aggregation */
hw->queues = 16;
#endif /* CONFIG_IWL4965_HT */
}
int iwl_setup(struct iwl_priv *priv)
{
int ret = 0;
iwlcore_init_hw(priv);
ret = priv->cfg->ops->lib->init_drv(priv);
return ret;
}
EXPORT_SYMBOL(iwl_setup);
......@@ -76,6 +76,8 @@
#define IWL_SKU_N 0x8
struct iwl_lib_ops {
/* iwlwifi driver (priv) init */
int (*init_drv)(struct iwl_priv *priv);
/* eeprom operations (as defined in iwl-eeprom.h) */
struct iwl_eeprom_ops eeprom_ops;
};
......@@ -110,4 +112,12 @@ struct iwl_cfg {
struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
struct ieee80211_ops *hw_ops);
void iwlcore_clear_stations_table(struct iwl_priv *priv);
void iwlcore_reset_qos(struct iwl_priv *priv);
int iwlcore_set_rxon_channel(struct iwl_priv *priv,
enum ieee80211_band band,
u16 channel);
int iwl_setup(struct iwl_priv *priv);
#endif /* __iwl_core_h__ */
This diff is collapsed.
......@@ -137,6 +137,8 @@ struct iwl4965_eeprom_channel {
* Look for this in calib_version member of struct iwl4965_eeprom. */
#define EEPROM_TX_POWER_VERSION_NEW (5)
/* 2.4 GHz */
extern const u8 iwl_eeprom_band_1[14];
/*
* 4965 factory calibration data for one txpower level, on one channel,
......@@ -364,4 +366,10 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv);
int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
int iwl_init_channel_map(struct iwl_priv *priv);
void iwl_free_channel_map(struct iwl_priv *priv);
const struct iwl_channel_info *iwl4965_get_channel_info(
const struct iwl_priv *priv,
enum ieee80211_band band, u16 channel);
#endif /* __iwl_eeprom_h__ */
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment