Merge branch 'wireless-next' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi
This commit is contained in:
commit
7c4559c92d
@ -124,10 +124,10 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
|
|||||||
{
|
{
|
||||||
if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
||||||
iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
|
iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
|
||||||
priv->cfg->base_params->num_of_queues =
|
cfg(priv)->base_params->num_of_queues =
|
||||||
iwlagn_mod_params.num_of_queues;
|
iwlagn_mod_params.num_of_queues;
|
||||||
|
|
||||||
hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
|
hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
|
||||||
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
|
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
|
||||||
|
|
||||||
hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
|
hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
|
||||||
@ -135,14 +135,14 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
|
|||||||
|
|
||||||
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ);
|
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ);
|
||||||
|
|
||||||
hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
|
hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
|
||||||
if (priv->cfg->rx_with_siso_diversity)
|
if (cfg(priv)->rx_with_siso_diversity)
|
||||||
hw_params(priv).rx_chains_num = 1;
|
hw_params(priv).rx_chains_num = 1;
|
||||||
else
|
else
|
||||||
hw_params(priv).rx_chains_num =
|
hw_params(priv).rx_chains_num =
|
||||||
num_of_ant(priv->cfg->valid_rx_ant);
|
num_of_ant(cfg(priv)->valid_rx_ant);
|
||||||
hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
|
hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
|
||||||
hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
|
hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
|
||||||
|
|
||||||
iwl1000_set_ct_threshold(priv);
|
iwl1000_set_ct_threshold(priv);
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ static void iwl2000_nic_config(struct iwl_priv *priv)
|
|||||||
{
|
{
|
||||||
iwl_rf_config(priv);
|
iwl_rf_config(priv);
|
||||||
|
|
||||||
if (priv->cfg->iq_invert)
|
if (cfg(priv)->iq_invert)
|
||||||
iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,
|
iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,
|
||||||
CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
|
CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
|
||||||
}
|
}
|
||||||
@ -120,10 +120,10 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
|
|||||||
{
|
{
|
||||||
if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
||||||
iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
|
iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
|
||||||
priv->cfg->base_params->num_of_queues =
|
cfg(priv)->base_params->num_of_queues =
|
||||||
iwlagn_mod_params.num_of_queues;
|
iwlagn_mod_params.num_of_queues;
|
||||||
|
|
||||||
hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
|
hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
|
||||||
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
|
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
|
||||||
|
|
||||||
hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE;
|
hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE;
|
||||||
@ -131,14 +131,14 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
|
|||||||
|
|
||||||
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ);
|
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ);
|
||||||
|
|
||||||
hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
|
hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
|
||||||
if (priv->cfg->rx_with_siso_diversity)
|
if (cfg(priv)->rx_with_siso_diversity)
|
||||||
hw_params(priv).rx_chains_num = 1;
|
hw_params(priv).rx_chains_num = 1;
|
||||||
else
|
else
|
||||||
hw_params(priv).rx_chains_num =
|
hw_params(priv).rx_chains_num =
|
||||||
num_of_ant(priv->cfg->valid_rx_ant);
|
num_of_ant(cfg(priv)->valid_rx_ant);
|
||||||
hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
|
hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
|
||||||
hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
|
hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
|
||||||
|
|
||||||
iwl2000_set_ct_threshold(priv);
|
iwl2000_set_ct_threshold(priv);
|
||||||
|
|
||||||
@ -254,13 +254,13 @@ static struct iwl_bt_params iwl2030_bt_params = {
|
|||||||
.iq_invert = true \
|
.iq_invert = true \
|
||||||
|
|
||||||
struct iwl_cfg iwl2000_2bgn_cfg = {
|
struct iwl_cfg iwl2000_2bgn_cfg = {
|
||||||
.name = "2000 Series 2x2 BGN",
|
.name = "Intel(R) Centrino(R) Wireless-N 2200 BGN",
|
||||||
IWL_DEVICE_2000,
|
IWL_DEVICE_2000,
|
||||||
.ht_params = &iwl2000_ht_params,
|
.ht_params = &iwl2000_ht_params,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iwl_cfg iwl2000_2bgn_d_cfg = {
|
struct iwl_cfg iwl2000_2bgn_d_cfg = {
|
||||||
.name = "2000D Series 2x2 BGN",
|
.name = "Intel(R) Centrino(R) Wireless-N 2200D BGN",
|
||||||
IWL_DEVICE_2000,
|
IWL_DEVICE_2000,
|
||||||
.ht_params = &iwl2000_ht_params,
|
.ht_params = &iwl2000_ht_params,
|
||||||
};
|
};
|
||||||
@ -282,7 +282,7 @@ struct iwl_cfg iwl2000_2bgn_d_cfg = {
|
|||||||
.iq_invert = true \
|
.iq_invert = true \
|
||||||
|
|
||||||
struct iwl_cfg iwl2030_2bgn_cfg = {
|
struct iwl_cfg iwl2030_2bgn_cfg = {
|
||||||
.name = "2000 Series 2x2 BGN/BT",
|
.name = "Intel(R) Centrino(R) Wireless-N 2230 BGN",
|
||||||
IWL_DEVICE_2030,
|
IWL_DEVICE_2030,
|
||||||
.ht_params = &iwl2000_ht_params,
|
.ht_params = &iwl2000_ht_params,
|
||||||
};
|
};
|
||||||
@ -304,13 +304,13 @@ struct iwl_cfg iwl2030_2bgn_cfg = {
|
|||||||
.iq_invert = true \
|
.iq_invert = true \
|
||||||
|
|
||||||
struct iwl_cfg iwl105_bgn_cfg = {
|
struct iwl_cfg iwl105_bgn_cfg = {
|
||||||
.name = "105 Series 1x1 BGN",
|
.name = "Intel(R) Centrino(R) Wireless-N 105 BGN",
|
||||||
IWL_DEVICE_105,
|
IWL_DEVICE_105,
|
||||||
.ht_params = &iwl2000_ht_params,
|
.ht_params = &iwl2000_ht_params,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iwl_cfg iwl105_bgn_d_cfg = {
|
struct iwl_cfg iwl105_bgn_d_cfg = {
|
||||||
.name = "105D Series 1x1 BGN",
|
.name = "Intel(R) Centrino(R) Wireless-N 105D BGN",
|
||||||
IWL_DEVICE_105,
|
IWL_DEVICE_105,
|
||||||
.ht_params = &iwl2000_ht_params,
|
.ht_params = &iwl2000_ht_params,
|
||||||
};
|
};
|
||||||
@ -333,7 +333,7 @@ struct iwl_cfg iwl105_bgn_d_cfg = {
|
|||||||
.iq_invert = true \
|
.iq_invert = true \
|
||||||
|
|
||||||
struct iwl_cfg iwl135_bgn_cfg = {
|
struct iwl_cfg iwl135_bgn_cfg = {
|
||||||
.name = "135 Series 1x1 BGN/BT",
|
.name = "Intel(R) Centrino(R) Wireless-N 135 BGN",
|
||||||
IWL_DEVICE_135,
|
IWL_DEVICE_135,
|
||||||
.ht_params = &iwl2000_ht_params,
|
.ht_params = &iwl2000_ht_params,
|
||||||
};
|
};
|
||||||
|
@ -166,10 +166,10 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
|
|||||||
{
|
{
|
||||||
if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
||||||
iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
|
iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
|
||||||
priv->cfg->base_params->num_of_queues =
|
cfg(priv)->base_params->num_of_queues =
|
||||||
iwlagn_mod_params.num_of_queues;
|
iwlagn_mod_params.num_of_queues;
|
||||||
|
|
||||||
hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
|
hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
|
||||||
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
|
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
|
||||||
|
|
||||||
hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
|
hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
|
||||||
@ -178,10 +178,10 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
|
|||||||
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
||||||
BIT(IEEE80211_BAND_5GHZ);
|
BIT(IEEE80211_BAND_5GHZ);
|
||||||
|
|
||||||
hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
|
hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
|
||||||
hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
|
hw_params(priv).rx_chains_num = num_of_ant(cfg(priv)->valid_rx_ant);
|
||||||
hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
|
hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
|
||||||
hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
|
hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
|
||||||
|
|
||||||
iwl5000_set_ct_threshold(priv);
|
iwl5000_set_ct_threshold(priv);
|
||||||
|
|
||||||
@ -195,10 +195,10 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
|
|||||||
{
|
{
|
||||||
if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
||||||
iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
|
iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
|
||||||
priv->cfg->base_params->num_of_queues =
|
cfg(priv)->base_params->num_of_queues =
|
||||||
iwlagn_mod_params.num_of_queues;
|
iwlagn_mod_params.num_of_queues;
|
||||||
|
|
||||||
hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
|
hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
|
||||||
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
|
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
|
||||||
|
|
||||||
hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
|
hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
|
||||||
@ -207,10 +207,10 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
|
|||||||
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
||||||
BIT(IEEE80211_BAND_5GHZ);
|
BIT(IEEE80211_BAND_5GHZ);
|
||||||
|
|
||||||
hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
|
hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
|
||||||
hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
|
hw_params(priv).rx_chains_num = num_of_ant(cfg(priv)->valid_rx_ant);
|
||||||
hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
|
hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
|
||||||
hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
|
hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
|
||||||
|
|
||||||
iwl5150_set_ct_threshold(priv);
|
iwl5150_set_ct_threshold(priv);
|
||||||
|
|
||||||
|
@ -102,14 +102,14 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
|
|||||||
iwl_rf_config(priv);
|
iwl_rf_config(priv);
|
||||||
|
|
||||||
/* no locking required for register write */
|
/* no locking required for register write */
|
||||||
if (priv->cfg->pa_type == IWL_PA_INTERNAL) {
|
if (cfg(priv)->pa_type == IWL_PA_INTERNAL) {
|
||||||
/* 2x2 IPA phy type */
|
/* 2x2 IPA phy type */
|
||||||
iwl_write32(bus(priv), CSR_GP_DRIVER_REG,
|
iwl_write32(bus(priv), CSR_GP_DRIVER_REG,
|
||||||
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
|
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
|
||||||
}
|
}
|
||||||
/* do additional nic configuration if needed */
|
/* do additional nic configuration if needed */
|
||||||
if (priv->cfg->additional_nic_config)
|
if (cfg(priv)->additional_nic_config)
|
||||||
priv->cfg->additional_nic_config(priv);
|
cfg(priv)->additional_nic_config(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
|
static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
|
||||||
@ -141,10 +141,10 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
|||||||
{
|
{
|
||||||
if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
||||||
iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
|
iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
|
||||||
priv->cfg->base_params->num_of_queues =
|
cfg(priv)->base_params->num_of_queues =
|
||||||
iwlagn_mod_params.num_of_queues;
|
iwlagn_mod_params.num_of_queues;
|
||||||
|
|
||||||
hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
|
hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
|
||||||
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
|
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
|
||||||
|
|
||||||
hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE;
|
hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE;
|
||||||
@ -153,14 +153,14 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
|||||||
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
||||||
BIT(IEEE80211_BAND_5GHZ);
|
BIT(IEEE80211_BAND_5GHZ);
|
||||||
|
|
||||||
hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
|
hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
|
||||||
if (priv->cfg->rx_with_siso_diversity)
|
if (cfg(priv)->rx_with_siso_diversity)
|
||||||
hw_params(priv).rx_chains_num = 1;
|
hw_params(priv).rx_chains_num = 1;
|
||||||
else
|
else
|
||||||
hw_params(priv).rx_chains_num =
|
hw_params(priv).rx_chains_num =
|
||||||
num_of_ant(priv->cfg->valid_rx_ant);
|
num_of_ant(cfg(priv)->valid_rx_ant);
|
||||||
hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
|
hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
|
||||||
hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
|
hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
|
||||||
|
|
||||||
iwl6000_set_ct_threshold(priv);
|
iwl6000_set_ct_threshold(priv);
|
||||||
|
|
||||||
@ -423,7 +423,7 @@ struct iwl_cfg iwl6030_2bg_cfg = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct iwl_cfg iwl6035_2agn_cfg = {
|
struct iwl_cfg iwl6035_2agn_cfg = {
|
||||||
.name = "6035 Series 2x2 AGN/BT",
|
.name = "Intel(R) Centrino(R) Advanced-N 6235 AGN",
|
||||||
IWL_DEVICE_6030,
|
IWL_DEVICE_6030,
|
||||||
.ht_params = &iwl6000_ht_params,
|
.ht_params = &iwl6000_ht_params,
|
||||||
};
|
};
|
||||||
|
@ -513,7 +513,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv)
|
|||||||
|
|
||||||
iwl_prepare_legacy_sensitivity_tbl(priv, data, &cmd.enhance_table[0]);
|
iwl_prepare_legacy_sensitivity_tbl(priv, data, &cmd.enhance_table[0]);
|
||||||
|
|
||||||
if (priv->cfg->base_params->hd_v2) {
|
if (cfg(priv)->base_params->hd_v2) {
|
||||||
cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX] =
|
cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX] =
|
||||||
HD_INA_NON_SQUARE_DET_OFDM_DATA_V2;
|
HD_INA_NON_SQUARE_DET_OFDM_DATA_V2;
|
||||||
cmd.enhance_table[HD_INA_NON_SQUARE_DET_CCK_INDEX] =
|
cmd.enhance_table[HD_INA_NON_SQUARE_DET_CCK_INDEX] =
|
||||||
@ -847,7 +847,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
|
|||||||
* connect the first valid tx chain
|
* connect the first valid tx chain
|
||||||
*/
|
*/
|
||||||
first_chain =
|
first_chain =
|
||||||
find_first_chain(priv->cfg->valid_tx_ant);
|
find_first_chain(cfg(priv)->valid_tx_ant);
|
||||||
data->disconn_array[first_chain] = 0;
|
data->disconn_array[first_chain] = 0;
|
||||||
active_chains |= BIT(first_chain);
|
active_chains |= BIT(first_chain);
|
||||||
IWL_DEBUG_CALIB(priv,
|
IWL_DEBUG_CALIB(priv,
|
||||||
@ -890,7 +890,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
delta_g = (priv->cfg->base_params->chain_noise_scale *
|
delta_g = (cfg(priv)->base_params->chain_noise_scale *
|
||||||
((s32)average_noise[default_chain] -
|
((s32)average_noise[default_chain] -
|
||||||
(s32)average_noise[i])) / 1500;
|
(s32)average_noise[i])) / 1500;
|
||||||
|
|
||||||
@ -1047,8 +1047,8 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Analyze signal for disconnected antenna */
|
/* Analyze signal for disconnected antenna */
|
||||||
if (priv->cfg->bt_params &&
|
if (cfg(priv)->bt_params &&
|
||||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
cfg(priv)->bt_params->advanced_bt_coexist) {
|
||||||
/* Disable disconnected antenna algorithm for advanced
|
/* Disable disconnected antenna algorithm for advanced
|
||||||
bt coex, assuming valid antennas are connected */
|
bt coex, assuming valid antennas are connected */
|
||||||
data->active_chains = hw_params(priv).valid_rx_ant;
|
data->active_chains = hw_params(priv).valid_rx_ant;
|
||||||
@ -1082,7 +1082,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
|
|||||||
|
|
||||||
iwlagn_gain_computation(priv, average_noise,
|
iwlagn_gain_computation(priv, average_noise,
|
||||||
min_average_noise_antenna_i, min_average_noise,
|
min_average_noise_antenna_i, min_average_noise,
|
||||||
find_first_chain(priv->cfg->valid_rx_ant));
|
find_first_chain(cfg(priv)->valid_rx_ant));
|
||||||
|
|
||||||
/* Some power changes may have been made during the calibration.
|
/* Some power changes may have been made during the calibration.
|
||||||
* Update and commit the RXON
|
* Update and commit the RXON
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
|
||||||
|
#include "iwl-wifi.h"
|
||||||
#include "iwl-dev.h"
|
#include "iwl-dev.h"
|
||||||
#include "iwl-core.h"
|
#include "iwl-core.h"
|
||||||
#include "iwl-io.h"
|
#include "iwl-io.h"
|
||||||
@ -150,7 +151,7 @@ static u32 eeprom_indirect_address(const struct iwl_shared *shrd, u32 address)
|
|||||||
const u8 *iwl_eeprom_query_addr(const struct iwl_shared *shrd, size_t offset)
|
const u8 *iwl_eeprom_query_addr(const struct iwl_shared *shrd, size_t offset)
|
||||||
{
|
{
|
||||||
u32 address = eeprom_indirect_address(shrd, offset);
|
u32 address = eeprom_indirect_address(shrd, offset);
|
||||||
BUG_ON(address >= shrd->priv->cfg->base_params->eeprom_size);
|
BUG_ON(address >= shrd->cfg->base_params->eeprom_size);
|
||||||
return &shrd->eeprom[address];
|
return &shrd->eeprom[address];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +233,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
|
|||||||
IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
|
IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
|
||||||
IWL_PAN_SCD_MULTICAST_MSK;
|
IWL_PAN_SCD_MULTICAST_MSK;
|
||||||
|
|
||||||
if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
|
if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||||
flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
|
flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
|
||||||
|
|
||||||
IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
|
IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
|
||||||
@ -374,15 +375,15 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
|
|||||||
BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) !=
|
BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) !=
|
||||||
sizeof(basic.bt3_lookup_table));
|
sizeof(basic.bt3_lookup_table));
|
||||||
|
|
||||||
if (priv->cfg->bt_params) {
|
if (cfg(priv)->bt_params) {
|
||||||
if (priv->cfg->bt_params->bt_session_2) {
|
if (cfg(priv)->bt_params->bt_session_2) {
|
||||||
bt_cmd_2000.prio_boost = cpu_to_le32(
|
bt_cmd_2000.prio_boost = cpu_to_le32(
|
||||||
priv->cfg->bt_params->bt_prio_boost);
|
cfg(priv)->bt_params->bt_prio_boost);
|
||||||
bt_cmd_2000.tx_prio_boost = 0;
|
bt_cmd_2000.tx_prio_boost = 0;
|
||||||
bt_cmd_2000.rx_prio_boost = 0;
|
bt_cmd_2000.rx_prio_boost = 0;
|
||||||
} else {
|
} else {
|
||||||
bt_cmd_6000.prio_boost =
|
bt_cmd_6000.prio_boost =
|
||||||
priv->cfg->bt_params->bt_prio_boost;
|
cfg(priv)->bt_params->bt_prio_boost;
|
||||||
bt_cmd_6000.tx_prio_boost = 0;
|
bt_cmd_6000.tx_prio_boost = 0;
|
||||||
bt_cmd_6000.rx_prio_boost = 0;
|
bt_cmd_6000.rx_prio_boost = 0;
|
||||||
}
|
}
|
||||||
@ -430,7 +431,7 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
|
|||||||
priv->bt_full_concurrent ?
|
priv->bt_full_concurrent ?
|
||||||
"full concurrency" : "3-wire");
|
"full concurrency" : "3-wire");
|
||||||
|
|
||||||
if (priv->cfg->bt_params->bt_session_2) {
|
if (cfg(priv)->bt_params->bt_session_2) {
|
||||||
memcpy(&bt_cmd_2000.basic, &basic,
|
memcpy(&bt_cmd_2000.basic, &basic,
|
||||||
sizeof(basic));
|
sizeof(basic));
|
||||||
ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
|
ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
|
||||||
@ -799,8 +800,8 @@ static bool is_single_rx_stream(struct iwl_priv *priv)
|
|||||||
*/
|
*/
|
||||||
static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
|
static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
|
||||||
{
|
{
|
||||||
if (priv->cfg->bt_params &&
|
if (cfg(priv)->bt_params &&
|
||||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
cfg(priv)->bt_params->advanced_bt_coexist &&
|
||||||
(priv->bt_full_concurrent ||
|
(priv->bt_full_concurrent ||
|
||||||
priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
|
priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
|
||||||
/*
|
/*
|
||||||
@ -871,8 +872,8 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
|||||||
else
|
else
|
||||||
active_chains = hw_params(priv).valid_rx_ant;
|
active_chains = hw_params(priv).valid_rx_ant;
|
||||||
|
|
||||||
if (priv->cfg->bt_params &&
|
if (cfg(priv)->bt_params &&
|
||||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
cfg(priv)->bt_params->advanced_bt_coexist &&
|
||||||
(priv->bt_full_concurrent ||
|
(priv->bt_full_concurrent ||
|
||||||
priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
|
priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
|
||||||
/*
|
/*
|
||||||
@ -1158,7 +1159,7 @@ int iwlagn_suspend(struct iwl_priv *priv,
|
|||||||
* since the uCode will add 0x10 before using the value.
|
* since the uCode will add 0x10 before using the value.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
|
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
|
||||||
seq = priv->shrd->tid_data[IWL_AP_ID][i].seq_number;
|
seq = priv->tid_data[IWL_AP_ID][i].seq_number;
|
||||||
seq -= 0x10;
|
seq -= 0x10;
|
||||||
wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq);
|
wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq);
|
||||||
}
|
}
|
||||||
@ -1195,7 +1196,7 @@ int iwlagn_suspend(struct iwl_priv *priv,
|
|||||||
|
|
||||||
priv->shrd->wowlan = true;
|
priv->shrd->wowlan = true;
|
||||||
|
|
||||||
ret = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
|
ret = iwl_load_ucode_wait_alive(trans(priv), IWL_UCODE_WOWLAN);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1086,7 +1086,7 @@ done:
|
|||||||
(priv->tm_fixed_rate != lq_sta->dbg_fixed_rate))
|
(priv->tm_fixed_rate != lq_sta->dbg_fixed_rate))
|
||||||
rs_program_fix_rate(priv, lq_sta);
|
rs_program_fix_rate(priv, lq_sta);
|
||||||
#endif
|
#endif
|
||||||
if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist)
|
if (cfg(priv)->bt_params && cfg(priv)->bt_params->advanced_bt_coexist)
|
||||||
rs_bt_update_lq(priv, ctx, lq_sta);
|
rs_bt_update_lq(priv, ctx, lq_sta);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2273,7 +2273,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
|
|||||||
tid = rs_tl_add_packet(lq_sta, hdr);
|
tid = rs_tl_add_packet(lq_sta, hdr);
|
||||||
if ((tid != IWL_MAX_TID_COUNT) &&
|
if ((tid != IWL_MAX_TID_COUNT) &&
|
||||||
(lq_sta->tx_agg_tid_en & (1 << tid))) {
|
(lq_sta->tx_agg_tid_en & (1 << tid))) {
|
||||||
tid_data = &priv->shrd->tid_data[lq_sta->lq.sta_id][tid];
|
tid_data = &priv->tid_data[lq_sta->lq.sta_id][tid];
|
||||||
if (tid_data->agg.state == IWL_AGG_OFF)
|
if (tid_data->agg.state == IWL_AGG_OFF)
|
||||||
lq_sta->is_agg = 0;
|
lq_sta->is_agg = 0;
|
||||||
else
|
else
|
||||||
@ -2645,8 +2645,7 @@ lq_update:
|
|||||||
(lq_sta->tx_agg_tid_en & (1 << tid)) &&
|
(lq_sta->tx_agg_tid_en & (1 << tid)) &&
|
||||||
(tid != IWL_MAX_TID_COUNT)) {
|
(tid != IWL_MAX_TID_COUNT)) {
|
||||||
u8 sta_id = lq_sta->lq.sta_id;
|
u8 sta_id = lq_sta->lq.sta_id;
|
||||||
tid_data =
|
tid_data = &priv->tid_data[sta_id][tid];
|
||||||
&priv->shrd->tid_data[sta_id][tid];
|
|
||||||
if (tid_data->agg.state == IWL_AGG_OFF) {
|
if (tid_data->agg.state == IWL_AGG_OFF) {
|
||||||
IWL_DEBUG_RATE(priv,
|
IWL_DEBUG_RATE(priv,
|
||||||
"try to aggregate tid %d\n",
|
"try to aggregate tid %d\n",
|
||||||
@ -3055,11 +3054,11 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
|
|||||||
* overwrite if needed, pass aggregation time limit
|
* overwrite if needed, pass aggregation time limit
|
||||||
* to uCode in uSec
|
* to uCode in uSec
|
||||||
*/
|
*/
|
||||||
if (priv && priv->cfg->bt_params &&
|
if (priv && cfg(priv)->bt_params &&
|
||||||
priv->cfg->bt_params->agg_time_limit &&
|
cfg(priv)->bt_params->agg_time_limit &&
|
||||||
priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)
|
priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)
|
||||||
lq_cmd->agg_params.agg_time_limit =
|
lq_cmd->agg_params.agg_time_limit =
|
||||||
cpu_to_le16(priv->cfg->bt_params->agg_time_limit);
|
cpu_to_le16(cfg(priv)->bt_params->agg_time_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
|
static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
|
||||||
|
@ -318,7 +318,7 @@ static bool iwlagn_good_plcp_health(struct iwl_priv *priv,
|
|||||||
unsigned int msecs)
|
unsigned int msecs)
|
||||||
{
|
{
|
||||||
int delta;
|
int delta;
|
||||||
int threshold = priv->cfg->base_params->plcp_delta_threshold;
|
int threshold = cfg(priv)->base_params->plcp_delta_threshold;
|
||||||
|
|
||||||
if (threshold == IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
|
if (threshold == IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
|
||||||
IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
|
IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
|
||||||
@ -583,8 +583,8 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv,
|
|||||||
iwlagn_rx_calc_noise(priv);
|
iwlagn_rx_calc_noise(priv);
|
||||||
queue_work(priv->shrd->workqueue, &priv->run_time_calib_work);
|
queue_work(priv->shrd->workqueue, &priv->run_time_calib_work);
|
||||||
}
|
}
|
||||||
if (priv->cfg->lib->temperature && change)
|
if (cfg(priv)->lib->temperature && change)
|
||||||
priv->cfg->lib->temperature(priv);
|
cfg(priv)->lib->temperature(priv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1136,8 +1136,8 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
|
|||||||
init_waitqueue_head(&priv->shrd->notif_waitq);
|
init_waitqueue_head(&priv->shrd->notif_waitq);
|
||||||
|
|
||||||
/* Set up BT Rx handlers */
|
/* Set up BT Rx handlers */
|
||||||
if (priv->cfg->lib->bt_rx_handler_setup)
|
if (cfg(priv)->lib->bt_rx_handler_setup)
|
||||||
priv->cfg->lib->bt_rx_handler_setup(priv);
|
cfg(priv)->lib->bt_rx_handler_setup(priv);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,9 +296,9 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION &&
|
if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION &&
|
||||||
priv->cfg->ht_params && priv->cfg->ht_params->smps_mode)
|
cfg(priv)->ht_params && cfg(priv)->ht_params->smps_mode)
|
||||||
ieee80211_request_smps(ctx->vif,
|
ieee80211_request_smps(ctx->vif,
|
||||||
priv->cfg->ht_params->smps_mode);
|
cfg(priv)->ht_params->smps_mode);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -445,8 +445,8 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
|||||||
* force CTS-to-self frames protection if RTS-CTS is not preferred
|
* force CTS-to-self frames protection if RTS-CTS is not preferred
|
||||||
* one aggregation protection method
|
* one aggregation protection method
|
||||||
*/
|
*/
|
||||||
if (!(priv->cfg->ht_params &&
|
if (!(cfg(priv)->ht_params &&
|
||||||
priv->cfg->ht_params->use_rts_for_aggregation))
|
cfg(priv)->ht_params->use_rts_for_aggregation))
|
||||||
ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
|
ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
|
||||||
|
|
||||||
if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
|
if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
|
||||||
|
@ -130,25 +130,15 @@ int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
|||||||
return iwl_process_add_sta_resp(priv, addsta, pkt);
|
return iwl_process_add_sta_resp(priv, addsta, pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
|
|
||||||
{
|
|
||||||
u16 size = (u16)sizeof(struct iwl_addsta_cmd);
|
|
||||||
struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data;
|
|
||||||
memcpy(addsta, cmd, size);
|
|
||||||
/* resrved in agn */
|
|
||||||
addsta->legacy_reserved = cpu_to_le16(0);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int iwl_send_add_sta(struct iwl_priv *priv,
|
int iwl_send_add_sta(struct iwl_priv *priv,
|
||||||
struct iwl_addsta_cmd *sta, u8 flags)
|
struct iwl_addsta_cmd *sta, u8 flags)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
u8 data[sizeof(*sta)];
|
|
||||||
struct iwl_host_cmd cmd = {
|
struct iwl_host_cmd cmd = {
|
||||||
.id = REPLY_ADD_STA,
|
.id = REPLY_ADD_STA,
|
||||||
.flags = flags,
|
.flags = flags,
|
||||||
.data = { data, },
|
.data = { sta, },
|
||||||
|
.len = { sizeof(*sta), },
|
||||||
};
|
};
|
||||||
u8 sta_id __maybe_unused = sta->sta.sta_id;
|
u8 sta_id __maybe_unused = sta->sta.sta_id;
|
||||||
|
|
||||||
@ -160,7 +150,6 @@ int iwl_send_add_sta(struct iwl_priv *priv,
|
|||||||
might_sleep();
|
might_sleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.len[0] = iwlagn_build_addsta_hcmd(sta, data);
|
|
||||||
ret = iwl_trans_send_cmd(trans(priv), &cmd);
|
ret = iwl_trans_send_cmd(trans(priv), &cmd);
|
||||||
|
|
||||||
if (ret || (flags & CMD_ASYNC))
|
if (ret || (flags & CMD_ASYNC))
|
||||||
@ -463,6 +452,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
|
|||||||
const u8 *addr)
|
const u8 *addr)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
u8 tid;
|
||||||
|
|
||||||
if (!iwl_is_ready(priv->shrd)) {
|
if (!iwl_is_ready(priv->shrd)) {
|
||||||
IWL_DEBUG_INFO(priv,
|
IWL_DEBUG_INFO(priv,
|
||||||
@ -501,6 +491,10 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
|
|||||||
priv->stations[sta_id].lq = NULL;
|
priv->stations[sta_id].lq = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
|
||||||
|
memset(&priv->tid_data[sta_id][tid], 0,
|
||||||
|
sizeof(priv->tid_data[sta_id][tid]));
|
||||||
|
|
||||||
priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
|
priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
|
||||||
|
|
||||||
priv->num_stations--;
|
priv->num_stations--;
|
||||||
|
@ -633,7 +633,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)
|
|||||||
INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
|
INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
|
||||||
INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
|
INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
|
||||||
|
|
||||||
if (priv->cfg->base_params->adv_thermal_throttle) {
|
if (cfg(priv)->base_params->adv_thermal_throttle) {
|
||||||
IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n");
|
IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n");
|
||||||
tt->restriction = kcalloc(IWL_TI_STATE_MAX,
|
tt->restriction = kcalloc(IWL_TI_STATE_MAX,
|
||||||
sizeof(struct iwl_tt_restriction),
|
sizeof(struct iwl_tt_restriction),
|
||||||
|
@ -74,8 +74,8 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
|
|||||||
else if (ieee80211_is_back_req(fc))
|
else if (ieee80211_is_back_req(fc))
|
||||||
tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
|
tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
|
||||||
else if (info->band == IEEE80211_BAND_2GHZ &&
|
else if (info->band == IEEE80211_BAND_2GHZ &&
|
||||||
priv->cfg->bt_params &&
|
cfg(priv)->bt_params &&
|
||||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
cfg(priv)->bt_params->advanced_bt_coexist &&
|
||||||
(ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) ||
|
(ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) ||
|
||||||
ieee80211_is_reassoc_req(fc) ||
|
ieee80211_is_reassoc_req(fc) ||
|
||||||
skb->protocol == cpu_to_be16(ETH_P_PAE)))
|
skb->protocol == cpu_to_be16(ETH_P_PAE)))
|
||||||
@ -191,8 +191,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
|
|||||||
rate_flags |= RATE_MCS_CCK_MSK;
|
rate_flags |= RATE_MCS_CCK_MSK;
|
||||||
|
|
||||||
/* Set up antennas */
|
/* Set up antennas */
|
||||||
if (priv->cfg->bt_params &&
|
if (cfg(priv)->bt_params &&
|
||||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
cfg(priv)->bt_params->advanced_bt_coexist &&
|
||||||
priv->bt_full_concurrent) {
|
priv->bt_full_concurrent) {
|
||||||
/* operated as 1x1 in full concurrency mode */
|
/* operated as 1x1 in full concurrency mode */
|
||||||
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
|
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
|
||||||
@ -262,8 +262,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||||||
|
|
||||||
__le16 fc;
|
__le16 fc;
|
||||||
u8 hdr_len;
|
u8 hdr_len;
|
||||||
u16 len;
|
u16 len, seq_number = 0;
|
||||||
u8 sta_id;
|
u8 sta_id, tid = IWL_MAX_TID_COUNT;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
bool is_agg = false;
|
bool is_agg = false;
|
||||||
|
|
||||||
@ -368,8 +368,50 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||||||
info->driver_data[0] = ctx;
|
info->driver_data[0] = ctx;
|
||||||
info->driver_data[1] = dev_cmd;
|
info->driver_data[1] = dev_cmd;
|
||||||
|
|
||||||
if (iwl_trans_tx(trans(priv), skb, dev_cmd, ctx->ctxid, sta_id))
|
if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) {
|
||||||
|
u8 *qc = NULL;
|
||||||
|
struct iwl_tid_data *tid_data;
|
||||||
|
qc = ieee80211_get_qos_ctl(hdr);
|
||||||
|
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
|
||||||
|
if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
|
||||||
goto drop_unlock_sta;
|
goto drop_unlock_sta;
|
||||||
|
tid_data = &priv->tid_data[sta_id][tid];
|
||||||
|
|
||||||
|
/* aggregation is on for this <sta,tid> */
|
||||||
|
if (info->flags & IEEE80211_TX_CTL_AMPDU &&
|
||||||
|
tid_data->agg.state != IWL_AGG_ON) {
|
||||||
|
IWL_ERR(priv, "TX_CTL_AMPDU while not in AGG:"
|
||||||
|
" Tx flags = 0x%08x, agg.state = %d",
|
||||||
|
info->flags, tid_data->agg.state);
|
||||||
|
IWL_ERR(priv, "sta_id = %d, tid = %d seq_num = %d",
|
||||||
|
sta_id, tid, SEQ_TO_SN(tid_data->seq_number));
|
||||||
|
goto drop_unlock_sta;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We can receive packets from the stack in IWL_AGG_{ON,OFF}
|
||||||
|
* only. Check this here.
|
||||||
|
*/
|
||||||
|
if (WARN_ONCE(tid_data->agg.state != IWL_AGG_ON &&
|
||||||
|
tid_data->agg.state != IWL_AGG_OFF,
|
||||||
|
"Tx while agg.state = %d", tid_data->agg.state))
|
||||||
|
goto drop_unlock_sta;
|
||||||
|
|
||||||
|
seq_number = tid_data->seq_number;
|
||||||
|
seq_number &= IEEE80211_SCTL_SEQ;
|
||||||
|
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
|
||||||
|
hdr->seq_ctrl |= cpu_to_le16(seq_number);
|
||||||
|
seq_number += 0x10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy MAC header from skb into command buffer */
|
||||||
|
memcpy(tx_cmd->hdr, hdr, hdr_len);
|
||||||
|
|
||||||
|
if (iwl_trans_tx(trans(priv), skb, dev_cmd, ctx->ctxid, sta_id, tid))
|
||||||
|
goto drop_unlock_sta;
|
||||||
|
|
||||||
|
if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc) &&
|
||||||
|
!ieee80211_has_morefrags(fc))
|
||||||
|
priv->tid_data[sta_id][tid].seq_number = seq_number;
|
||||||
|
|
||||||
spin_unlock(&priv->shrd->sta_lock);
|
spin_unlock(&priv->shrd->sta_lock);
|
||||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||||
@ -395,10 +437,81 @@ drop_unlock_priv:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||||
|
struct ieee80211_sta *sta, u16 tid)
|
||||||
|
{
|
||||||
|
struct iwl_tid_data *tid_data;
|
||||||
|
unsigned long flags;
|
||||||
|
int sta_id;
|
||||||
|
|
||||||
|
sta_id = iwl_sta_id(sta);
|
||||||
|
|
||||||
|
if (sta_id == IWL_INVALID_STATION) {
|
||||||
|
IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||||
|
|
||||||
|
tid_data = &priv->tid_data[sta_id][tid];
|
||||||
|
|
||||||
|
switch (priv->tid_data[sta_id][tid].agg.state) {
|
||||||
|
case IWL_EMPTYING_HW_QUEUE_ADDBA:
|
||||||
|
/*
|
||||||
|
* This can happen if the peer stops aggregation
|
||||||
|
* again before we've had a chance to drain the
|
||||||
|
* queue we selected previously, i.e. before the
|
||||||
|
* session was really started completely.
|
||||||
|
*/
|
||||||
|
IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
|
||||||
|
goto turn_off;
|
||||||
|
case IWL_AGG_ON:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
IWL_WARN(priv, "Stopping AGG while state not ON "
|
||||||
|
"or starting for %d on %d (%d)\n", sta_id, tid,
|
||||||
|
priv->tid_data[sta_id][tid].agg.state);
|
||||||
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number);
|
||||||
|
|
||||||
|
/* There are still packets for this RA / TID in the HW */
|
||||||
|
if (tid_data->agg.ssn != tid_data->next_reclaimed) {
|
||||||
|
IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, "
|
||||||
|
"next_recl = %d",
|
||||||
|
tid_data->agg.ssn,
|
||||||
|
tid_data->next_reclaimed);
|
||||||
|
priv->tid_data[sta_id][tid].agg.state =
|
||||||
|
IWL_EMPTYING_HW_QUEUE_DELBA;
|
||||||
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d",
|
||||||
|
tid_data->agg.ssn);
|
||||||
|
turn_off:
|
||||||
|
priv->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF;
|
||||||
|
|
||||||
|
/* do not restore/save irqs */
|
||||||
|
spin_unlock(&priv->shrd->sta_lock);
|
||||||
|
spin_lock(&priv->shrd->lock);
|
||||||
|
|
||||||
|
iwl_trans_tx_agg_disable(trans(priv), sta_id, tid);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||||
|
|
||||||
|
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
|
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
|
||||||
{
|
{
|
||||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
struct iwl_tid_data *tid_data;
|
||||||
|
unsigned long flags;
|
||||||
int sta_id;
|
int sta_id;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -413,7 +526,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
|||||||
if (unlikely(tid >= IWL_MAX_TID_COUNT))
|
if (unlikely(tid >= IWL_MAX_TID_COUNT))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (priv->shrd->tid_data[sta_id][tid].agg.state != IWL_AGG_OFF) {
|
if (priv->tid_data[sta_id][tid].agg.state != IWL_AGG_OFF) {
|
||||||
IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n");
|
IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n");
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
@ -422,27 +535,136 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = iwl_trans_tx_agg_alloc(trans(priv), vif_priv->ctx->ctxid, sta_id,
|
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||||
tid, ssn);
|
|
||||||
|
tid_data = &priv->tid_data[sta_id][tid];
|
||||||
|
tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number);
|
||||||
|
|
||||||
|
*ssn = tid_data->agg.ssn;
|
||||||
|
|
||||||
|
ret = iwl_trans_tx_agg_alloc(trans(priv), sta_id, tid);
|
||||||
|
if (ret) {
|
||||||
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*ssn == tid_data->next_reclaimed) {
|
||||||
|
IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d",
|
||||||
|
tid_data->agg.ssn);
|
||||||
|
tid_data->agg.state = IWL_AGG_ON;
|
||||||
|
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||||
|
} else {
|
||||||
|
IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, "
|
||||||
|
"next_reclaimed = %d",
|
||||||
|
tid_data->agg.ssn,
|
||||||
|
tid_data->next_reclaimed);
|
||||||
|
tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta, u16 tid)
|
struct ieee80211_sta *sta, u16 tid, u8 buf_size)
|
||||||
{
|
{
|
||||||
int sta_id;
|
struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
|
||||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
|
||||||
|
unsigned long flags;
|
||||||
|
u16 ssn;
|
||||||
|
|
||||||
sta_id = iwl_sta_id(sta);
|
buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF);
|
||||||
|
|
||||||
if (sta_id == IWL_INVALID_STATION) {
|
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||||
IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
|
ssn = priv->tid_data[sta_priv->sta_id][tid].agg.ssn;
|
||||||
return -ENXIO;
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||||
|
|
||||||
|
iwl_trans_tx_agg_setup(trans(priv), ctx->ctxid, sta_priv->sta_id, tid,
|
||||||
|
buf_size, ssn);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the limit is 0, then it wasn't initialised yet,
|
||||||
|
* use the default. We can do that since we take the
|
||||||
|
* minimum below, and we don't want to go above our
|
||||||
|
* default due to hardware restrictions.
|
||||||
|
*/
|
||||||
|
if (sta_priv->max_agg_bufsize == 0)
|
||||||
|
sta_priv->max_agg_bufsize =
|
||||||
|
LINK_QUAL_AGG_FRAME_LIMIT_DEF;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Even though in theory the peer could have different
|
||||||
|
* aggregation reorder buffer sizes for different sessions,
|
||||||
|
* our ucode doesn't allow for that and has a global limit
|
||||||
|
* for each station. Therefore, use the minimum of all the
|
||||||
|
* aggregation sessions and our default value.
|
||||||
|
*/
|
||||||
|
sta_priv->max_agg_bufsize =
|
||||||
|
min(sta_priv->max_agg_bufsize, buf_size);
|
||||||
|
|
||||||
|
if (cfg(priv)->ht_params &&
|
||||||
|
cfg(priv)->ht_params->use_rts_for_aggregation) {
|
||||||
|
/*
|
||||||
|
* switch to RTS/CTS if it is the prefer protection
|
||||||
|
* method for HT traffic
|
||||||
|
*/
|
||||||
|
|
||||||
|
sta_priv->lq_sta.lq.general_params.flags |=
|
||||||
|
LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
|
||||||
|
}
|
||||||
|
priv->agg_tids_count++;
|
||||||
|
IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
|
||||||
|
priv->agg_tids_count);
|
||||||
|
|
||||||
|
sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit =
|
||||||
|
sta_priv->max_agg_bufsize;
|
||||||
|
|
||||||
|
IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n",
|
||||||
|
sta->addr, tid);
|
||||||
|
|
||||||
|
return iwl_send_lq_cmd(priv, ctx,
|
||||||
|
&sta_priv->lq_sta.lq, CMD_ASYNC, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return iwl_trans_tx_agg_disable(trans(priv), vif_priv->ctx->ctxid,
|
static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid)
|
||||||
sta_id, tid);
|
{
|
||||||
|
struct iwl_tid_data *tid_data = &priv->tid_data[sta_id][tid];
|
||||||
|
enum iwl_rxon_context_id ctx;
|
||||||
|
struct ieee80211_vif *vif;
|
||||||
|
u8 *addr;
|
||||||
|
|
||||||
|
lockdep_assert_held(&priv->shrd->sta_lock);
|
||||||
|
|
||||||
|
addr = priv->stations[sta_id].sta.sta.addr;
|
||||||
|
ctx = priv->stations[sta_id].ctxid;
|
||||||
|
vif = priv->contexts[ctx].vif;
|
||||||
|
|
||||||
|
switch (priv->tid_data[sta_id][tid].agg.state) {
|
||||||
|
case IWL_EMPTYING_HW_QUEUE_DELBA:
|
||||||
|
/* There are no packets for this RA / TID in the HW any more */
|
||||||
|
if (tid_data->agg.ssn == tid_data->next_reclaimed) {
|
||||||
|
IWL_DEBUG_TX_QUEUES(priv,
|
||||||
|
"Can continue DELBA flow ssn = next_recl ="
|
||||||
|
" %d", tid_data->next_reclaimed);
|
||||||
|
iwl_trans_tx_agg_disable(trans(priv), sta_id, tid);
|
||||||
|
tid_data->agg.state = IWL_AGG_OFF;
|
||||||
|
ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IWL_EMPTYING_HW_QUEUE_ADDBA:
|
||||||
|
/* There are no packets for this RA / TID in the HW any more */
|
||||||
|
if (tid_data->agg.ssn == tid_data->next_reclaimed) {
|
||||||
|
IWL_DEBUG_TX_QUEUES(priv,
|
||||||
|
"Can continue ADDBA flow ssn = next_recl ="
|
||||||
|
" %d", tid_data->next_reclaimed);
|
||||||
|
tid_data->agg.state = IWL_AGG_ON;
|
||||||
|
ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iwlagn_non_agg_tx_status(struct iwl_priv *priv,
|
static void iwlagn_non_agg_tx_status(struct iwl_priv *priv,
|
||||||
@ -582,7 +804,7 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv,
|
|||||||
IWLAGN_TX_RES_TID_POS;
|
IWLAGN_TX_RES_TID_POS;
|
||||||
int sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >>
|
int sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >>
|
||||||
IWLAGN_TX_RES_RA_POS;
|
IWLAGN_TX_RES_RA_POS;
|
||||||
struct iwl_ht_agg *agg = &priv->shrd->tid_data[sta_id][tid].agg;
|
struct iwl_ht_agg *agg = &priv->tid_data[sta_id][tid].agg;
|
||||||
u32 status = le16_to_cpu(tx_resp->status.status);
|
u32 status = le16_to_cpu(tx_resp->status.status);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -598,8 +820,8 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv,
|
|||||||
* notification again.
|
* notification again.
|
||||||
*/
|
*/
|
||||||
if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 &&
|
if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 &&
|
||||||
priv->cfg->bt_params &&
|
cfg(priv)->bt_params &&
|
||||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
cfg(priv)->bt_params->advanced_bt_coexist) {
|
||||||
IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n");
|
IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -772,7 +994,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
|||||||
struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
|
struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
|
||||||
struct ieee80211_hdr *hdr;
|
struct ieee80211_hdr *hdr;
|
||||||
u32 status = le16_to_cpu(tx_resp->status.status);
|
u32 status = le16_to_cpu(tx_resp->status.status);
|
||||||
u32 ssn = iwlagn_get_scd_ssn(tx_resp);
|
u16 ssn = iwlagn_get_scd_ssn(tx_resp);
|
||||||
int tid;
|
int tid;
|
||||||
int sta_id;
|
int sta_id;
|
||||||
int freed;
|
int freed;
|
||||||
@ -794,11 +1016,34 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
|||||||
iwl_rx_reply_tx_agg(priv, tx_resp);
|
iwl_rx_reply_tx_agg(priv, tx_resp);
|
||||||
|
|
||||||
if (tx_resp->frame_count == 1) {
|
if (tx_resp->frame_count == 1) {
|
||||||
IWL_DEBUG_TX_REPLY(priv, "Q %d, ssn %d", txq_id, ssn);
|
u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl);
|
||||||
|
next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10);
|
||||||
|
|
||||||
|
if (is_agg) {
|
||||||
|
/* If this is an aggregation queue, we can rely on the
|
||||||
|
* ssn since the wifi sequence number corresponds to
|
||||||
|
* the index in the TFD ring (%256).
|
||||||
|
* The seq_ctl is the sequence control of the packet
|
||||||
|
* to which this Tx response relates. But if there is a
|
||||||
|
* hole in the bitmap of the BA we received, this Tx
|
||||||
|
* response may allow to reclaim the hole and all the
|
||||||
|
* subsequent packets that were already acked.
|
||||||
|
* In that case, seq_ctl != ssn, and the next packet
|
||||||
|
* to be reclaimed will be ssn and not seq_ctl.
|
||||||
|
*/
|
||||||
|
next_reclaimed = ssn;
|
||||||
|
}
|
||||||
|
|
||||||
__skb_queue_head_init(&skbs);
|
__skb_queue_head_init(&skbs);
|
||||||
|
priv->tid_data[sta_id][tid].next_reclaimed = next_reclaimed;
|
||||||
|
|
||||||
|
IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d",
|
||||||
|
next_reclaimed);
|
||||||
|
|
||||||
/*we can free until ssn % q.n_bd not inclusive */
|
/*we can free until ssn % q.n_bd not inclusive */
|
||||||
iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id,
|
WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id,
|
||||||
ssn, status, &skbs);
|
ssn, status, &skbs));
|
||||||
|
iwlagn_check_ratid_empty(priv, sta_id, tid);
|
||||||
freed = 0;
|
freed = 0;
|
||||||
while (!skb_queue_empty(&skbs)) {
|
while (!skb_queue_empty(&skbs)) {
|
||||||
skb = __skb_dequeue(&skbs);
|
skb = __skb_dequeue(&skbs);
|
||||||
@ -893,24 +1138,10 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
|||||||
|
|
||||||
sta_id = ba_resp->sta_id;
|
sta_id = ba_resp->sta_id;
|
||||||
tid = ba_resp->tid;
|
tid = ba_resp->tid;
|
||||||
agg = &priv->shrd->tid_data[sta_id][tid].agg;
|
agg = &priv->tid_data[sta_id][tid].agg;
|
||||||
|
|
||||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||||
|
|
||||||
if (unlikely(agg->txq_id != scd_flow)) {
|
|
||||||
/*
|
|
||||||
* FIXME: this is a uCode bug which need to be addressed,
|
|
||||||
* log the information and return for now!
|
|
||||||
* since it is possible happen very often and in order
|
|
||||||
* not to fill the syslog, don't enable the logging by default
|
|
||||||
*/
|
|
||||||
IWL_DEBUG_TX_REPLY(priv,
|
|
||||||
"BA scd_flow %d does not match txq_id %d\n",
|
|
||||||
scd_flow, agg->txq_id);
|
|
||||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlikely(!agg->wait_for_ba)) {
|
if (unlikely(!agg->wait_for_ba)) {
|
||||||
if (unlikely(ba_resp->bitmap))
|
if (unlikely(ba_resp->bitmap))
|
||||||
IWL_ERR(priv, "Received BA when not expected\n");
|
IWL_ERR(priv, "Received BA when not expected\n");
|
||||||
@ -918,6 +1149,17 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__skb_queue_head_init(&reclaimed_skbs);
|
||||||
|
|
||||||
|
/* Release all TFDs before the SSN, i.e. all TFDs in front of
|
||||||
|
* block-ack window (we assume that they've been successfully
|
||||||
|
* transmitted ... if not, it's too late anyway). */
|
||||||
|
if (iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow,
|
||||||
|
ba_resp_scd_ssn, 0, &reclaimed_skbs)) {
|
||||||
|
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
|
IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
|
||||||
"sta_id = %d\n",
|
"sta_id = %d\n",
|
||||||
agg->wait_for_ba,
|
agg->wait_for_ba,
|
||||||
@ -925,7 +1167,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
|||||||
ba_resp->sta_id);
|
ba_resp->sta_id);
|
||||||
IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, "
|
IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, "
|
||||||
"scd_flow = %d, scd_ssn = %d\n",
|
"scd_flow = %d, scd_ssn = %d\n",
|
||||||
ba_resp->tid, ba_resp->seq_ctl,
|
ba_resp->tid, le16_to_cpu(ba_resp->seq_ctl),
|
||||||
(unsigned long long)le64_to_cpu(ba_resp->bitmap),
|
(unsigned long long)le64_to_cpu(ba_resp->bitmap),
|
||||||
scd_flow, ba_resp_scd_ssn);
|
scd_flow, ba_resp_scd_ssn);
|
||||||
|
|
||||||
@ -946,13 +1188,9 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
|||||||
IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n",
|
IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n",
|
||||||
ba_resp->txed, ba_resp->txed_2_done);
|
ba_resp->txed, ba_resp->txed_2_done);
|
||||||
|
|
||||||
__skb_queue_head_init(&reclaimed_skbs);
|
priv->tid_data[sta_id][tid].next_reclaimed = ba_resp_scd_ssn;
|
||||||
|
|
||||||
/* Release all TFDs before the SSN, i.e. all TFDs in front of
|
iwlagn_check_ratid_empty(priv, sta_id, tid);
|
||||||
* block-ack window (we assume that they've been successfully
|
|
||||||
* transmitted ... if not, it's too late anyway). */
|
|
||||||
iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow, ba_resp_scd_ssn,
|
|
||||||
0, &reclaimed_skbs);
|
|
||||||
freed = 0;
|
freed = 0;
|
||||||
while (!skb_queue_empty(&reclaimed_skbs)) {
|
while (!skb_queue_empty(&reclaimed_skbs)) {
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include <asm/div64.h>
|
#include <asm/div64.h>
|
||||||
|
|
||||||
#include "iwl-eeprom.h"
|
#include "iwl-eeprom.h"
|
||||||
|
#include "iwl-wifi.h"
|
||||||
#include "iwl-dev.h"
|
#include "iwl-dev.h"
|
||||||
#include "iwl-core.h"
|
#include "iwl-core.h"
|
||||||
#include "iwl-io.h"
|
#include "iwl-io.h"
|
||||||
@ -515,7 +516,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
|
|||||||
|
|
||||||
static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
|
static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
|
||||||
{
|
{
|
||||||
const char *name_pre = priv->cfg->fw_name_pre;
|
const char *name_pre = cfg(priv)->fw_name_pre;
|
||||||
char tag[8];
|
char tag[8];
|
||||||
|
|
||||||
if (first) {
|
if (first) {
|
||||||
@ -524,14 +525,14 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
|
|||||||
strcpy(tag, UCODE_EXPERIMENTAL_TAG);
|
strcpy(tag, UCODE_EXPERIMENTAL_TAG);
|
||||||
} else if (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) {
|
} else if (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) {
|
||||||
#endif
|
#endif
|
||||||
priv->fw_index = priv->cfg->ucode_api_max;
|
priv->fw_index = cfg(priv)->ucode_api_max;
|
||||||
sprintf(tag, "%d", priv->fw_index);
|
sprintf(tag, "%d", priv->fw_index);
|
||||||
} else {
|
} else {
|
||||||
priv->fw_index--;
|
priv->fw_index--;
|
||||||
sprintf(tag, "%d", priv->fw_index);
|
sprintf(tag, "%d", priv->fw_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->fw_index < priv->cfg->ucode_api_min) {
|
if (priv->fw_index < cfg(priv)->ucode_api_min) {
|
||||||
IWL_ERR(priv, "no suitable firmware found!\n");
|
IWL_ERR(priv, "no suitable firmware found!\n");
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
@ -836,9 +837,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||||||
struct iwl_ucode_header *ucode;
|
struct iwl_ucode_header *ucode;
|
||||||
int err;
|
int err;
|
||||||
struct iwlagn_firmware_pieces pieces;
|
struct iwlagn_firmware_pieces pieces;
|
||||||
const unsigned int api_max = priv->cfg->ucode_api_max;
|
const unsigned int api_max = cfg(priv)->ucode_api_max;
|
||||||
unsigned int api_ok = priv->cfg->ucode_api_ok;
|
unsigned int api_ok = cfg(priv)->ucode_api_ok;
|
||||||
const unsigned int api_min = priv->cfg->ucode_api_min;
|
const unsigned int api_min = cfg(priv)->ucode_api_min;
|
||||||
u32 api_ver;
|
u32 api_ver;
|
||||||
char buildstr[25];
|
char buildstr[25];
|
||||||
u32 build;
|
u32 build;
|
||||||
@ -1027,14 +1028,14 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||||||
priv->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
|
priv->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
|
||||||
else
|
else
|
||||||
priv->init_evtlog_size =
|
priv->init_evtlog_size =
|
||||||
priv->cfg->base_params->max_event_log_size;
|
cfg(priv)->base_params->max_event_log_size;
|
||||||
priv->init_errlog_ptr = pieces.init_errlog_ptr;
|
priv->init_errlog_ptr = pieces.init_errlog_ptr;
|
||||||
priv->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
|
priv->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
|
||||||
if (pieces.inst_evtlog_size)
|
if (pieces.inst_evtlog_size)
|
||||||
priv->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
|
priv->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
|
||||||
else
|
else
|
||||||
priv->inst_evtlog_size =
|
priv->inst_evtlog_size =
|
||||||
priv->cfg->base_params->max_event_log_size;
|
cfg(priv)->base_params->max_event_log_size;
|
||||||
priv->inst_errlog_ptr = pieces.inst_errlog_ptr;
|
priv->inst_errlog_ptr = pieces.inst_errlog_ptr;
|
||||||
#ifndef CONFIG_IWLWIFI_P2P
|
#ifndef CONFIG_IWLWIFI_P2P
|
||||||
ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
|
ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
|
||||||
@ -1043,7 +1044,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||||||
priv->new_scan_threshold_behaviour =
|
priv->new_scan_threshold_behaviour =
|
||||||
!!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
|
!!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
|
||||||
|
|
||||||
if (!(priv->cfg->sku & EEPROM_SKU_CAP_IPAN_ENABLE))
|
if (!(cfg(priv)->sku & EEPROM_SKU_CAP_IPAN_ENABLE))
|
||||||
ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
|
ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1124,7 +1125,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
|
|||||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||||
priv->thermal_throttle.ct_kill_toggle = false;
|
priv->thermal_throttle.ct_kill_toggle = false;
|
||||||
|
|
||||||
if (priv->cfg->base_params->support_ct_kill_exit) {
|
if (cfg(priv)->base_params->support_ct_kill_exit) {
|
||||||
adv_cmd.critical_temperature_enter =
|
adv_cmd.critical_temperature_enter =
|
||||||
cpu_to_le32(hw_params(priv).ct_kill_threshold);
|
cpu_to_le32(hw_params(priv).ct_kill_threshold);
|
||||||
adv_cmd.critical_temperature_exit =
|
adv_cmd.critical_temperature_exit =
|
||||||
@ -1219,10 +1220,10 @@ int iwl_alive_start(struct iwl_priv *priv)
|
|||||||
return -ERFKILL;
|
return -ERFKILL;
|
||||||
|
|
||||||
/* download priority table before any calibration request */
|
/* download priority table before any calibration request */
|
||||||
if (priv->cfg->bt_params &&
|
if (cfg(priv)->bt_params &&
|
||||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
cfg(priv)->bt_params->advanced_bt_coexist) {
|
||||||
/* Configure Bluetooth device coexistence support */
|
/* Configure Bluetooth device coexistence support */
|
||||||
if (priv->cfg->bt_params->bt_sco_disable)
|
if (cfg(priv)->bt_params->bt_sco_disable)
|
||||||
priv->bt_enable_pspoll = false;
|
priv->bt_enable_pspoll = false;
|
||||||
else
|
else
|
||||||
priv->bt_enable_pspoll = true;
|
priv->bt_enable_pspoll = true;
|
||||||
@ -1261,7 +1262,7 @@ int iwl_alive_start(struct iwl_priv *priv)
|
|||||||
priv->active_rate = IWL_RATES_MASK;
|
priv->active_rate = IWL_RATES_MASK;
|
||||||
|
|
||||||
/* Configure Tx antenna selection based on H/W config */
|
/* Configure Tx antenna selection based on H/W config */
|
||||||
iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant);
|
iwlagn_send_tx_ant_config(priv, cfg(priv)->valid_tx_ant);
|
||||||
|
|
||||||
if (iwl_is_associated_ctx(ctx) && !priv->shrd->wowlan) {
|
if (iwl_is_associated_ctx(ctx) && !priv->shrd->wowlan) {
|
||||||
struct iwl_rxon_cmd *active_rxon =
|
struct iwl_rxon_cmd *active_rxon =
|
||||||
@ -1330,9 +1331,9 @@ void __iwl_down(struct iwl_priv *priv)
|
|||||||
priv->bt_status = 0;
|
priv->bt_status = 0;
|
||||||
priv->cur_rssi_ctx = NULL;
|
priv->cur_rssi_ctx = NULL;
|
||||||
priv->bt_is_sco = 0;
|
priv->bt_is_sco = 0;
|
||||||
if (priv->cfg->bt_params)
|
if (cfg(priv)->bt_params)
|
||||||
priv->bt_traffic_load =
|
priv->bt_traffic_load =
|
||||||
priv->cfg->bt_params->bt_init_traffic_load;
|
cfg(priv)->bt_params->bt_init_traffic_load;
|
||||||
else
|
else
|
||||||
priv->bt_traffic_load = 0;
|
priv->bt_traffic_load = 0;
|
||||||
priv->bt_full_concurrent = false;
|
priv->bt_full_concurrent = false;
|
||||||
@ -1514,8 +1515,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
|
|||||||
|
|
||||||
iwl_setup_scan_deferred_work(priv);
|
iwl_setup_scan_deferred_work(priv);
|
||||||
|
|
||||||
if (priv->cfg->lib->bt_setup_deferred_work)
|
if (cfg(priv)->lib->bt_setup_deferred_work)
|
||||||
priv->cfg->lib->bt_setup_deferred_work(priv);
|
cfg(priv)->lib->bt_setup_deferred_work(priv);
|
||||||
|
|
||||||
init_timer(&priv->statistics_periodic);
|
init_timer(&priv->statistics_periodic);
|
||||||
priv->statistics_periodic.data = (unsigned long)priv;
|
priv->statistics_periodic.data = (unsigned long)priv;
|
||||||
@ -1532,8 +1533,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
|
|||||||
|
|
||||||
static void iwl_cancel_deferred_work(struct iwl_priv *priv)
|
static void iwl_cancel_deferred_work(struct iwl_priv *priv)
|
||||||
{
|
{
|
||||||
if (priv->cfg->lib->cancel_deferred_work)
|
if (cfg(priv)->lib->cancel_deferred_work)
|
||||||
priv->cfg->lib->cancel_deferred_work(priv);
|
cfg(priv)->lib->cancel_deferred_work(priv);
|
||||||
|
|
||||||
cancel_work_sync(&priv->run_time_calib_work);
|
cancel_work_sync(&priv->run_time_calib_work);
|
||||||
cancel_work_sync(&priv->beacon_update);
|
cancel_work_sync(&priv->beacon_update);
|
||||||
@ -1602,8 +1603,8 @@ static int iwl_init_drv(struct iwl_priv *priv)
|
|||||||
iwl_init_scan_params(priv);
|
iwl_init_scan_params(priv);
|
||||||
|
|
||||||
/* init bt coex */
|
/* init bt coex */
|
||||||
if (priv->cfg->bt_params &&
|
if (cfg(priv)->bt_params &&
|
||||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
cfg(priv)->bt_params->advanced_bt_coexist) {
|
||||||
priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
|
priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
|
||||||
priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
|
priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
|
||||||
priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
|
priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
|
||||||
@ -1668,17 +1669,17 @@ static int iwl_set_hw_params(struct iwl_priv *priv)
|
|||||||
get_order(IWL_RX_BUF_SIZE_4K);
|
get_order(IWL_RX_BUF_SIZE_4K);
|
||||||
|
|
||||||
if (iwlagn_mod_params.disable_11n)
|
if (iwlagn_mod_params.disable_11n)
|
||||||
priv->cfg->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
|
cfg(priv)->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
|
||||||
|
|
||||||
hw_params(priv).num_ampdu_queues =
|
hw_params(priv).num_ampdu_queues =
|
||||||
priv->cfg->base_params->num_of_ampdu_queues;
|
cfg(priv)->base_params->num_of_ampdu_queues;
|
||||||
hw_params(priv).shadow_reg_enable =
|
hw_params(priv).shadow_reg_enable =
|
||||||
priv->cfg->base_params->shadow_reg_enable;
|
cfg(priv)->base_params->shadow_reg_enable;
|
||||||
hw_params(priv).sku = priv->cfg->sku;
|
hw_params(priv).sku = cfg(priv)->sku;
|
||||||
hw_params(priv).wd_timeout = priv->cfg->base_params->wd_timeout;
|
hw_params(priv).wd_timeout = cfg(priv)->base_params->wd_timeout;
|
||||||
|
|
||||||
/* Device-specific setup */
|
/* Device-specific setup */
|
||||||
return priv->cfg->lib->set_hw_params(priv);
|
return cfg(priv)->lib->set_hw_params(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1757,7 +1758,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
|
|||||||
iwl_debug_config(priv);
|
iwl_debug_config(priv);
|
||||||
|
|
||||||
IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
|
IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
|
||||||
priv->cfg = cfg;
|
cfg(priv) = cfg;
|
||||||
|
|
||||||
/* is antenna coupling more than 35dB ? */
|
/* is antenna coupling more than 35dB ? */
|
||||||
priv->bt_ant_couple_ok =
|
priv->bt_ant_couple_ok =
|
||||||
@ -1791,7 +1792,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
|
|||||||
***********************/
|
***********************/
|
||||||
hw_rev = iwl_hw_detect(priv);
|
hw_rev = iwl_hw_detect(priv);
|
||||||
IWL_INFO(priv, "Detected %s, REV=0x%X\n",
|
IWL_INFO(priv, "Detected %s, REV=0x%X\n",
|
||||||
priv->cfg->name, hw_rev);
|
cfg(priv)->name, hw_rev);
|
||||||
|
|
||||||
err = iwl_trans_request_irq(trans(priv));
|
err = iwl_trans_request_irq(trans(priv));
|
||||||
if (err)
|
if (err)
|
||||||
@ -1915,12 +1916,7 @@ void __devexit iwl_remove(struct iwl_priv * priv)
|
|||||||
set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
|
set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
|
||||||
|
|
||||||
iwl_testmode_cleanup(priv);
|
iwl_testmode_cleanup(priv);
|
||||||
iwl_leds_exit(priv);
|
iwlagn_mac_unregister(priv);
|
||||||
|
|
||||||
if (priv->mac80211_registered) {
|
|
||||||
ieee80211_unregister_hw(priv->hw);
|
|
||||||
priv->mac80211_registered = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
iwl_tt_exit(priv);
|
iwl_tt_exit(priv);
|
||||||
|
|
||||||
|
@ -91,6 +91,7 @@ void iwlagn_prepare_restart(struct iwl_priv *priv);
|
|||||||
struct ieee80211_hw *iwl_alloc_all(void);
|
struct ieee80211_hw *iwl_alloc_all(void);
|
||||||
int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
||||||
struct iwlagn_ucode_capabilities *capa);
|
struct iwlagn_ucode_capabilities *capa);
|
||||||
|
void iwlagn_mac_unregister(struct iwl_priv *priv);
|
||||||
|
|
||||||
/* RXON */
|
/* RXON */
|
||||||
int iwlagn_set_pan_params(struct iwl_priv *priv);
|
int iwlagn_set_pan_params(struct iwl_priv *priv);
|
||||||
@ -108,11 +109,6 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf,
|
|||||||
int iwlagn_rx_calib_result(struct iwl_priv *priv,
|
int iwlagn_rx_calib_result(struct iwl_priv *priv,
|
||||||
struct iwl_rx_mem_buffer *rxb,
|
struct iwl_rx_mem_buffer *rxb,
|
||||||
struct iwl_device_cmd *cmd);
|
struct iwl_device_cmd *cmd);
|
||||||
int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type);
|
|
||||||
void iwl_send_prio_tbl(struct iwl_trans *trans);
|
|
||||||
int iwlagn_run_init_ucode(struct iwl_priv *priv);
|
|
||||||
int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
|
|
||||||
enum iwl_ucode_type ucode_type);
|
|
||||||
|
|
||||||
/* lib */
|
/* lib */
|
||||||
int iwlagn_send_tx_power(struct iwl_priv *priv);
|
int iwlagn_send_tx_power(struct iwl_priv *priv);
|
||||||
@ -137,6 +133,8 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv);
|
|||||||
int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
|
int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
|
||||||
int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn);
|
struct ieee80211_sta *sta, u16 tid, u16 *ssn);
|
||||||
|
int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||||
|
struct ieee80211_sta *sta, u16 tid, u8 buf_size);
|
||||||
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta, u16 tid);
|
struct ieee80211_sta *sta, u16 tid);
|
||||||
int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||||
@ -356,7 +354,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
|
|||||||
void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv);
|
void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv);
|
||||||
void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac);
|
void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac);
|
||||||
|
|
||||||
extern int iwlagn_init_alive_start(struct iwl_priv *priv);
|
|
||||||
extern int iwl_alive_start(struct iwl_priv *priv);
|
extern int iwl_alive_start(struct iwl_priv *priv);
|
||||||
/* svtool */
|
/* svtool */
|
||||||
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
|
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
|
||||||
|
@ -60,8 +60,8 @@ static void iwl_init_ht_hw_capab(const struct iwl_priv *priv,
|
|||||||
|
|
||||||
ht_info->ht_supported = true;
|
ht_info->ht_supported = true;
|
||||||
|
|
||||||
if (priv->cfg->ht_params &&
|
if (cfg(priv)->ht_params &&
|
||||||
priv->cfg->ht_params->ht_greenfield_support)
|
cfg(priv)->ht_params->ht_greenfield_support)
|
||||||
ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
|
ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
|
||||||
ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
|
ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
|
||||||
max_bit_rate = MAX_BIT_RATE_20_MHZ;
|
max_bit_rate = MAX_BIT_RATE_20_MHZ;
|
||||||
@ -76,11 +76,7 @@ static void iwl_init_ht_hw_capab(const struct iwl_priv *priv,
|
|||||||
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
||||||
|
|
||||||
ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
|
ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
|
||||||
if (priv->cfg->bt_params && priv->cfg->bt_params->ampdu_factor)
|
|
||||||
ht_info->ampdu_factor = priv->cfg->bt_params->ampdu_factor;
|
|
||||||
ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
|
ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
|
||||||
if (priv->cfg->bt_params && priv->cfg->bt_params->ampdu_density)
|
|
||||||
ht_info->ampdu_density = priv->cfg->bt_params->ampdu_density;
|
|
||||||
|
|
||||||
ht_info->mcs.rx_mask[0] = 0xFF;
|
ht_info->mcs.rx_mask[0] = 0xFF;
|
||||||
if (rx_chains_num >= 2)
|
if (rx_chains_num >= 2)
|
||||||
@ -141,7 +137,7 @@ int iwl_init_geos(struct iwl_priv *priv)
|
|||||||
sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
|
sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
|
||||||
sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
|
sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
|
||||||
|
|
||||||
if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
|
if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||||
iwl_init_ht_hw_capab(priv, &sband->ht_cap,
|
iwl_init_ht_hw_capab(priv, &sband->ht_cap,
|
||||||
IEEE80211_BAND_5GHZ);
|
IEEE80211_BAND_5GHZ);
|
||||||
|
|
||||||
@ -151,7 +147,7 @@ int iwl_init_geos(struct iwl_priv *priv)
|
|||||||
sband->bitrates = rates;
|
sband->bitrates = rates;
|
||||||
sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
|
sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
|
||||||
|
|
||||||
if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
|
if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||||
iwl_init_ht_hw_capab(priv, &sband->ht_cap,
|
iwl_init_ht_hw_capab(priv, &sband->ht_cap,
|
||||||
IEEE80211_BAND_2GHZ);
|
IEEE80211_BAND_2GHZ);
|
||||||
|
|
||||||
@ -206,12 +202,12 @@ int iwl_init_geos(struct iwl_priv *priv)
|
|||||||
priv->tx_power_next = max_tx_power;
|
priv->tx_power_next = max_tx_power;
|
||||||
|
|
||||||
if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
|
if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
|
||||||
priv->cfg->sku & EEPROM_SKU_CAP_BAND_52GHZ) {
|
cfg(priv)->sku & EEPROM_SKU_CAP_BAND_52GHZ) {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
bus_get_hw_id(bus(priv), buf, sizeof(buf));
|
bus_get_hw_id(bus(priv), buf, sizeof(buf));
|
||||||
IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
|
IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
|
||||||
"Please send your %s to maintainer.\n", buf);
|
"Please send your %s to maintainer.\n", buf);
|
||||||
priv->cfg->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
|
cfg(priv)->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
|
IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
|
||||||
@ -966,9 +962,9 @@ int iwl_apm_init(struct iwl_priv *priv)
|
|||||||
bus_apm_config(bus(priv));
|
bus_apm_config(bus(priv));
|
||||||
|
|
||||||
/* Configure analog phase-lock-loop before activating to D0A */
|
/* Configure analog phase-lock-loop before activating to D0A */
|
||||||
if (priv->cfg->base_params->pll_cfg_val)
|
if (cfg(priv)->base_params->pll_cfg_val)
|
||||||
iwl_set_bit(bus(priv), CSR_ANA_PLL_CFG,
|
iwl_set_bit(bus(priv), CSR_ANA_PLL_CFG,
|
||||||
priv->cfg->base_params->pll_cfg_val);
|
cfg(priv)->base_params->pll_cfg_val);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set "initialization complete" bit to move adapter from
|
* Set "initialization complete" bit to move adapter from
|
||||||
@ -1465,7 +1461,7 @@ void iwl_bg_watchdog(unsigned long data)
|
|||||||
if (iwl_is_rfkill(priv->shrd))
|
if (iwl_is_rfkill(priv->shrd))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
timeout = priv->cfg->base_params->wd_timeout;
|
timeout = cfg(priv)->base_params->wd_timeout;
|
||||||
if (timeout == 0)
|
if (timeout == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1490,11 +1486,11 @@ void iwl_bg_watchdog(unsigned long data)
|
|||||||
|
|
||||||
void iwl_setup_watchdog(struct iwl_priv *priv)
|
void iwl_setup_watchdog(struct iwl_priv *priv)
|
||||||
{
|
{
|
||||||
unsigned int timeout = priv->cfg->base_params->wd_timeout;
|
unsigned int timeout = cfg(priv)->base_params->wd_timeout;
|
||||||
|
|
||||||
if (!iwlagn_mod_params.wd_disable) {
|
if (!iwlagn_mod_params.wd_disable) {
|
||||||
/* use system default */
|
/* use system default */
|
||||||
if (timeout && !priv->cfg->base_params->wd_disable)
|
if (timeout && !cfg(priv)->base_params->wd_disable)
|
||||||
mod_timer(&priv->watchdog,
|
mod_timer(&priv->watchdog,
|
||||||
jiffies +
|
jiffies +
|
||||||
msecs_to_jiffies(IWL_WD_TICK(timeout)));
|
msecs_to_jiffies(IWL_WD_TICK(timeout)));
|
||||||
@ -1584,34 +1580,6 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
|
|||||||
return cpu_to_le32(res);
|
return cpu_to_le32(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
|
|
||||||
enum iwl_rxon_context_id ctx,
|
|
||||||
u8 sta_id, u8 tid)
|
|
||||||
{
|
|
||||||
struct ieee80211_vif *vif;
|
|
||||||
u8 *addr = priv->stations[sta_id].sta.sta.addr;
|
|
||||||
|
|
||||||
if (ctx == NUM_IWL_RXON_CTX)
|
|
||||||
ctx = priv->stations[sta_id].ctxid;
|
|
||||||
vif = priv->contexts[ctx].vif;
|
|
||||||
|
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
|
|
||||||
enum iwl_rxon_context_id ctx,
|
|
||||||
u8 sta_id, u8 tid)
|
|
||||||
{
|
|
||||||
struct ieee80211_vif *vif;
|
|
||||||
u8 *addr = priv->stations[sta_id].sta.sta.addr;
|
|
||||||
|
|
||||||
if (ctx == NUM_IWL_RXON_CTX)
|
|
||||||
ctx = priv->stations[sta_id].ctxid;
|
|
||||||
vif = priv->contexts[ctx].vif;
|
|
||||||
|
|
||||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state)
|
void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state)
|
||||||
{
|
{
|
||||||
wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
|
wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
|
||||||
@ -1619,8 +1587,7 @@ void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state)
|
|||||||
|
|
||||||
void iwl_nic_config(struct iwl_priv *priv)
|
void iwl_nic_config(struct iwl_priv *priv)
|
||||||
{
|
{
|
||||||
priv->cfg->lib->nic_config(priv);
|
cfg(priv)->lib->nic_config(priv);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||||
|
@ -142,8 +142,6 @@ struct iwl_base_params {
|
|||||||
* @bt_init_traffic_load: specify initial bt traffic load
|
* @bt_init_traffic_load: specify initial bt traffic load
|
||||||
* @bt_prio_boost: default bt priority boost value
|
* @bt_prio_boost: default bt priority boost value
|
||||||
* @agg_time_limit: maximum number of uSec in aggregation
|
* @agg_time_limit: maximum number of uSec in aggregation
|
||||||
* @ampdu_factor: Maximum A-MPDU length factor
|
|
||||||
* @ampdu_density: Minimum A-MPDU spacing
|
|
||||||
* @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode
|
* @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode
|
||||||
*/
|
*/
|
||||||
struct iwl_bt_params {
|
struct iwl_bt_params {
|
||||||
@ -151,8 +149,6 @@ struct iwl_bt_params {
|
|||||||
u8 bt_init_traffic_load;
|
u8 bt_init_traffic_load;
|
||||||
u8 bt_prio_boost;
|
u8 bt_prio_boost;
|
||||||
u16 agg_time_limit;
|
u16 agg_time_limit;
|
||||||
u8 ampdu_factor;
|
|
||||||
u8 ampdu_density;
|
|
||||||
bool bt_sco_disable;
|
bool bt_sco_disable;
|
||||||
bool bt_session_2;
|
bool bt_session_2;
|
||||||
};
|
};
|
||||||
@ -165,77 +161,6 @@ struct iwl_ht_params {
|
|||||||
enum ieee80211_smps_mode smps_mode;
|
enum ieee80211_smps_mode smps_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* struct iwl_cfg
|
|
||||||
* @name: Offical name of the device
|
|
||||||
* @fw_name_pre: Firmware filename prefix. The api version and extension
|
|
||||||
* (.ucode) will be added to filename before loading from disk. The
|
|
||||||
* filename is constructed as fw_name_pre<api>.ucode.
|
|
||||||
* @ucode_api_max: Highest version of uCode API supported by driver.
|
|
||||||
* @ucode_api_ok: oldest version of the uCode API that is OK to load
|
|
||||||
* without a warning, for use in transitions
|
|
||||||
* @ucode_api_min: Lowest version of uCode API supported by driver.
|
|
||||||
* @valid_tx_ant: valid transmit antenna
|
|
||||||
* @valid_rx_ant: valid receive antenna
|
|
||||||
* @sku: sku information from EEPROM
|
|
||||||
* @eeprom_ver: EEPROM version
|
|
||||||
* @eeprom_calib_ver: EEPROM calibration version
|
|
||||||
* @lib: pointer to the lib ops
|
|
||||||
* @additional_nic_config: additional nic configuration
|
|
||||||
* @base_params: pointer to basic parameters
|
|
||||||
* @ht_params: point to ht patameters
|
|
||||||
* @bt_params: pointer to bt parameters
|
|
||||||
* @pa_type: used by 6000 series only to identify the type of Power Amplifier
|
|
||||||
* @need_temp_offset_calib: need to perform temperature offset calibration
|
|
||||||
* @no_xtal_calib: some devices do not need crystal calibration data,
|
|
||||||
* don't send it to those
|
|
||||||
* @scan_antennas: available antenna for scan operation
|
|
||||||
* @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
|
|
||||||
* @adv_pm: advance power management
|
|
||||||
* @rx_with_siso_diversity: 1x1 device with rx antenna diversity
|
|
||||||
* @internal_wimax_coex: internal wifi/wimax combo device
|
|
||||||
* @iq_invert: I/Q inversion
|
|
||||||
* @temp_offset_v2: support v2 of temperature offset calibration
|
|
||||||
*
|
|
||||||
* We enable the driver to be backward compatible wrt API version. The
|
|
||||||
* driver specifies which APIs it supports (with @ucode_api_max being the
|
|
||||||
* highest and @ucode_api_min the lowest). Firmware will only be loaded if
|
|
||||||
* it has a supported API version.
|
|
||||||
*
|
|
||||||
* The ideal usage of this infrastructure is to treat a new ucode API
|
|
||||||
* release as a new hardware revision.
|
|
||||||
*/
|
|
||||||
struct iwl_cfg {
|
|
||||||
/* params specific to an individual device within a device family */
|
|
||||||
const char *name;
|
|
||||||
const char *fw_name_pre;
|
|
||||||
const unsigned int ucode_api_max;
|
|
||||||
const unsigned int ucode_api_ok;
|
|
||||||
const unsigned int ucode_api_min;
|
|
||||||
u8 valid_tx_ant;
|
|
||||||
u8 valid_rx_ant;
|
|
||||||
u16 sku;
|
|
||||||
u16 eeprom_ver;
|
|
||||||
u16 eeprom_calib_ver;
|
|
||||||
const struct iwl_lib_ops *lib;
|
|
||||||
void (*additional_nic_config)(struct iwl_priv *priv);
|
|
||||||
/* params not likely to change within a device family */
|
|
||||||
struct iwl_base_params *base_params;
|
|
||||||
/* params likely to change within a device family */
|
|
||||||
struct iwl_ht_params *ht_params;
|
|
||||||
struct iwl_bt_params *bt_params;
|
|
||||||
enum iwl_pa_type pa_type; /* if used set to IWL_PA_SYSTEM */
|
|
||||||
const bool need_temp_offset_calib; /* if used set to true */
|
|
||||||
const bool no_xtal_calib;
|
|
||||||
u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
|
|
||||||
enum iwl_led_mode led_mode;
|
|
||||||
const bool adv_pm;
|
|
||||||
const bool rx_with_siso_diversity;
|
|
||||||
const bool internal_wimax_coex;
|
|
||||||
const bool iq_invert;
|
|
||||||
const bool temp_offset_v2;
|
|
||||||
};
|
|
||||||
|
|
||||||
/***************************
|
/***************************
|
||||||
* L i b *
|
* L i b *
|
||||||
***************************/
|
***************************/
|
||||||
@ -368,8 +293,8 @@ static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
|
|||||||
|
|
||||||
static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
|
static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
|
||||||
{
|
{
|
||||||
return priv->cfg->bt_params &&
|
return cfg(priv)->bt_params &&
|
||||||
priv->cfg->bt_params->advanced_bt_coexist;
|
cfg(priv)->bt_params->advanced_bt_coexist;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void iwl_enable_rfkill_int(struct iwl_priv *priv)
|
static inline void iwl_enable_rfkill_int(struct iwl_priv *priv)
|
||||||
|
@ -372,15 +372,13 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
|
|||||||
i, station->sta.sta.addr,
|
i, station->sta.sta.addr,
|
||||||
station->sta.station_flags_msk);
|
station->sta.station_flags_msk);
|
||||||
pos += scnprintf(buf + pos, bufsz - pos,
|
pos += scnprintf(buf + pos, bufsz - pos,
|
||||||
"TID\tseq_num\ttxq_id\ttfds\trate_n_flags\n");
|
"TID\tseq_num\trate_n_flags\n");
|
||||||
|
|
||||||
for (j = 0; j < IWL_MAX_TID_COUNT; j++) {
|
for (j = 0; j < IWL_MAX_TID_COUNT; j++) {
|
||||||
tid_data = &priv->shrd->tid_data[i][j];
|
tid_data = &priv->tid_data[i][j];
|
||||||
pos += scnprintf(buf + pos, bufsz - pos,
|
pos += scnprintf(buf + pos, bufsz - pos,
|
||||||
"%d:\t%#x\t%#x\t%u\t%#x",
|
"%d:\t%#x\t%#x",
|
||||||
j, tid_data->seq_number,
|
j, tid_data->seq_number,
|
||||||
tid_data->agg.txq_id,
|
|
||||||
tid_data->tfds_in_queue,
|
|
||||||
tid_data->agg.rate_n_flags);
|
tid_data->agg.rate_n_flags);
|
||||||
|
|
||||||
if (tid_data->agg.wait_for_ba)
|
if (tid_data->agg.wait_for_ba)
|
||||||
@ -408,7 +406,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
|
|||||||
const u8 *ptr;
|
const u8 *ptr;
|
||||||
char *buf;
|
char *buf;
|
||||||
u16 eeprom_ver;
|
u16 eeprom_ver;
|
||||||
size_t eeprom_len = priv->cfg->base_params->eeprom_size;
|
size_t eeprom_len = cfg(priv)->base_params->eeprom_size;
|
||||||
buf_size = 4 * eeprom_len + 256;
|
buf_size = 4 * eeprom_len + 256;
|
||||||
|
|
||||||
if (eeprom_len % 16) {
|
if (eeprom_len % 16) {
|
||||||
@ -1542,15 +1540,15 @@ 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) {
|
if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) {
|
||||||
pos += scnprintf(buf + pos, bufsz - pos,
|
pos += scnprintf(buf + pos, bufsz - pos,
|
||||||
"tx power: (1/2 dB step)\n");
|
"tx power: (1/2 dB step)\n");
|
||||||
if ((priv->cfg->valid_tx_ant & ANT_A) && tx->tx_power.ant_a)
|
if ((cfg(priv)->valid_tx_ant & ANT_A) && tx->tx_power.ant_a)
|
||||||
pos += scnprintf(buf + pos, bufsz - pos,
|
pos += scnprintf(buf + pos, bufsz - pos,
|
||||||
fmt_hex, "antenna A:",
|
fmt_hex, "antenna A:",
|
||||||
tx->tx_power.ant_a);
|
tx->tx_power.ant_a);
|
||||||
if ((priv->cfg->valid_tx_ant & ANT_B) && tx->tx_power.ant_b)
|
if ((cfg(priv)->valid_tx_ant & ANT_B) && tx->tx_power.ant_b)
|
||||||
pos += scnprintf(buf + pos, bufsz - pos,
|
pos += scnprintf(buf + pos, bufsz - pos,
|
||||||
fmt_hex, "antenna B:",
|
fmt_hex, "antenna B:",
|
||||||
tx->tx_power.ant_b);
|
tx->tx_power.ant_b);
|
||||||
if ((priv->cfg->valid_tx_ant & ANT_C) && tx->tx_power.ant_c)
|
if ((cfg(priv)->valid_tx_ant & ANT_C) && tx->tx_power.ant_c)
|
||||||
pos += scnprintf(buf + pos, bufsz - pos,
|
pos += scnprintf(buf + pos, bufsz - pos,
|
||||||
fmt_hex, "antenna C:",
|
fmt_hex, "antenna C:",
|
||||||
tx->tx_power.ant_c);
|
tx->tx_power.ant_c);
|
||||||
@ -2221,7 +2219,7 @@ static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,
|
|||||||
const size_t bufsz = sizeof(buf);
|
const size_t bufsz = sizeof(buf);
|
||||||
|
|
||||||
pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
|
pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
|
||||||
priv->cfg->base_params->plcp_delta_threshold);
|
cfg(priv)->base_params->plcp_delta_threshold);
|
||||||
|
|
||||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||||
}
|
}
|
||||||
@ -2243,10 +2241,10 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
|
if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
|
||||||
(plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
|
(plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
|
||||||
priv->cfg->base_params->plcp_delta_threshold =
|
cfg(priv)->base_params->plcp_delta_threshold =
|
||||||
IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
|
IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
|
||||||
else
|
else
|
||||||
priv->cfg->base_params->plcp_delta_threshold = plcp;
|
cfg(priv)->base_params->plcp_delta_threshold = plcp;
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2348,7 +2346,7 @@ static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file,
|
|||||||
if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT)
|
if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT)
|
||||||
timeout = IWL_DEF_WD_TIMEOUT;
|
timeout = IWL_DEF_WD_TIMEOUT;
|
||||||
|
|
||||||
priv->cfg->base_params->wd_timeout = timeout;
|
cfg(priv)->base_params->wd_timeout = timeout;
|
||||||
iwl_setup_watchdog(priv);
|
iwl_setup_watchdog(priv);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@ -2408,10 +2406,10 @@ static ssize_t iwl_dbgfs_protection_mode_read(struct file *file,
|
|||||||
char buf[40];
|
char buf[40];
|
||||||
const size_t bufsz = sizeof(buf);
|
const size_t bufsz = sizeof(buf);
|
||||||
|
|
||||||
if (priv->cfg->ht_params)
|
if (cfg(priv)->ht_params)
|
||||||
pos += scnprintf(buf + pos, bufsz - pos,
|
pos += scnprintf(buf + pos, bufsz - pos,
|
||||||
"use %s for aggregation\n",
|
"use %s for aggregation\n",
|
||||||
(priv->cfg->ht_params->use_rts_for_aggregation) ?
|
(cfg(priv)->ht_params->use_rts_for_aggregation) ?
|
||||||
"rts/cts" : "cts-to-self");
|
"rts/cts" : "cts-to-self");
|
||||||
else
|
else
|
||||||
pos += scnprintf(buf + pos, bufsz - pos, "N/A");
|
pos += scnprintf(buf + pos, bufsz - pos, "N/A");
|
||||||
@ -2428,7 +2426,7 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
|
|||||||
int buf_size;
|
int buf_size;
|
||||||
int rts;
|
int rts;
|
||||||
|
|
||||||
if (!priv->cfg->ht_params)
|
if (!cfg(priv)->ht_params)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
@ -2438,9 +2436,9 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
|
|||||||
if (sscanf(buf, "%d", &rts) != 1)
|
if (sscanf(buf, "%d", &rts) != 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (rts)
|
if (rts)
|
||||||
priv->cfg->ht_params->use_rts_for_aggregation = true;
|
cfg(priv)->ht_params->use_rts_for_aggregation = true;
|
||||||
else
|
else
|
||||||
priv->cfg->ht_params->use_rts_for_aggregation = false;
|
cfg(priv)->ht_params->use_rts_for_aggregation = false;
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,6 +189,69 @@ struct iwl_qos_info {
|
|||||||
struct iwl_qosparam_cmd def_qos_parm;
|
struct iwl_qosparam_cmd def_qos_parm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum iwl_agg_state
|
||||||
|
*
|
||||||
|
* The state machine of the BA agreement establishment / tear down.
|
||||||
|
* These states relate to a specific RA / TID.
|
||||||
|
*
|
||||||
|
* @IWL_AGG_OFF: aggregation is not used
|
||||||
|
* @IWL_AGG_ON: aggregation session is up
|
||||||
|
* @IWL_EMPTYING_HW_QUEUE_ADDBA: establishing a BA session - waiting for the
|
||||||
|
* HW queue to be empty from packets for this RA /TID.
|
||||||
|
* @IWL_EMPTYING_HW_QUEUE_DELBA: tearing down a BA session - waiting for the
|
||||||
|
* HW queue to be empty from packets for this RA /TID.
|
||||||
|
*/
|
||||||
|
enum iwl_agg_state {
|
||||||
|
IWL_AGG_OFF = 0,
|
||||||
|
IWL_AGG_ON,
|
||||||
|
IWL_EMPTYING_HW_QUEUE_ADDBA,
|
||||||
|
IWL_EMPTYING_HW_QUEUE_DELBA,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct iwl_ht_agg - aggregation state machine
|
||||||
|
|
||||||
|
* This structs holds the states for the BA agreement establishment and tear
|
||||||
|
* down. It also holds the state during the BA session itself. This struct is
|
||||||
|
* duplicated for each RA / TID.
|
||||||
|
|
||||||
|
* @rate_n_flags: Rate at which Tx was attempted. Holds the data between the
|
||||||
|
* Tx response (REPLY_TX), and the block ack notification
|
||||||
|
* (REPLY_COMPRESSED_BA).
|
||||||
|
* @state: state of the BA agreement establishment / tear down.
|
||||||
|
* @txq_id: Tx queue used by the BA session - used by the transport layer.
|
||||||
|
* Needed by the upper layer for debugfs only.
|
||||||
|
* @ssn: the first packet to be sent in AGG HW queue in Tx AGG start flow, or
|
||||||
|
* the first packet to be sent in legacy HW queue in Tx AGG stop flow.
|
||||||
|
* Basically when next_reclaimed reaches ssn, we can tell mac80211 that
|
||||||
|
* we are ready to finish the Tx AGG stop / start flow.
|
||||||
|
* @wait_for_ba: Expect block-ack before next Tx reply
|
||||||
|
*/
|
||||||
|
struct iwl_ht_agg {
|
||||||
|
u32 rate_n_flags;
|
||||||
|
enum iwl_agg_state state;
|
||||||
|
u16 txq_id;
|
||||||
|
u16 ssn;
|
||||||
|
bool wait_for_ba;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct iwl_tid_data - one for each RA / TID
|
||||||
|
|
||||||
|
* This structs holds the states for each RA / TID.
|
||||||
|
|
||||||
|
* @seq_number: the next WiFi sequence number to use
|
||||||
|
* @next_reclaimed: the WiFi sequence number of the next packet to be acked.
|
||||||
|
* This is basically (last acked packet++).
|
||||||
|
* @agg: aggregation state machine
|
||||||
|
*/
|
||||||
|
struct iwl_tid_data {
|
||||||
|
u16 seq_number;
|
||||||
|
u16 next_reclaimed;
|
||||||
|
struct iwl_ht_agg agg;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure should be accessed with sta_lock held. When station addition
|
* Structure should be accessed with sta_lock held. When station addition
|
||||||
* is in progress (IWL_STA_UCODE_INPROGRESS) it is possible to access only
|
* is in progress (IWL_STA_UCODE_INPROGRESS) it is possible to access only
|
||||||
@ -512,16 +575,6 @@ enum iwl_access_mode {
|
|||||||
IWL_OTP_ACCESS_RELATIVE,
|
IWL_OTP_ACCESS_RELATIVE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* enum iwl_pa_type - Power Amplifier type
|
|
||||||
* @IWL_PA_SYSTEM: based on uCode configuration
|
|
||||||
* @IWL_PA_INTERNAL: use Internal only
|
|
||||||
*/
|
|
||||||
enum iwl_pa_type {
|
|
||||||
IWL_PA_SYSTEM = 0,
|
|
||||||
IWL_PA_INTERNAL = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* reply_tx_statistics (for _agn devices) */
|
/* reply_tx_statistics (for _agn devices) */
|
||||||
struct reply_tx_error_statistics {
|
struct reply_tx_error_statistics {
|
||||||
u32 pp_delay;
|
u32 pp_delay;
|
||||||
@ -776,7 +829,6 @@ struct iwl_priv {
|
|||||||
struct ieee80211_channel *ieee_channels;
|
struct ieee80211_channel *ieee_channels;
|
||||||
struct ieee80211_rate *ieee_rates;
|
struct ieee80211_rate *ieee_rates;
|
||||||
struct kmem_cache *tx_cmd_pool;
|
struct kmem_cache *tx_cmd_pool;
|
||||||
struct iwl_cfg *cfg;
|
|
||||||
|
|
||||||
enum ieee80211_band band;
|
enum ieee80211_band band;
|
||||||
|
|
||||||
@ -880,6 +932,7 @@ struct iwl_priv {
|
|||||||
int num_stations;
|
int num_stations;
|
||||||
struct iwl_station_entry stations[IWLAGN_STATION_COUNT];
|
struct iwl_station_entry stations[IWLAGN_STATION_COUNT];
|
||||||
unsigned long ucode_key_table;
|
unsigned long ucode_key_table;
|
||||||
|
struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT];
|
||||||
|
|
||||||
u8 mac80211_registered;
|
u8 mac80211_registered;
|
||||||
|
|
||||||
|
@ -230,8 +230,8 @@ int iwl_eeprom_check_version(struct iwl_priv *priv)
|
|||||||
eeprom_ver = iwl_eeprom_query16(priv->shrd, EEPROM_VERSION);
|
eeprom_ver = iwl_eeprom_query16(priv->shrd, EEPROM_VERSION);
|
||||||
calib_ver = iwl_eeprom_calib_version(priv->shrd);
|
calib_ver = iwl_eeprom_calib_version(priv->shrd);
|
||||||
|
|
||||||
if (eeprom_ver < priv->cfg->eeprom_ver ||
|
if (eeprom_ver < cfg(priv)->eeprom_ver ||
|
||||||
calib_ver < priv->cfg->eeprom_calib_ver)
|
calib_ver < cfg(priv)->eeprom_calib_ver)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
|
IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
|
||||||
@ -241,8 +241,8 @@ int iwl_eeprom_check_version(struct iwl_priv *priv)
|
|||||||
err:
|
err:
|
||||||
IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x "
|
IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x "
|
||||||
"CALIB=0x%x < 0x%x\n",
|
"CALIB=0x%x < 0x%x\n",
|
||||||
eeprom_ver, priv->cfg->eeprom_ver,
|
eeprom_ver, cfg(priv)->eeprom_ver,
|
||||||
calib_ver, priv->cfg->eeprom_calib_ver);
|
calib_ver, cfg(priv)->eeprom_calib_ver);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -252,35 +252,35 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv)
|
|||||||
struct iwl_shared *shrd = priv->shrd;
|
struct iwl_shared *shrd = priv->shrd;
|
||||||
u16 radio_cfg;
|
u16 radio_cfg;
|
||||||
|
|
||||||
if (!priv->cfg->sku) {
|
if (!cfg(priv)->sku) {
|
||||||
/* not using sku overwrite */
|
/* not using sku overwrite */
|
||||||
priv->cfg->sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP);
|
cfg(priv)->sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP);
|
||||||
if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE &&
|
if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE &&
|
||||||
!priv->cfg->ht_params) {
|
!cfg(priv)->ht_params) {
|
||||||
IWL_ERR(priv, "Invalid 11n configuration\n");
|
IWL_ERR(priv, "Invalid 11n configuration\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!priv->cfg->sku) {
|
if (!cfg(priv)->sku) {
|
||||||
IWL_ERR(priv, "Invalid device sku\n");
|
IWL_ERR(priv, "Invalid device sku\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
IWL_INFO(priv, "Device SKU: 0X%x\n", priv->cfg->sku);
|
IWL_INFO(priv, "Device SKU: 0x%X\n", cfg(priv)->sku);
|
||||||
|
|
||||||
if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) {
|
if (!cfg(priv)->valid_tx_ant && !cfg(priv)->valid_rx_ant) {
|
||||||
/* not using .cfg overwrite */
|
/* not using .cfg overwrite */
|
||||||
radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG);
|
radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG);
|
||||||
priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
|
cfg(priv)->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
|
||||||
priv->cfg->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
|
cfg(priv)->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
|
||||||
if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) {
|
if (!cfg(priv)->valid_tx_ant || !cfg(priv)->valid_rx_ant) {
|
||||||
IWL_ERR(priv, "Invalid chain (0X%x, 0X%x)\n",
|
IWL_ERR(priv, "Invalid chain (0x%X, 0x%X)\n",
|
||||||
priv->cfg->valid_tx_ant,
|
cfg(priv)->valid_tx_ant,
|
||||||
priv->cfg->valid_rx_ant);
|
cfg(priv)->valid_rx_ant);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
IWL_INFO(priv, "Valid Tx ant: 0X%x, Valid Rx ant: 0X%x\n",
|
IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
|
||||||
priv->cfg->valid_tx_ant, priv->cfg->valid_rx_ant);
|
cfg(priv)->valid_tx_ant, cfg(priv)->valid_rx_ant);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* for some special cases,
|
* for some special cases,
|
||||||
@ -369,7 +369,7 @@ static int iwl_init_otp_access(struct iwl_bus *bus)
|
|||||||
* CSR auto clock gate disable bit -
|
* CSR auto clock gate disable bit -
|
||||||
* this is only applicable for HW with OTP shadow RAM
|
* this is only applicable for HW with OTP shadow RAM
|
||||||
*/
|
*/
|
||||||
if (priv(bus)->cfg->base_params->shadow_ram_support)
|
if (cfg(bus)->base_params->shadow_ram_support)
|
||||||
iwl_set_bit(bus, CSR_DBG_LINK_PWR_MGMT_REG,
|
iwl_set_bit(bus, CSR_DBG_LINK_PWR_MGMT_REG,
|
||||||
CSR_RESET_LINK_PWR_MGMT_DISABLED);
|
CSR_RESET_LINK_PWR_MGMT_DISABLED);
|
||||||
}
|
}
|
||||||
@ -489,7 +489,7 @@ static int iwl_find_otp_image(struct iwl_bus *bus,
|
|||||||
}
|
}
|
||||||
/* more in the link list, continue */
|
/* more in the link list, continue */
|
||||||
usedblocks++;
|
usedblocks++;
|
||||||
} while (usedblocks <= priv(bus)->cfg->base_params->max_ll_items);
|
} while (usedblocks <= cfg(bus)->base_params->max_ll_items);
|
||||||
|
|
||||||
/* OTP has no valid blocks */
|
/* OTP has no valid blocks */
|
||||||
IWL_DEBUG_EEPROM(bus, "OTP has no valid blocks\n");
|
IWL_DEBUG_EEPROM(bus, "OTP has no valid blocks\n");
|
||||||
@ -629,7 +629,7 @@ void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
|
|||||||
((txp->delta_20_in_40 & 0xf0) >> 4),
|
((txp->delta_20_in_40 & 0xf0) >> 4),
|
||||||
(txp->delta_20_in_40 & 0x0f));
|
(txp->delta_20_in_40 & 0x0f));
|
||||||
|
|
||||||
max_txp_avg = iwl_get_max_txpower_avg(priv->cfg, txp_array, idx,
|
max_txp_avg = iwl_get_max_txpower_avg(cfg(priv), txp_array, idx,
|
||||||
&max_txp_avg_halfdbm);
|
&max_txp_avg_halfdbm);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -667,7 +667,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
|
|||||||
if (trans(priv)->nvm_device_type == -ENOENT)
|
if (trans(priv)->nvm_device_type == -ENOENT)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
/* allocate eeprom */
|
/* allocate eeprom */
|
||||||
sz = priv->cfg->base_params->eeprom_size;
|
sz = cfg(priv)->base_params->eeprom_size;
|
||||||
IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz);
|
IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz);
|
||||||
shrd->eeprom = kzalloc(sz, GFP_KERNEL);
|
shrd->eeprom = kzalloc(sz, GFP_KERNEL);
|
||||||
if (!shrd->eeprom) {
|
if (!shrd->eeprom) {
|
||||||
@ -709,7 +709,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
|
|||||||
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
|
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
|
||||||
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
|
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
|
||||||
/* traversing the linked list if no shadow ram supported */
|
/* traversing the linked list if no shadow ram supported */
|
||||||
if (!priv->cfg->base_params->shadow_ram_support) {
|
if (!cfg(priv)->base_params->shadow_ram_support) {
|
||||||
if (iwl_find_otp_image(bus(priv), &validblockaddr)) {
|
if (iwl_find_otp_image(bus(priv), &validblockaddr)) {
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
goto done;
|
goto done;
|
||||||
@ -776,7 +776,7 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
|
|||||||
const u8 **eeprom_ch_index)
|
const u8 **eeprom_ch_index)
|
||||||
{
|
{
|
||||||
struct iwl_shared *shrd = priv->shrd;
|
struct iwl_shared *shrd = priv->shrd;
|
||||||
u32 offset = priv->cfg->lib->
|
u32 offset = cfg(priv)->lib->
|
||||||
eeprom_ops.regulatory_bands[eep_band - 1];
|
eeprom_ops.regulatory_bands[eep_band - 1];
|
||||||
switch (eep_band) {
|
switch (eep_band) {
|
||||||
case 1: /* 2.4GHz band */
|
case 1: /* 2.4GHz band */
|
||||||
@ -983,9 +983,9 @@ int iwl_init_channel_map(struct iwl_priv *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we do have HT40 channels */
|
/* Check if we do have HT40 channels */
|
||||||
if (priv->cfg->lib->eeprom_ops.regulatory_bands[5] ==
|
if (cfg(priv)->lib->eeprom_ops.regulatory_bands[5] ==
|
||||||
EEPROM_REGULATORY_BAND_NO_HT40 &&
|
EEPROM_REGULATORY_BAND_NO_HT40 &&
|
||||||
priv->cfg->lib->eeprom_ops.regulatory_bands[6] ==
|
cfg(priv)->lib->eeprom_ops.regulatory_bands[6] ==
|
||||||
EEPROM_REGULATORY_BAND_NO_HT40)
|
EEPROM_REGULATORY_BAND_NO_HT40)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -1021,8 +1021,8 @@ int iwl_init_channel_map(struct iwl_priv *priv)
|
|||||||
* driver need to process addition information
|
* driver need to process addition information
|
||||||
* to determine the max channel tx power limits
|
* to determine the max channel tx power limits
|
||||||
*/
|
*/
|
||||||
if (priv->cfg->lib->eeprom_ops.update_enhanced_txpower)
|
if (cfg(priv)->lib->eeprom_ops.update_enhanced_txpower)
|
||||||
priv->cfg->lib->eeprom_ops.update_enhanced_txpower(priv);
|
cfg(priv)->lib->eeprom_ops.update_enhanced_txpower(priv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -283,16 +283,29 @@ u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr)
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val)
|
int _iwl_write_targ_mem_words(struct iwl_bus *bus, u32 addr,
|
||||||
|
void *buf, int words)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
int offs, result = 0;
|
||||||
|
u32 *vals = buf;
|
||||||
|
|
||||||
spin_lock_irqsave(&bus->reg_lock, flags);
|
spin_lock_irqsave(&bus->reg_lock, flags);
|
||||||
if (!iwl_grab_nic_access(bus)) {
|
if (!iwl_grab_nic_access(bus)) {
|
||||||
iwl_write32(bus, HBUS_TARG_MEM_WADDR, addr);
|
iwl_write32(bus, HBUS_TARG_MEM_WADDR, addr);
|
||||||
wmb();
|
wmb();
|
||||||
iwl_write32(bus, HBUS_TARG_MEM_WDAT, val);
|
|
||||||
|
for (offs = 0; offs < words; offs++)
|
||||||
|
iwl_write32(bus, HBUS_TARG_MEM_WDAT, vals[offs]);
|
||||||
iwl_release_nic_access(bus);
|
iwl_release_nic_access(bus);
|
||||||
}
|
} else
|
||||||
|
result = -EBUSY;
|
||||||
spin_unlock_irqrestore(&bus->reg_lock, flags);
|
spin_unlock_irqrestore(&bus->reg_lock, flags);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val)
|
||||||
|
{
|
||||||
|
return _iwl_write_targ_mem_words(bus, addr, &val, 1);
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,9 @@ void _iwl_read_targ_mem_words(struct iwl_bus *bus, u32 addr,
|
|||||||
(bufsize) / sizeof(u32));\
|
(bufsize) / sizeof(u32));\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
int _iwl_write_targ_mem_words(struct iwl_bus *bus, u32 addr,
|
||||||
|
void *buf, int words);
|
||||||
|
|
||||||
u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr);
|
u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr);
|
||||||
void iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val);
|
int iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val);
|
||||||
#endif
|
#endif
|
||||||
|
@ -137,11 +137,11 @@ static int iwl_led_cmd(struct iwl_priv *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n",
|
IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n",
|
||||||
priv->cfg->base_params->led_compensation);
|
cfg(priv)->base_params->led_compensation);
|
||||||
led_cmd.on = iwl_blink_compensation(priv, on,
|
led_cmd.on = iwl_blink_compensation(priv, on,
|
||||||
priv->cfg->base_params->led_compensation);
|
cfg(priv)->base_params->led_compensation);
|
||||||
led_cmd.off = iwl_blink_compensation(priv, off,
|
led_cmd.off = iwl_blink_compensation(priv, off,
|
||||||
priv->cfg->base_params->led_compensation);
|
cfg(priv)->base_params->led_compensation);
|
||||||
|
|
||||||
ret = iwl_send_led_cmd(priv, &led_cmd);
|
ret = iwl_send_led_cmd(priv, &led_cmd);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
@ -178,7 +178,7 @@ void iwl_leds_init(struct iwl_priv *priv)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (mode == IWL_LED_DEFAULT)
|
if (mode == IWL_LED_DEFAULT)
|
||||||
mode = priv->cfg->led_mode;
|
mode = cfg(priv)->led_mode;
|
||||||
|
|
||||||
priv->led.name = kasprintf(GFP_KERNEL, "%s-led",
|
priv->led.name = kasprintf(GFP_KERNEL, "%s-led",
|
||||||
wiphy_name(priv->hw->wiphy));
|
wiphy_name(priv->hw->wiphy));
|
||||||
|
@ -36,20 +36,6 @@ struct iwl_priv;
|
|||||||
#define IWL_LED_ACTIVITY (0<<1)
|
#define IWL_LED_ACTIVITY (0<<1)
|
||||||
#define IWL_LED_LINK (1<<1)
|
#define IWL_LED_LINK (1<<1)
|
||||||
|
|
||||||
/*
|
|
||||||
* LED mode
|
|
||||||
* IWL_LED_DEFAULT: use device default
|
|
||||||
* IWL_LED_RF_STATE: turn LED on/off based on RF state
|
|
||||||
* LED ON = RF ON
|
|
||||||
* LED OFF = RF OFF
|
|
||||||
* IWL_LED_BLINK: adjust led blink rate based on blink table
|
|
||||||
*/
|
|
||||||
enum iwl_led_mode {
|
|
||||||
IWL_LED_DEFAULT,
|
|
||||||
IWL_LED_RF_STATE,
|
|
||||||
IWL_LED_BLINK,
|
|
||||||
};
|
|
||||||
|
|
||||||
void iwlagn_led_enable(struct iwl_priv *priv);
|
void iwlagn_led_enable(struct iwl_priv *priv);
|
||||||
void iwl_leds_init(struct iwl_priv *priv);
|
void iwl_leds_init(struct iwl_priv *priv);
|
||||||
void iwl_leds_exit(struct iwl_priv *priv);
|
void iwl_leds_exit(struct iwl_priv *priv);
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include <asm/div64.h>
|
#include <asm/div64.h>
|
||||||
|
|
||||||
#include "iwl-eeprom.h"
|
#include "iwl-eeprom.h"
|
||||||
|
#include "iwl-wifi.h"
|
||||||
#include "iwl-dev.h"
|
#include "iwl-dev.h"
|
||||||
#include "iwl-core.h"
|
#include "iwl-core.h"
|
||||||
#include "iwl-io.h"
|
#include "iwl-io.h"
|
||||||
@ -160,7 +161,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
|||||||
hw->flags |= IEEE80211_HW_SUPPORTS_PS |
|
hw->flags |= IEEE80211_HW_SUPPORTS_PS |
|
||||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
|
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
|
||||||
|
|
||||||
if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
|
if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||||
hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
|
hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
|
||||||
IEEE80211_HW_SUPPORTS_STATIC_SMPS;
|
IEEE80211_HW_SUPPORTS_STATIC_SMPS;
|
||||||
|
|
||||||
@ -245,6 +246,15 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void iwlagn_mac_unregister(struct iwl_priv *priv)
|
||||||
|
{
|
||||||
|
if (!priv->mac80211_registered)
|
||||||
|
return;
|
||||||
|
iwl_leds_exit(priv);
|
||||||
|
ieee80211_unregister_hw(priv->hw);
|
||||||
|
priv->mac80211_registered = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int __iwl_up(struct iwl_priv *priv)
|
static int __iwl_up(struct iwl_priv *priv)
|
||||||
{
|
{
|
||||||
struct iwl_rxon_context *ctx;
|
struct iwl_rxon_context *ctx;
|
||||||
@ -265,13 +275,13 @@ static int __iwl_up(struct iwl_priv *priv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = iwlagn_run_init_ucode(priv);
|
ret = iwl_run_init_ucode(trans(priv));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret);
|
IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR);
|
ret = iwl_load_ucode_wait_alive(trans(priv), IWL_UCODE_REGULAR);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret);
|
IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret);
|
||||||
goto error;
|
goto error;
|
||||||
@ -611,12 +621,11 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
|
|||||||
struct iwl_priv *priv = hw->priv;
|
struct iwl_priv *priv = hw->priv;
|
||||||
int ret = -EINVAL;
|
int ret = -EINVAL;
|
||||||
struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
|
struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
|
||||||
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
|
|
||||||
|
|
||||||
IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
|
IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
|
||||||
sta->addr, tid);
|
sta->addr, tid);
|
||||||
|
|
||||||
if (!(priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE))
|
if (!(cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE))
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
|
|
||||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||||
@ -647,8 +656,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
|
|||||||
}
|
}
|
||||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||||
ret = 0;
|
ret = 0;
|
||||||
if (!priv->agg_tids_count && priv->cfg->ht_params &&
|
if (!priv->agg_tids_count && cfg(priv)->ht_params &&
|
||||||
priv->cfg->ht_params->use_rts_for_aggregation) {
|
cfg(priv)->ht_params->use_rts_for_aggregation) {
|
||||||
/*
|
/*
|
||||||
* switch off RTS/CTS if it was previously enabled
|
* switch off RTS/CTS if it was previously enabled
|
||||||
*/
|
*/
|
||||||
@ -659,54 +668,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||||
buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF);
|
ret = iwlagn_tx_agg_oper(priv, vif, sta, tid, buf_size);
|
||||||
|
|
||||||
iwl_trans_tx_agg_setup(trans(priv), ctx->ctxid, iwl_sta_id(sta),
|
|
||||||
tid, buf_size);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the limit is 0, then it wasn't initialised yet,
|
|
||||||
* use the default. We can do that since we take the
|
|
||||||
* minimum below, and we don't want to go above our
|
|
||||||
* default due to hardware restrictions.
|
|
||||||
*/
|
|
||||||
if (sta_priv->max_agg_bufsize == 0)
|
|
||||||
sta_priv->max_agg_bufsize =
|
|
||||||
LINK_QUAL_AGG_FRAME_LIMIT_DEF;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Even though in theory the peer could have different
|
|
||||||
* aggregation reorder buffer sizes for different sessions,
|
|
||||||
* our ucode doesn't allow for that and has a global limit
|
|
||||||
* for each station. Therefore, use the minimum of all the
|
|
||||||
* aggregation sessions and our default value.
|
|
||||||
*/
|
|
||||||
sta_priv->max_agg_bufsize =
|
|
||||||
min(sta_priv->max_agg_bufsize, buf_size);
|
|
||||||
|
|
||||||
if (priv->cfg->ht_params &&
|
|
||||||
priv->cfg->ht_params->use_rts_for_aggregation) {
|
|
||||||
/*
|
|
||||||
* switch to RTS/CTS if it is the prefer protection
|
|
||||||
* method for HT traffic
|
|
||||||
*/
|
|
||||||
|
|
||||||
sta_priv->lq_sta.lq.general_params.flags |=
|
|
||||||
LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
|
|
||||||
}
|
|
||||||
priv->agg_tids_count++;
|
|
||||||
IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
|
|
||||||
priv->agg_tids_count);
|
|
||||||
|
|
||||||
sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit =
|
|
||||||
sta_priv->max_agg_bufsize;
|
|
||||||
|
|
||||||
iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
|
|
||||||
&sta_priv->lq_sta.lq, CMD_ASYNC, false);
|
|
||||||
|
|
||||||
IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n",
|
|
||||||
sta->addr, tid);
|
|
||||||
ret = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mutex_unlock(&priv->shrd->mutex);
|
mutex_unlock(&priv->shrd->mutex);
|
||||||
@ -792,7 +754,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
|
|||||||
if (!iwl_is_associated_ctx(ctx))
|
if (!iwl_is_associated_ctx(ctx))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!priv->cfg->lib->set_channel_switch)
|
if (!cfg(priv)->lib->set_channel_switch)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ch = channel->hw_value;
|
ch = channel->hw_value;
|
||||||
@ -832,7 +794,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
|
|||||||
*/
|
*/
|
||||||
set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status);
|
set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status);
|
||||||
priv->switch_channel = cpu_to_le16(ch);
|
priv->switch_channel = cpu_to_le16(ch);
|
||||||
if (priv->cfg->lib->set_channel_switch(priv, ch_switch)) {
|
if (cfg(priv)->lib->set_channel_switch(priv, ch_switch)) {
|
||||||
clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status);
|
clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status);
|
||||||
priv->switch_channel = 0;
|
priv->switch_channel = 0;
|
||||||
ieee80211_chswitch_done(ctx->vif, false);
|
ieee80211_chswitch_done(ctx->vif, false);
|
||||||
@ -1125,8 +1087,8 @@ static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
|
|||||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||||
mutex_lock(&priv->shrd->mutex);
|
mutex_lock(&priv->shrd->mutex);
|
||||||
|
|
||||||
if (priv->cfg->bt_params &&
|
if (cfg(priv)->bt_params &&
|
||||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
cfg(priv)->bt_params->advanced_bt_coexist) {
|
||||||
if (rssi_event == RSSI_EVENT_LOW)
|
if (rssi_event == RSSI_EVENT_LOW)
|
||||||
priv->bt_enable_pspoll = true;
|
priv->bt_enable_pspoll = true;
|
||||||
else if (rssi_event == RSSI_EVENT_HIGH)
|
else if (rssi_event == RSSI_EVENT_HIGH)
|
||||||
@ -1237,7 +1199,7 @@ static int iwl_setup_interface(struct iwl_priv *priv,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist &&
|
if (cfg(priv)->bt_params && cfg(priv)->bt_params->advanced_bt_coexist &&
|
||||||
vif->type == NL80211_IFTYPE_ADHOC) {
|
vif->type == NL80211_IFTYPE_ADHOC) {
|
||||||
/*
|
/*
|
||||||
* pretend to have high BT traffic as long as we
|
* pretend to have high BT traffic as long as we
|
||||||
|
@ -167,7 +167,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
|
|||||||
u8 skip;
|
u8 skip;
|
||||||
u32 slp_itrvl;
|
u32 slp_itrvl;
|
||||||
|
|
||||||
if (priv->cfg->adv_pm) {
|
if (cfg(priv)->adv_pm) {
|
||||||
table = apm_range_2;
|
table = apm_range_2;
|
||||||
if (period <= IWL_DTIM_RANGE_1_MAX)
|
if (period <= IWL_DTIM_RANGE_1_MAX)
|
||||||
table = apm_range_1;
|
table = apm_range_1;
|
||||||
@ -221,7 +221,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
|
|||||||
cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
|
cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
|
||||||
|
|
||||||
if (iwl_advanced_bt_coexist(priv)) {
|
if (iwl_advanced_bt_coexist(priv)) {
|
||||||
if (!priv->cfg->bt_params->bt_sco_disable)
|
if (!cfg(priv)->bt_params->bt_sco_disable)
|
||||||
cmd->flags |= IWL_POWER_BT_SCO_ENA;
|
cmd->flags |= IWL_POWER_BT_SCO_ENA;
|
||||||
else
|
else
|
||||||
cmd->flags &= ~IWL_POWER_BT_SCO_ENA;
|
cmd->flags &= ~IWL_POWER_BT_SCO_ENA;
|
||||||
@ -307,7 +307,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
|
|||||||
cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
|
cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
|
||||||
|
|
||||||
if (iwl_advanced_bt_coexist(priv)) {
|
if (iwl_advanced_bt_coexist(priv)) {
|
||||||
if (!priv->cfg->bt_params->bt_sco_disable)
|
if (!cfg(priv)->bt_params->bt_sco_disable)
|
||||||
cmd->flags |= IWL_POWER_BT_SCO_ENA;
|
cmd->flags |= IWL_POWER_BT_SCO_ENA;
|
||||||
else
|
else
|
||||||
cmd->flags &= ~IWL_POWER_BT_SCO_ENA;
|
cmd->flags &= ~IWL_POWER_BT_SCO_ENA;
|
||||||
@ -350,7 +350,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
|
|||||||
|
|
||||||
if (priv->shrd->wowlan)
|
if (priv->shrd->wowlan)
|
||||||
iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper);
|
iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper);
|
||||||
else if (!priv->cfg->base_params->no_idle_support &&
|
else if (!cfg(priv)->base_params->no_idle_support &&
|
||||||
priv->hw->conf.flags & IEEE80211_CONF_IDLE)
|
priv->hw->conf.flags & IEEE80211_CONF_IDLE)
|
||||||
iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
|
iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
|
||||||
else if (iwl_tt_is_low_power_state(priv)) {
|
else if (iwl_tt_is_low_power_state(priv)) {
|
||||||
|
@ -691,8 +691,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||||||
* Internal scans are passive, so we can indiscriminately set
|
* Internal scans are passive, so we can indiscriminately set
|
||||||
* the BT ignore flag on 2.4 GHz since it applies to TX only.
|
* the BT ignore flag on 2.4 GHz since it applies to TX only.
|
||||||
*/
|
*/
|
||||||
if (priv->cfg->bt_params &&
|
if (cfg(priv)->bt_params &&
|
||||||
priv->cfg->bt_params->advanced_bt_coexist)
|
cfg(priv)->bt_params->advanced_bt_coexist)
|
||||||
scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT;
|
scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT;
|
||||||
break;
|
break;
|
||||||
case IEEE80211_BAND_5GHZ:
|
case IEEE80211_BAND_5GHZ:
|
||||||
@ -733,12 +733,12 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||||||
|
|
||||||
band = priv->scan_band;
|
band = priv->scan_band;
|
||||||
|
|
||||||
if (priv->cfg->scan_rx_antennas[band])
|
if (cfg(priv)->scan_rx_antennas[band])
|
||||||
rx_ant = priv->cfg->scan_rx_antennas[band];
|
rx_ant = cfg(priv)->scan_rx_antennas[band];
|
||||||
|
|
||||||
if (band == IEEE80211_BAND_2GHZ &&
|
if (band == IEEE80211_BAND_2GHZ &&
|
||||||
priv->cfg->bt_params &&
|
cfg(priv)->bt_params &&
|
||||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
cfg(priv)->bt_params->advanced_bt_coexist) {
|
||||||
/* transmit 2.4 GHz probes only on first antenna */
|
/* transmit 2.4 GHz probes only on first antenna */
|
||||||
scan_tx_antennas = first_antenna(scan_tx_antennas);
|
scan_tx_antennas = first_antenna(scan_tx_antennas);
|
||||||
}
|
}
|
||||||
@ -762,8 +762,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||||||
|
|
||||||
rx_ant = first_antenna(active_chains);
|
rx_ant = first_antenna(active_chains);
|
||||||
}
|
}
|
||||||
if (priv->cfg->bt_params &&
|
if (cfg(priv)->bt_params &&
|
||||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
cfg(priv)->bt_params->advanced_bt_coexist &&
|
||||||
priv->bt_full_concurrent) {
|
priv->bt_full_concurrent) {
|
||||||
/* operated as 1x1 in full concurrency mode */
|
/* operated as 1x1 in full concurrency mode */
|
||||||
rx_ant = first_antenna(rx_ant);
|
rx_ant = first_antenna(rx_ant);
|
||||||
|
@ -94,7 +94,6 @@
|
|||||||
* This implementation is iwl-pci.c
|
* This implementation is iwl-pci.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct iwl_cfg;
|
|
||||||
struct iwl_bus;
|
struct iwl_bus;
|
||||||
struct iwl_priv;
|
struct iwl_priv;
|
||||||
struct iwl_trans;
|
struct iwl_trans;
|
||||||
@ -199,64 +198,6 @@ struct iwl_hw_params {
|
|||||||
const struct iwl_sensitivity_ranges *sens;
|
const struct iwl_sensitivity_ranges *sens;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* enum iwl_agg_state
|
|
||||||
*
|
|
||||||
* The state machine of the BA agreement establishment / tear down.
|
|
||||||
* These states relate to a specific RA / TID.
|
|
||||||
*
|
|
||||||
* @IWL_AGG_OFF: aggregation is not used
|
|
||||||
* @IWL_AGG_ON: aggregation session is up
|
|
||||||
* @IWL_EMPTYING_HW_QUEUE_ADDBA: establishing a BA session - waiting for the
|
|
||||||
* HW queue to be empty from packets for this RA /TID.
|
|
||||||
* @IWL_EMPTYING_HW_QUEUE_DELBA: tearing down a BA session - waiting for the
|
|
||||||
* HW queue to be empty from packets for this RA /TID.
|
|
||||||
*/
|
|
||||||
enum iwl_agg_state {
|
|
||||||
IWL_AGG_OFF = 0,
|
|
||||||
IWL_AGG_ON,
|
|
||||||
IWL_EMPTYING_HW_QUEUE_ADDBA,
|
|
||||||
IWL_EMPTYING_HW_QUEUE_DELBA,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct iwl_ht_agg - aggregation state machine
|
|
||||||
|
|
||||||
* This structs holds the states for the BA agreement establishment and tear
|
|
||||||
* down. It also holds the state during the BA session itself. This struct is
|
|
||||||
* duplicated for each RA / TID.
|
|
||||||
|
|
||||||
* @rate_n_flags: Rate at which Tx was attempted. Holds the data between the
|
|
||||||
* Tx response (REPLY_TX), and the block ack notification
|
|
||||||
* (REPLY_COMPRESSED_BA).
|
|
||||||
* @state: state of the BA agreement establishment / tear down.
|
|
||||||
* @txq_id: Tx queue used by the BA session - used by the transport layer.
|
|
||||||
* Needed by the upper layer for debugfs only.
|
|
||||||
* @wait_for_ba: Expect block-ack before next Tx reply
|
|
||||||
*/
|
|
||||||
struct iwl_ht_agg {
|
|
||||||
u32 rate_n_flags;
|
|
||||||
enum iwl_agg_state state;
|
|
||||||
u16 txq_id;
|
|
||||||
bool wait_for_ba;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct iwl_tid_data - one for each RA / TID
|
|
||||||
|
|
||||||
* This structs holds the states for each RA / TID.
|
|
||||||
|
|
||||||
* @seq_number: the next WiFi sequence number to use
|
|
||||||
* @tfds_in_queue: number of packets sent to the HW queues.
|
|
||||||
* Exported for debugfs only
|
|
||||||
* @agg: aggregation state machine
|
|
||||||
*/
|
|
||||||
struct iwl_tid_data {
|
|
||||||
u16 seq_number;
|
|
||||||
u16 tfds_in_queue;
|
|
||||||
struct iwl_ht_agg agg;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum iwl_ucode_type
|
* enum iwl_ucode_type
|
||||||
*
|
*
|
||||||
@ -303,6 +244,101 @@ struct iwl_notification_wait {
|
|||||||
bool triggered, aborted;
|
bool triggered, aborted;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum iwl_pa_type - Power Amplifier type
|
||||||
|
* @IWL_PA_SYSTEM: based on uCode configuration
|
||||||
|
* @IWL_PA_INTERNAL: use Internal only
|
||||||
|
*/
|
||||||
|
enum iwl_pa_type {
|
||||||
|
IWL_PA_SYSTEM = 0,
|
||||||
|
IWL_PA_INTERNAL = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LED mode
|
||||||
|
* IWL_LED_DEFAULT: use device default
|
||||||
|
* IWL_LED_RF_STATE: turn LED on/off based on RF state
|
||||||
|
* LED ON = RF ON
|
||||||
|
* LED OFF = RF OFF
|
||||||
|
* IWL_LED_BLINK: adjust led blink rate based on blink table
|
||||||
|
*/
|
||||||
|
enum iwl_led_mode {
|
||||||
|
IWL_LED_DEFAULT,
|
||||||
|
IWL_LED_RF_STATE,
|
||||||
|
IWL_LED_BLINK,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct iwl_cfg
|
||||||
|
* @name: Offical name of the device
|
||||||
|
* @fw_name_pre: Firmware filename prefix. The api version and extension
|
||||||
|
* (.ucode) will be added to filename before loading from disk. The
|
||||||
|
* filename is constructed as fw_name_pre<api>.ucode.
|
||||||
|
* @ucode_api_max: Highest version of uCode API supported by driver.
|
||||||
|
* @ucode_api_ok: oldest version of the uCode API that is OK to load
|
||||||
|
* without a warning, for use in transitions
|
||||||
|
* @ucode_api_min: Lowest version of uCode API supported by driver.
|
||||||
|
* @valid_tx_ant: valid transmit antenna
|
||||||
|
* @valid_rx_ant: valid receive antenna
|
||||||
|
* @sku: sku information from EEPROM
|
||||||
|
* @eeprom_ver: EEPROM version
|
||||||
|
* @eeprom_calib_ver: EEPROM calibration version
|
||||||
|
* @lib: pointer to the lib ops
|
||||||
|
* @additional_nic_config: additional nic configuration
|
||||||
|
* @base_params: pointer to basic parameters
|
||||||
|
* @ht_params: point to ht patameters
|
||||||
|
* @bt_params: pointer to bt parameters
|
||||||
|
* @pa_type: used by 6000 series only to identify the type of Power Amplifier
|
||||||
|
* @need_temp_offset_calib: need to perform temperature offset calibration
|
||||||
|
* @no_xtal_calib: some devices do not need crystal calibration data,
|
||||||
|
* don't send it to those
|
||||||
|
* @scan_rx_antennas: available antenna for scan operation
|
||||||
|
* @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
|
||||||
|
* @adv_pm: advance power management
|
||||||
|
* @rx_with_siso_diversity: 1x1 device with rx antenna diversity
|
||||||
|
* @internal_wimax_coex: internal wifi/wimax combo device
|
||||||
|
* @iq_invert: I/Q inversion
|
||||||
|
* @temp_offset_v2: support v2 of temperature offset calibration
|
||||||
|
*
|
||||||
|
* We enable the driver to be backward compatible wrt API version. The
|
||||||
|
* driver specifies which APIs it supports (with @ucode_api_max being the
|
||||||
|
* highest and @ucode_api_min the lowest). Firmware will only be loaded if
|
||||||
|
* it has a supported API version.
|
||||||
|
*
|
||||||
|
* The ideal usage of this infrastructure is to treat a new ucode API
|
||||||
|
* release as a new hardware revision.
|
||||||
|
*/
|
||||||
|
struct iwl_cfg {
|
||||||
|
/* params specific to an individual device within a device family */
|
||||||
|
const char *name;
|
||||||
|
const char *fw_name_pre;
|
||||||
|
const unsigned int ucode_api_max;
|
||||||
|
const unsigned int ucode_api_ok;
|
||||||
|
const unsigned int ucode_api_min;
|
||||||
|
u8 valid_tx_ant;
|
||||||
|
u8 valid_rx_ant;
|
||||||
|
u16 sku;
|
||||||
|
u16 eeprom_ver;
|
||||||
|
u16 eeprom_calib_ver;
|
||||||
|
const struct iwl_lib_ops *lib;
|
||||||
|
void (*additional_nic_config)(struct iwl_priv *priv);
|
||||||
|
/* params not likely to change within a device family */
|
||||||
|
struct iwl_base_params *base_params;
|
||||||
|
/* params likely to change within a device family */
|
||||||
|
struct iwl_ht_params *ht_params;
|
||||||
|
struct iwl_bt_params *bt_params;
|
||||||
|
enum iwl_pa_type pa_type; /* if used set to IWL_PA_SYSTEM */
|
||||||
|
const bool need_temp_offset_calib; /* if used set to true */
|
||||||
|
const bool no_xtal_calib;
|
||||||
|
u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
|
||||||
|
enum iwl_led_mode led_mode;
|
||||||
|
const bool adv_pm;
|
||||||
|
const bool rx_with_siso_diversity;
|
||||||
|
const bool internal_wimax_coex;
|
||||||
|
const bool iq_invert;
|
||||||
|
const bool temp_offset_v2;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct iwl_shared - shared fields for all the layers of the driver
|
* struct iwl_shared - shared fields for all the layers of the driver
|
||||||
*
|
*
|
||||||
@ -311,15 +347,20 @@ struct iwl_notification_wait {
|
|||||||
* @ucode_owner: IWL_OWNERSHIP_*
|
* @ucode_owner: IWL_OWNERSHIP_*
|
||||||
* @cmd_queue: command queue number
|
* @cmd_queue: command queue number
|
||||||
* @status: STATUS_*
|
* @status: STATUS_*
|
||||||
|
* @wowlan: are we running wowlan uCode
|
||||||
* @valid_contexts: microcode/device supports multiple contexts
|
* @valid_contexts: microcode/device supports multiple contexts
|
||||||
* @bus: pointer to the bus layer data
|
* @bus: pointer to the bus layer data
|
||||||
|
* @cfg: see struct iwl_cfg
|
||||||
* @priv: pointer to the upper layer data
|
* @priv: pointer to the upper layer data
|
||||||
|
* @trans: pointer to the transport layer data
|
||||||
* @hw_params: see struct iwl_hw_params
|
* @hw_params: see struct iwl_hw_params
|
||||||
* @workqueue: the workqueue used by all the layers of the driver
|
* @workqueue: the workqueue used by all the layers of the driver
|
||||||
* @lock: protect general shared data
|
* @lock: protect general shared data
|
||||||
* @sta_lock: protects the station table.
|
* @sta_lock: protects the station table.
|
||||||
* If lock and sta_lock are needed, lock must be acquired first.
|
* If lock and sta_lock are needed, lock must be acquired first.
|
||||||
* @mutex:
|
* @mutex:
|
||||||
|
* @wait_command_queue: the wait_queue for SYNC host command nad uCode load
|
||||||
|
* @eeprom: pointer to the eeprom/OTP image
|
||||||
* @ucode_type: indicator of loaded ucode image
|
* @ucode_type: indicator of loaded ucode image
|
||||||
* @notif_waits: things waiting for notification
|
* @notif_waits: things waiting for notification
|
||||||
* @notif_wait_lock: lock protecting notification
|
* @notif_wait_lock: lock protecting notification
|
||||||
@ -340,6 +381,7 @@ struct iwl_shared {
|
|||||||
u8 valid_contexts;
|
u8 valid_contexts;
|
||||||
|
|
||||||
struct iwl_bus *bus;
|
struct iwl_bus *bus;
|
||||||
|
struct iwl_cfg *cfg;
|
||||||
struct iwl_priv *priv;
|
struct iwl_priv *priv;
|
||||||
struct iwl_trans *trans;
|
struct iwl_trans *trans;
|
||||||
struct iwl_hw_params hw_params;
|
struct iwl_hw_params hw_params;
|
||||||
@ -349,8 +391,6 @@ struct iwl_shared {
|
|||||||
spinlock_t sta_lock;
|
spinlock_t sta_lock;
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
|
|
||||||
struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT];
|
|
||||||
|
|
||||||
wait_queue_head_t wait_command_queue;
|
wait_queue_head_t wait_command_queue;
|
||||||
|
|
||||||
/* eeprom -- this is in the card's little endian byte order */
|
/* eeprom -- this is in the card's little endian byte order */
|
||||||
@ -373,6 +413,7 @@ struct iwl_shared {
|
|||||||
|
|
||||||
/*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */
|
/*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */
|
||||||
#define priv(_m) ((_m)->shrd->priv)
|
#define priv(_m) ((_m)->shrd->priv)
|
||||||
|
#define cfg(_m) ((_m)->shrd->cfg)
|
||||||
#define bus(_m) ((_m)->shrd->bus)
|
#define bus(_m) ((_m)->shrd->bus)
|
||||||
#define trans(_m) ((_m)->shrd->trans)
|
#define trans(_m) ((_m)->shrd->trans)
|
||||||
#define hw_params(_m) ((_m)->shrd->hw_params)
|
#define hw_params(_m) ((_m)->shrd->hw_params)
|
||||||
@ -494,12 +535,6 @@ int __must_check iwl_rx_dispatch(struct iwl_priv *priv,
|
|||||||
struct iwl_device_cmd *cmd);
|
struct iwl_device_cmd *cmd);
|
||||||
|
|
||||||
int iwlagn_hw_valid_rtc_data_addr(u32 addr);
|
int iwlagn_hw_valid_rtc_data_addr(u32 addr);
|
||||||
void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
|
|
||||||
enum iwl_rxon_context_id ctx,
|
|
||||||
u8 sta_id, u8 tid);
|
|
||||||
void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
|
|
||||||
enum iwl_rxon_context_id ctx,
|
|
||||||
u8 sta_id, u8 tid);
|
|
||||||
void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state);
|
void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state);
|
||||||
void iwl_nic_config(struct iwl_priv *priv);
|
void iwl_nic_config(struct iwl_priv *priv);
|
||||||
void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb);
|
void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb);
|
||||||
|
@ -70,6 +70,7 @@
|
|||||||
#include <net/mac80211.h>
|
#include <net/mac80211.h>
|
||||||
#include <net/netlink.h>
|
#include <net/netlink.h>
|
||||||
|
|
||||||
|
#include "iwl-wifi.h"
|
||||||
#include "iwl-dev.h"
|
#include "iwl-dev.h"
|
||||||
#include "iwl-core.h"
|
#include "iwl-core.h"
|
||||||
#include "iwl-debug.h"
|
#include "iwl-debug.h"
|
||||||
@ -380,7 +381,7 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
|
|||||||
iwl_init_notification_wait(priv->shrd, &calib_wait,
|
iwl_init_notification_wait(priv->shrd, &calib_wait,
|
||||||
CALIBRATION_COMPLETE_NOTIFICATION,
|
CALIBRATION_COMPLETE_NOTIFICATION,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
ret = iwlagn_init_alive_start(priv);
|
ret = iwl_init_alive_start(trans(priv));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
IWL_DEBUG_INFO(priv,
|
IWL_DEBUG_INFO(priv,
|
||||||
"Error configuring init calibration: %d\n", ret);
|
"Error configuring init calibration: %d\n", ret);
|
||||||
@ -417,6 +418,7 @@ cfg_init_calib_error:
|
|||||||
static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||||
{
|
{
|
||||||
struct iwl_priv *priv = hw->priv;
|
struct iwl_priv *priv = hw->priv;
|
||||||
|
struct iwl_trans *trans = trans(priv);
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
unsigned char *rsp_data_ptr = NULL;
|
unsigned char *rsp_data_ptr = NULL;
|
||||||
int status = 0, rsp_data_len = 0;
|
int status = 0, rsp_data_len = 0;
|
||||||
@ -425,8 +427,8 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
|||||||
|
|
||||||
switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
|
switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
|
||||||
case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
|
case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
|
||||||
rsp_data_ptr = (unsigned char *)priv->cfg->name;
|
rsp_data_ptr = (unsigned char *)cfg(priv)->name;
|
||||||
rsp_data_len = strlen(priv->cfg->name);
|
rsp_data_len = strlen(cfg(priv)->name);
|
||||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
|
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
|
||||||
rsp_data_len + 20);
|
rsp_data_len + 20);
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
@ -445,7 +447,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
|
case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
|
||||||
status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
|
status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT);
|
||||||
if (status)
|
if (status)
|
||||||
IWL_DEBUG_INFO(priv,
|
IWL_DEBUG_INFO(priv,
|
||||||
"Error loading init ucode: %d\n", status);
|
"Error loading init ucode: %d\n", status);
|
||||||
@ -453,11 +455,11 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
|||||||
|
|
||||||
case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
|
case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
|
||||||
iwl_testmode_cfg_init_calib(priv);
|
iwl_testmode_cfg_init_calib(priv);
|
||||||
iwl_trans_stop_device(trans(priv));
|
iwl_trans_stop_device(trans);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
|
case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
|
||||||
status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR);
|
status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_REGULAR);
|
||||||
if (status) {
|
if (status) {
|
||||||
IWL_DEBUG_INFO(priv,
|
IWL_DEBUG_INFO(priv,
|
||||||
"Error loading runtime ucode: %d\n", status);
|
"Error loading runtime ucode: %d\n", status);
|
||||||
@ -471,8 +473,8 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
|||||||
|
|
||||||
case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
|
case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
|
||||||
iwl_scan_cancel_timeout(priv, 200);
|
iwl_scan_cancel_timeout(priv, 200);
|
||||||
iwl_trans_stop_device(trans(priv));
|
iwl_trans_stop_device(trans);
|
||||||
status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
|
status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_WOWLAN);
|
||||||
if (status) {
|
if (status) {
|
||||||
IWL_DEBUG_INFO(priv,
|
IWL_DEBUG_INFO(priv,
|
||||||
"Error loading WOWLAN ucode: %d\n", status);
|
"Error loading WOWLAN ucode: %d\n", status);
|
||||||
@ -487,7 +489,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
|||||||
case IWL_TM_CMD_APP2DEV_GET_EEPROM:
|
case IWL_TM_CMD_APP2DEV_GET_EEPROM:
|
||||||
if (priv->shrd->eeprom) {
|
if (priv->shrd->eeprom) {
|
||||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
|
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
|
||||||
priv->cfg->base_params->eeprom_size + 20);
|
cfg(priv)->base_params->eeprom_size + 20);
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
IWL_DEBUG_INFO(priv,
|
IWL_DEBUG_INFO(priv,
|
||||||
"Error allocating memory\n");
|
"Error allocating memory\n");
|
||||||
@ -496,7 +498,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
|||||||
NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND,
|
NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND,
|
||||||
IWL_TM_CMD_DEV2APP_EEPROM_RSP);
|
IWL_TM_CMD_DEV2APP_EEPROM_RSP);
|
||||||
NLA_PUT(skb, IWL_TM_ATTR_EEPROM,
|
NLA_PUT(skb, IWL_TM_ATTR_EEPROM,
|
||||||
priv->cfg->base_params->eeprom_size,
|
cfg(priv)->base_params->eeprom_size,
|
||||||
priv->shrd->eeprom);
|
priv->shrd->eeprom);
|
||||||
status = cfg80211_testmode_reply(skb);
|
status = cfg80211_testmode_reply(skb);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
|
@ -236,6 +236,7 @@ struct iwl_trans_pcie {
|
|||||||
const u8 *ac_to_fifo[NUM_IWL_RXON_CTX];
|
const u8 *ac_to_fifo[NUM_IWL_RXON_CTX];
|
||||||
const u8 *ac_to_queue[NUM_IWL_RXON_CTX];
|
const u8 *ac_to_queue[NUM_IWL_RXON_CTX];
|
||||||
u8 mcast_queue[NUM_IWL_RXON_CTX];
|
u8 mcast_queue[NUM_IWL_RXON_CTX];
|
||||||
|
u8 agg_txq[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT];
|
||||||
|
|
||||||
struct iwl_tx_queue *txq;
|
struct iwl_tx_queue *txq;
|
||||||
unsigned long txq_ctx_active_msk;
|
unsigned long txq_ctx_active_msk;
|
||||||
@ -280,20 +281,16 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans,
|
|||||||
void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
|
void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
|
||||||
struct iwl_tx_queue *txq,
|
struct iwl_tx_queue *txq,
|
||||||
u16 byte_cnt);
|
u16 byte_cnt);
|
||||||
void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id);
|
|
||||||
int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans,
|
int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans,
|
||||||
enum iwl_rxon_context_id ctx, int sta_id,
|
int sta_id, int tid);
|
||||||
int tid);
|
|
||||||
void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index);
|
void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index);
|
||||||
void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
|
void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
|
||||||
struct iwl_tx_queue *txq,
|
struct iwl_tx_queue *txq,
|
||||||
int tx_fifo_id, int scd_retry);
|
int tx_fifo_id, int scd_retry);
|
||||||
int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
|
int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans, int sta_id, int tid);
|
||||||
enum iwl_rxon_context_id ctx, int sta_id,
|
|
||||||
int tid, u16 *ssn);
|
|
||||||
void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
|
void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
|
||||||
enum iwl_rxon_context_id ctx,
|
enum iwl_rxon_context_id ctx,
|
||||||
int sta_id, int tid, int frame_limit);
|
int sta_id, int tid, int frame_limit, u16 ssn);
|
||||||
void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
|
void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
|
||||||
int index, enum dma_data_direction dma_dir);
|
int index, enum dma_data_direction dma_dir);
|
||||||
int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
|
int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
|
||||||
|
@ -672,7 +672,7 @@ static void iwl_irq_handle_error(struct iwl_trans *trans)
|
|||||||
{
|
{
|
||||||
struct iwl_priv *priv = priv(trans);
|
struct iwl_priv *priv = priv(trans);
|
||||||
/* W/A for WiFi/WiMAX coex and WiMAX own the RF */
|
/* W/A for WiFi/WiMAX coex and WiMAX own the RF */
|
||||||
if (priv->cfg->internal_wimax_coex &&
|
if (cfg(priv)->internal_wimax_coex &&
|
||||||
(!(iwl_read_prph(bus(trans), APMG_CLK_CTRL_REG) &
|
(!(iwl_read_prph(bus(trans), APMG_CLK_CTRL_REG) &
|
||||||
APMS_CLK_VAL_MRB_FUNC_MODE) ||
|
APMS_CLK_VAL_MRB_FUNC_MODE) ||
|
||||||
(iwl_read_prph(bus(trans), APMG_PS_CTRL_REG) &
|
(iwl_read_prph(bus(trans), APMG_PS_CTRL_REG) &
|
||||||
|
@ -408,6 +408,7 @@ static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id)
|
|||||||
void iwl_trans_set_wr_ptrs(struct iwl_trans *trans,
|
void iwl_trans_set_wr_ptrs(struct iwl_trans *trans,
|
||||||
int txq_id, u32 index)
|
int txq_id, u32 index)
|
||||||
{
|
{
|
||||||
|
IWL_DEBUG_TX_QUEUES(trans, "Q %d WrPtr: %d", txq_id, index & 0xff);
|
||||||
iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR,
|
iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR,
|
||||||
(index & 0xff) | (txq_id << 8));
|
(index & 0xff) | (txq_id << 8));
|
||||||
iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(txq_id), index);
|
iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(txq_id), index);
|
||||||
@ -446,14 +447,21 @@ static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool is_agg_txqid_valid(struct iwl_trans *trans, int txq_id)
|
||||||
|
{
|
||||||
|
if (txq_id < IWLAGN_FIRST_AMPDU_QUEUE)
|
||||||
|
return false;
|
||||||
|
return txq_id < (IWLAGN_FIRST_AMPDU_QUEUE +
|
||||||
|
hw_params(trans).num_ampdu_queues);
|
||||||
|
}
|
||||||
|
|
||||||
void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
|
void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
|
||||||
enum iwl_rxon_context_id ctx, int sta_id,
|
enum iwl_rxon_context_id ctx, int sta_id,
|
||||||
int tid, int frame_limit)
|
int tid, int frame_limit, u16 ssn)
|
||||||
{
|
{
|
||||||
int tx_fifo, txq_id, ssn_idx;
|
int tx_fifo, txq_id;
|
||||||
u16 ra_tid;
|
u16 ra_tid;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct iwl_tid_data *tid_data;
|
|
||||||
|
|
||||||
struct iwl_trans_pcie *trans_pcie =
|
struct iwl_trans_pcie *trans_pcie =
|
||||||
IWL_TRANS_GET_PCIE_TRANS(trans);
|
IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||||
@ -469,11 +477,15 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&trans->shrd->sta_lock, flags);
|
txq_id = trans_pcie->agg_txq[sta_id][tid];
|
||||||
tid_data = &trans->shrd->tid_data[sta_id][tid];
|
if (WARN_ON_ONCE(is_agg_txqid_valid(trans, txq_id) == false)) {
|
||||||
ssn_idx = SEQ_TO_SN(tid_data->seq_number);
|
IWL_ERR(trans,
|
||||||
txq_id = tid_data->agg.txq_id;
|
"queue number out of range: %d, must be %d to %d\n",
|
||||||
spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
|
txq_id, IWLAGN_FIRST_AMPDU_QUEUE,
|
||||||
|
IWLAGN_FIRST_AMPDU_QUEUE +
|
||||||
|
hw_params(trans).num_ampdu_queues - 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ra_tid = BUILD_RAxTID(sta_id, tid);
|
ra_tid = BUILD_RAxTID(sta_id, tid);
|
||||||
|
|
||||||
@ -493,9 +505,9 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
|
|||||||
|
|
||||||
/* Place first TFD at index corresponding to start sequence number.
|
/* Place first TFD at index corresponding to start sequence number.
|
||||||
* Assumes that ssn_idx is valid (!= 0xFFF) */
|
* Assumes that ssn_idx is valid (!= 0xFFF) */
|
||||||
trans_pcie->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
|
trans_pcie->txq[txq_id].q.read_ptr = (ssn & 0xff);
|
||||||
trans_pcie->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
|
trans_pcie->txq[txq_id].q.write_ptr = (ssn & 0xff);
|
||||||
iwl_trans_set_wr_ptrs(trans, txq_id, ssn_idx);
|
iwl_trans_set_wr_ptrs(trans, txq_id, ssn);
|
||||||
|
|
||||||
/* Set up Tx window size and frame limit for this queue */
|
/* Set up Tx window size and frame limit for this queue */
|
||||||
iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr +
|
iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr +
|
||||||
@ -539,12 +551,9 @@ static int iwlagn_txq_ctx_activate_free(struct iwl_trans *trans)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
|
int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
|
||||||
enum iwl_rxon_context_id ctx, int sta_id,
|
int sta_id, int tid)
|
||||||
int tid, u16 *ssn)
|
|
||||||
{
|
{
|
||||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||||
struct iwl_tid_data *tid_data;
|
|
||||||
unsigned long flags;
|
|
||||||
int txq_id;
|
int txq_id;
|
||||||
|
|
||||||
txq_id = iwlagn_txq_ctx_activate_free(trans);
|
txq_id = iwlagn_txq_ctx_activate_free(trans);
|
||||||
@ -553,34 +562,31 @@ int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
|
|||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&trans->shrd->sta_lock, flags);
|
trans_pcie->agg_txq[sta_id][tid] = txq_id;
|
||||||
tid_data = &trans->shrd->tid_data[sta_id][tid];
|
|
||||||
*ssn = SEQ_TO_SN(tid_data->seq_number);
|
|
||||||
tid_data->agg.txq_id = txq_id;
|
|
||||||
iwl_set_swq_id(&trans_pcie->txq[txq_id], get_ac_from_tid(tid), txq_id);
|
iwl_set_swq_id(&trans_pcie->txq[txq_id], get_ac_from_tid(tid), txq_id);
|
||||||
|
|
||||||
if (tid_data->tfds_in_queue == 0) {
|
|
||||||
IWL_DEBUG_TX_QUEUES(trans, "HW queue is empty\n");
|
|
||||||
tid_data->agg.state = IWL_AGG_ON;
|
|
||||||
iwl_start_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid);
|
|
||||||
} else {
|
|
||||||
IWL_DEBUG_TX_QUEUES(trans,
|
|
||||||
"HW queue is NOT empty: %d packets in HW"
|
|
||||||
" queue\n", tid_data->tfds_in_queue);
|
|
||||||
tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id)
|
int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int sta_id, int tid)
|
||||||
{
|
{
|
||||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||||
|
u8 txq_id = trans_pcie->agg_txq[sta_id][tid];
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(is_agg_txqid_valid(trans, txq_id) == false)) {
|
||||||
|
IWL_ERR(trans,
|
||||||
|
"queue number out of range: %d, must be %d to %d\n",
|
||||||
|
txq_id, IWLAGN_FIRST_AMPDU_QUEUE,
|
||||||
|
IWLAGN_FIRST_AMPDU_QUEUE +
|
||||||
|
hw_params(trans).num_ampdu_queues - 1);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
iwlagn_tx_queue_stop_scheduler(trans, txq_id);
|
iwlagn_tx_queue_stop_scheduler(trans, txq_id);
|
||||||
|
|
||||||
iwl_clear_bits_prph(bus(trans), SCD_AGGR_SEL, (1 << txq_id));
|
iwl_clear_bits_prph(bus(trans), SCD_AGGR_SEL, (1 << txq_id));
|
||||||
|
|
||||||
|
trans_pcie->agg_txq[sta_id][tid] = 0;
|
||||||
trans_pcie->txq[txq_id].q.read_ptr = 0;
|
trans_pcie->txq[txq_id].q.read_ptr = 0;
|
||||||
trans_pcie->txq[txq_id].q.write_ptr = 0;
|
trans_pcie->txq[txq_id].q.write_ptr = 0;
|
||||||
/* supposes that ssn_idx is valid (!= 0xFFF) */
|
/* supposes that ssn_idx is valid (!= 0xFFF) */
|
||||||
@ -589,82 +595,6 @@ void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id)
|
|||||||
iwl_clear_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id));
|
iwl_clear_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id));
|
||||||
iwl_txq_ctx_deactivate(trans_pcie, txq_id);
|
iwl_txq_ctx_deactivate(trans_pcie, txq_id);
|
||||||
iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], 0, 0);
|
iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], 0, 0);
|
||||||
}
|
|
||||||
|
|
||||||
int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans,
|
|
||||||
enum iwl_rxon_context_id ctx, int sta_id,
|
|
||||||
int tid)
|
|
||||||
{
|
|
||||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
|
||||||
unsigned long flags;
|
|
||||||
int read_ptr, write_ptr;
|
|
||||||
struct iwl_tid_data *tid_data;
|
|
||||||
int txq_id;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&trans->shrd->sta_lock, flags);
|
|
||||||
|
|
||||||
tid_data = &trans->shrd->tid_data[sta_id][tid];
|
|
||||||
txq_id = tid_data->agg.txq_id;
|
|
||||||
|
|
||||||
if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
|
|
||||||
(IWLAGN_FIRST_AMPDU_QUEUE +
|
|
||||||
hw_params(trans).num_ampdu_queues <= txq_id)) {
|
|
||||||
IWL_ERR(trans,
|
|
||||||
"queue number out of range: %d, must be %d to %d\n",
|
|
||||||
txq_id, IWLAGN_FIRST_AMPDU_QUEUE,
|
|
||||||
IWLAGN_FIRST_AMPDU_QUEUE +
|
|
||||||
hw_params(trans).num_ampdu_queues - 1);
|
|
||||||
spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (trans->shrd->tid_data[sta_id][tid].agg.state) {
|
|
||||||
case IWL_EMPTYING_HW_QUEUE_ADDBA:
|
|
||||||
/*
|
|
||||||
* This can happen if the peer stops aggregation
|
|
||||||
* again before we've had a chance to drain the
|
|
||||||
* queue we selected previously, i.e. before the
|
|
||||||
* session was really started completely.
|
|
||||||
*/
|
|
||||||
IWL_DEBUG_HT(trans, "AGG stop before setup done\n");
|
|
||||||
goto turn_off;
|
|
||||||
case IWL_AGG_ON:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
IWL_WARN(trans, "Stopping AGG while state not ON "
|
|
||||||
"or starting for %d on %d (%d)\n", sta_id, tid,
|
|
||||||
trans->shrd->tid_data[sta_id][tid].agg.state);
|
|
||||||
spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_ptr = trans_pcie->txq[txq_id].q.write_ptr;
|
|
||||||
read_ptr = trans_pcie->txq[txq_id].q.read_ptr;
|
|
||||||
|
|
||||||
/* The queue is not empty */
|
|
||||||
if (write_ptr != read_ptr) {
|
|
||||||
IWL_DEBUG_TX_QUEUES(trans,
|
|
||||||
"Stopping a non empty AGG HW QUEUE\n");
|
|
||||||
trans->shrd->tid_data[sta_id][tid].agg.state =
|
|
||||||
IWL_EMPTYING_HW_QUEUE_DELBA;
|
|
||||||
spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
IWL_DEBUG_TX_QUEUES(trans, "HW queue is empty\n");
|
|
||||||
turn_off:
|
|
||||||
trans->shrd->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF;
|
|
||||||
|
|
||||||
/* do not restore/save irqs */
|
|
||||||
spin_unlock(&trans->shrd->sta_lock);
|
|
||||||
spin_lock(&trans->shrd->lock);
|
|
||||||
|
|
||||||
iwl_trans_pcie_txq_agg_disable(trans, txq_id);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
|
||||||
|
|
||||||
iwl_stop_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1044,7 +1044,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
|
|||||||
|
|
||||||
static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||||
struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
|
struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
|
||||||
u8 sta_id)
|
u8 sta_id, u8 tid)
|
||||||
{
|
{
|
||||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
@ -1058,13 +1058,12 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
|||||||
dma_addr_t txcmd_phys;
|
dma_addr_t txcmd_phys;
|
||||||
dma_addr_t scratch_phys;
|
dma_addr_t scratch_phys;
|
||||||
u16 len, firstlen, secondlen;
|
u16 len, firstlen, secondlen;
|
||||||
u16 seq_number = 0;
|
|
||||||
u8 wait_write_ptr = 0;
|
u8 wait_write_ptr = 0;
|
||||||
u8 txq_id;
|
u8 txq_id;
|
||||||
u8 tid = 0;
|
|
||||||
bool is_agg = false;
|
bool is_agg = false;
|
||||||
__le16 fc = hdr->frame_control;
|
__le16 fc = hdr->frame_control;
|
||||||
u8 hdr_len = ieee80211_hdrlen(fc);
|
u8 hdr_len = ieee80211_hdrlen(fc);
|
||||||
|
u16 __maybe_unused wifi_seq;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send this frame after DTIM -- there's a special queue
|
* Send this frame after DTIM -- there's a special queue
|
||||||
@ -1085,44 +1084,28 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
|||||||
txq_id =
|
txq_id =
|
||||||
trans_pcie->ac_to_queue[ctx][skb_get_queue_mapping(skb)];
|
trans_pcie->ac_to_queue[ctx][skb_get_queue_mapping(skb)];
|
||||||
|
|
||||||
if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) {
|
|
||||||
u8 *qc = NULL;
|
|
||||||
struct iwl_tid_data *tid_data;
|
|
||||||
qc = ieee80211_get_qos_ctl(hdr);
|
|
||||||
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
|
|
||||||
tid_data = &trans->shrd->tid_data[sta_id][tid];
|
|
||||||
|
|
||||||
if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
seq_number = tid_data->seq_number;
|
|
||||||
seq_number &= IEEE80211_SCTL_SEQ;
|
|
||||||
hdr->seq_ctrl = hdr->seq_ctrl &
|
|
||||||
cpu_to_le16(IEEE80211_SCTL_FRAG);
|
|
||||||
hdr->seq_ctrl |= cpu_to_le16(seq_number);
|
|
||||||
/* aggregation is on for this <sta,tid> */
|
/* aggregation is on for this <sta,tid> */
|
||||||
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
|
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
|
||||||
if (WARN_ON_ONCE(tid_data->agg.state != IWL_AGG_ON)) {
|
WARN_ON(tid >= IWL_MAX_TID_COUNT);
|
||||||
IWL_ERR(trans, "TX_CTL_AMPDU while not in AGG:"
|
txq_id = trans_pcie->agg_txq[sta_id][tid];
|
||||||
" Tx flags = 0x%08x, agg.state = %d",
|
|
||||||
info->flags, tid_data->agg.state);
|
|
||||||
IWL_ERR(trans, "sta_id = %d, tid = %d "
|
|
||||||
"txq_id = %d, seq_num = %d", sta_id,
|
|
||||||
tid, tid_data->agg.txq_id,
|
|
||||||
seq_number >> 4);
|
|
||||||
}
|
|
||||||
txq_id = tid_data->agg.txq_id;
|
|
||||||
is_agg = true;
|
is_agg = true;
|
||||||
}
|
}
|
||||||
seq_number += 0x10;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy MAC header from skb into command buffer */
|
|
||||||
memcpy(tx_cmd->hdr, hdr, hdr_len);
|
|
||||||
|
|
||||||
txq = &trans_pcie->txq[txq_id];
|
txq = &trans_pcie->txq[txq_id];
|
||||||
q = &txq->q;
|
q = &txq->q;
|
||||||
|
|
||||||
|
/* In AGG mode, the index in the ring must correspond to the WiFi
|
||||||
|
* sequence number. This is a HW requirements to help the SCD to parse
|
||||||
|
* the BA.
|
||||||
|
* Check here that the packets are in the right place on the ring.
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||||
|
wifi_seq = SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
|
||||||
|
WARN_ONCE(is_agg && ((wifi_seq & 0xff) != q->write_ptr),
|
||||||
|
"Q: %d WiFi Seq %d tfdNum %d",
|
||||||
|
txq_id, wifi_seq, q->write_ptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Set up driver data for this TFD */
|
/* Set up driver data for this TFD */
|
||||||
txq->skbs[q->write_ptr] = skb;
|
txq->skbs[q->write_ptr] = skb;
|
||||||
txq->cmd[q->write_ptr] = dev_cmd;
|
txq->cmd[q->write_ptr] = dev_cmd;
|
||||||
@ -1222,13 +1205,6 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
|||||||
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
|
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
|
||||||
iwl_txq_update_write_ptr(trans, txq);
|
iwl_txq_update_write_ptr(trans, txq);
|
||||||
|
|
||||||
if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) {
|
|
||||||
trans->shrd->tid_data[sta_id][tid].tfds_in_queue++;
|
|
||||||
if (!ieee80211_has_morefrags(fc))
|
|
||||||
trans->shrd->tid_data[sta_id][tid].seq_number =
|
|
||||||
seq_number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At this point the frame is "transmitted" successfully
|
* At this point the frame is "transmitted" successfully
|
||||||
* and we will get a TX status notification eventually,
|
* and we will get a TX status notification eventually,
|
||||||
@ -1277,85 +1253,30 @@ static int iwl_trans_pcie_request_irq(struct iwl_trans *trans)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwlagn_txq_check_empty(struct iwl_trans *trans,
|
static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
|
||||||
int sta_id, u8 tid, int txq_id)
|
|
||||||
{
|
|
||||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
|
||||||
struct iwl_queue *q = &trans_pcie->txq[txq_id].q;
|
|
||||||
struct iwl_tid_data *tid_data = &trans->shrd->tid_data[sta_id][tid];
|
|
||||||
|
|
||||||
lockdep_assert_held(&trans->shrd->sta_lock);
|
|
||||||
|
|
||||||
switch (trans->shrd->tid_data[sta_id][tid].agg.state) {
|
|
||||||
case IWL_EMPTYING_HW_QUEUE_DELBA:
|
|
||||||
/* We are reclaiming the last packet of the */
|
|
||||||
/* aggregated HW queue */
|
|
||||||
if ((txq_id == tid_data->agg.txq_id) &&
|
|
||||||
(q->read_ptr == q->write_ptr)) {
|
|
||||||
IWL_DEBUG_TX_QUEUES(trans,
|
|
||||||
"HW queue empty: continue DELBA flow\n");
|
|
||||||
iwl_trans_pcie_txq_agg_disable(trans, txq_id);
|
|
||||||
tid_data->agg.state = IWL_AGG_OFF;
|
|
||||||
iwl_stop_tx_ba_trans_ready(priv(trans),
|
|
||||||
NUM_IWL_RXON_CTX,
|
|
||||||
sta_id, tid);
|
|
||||||
iwl_wake_queue(trans, &trans_pcie->txq[txq_id],
|
|
||||||
"DELBA flow complete");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case IWL_EMPTYING_HW_QUEUE_ADDBA:
|
|
||||||
/* We are reclaiming the last packet of the queue */
|
|
||||||
if (tid_data->tfds_in_queue == 0) {
|
|
||||||
IWL_DEBUG_TX_QUEUES(trans,
|
|
||||||
"HW queue empty: continue ADDBA flow\n");
|
|
||||||
tid_data->agg.state = IWL_AGG_ON;
|
|
||||||
iwl_start_tx_ba_trans_ready(priv(trans),
|
|
||||||
NUM_IWL_RXON_CTX,
|
|
||||||
sta_id, tid);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void iwl_free_tfds_in_queue(struct iwl_trans *trans,
|
|
||||||
int sta_id, int tid, int freed)
|
|
||||||
{
|
|
||||||
lockdep_assert_held(&trans->shrd->sta_lock);
|
|
||||||
|
|
||||||
if (trans->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed)
|
|
||||||
trans->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed;
|
|
||||||
else {
|
|
||||||
IWL_DEBUG_TX(trans, "free more than tfds_in_queue (%u:%d)\n",
|
|
||||||
trans->shrd->tid_data[sta_id][tid].tfds_in_queue,
|
|
||||||
freed);
|
|
||||||
trans->shrd->tid_data[sta_id][tid].tfds_in_queue = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
|
|
||||||
int txq_id, int ssn, u32 status,
|
int txq_id, int ssn, u32 status,
|
||||||
struct sk_buff_head *skbs)
|
struct sk_buff_head *skbs)
|
||||||
{
|
{
|
||||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||||
struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
|
struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
|
||||||
enum iwl_agg_state agg_state;
|
|
||||||
/* n_bd is usually 256 => n_bd - 1 = 0xff */
|
/* n_bd is usually 256 => n_bd - 1 = 0xff */
|
||||||
int tfd_num = ssn & (txq->q.n_bd - 1);
|
int tfd_num = ssn & (txq->q.n_bd - 1);
|
||||||
int freed = 0;
|
int freed = 0;
|
||||||
bool cond;
|
|
||||||
|
|
||||||
txq->time_stamp = jiffies;
|
txq->time_stamp = jiffies;
|
||||||
|
|
||||||
if (txq->sched_retry) {
|
if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE &&
|
||||||
agg_state =
|
txq_id != trans_pcie->agg_txq[sta_id][tid])) {
|
||||||
trans->shrd->tid_data[txq->sta_id][txq->tid].agg.state;
|
/*
|
||||||
cond = (agg_state != IWL_EMPTYING_HW_QUEUE_DELBA);
|
* FIXME: this is a uCode bug which need to be addressed,
|
||||||
} else {
|
* log the information and return for now.
|
||||||
cond = (status != TX_STATUS_FAIL_PASSIVE_NO_RX);
|
* Since it is can possibly happen very often and in order
|
||||||
|
* not to fill the syslog, don't use IWL_ERR or IWL_WARN
|
||||||
|
*/
|
||||||
|
IWL_DEBUG_TX_QUEUES(trans, "Bad queue mapping txq_id %d, "
|
||||||
|
"agg_txq[sta_id[tid] %d", txq_id,
|
||||||
|
trans_pcie->agg_txq[sta_id][tid]);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (txq->q.read_ptr != tfd_num) {
|
if (txq->q.read_ptr != tfd_num) {
|
||||||
@ -1363,12 +1284,12 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
|
|||||||
txq_id, iwl_get_queue_ac(txq), txq->q.read_ptr,
|
txq_id, iwl_get_queue_ac(txq), txq->q.read_ptr,
|
||||||
tfd_num, ssn);
|
tfd_num, ssn);
|
||||||
freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
|
freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
|
||||||
if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond)
|
if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
|
||||||
|
(!txq->sched_retry ||
|
||||||
|
status != TX_STATUS_FAIL_PASSIVE_NO_RX))
|
||||||
iwl_wake_queue(trans, txq, "Packets reclaimed");
|
iwl_wake_queue(trans, txq, "Packets reclaimed");
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
iwl_free_tfds_in_queue(trans, sta_id, tid, freed);
|
|
||||||
iwlagn_txq_check_empty(trans, sta_id, tid, txq_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iwl_trans_pcie_free(struct iwl_trans *trans)
|
static void iwl_trans_pcie_free(struct iwl_trans *trans)
|
||||||
|
@ -178,20 +178,18 @@ struct iwl_trans_ops {
|
|||||||
|
|
||||||
int (*tx)(struct iwl_trans *trans, struct sk_buff *skb,
|
int (*tx)(struct iwl_trans *trans, struct sk_buff *skb,
|
||||||
struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
|
struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
|
||||||
u8 sta_id);
|
u8 sta_id, u8 tid);
|
||||||
void (*reclaim)(struct iwl_trans *trans, int sta_id, int tid,
|
int (*reclaim)(struct iwl_trans *trans, int sta_id, int tid,
|
||||||
int txq_id, int ssn, u32 status,
|
int txq_id, int ssn, u32 status,
|
||||||
struct sk_buff_head *skbs);
|
struct sk_buff_head *skbs);
|
||||||
|
|
||||||
int (*tx_agg_disable)(struct iwl_trans *trans,
|
int (*tx_agg_disable)(struct iwl_trans *trans,
|
||||||
enum iwl_rxon_context_id ctx, int sta_id,
|
int sta_id, int tid);
|
||||||
int tid);
|
|
||||||
int (*tx_agg_alloc)(struct iwl_trans *trans,
|
int (*tx_agg_alloc)(struct iwl_trans *trans,
|
||||||
enum iwl_rxon_context_id ctx, int sta_id, int tid,
|
int sta_id, int tid);
|
||||||
u16 *ssn);
|
|
||||||
void (*tx_agg_setup)(struct iwl_trans *trans,
|
void (*tx_agg_setup)(struct iwl_trans *trans,
|
||||||
enum iwl_rxon_context_id ctx, int sta_id, int tid,
|
enum iwl_rxon_context_id ctx, int sta_id, int tid,
|
||||||
int frame_limit);
|
int frame_limit, u16 ssn);
|
||||||
|
|
||||||
void (*kick_nic)(struct iwl_trans *trans);
|
void (*kick_nic)(struct iwl_trans *trans);
|
||||||
|
|
||||||
@ -305,39 +303,38 @@ int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id,
|
|||||||
|
|
||||||
static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||||
struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
|
struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
|
||||||
u8 sta_id)
|
u8 sta_id, u8 tid)
|
||||||
{
|
{
|
||||||
return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id);
|
return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id, tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void iwl_trans_reclaim(struct iwl_trans *trans, int sta_id,
|
static inline int iwl_trans_reclaim(struct iwl_trans *trans, int sta_id,
|
||||||
int tid, int txq_id, int ssn, u32 status,
|
int tid, int txq_id, int ssn, u32 status,
|
||||||
struct sk_buff_head *skbs)
|
struct sk_buff_head *skbs)
|
||||||
{
|
{
|
||||||
trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn, status, skbs);
|
return trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn,
|
||||||
|
status, skbs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans,
|
static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans,
|
||||||
enum iwl_rxon_context_id ctx,
|
|
||||||
int sta_id, int tid)
|
int sta_id, int tid)
|
||||||
{
|
{
|
||||||
return trans->ops->tx_agg_disable(trans, ctx, sta_id, tid);
|
return trans->ops->tx_agg_disable(trans, sta_id, tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans,
|
static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans,
|
||||||
enum iwl_rxon_context_id ctx,
|
int sta_id, int tid)
|
||||||
int sta_id, int tid, u16 *ssn)
|
|
||||||
{
|
{
|
||||||
return trans->ops->tx_agg_alloc(trans, ctx, sta_id, tid, ssn);
|
return trans->ops->tx_agg_alloc(trans, sta_id, tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans,
|
static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans,
|
||||||
enum iwl_rxon_context_id ctx,
|
enum iwl_rxon_context_id ctx,
|
||||||
int sta_id, int tid,
|
int sta_id, int tid,
|
||||||
int frame_limit)
|
int frame_limit, u16 ssn)
|
||||||
{
|
{
|
||||||
trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit);
|
trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit, ssn);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void iwl_trans_kick_nic(struct iwl_trans *trans)
|
static inline void iwl_trans_kick_nic(struct iwl_trans *trans)
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
|
|
||||||
|
#include "iwl-wifi.h"
|
||||||
#include "iwl-dev.h"
|
#include "iwl-dev.h"
|
||||||
#include "iwl-core.h"
|
#include "iwl-core.h"
|
||||||
#include "iwl-io.h"
|
#include "iwl-io.h"
|
||||||
@ -213,23 +214,23 @@ static int iwl_load_given_ucode(struct iwl_trans *trans,
|
|||||||
/*
|
/*
|
||||||
* Calibration
|
* Calibration
|
||||||
*/
|
*/
|
||||||
static int iwl_set_Xtal_calib(struct iwl_priv *priv)
|
static int iwl_set_Xtal_calib(struct iwl_trans *trans)
|
||||||
{
|
{
|
||||||
struct iwl_calib_xtal_freq_cmd cmd;
|
struct iwl_calib_xtal_freq_cmd cmd;
|
||||||
__le16 *xtal_calib =
|
__le16 *xtal_calib =
|
||||||
(__le16 *)iwl_eeprom_query_addr(priv->shrd, EEPROM_XTAL);
|
(__le16 *)iwl_eeprom_query_addr(trans->shrd, EEPROM_XTAL);
|
||||||
|
|
||||||
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD);
|
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD);
|
||||||
cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
|
cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
|
||||||
cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]);
|
cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]);
|
||||||
return iwl_calib_set(trans(priv), (void *)&cmd, sizeof(cmd));
|
return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwl_set_temperature_offset_calib(struct iwl_priv *priv)
|
static int iwl_set_temperature_offset_calib(struct iwl_trans *trans)
|
||||||
{
|
{
|
||||||
struct iwl_calib_temperature_offset_cmd cmd;
|
struct iwl_calib_temperature_offset_cmd cmd;
|
||||||
__le16 *offset_calib =
|
__le16 *offset_calib =
|
||||||
(__le16 *)iwl_eeprom_query_addr(priv->shrd,
|
(__le16 *)iwl_eeprom_query_addr(trans->shrd,
|
||||||
EEPROM_RAW_TEMPERATURE);
|
EEPROM_RAW_TEMPERATURE);
|
||||||
|
|
||||||
memset(&cmd, 0, sizeof(cmd));
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
@ -238,45 +239,45 @@ static int iwl_set_temperature_offset_calib(struct iwl_priv *priv)
|
|||||||
if (!(cmd.radio_sensor_offset))
|
if (!(cmd.radio_sensor_offset))
|
||||||
cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
|
cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
|
||||||
|
|
||||||
IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",
|
IWL_DEBUG_CALIB(trans, "Radio sensor offset: %d\n",
|
||||||
le16_to_cpu(cmd.radio_sensor_offset));
|
le16_to_cpu(cmd.radio_sensor_offset));
|
||||||
return iwl_calib_set(trans(priv), (void *)&cmd, sizeof(cmd));
|
return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv)
|
static int iwl_set_temperature_offset_calib_v2(struct iwl_trans *trans)
|
||||||
{
|
{
|
||||||
struct iwl_calib_temperature_offset_v2_cmd cmd;
|
struct iwl_calib_temperature_offset_v2_cmd cmd;
|
||||||
__le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv->shrd,
|
__le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(trans->shrd,
|
||||||
EEPROM_KELVIN_TEMPERATURE);
|
EEPROM_KELVIN_TEMPERATURE);
|
||||||
__le16 *offset_calib_low =
|
__le16 *offset_calib_low =
|
||||||
(__le16 *)iwl_eeprom_query_addr(priv->shrd,
|
(__le16 *)iwl_eeprom_query_addr(trans->shrd,
|
||||||
EEPROM_RAW_TEMPERATURE);
|
EEPROM_RAW_TEMPERATURE);
|
||||||
struct iwl_eeprom_calib_hdr *hdr;
|
struct iwl_eeprom_calib_hdr *hdr;
|
||||||
|
|
||||||
memset(&cmd, 0, sizeof(cmd));
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
|
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
|
||||||
hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv->shrd,
|
hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(trans->shrd,
|
||||||
EEPROM_CALIB_ALL);
|
EEPROM_CALIB_ALL);
|
||||||
memcpy(&cmd.radio_sensor_offset_high, offset_calib_high,
|
memcpy(&cmd.radio_sensor_offset_high, offset_calib_high,
|
||||||
sizeof(*offset_calib_high));
|
sizeof(*offset_calib_high));
|
||||||
memcpy(&cmd.radio_sensor_offset_low, offset_calib_low,
|
memcpy(&cmd.radio_sensor_offset_low, offset_calib_low,
|
||||||
sizeof(*offset_calib_low));
|
sizeof(*offset_calib_low));
|
||||||
if (!(cmd.radio_sensor_offset_low)) {
|
if (!(cmd.radio_sensor_offset_low)) {
|
||||||
IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n");
|
IWL_DEBUG_CALIB(trans, "no info in EEPROM, use default\n");
|
||||||
cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET;
|
cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET;
|
||||||
cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET;
|
cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET;
|
||||||
}
|
}
|
||||||
memcpy(&cmd.burntVoltageRef, &hdr->voltage,
|
memcpy(&cmd.burntVoltageRef, &hdr->voltage,
|
||||||
sizeof(hdr->voltage));
|
sizeof(hdr->voltage));
|
||||||
|
|
||||||
IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n",
|
IWL_DEBUG_CALIB(trans, "Radio sensor offset high: %d\n",
|
||||||
le16_to_cpu(cmd.radio_sensor_offset_high));
|
le16_to_cpu(cmd.radio_sensor_offset_high));
|
||||||
IWL_DEBUG_CALIB(priv, "Radio sensor offset low: %d\n",
|
IWL_DEBUG_CALIB(trans, "Radio sensor offset low: %d\n",
|
||||||
le16_to_cpu(cmd.radio_sensor_offset_low));
|
le16_to_cpu(cmd.radio_sensor_offset_low));
|
||||||
IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n",
|
IWL_DEBUG_CALIB(trans, "Voltage Ref: %d\n",
|
||||||
le16_to_cpu(cmd.burntVoltageRef));
|
le16_to_cpu(cmd.burntVoltageRef));
|
||||||
|
|
||||||
return iwl_calib_set(trans(priv), (void *)&cmd, sizeof(cmd));
|
return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwl_send_calib_cfg(struct iwl_trans *trans)
|
static int iwl_send_calib_cfg(struct iwl_trans *trans)
|
||||||
@ -316,26 +317,26 @@ int iwlagn_rx_calib_result(struct iwl_priv *priv,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int iwlagn_init_alive_start(struct iwl_priv *priv)
|
int iwl_init_alive_start(struct iwl_trans *trans)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (priv->cfg->bt_params &&
|
if (cfg(trans)->bt_params &&
|
||||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
cfg(trans)->bt_params->advanced_bt_coexist) {
|
||||||
/*
|
/*
|
||||||
* Tell uCode we are ready to perform calibration
|
* Tell uCode we are ready to perform calibration
|
||||||
* need to perform this before any calibration
|
* need to perform this before any calibration
|
||||||
* no need to close the envlope since we are going
|
* no need to close the envlope since we are going
|
||||||
* to load the runtime uCode later.
|
* to load the runtime uCode later.
|
||||||
*/
|
*/
|
||||||
ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_OPEN,
|
ret = iwl_send_bt_env(trans, IWL_BT_COEX_ENV_OPEN,
|
||||||
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
|
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = iwl_send_calib_cfg(trans(priv));
|
ret = iwl_send_calib_cfg(trans);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -343,21 +344,21 @@ int iwlagn_init_alive_start(struct iwl_priv *priv)
|
|||||||
* temperature offset calibration is only needed for runtime ucode,
|
* temperature offset calibration is only needed for runtime ucode,
|
||||||
* so prepare the value now.
|
* so prepare the value now.
|
||||||
*/
|
*/
|
||||||
if (priv->cfg->need_temp_offset_calib) {
|
if (cfg(trans)->need_temp_offset_calib) {
|
||||||
if (priv->cfg->temp_offset_v2)
|
if (cfg(trans)->temp_offset_v2)
|
||||||
return iwl_set_temperature_offset_calib_v2(priv);
|
return iwl_set_temperature_offset_calib_v2(trans);
|
||||||
else
|
else
|
||||||
return iwl_set_temperature_offset_calib(priv);
|
return iwl_set_temperature_offset_calib(trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iwl_send_wimax_coex(struct iwl_priv *priv)
|
static int iwl_send_wimax_coex(struct iwl_trans *trans)
|
||||||
{
|
{
|
||||||
struct iwl_wimax_coex_cmd coex_cmd;
|
struct iwl_wimax_coex_cmd coex_cmd;
|
||||||
|
|
||||||
if (priv->cfg->base_params->support_wimax_coexist) {
|
if (cfg(trans)->base_params->support_wimax_coexist) {
|
||||||
/* UnMask wake up src at associated sleep */
|
/* UnMask wake up src at associated sleep */
|
||||||
coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK;
|
coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK;
|
||||||
|
|
||||||
@ -376,7 +377,7 @@ static int iwl_send_wimax_coex(struct iwl_priv *priv)
|
|||||||
/* coexistence is disabled */
|
/* coexistence is disabled */
|
||||||
memset(&coex_cmd, 0, sizeof(coex_cmd));
|
memset(&coex_cmd, 0, sizeof(coex_cmd));
|
||||||
}
|
}
|
||||||
return iwl_trans_send_cmd_pdu(trans(priv),
|
return iwl_trans_send_cmd_pdu(trans,
|
||||||
COEX_PRIORITY_TABLE_CMD, CMD_SYNC,
|
COEX_PRIORITY_TABLE_CMD, CMD_SYNC,
|
||||||
sizeof(coex_cmd), &coex_cmd);
|
sizeof(coex_cmd), &coex_cmd);
|
||||||
}
|
}
|
||||||
@ -431,8 +432,9 @@ int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int iwl_alive_notify(struct iwl_priv *priv)
|
static int iwl_alive_notify(struct iwl_trans *trans)
|
||||||
{
|
{
|
||||||
|
struct iwl_priv *priv = priv(trans);
|
||||||
struct iwl_rxon_context *ctx;
|
struct iwl_rxon_context *ctx;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -445,21 +447,21 @@ static int iwl_alive_notify(struct iwl_priv *priv)
|
|||||||
if (!priv->tx_cmd_pool)
|
if (!priv->tx_cmd_pool)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
iwl_trans_tx_start(trans(priv));
|
iwl_trans_tx_start(trans);
|
||||||
for_each_context(priv, ctx)
|
for_each_context(priv, ctx)
|
||||||
ctx->last_tx_rejected = false;
|
ctx->last_tx_rejected = false;
|
||||||
|
|
||||||
ret = iwl_send_wimax_coex(priv);
|
ret = iwl_send_wimax_coex(trans);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (!priv->cfg->no_xtal_calib) {
|
if (!cfg(priv)->no_xtal_calib) {
|
||||||
ret = iwl_set_Xtal_calib(priv);
|
ret = iwl_set_Xtal_calib(trans);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return iwl_send_calib_results(trans(priv));
|
return iwl_send_calib_results(trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -545,7 +547,7 @@ static int iwl_verify_ucode(struct iwl_trans *trans,
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct iwlagn_alive_data {
|
struct iwl_alive_data {
|
||||||
bool valid;
|
bool valid;
|
||||||
u8 subtype;
|
u8 subtype;
|
||||||
};
|
};
|
||||||
@ -554,7 +556,7 @@ static void iwl_alive_fn(struct iwl_trans *trans,
|
|||||||
struct iwl_rx_packet *pkt,
|
struct iwl_rx_packet *pkt,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct iwlagn_alive_data *alive_data = data;
|
struct iwl_alive_data *alive_data = data;
|
||||||
struct iwl_alive_resp *palive;
|
struct iwl_alive_resp *palive;
|
||||||
|
|
||||||
palive = &pkt->u.alive_frame;
|
palive = &pkt->u.alive_frame;
|
||||||
@ -640,12 +642,11 @@ void iwl_abort_notification_waits(struct iwl_shared *shrd)
|
|||||||
#define UCODE_ALIVE_TIMEOUT HZ
|
#define UCODE_ALIVE_TIMEOUT HZ
|
||||||
#define UCODE_CALIB_TIMEOUT (2*HZ)
|
#define UCODE_CALIB_TIMEOUT (2*HZ)
|
||||||
|
|
||||||
int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
|
int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
|
||||||
enum iwl_ucode_type ucode_type)
|
enum iwl_ucode_type ucode_type)
|
||||||
{
|
{
|
||||||
struct iwl_notification_wait alive_wait;
|
struct iwl_notification_wait alive_wait;
|
||||||
struct iwlagn_alive_data alive_data;
|
struct iwl_alive_data alive_data;
|
||||||
struct iwl_trans *trans = trans(priv);
|
|
||||||
int ret;
|
int ret;
|
||||||
enum iwl_ucode_type old_type;
|
enum iwl_ucode_type old_type;
|
||||||
|
|
||||||
@ -680,7 +681,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!alive_data.valid) {
|
if (!alive_data.valid) {
|
||||||
IWL_ERR(priv, "Loaded ucode is not valid!\n");
|
IWL_ERR(trans, "Loaded ucode is not valid!\n");
|
||||||
trans->shrd->ucode_type = old_type;
|
trans->shrd->ucode_type = old_type;
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
@ -701,9 +702,9 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
|
|||||||
msleep(5);
|
msleep(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = iwl_alive_notify(priv);
|
ret = iwl_alive_notify(trans);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
IWL_WARN(priv,
|
IWL_WARN(trans,
|
||||||
"Could not complete ALIVE transition: %d\n", ret);
|
"Could not complete ALIVE transition: %d\n", ret);
|
||||||
trans->shrd->ucode_type = old_type;
|
trans->shrd->ucode_type = old_type;
|
||||||
return ret;
|
return ret;
|
||||||
@ -712,30 +713,30 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int iwlagn_run_init_ucode(struct iwl_priv *priv)
|
int iwl_run_init_ucode(struct iwl_trans *trans)
|
||||||
{
|
{
|
||||||
struct iwl_notification_wait calib_wait;
|
struct iwl_notification_wait calib_wait;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
lockdep_assert_held(&priv->shrd->mutex);
|
lockdep_assert_held(&trans->shrd->mutex);
|
||||||
|
|
||||||
/* No init ucode required? Curious, but maybe ok */
|
/* No init ucode required? Curious, but maybe ok */
|
||||||
if (!trans(priv)->ucode_init.code.len)
|
if (!trans->ucode_init.code.len)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (priv->shrd->ucode_type != IWL_UCODE_NONE)
|
if (trans->shrd->ucode_type != IWL_UCODE_NONE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
iwl_init_notification_wait(priv->shrd, &calib_wait,
|
iwl_init_notification_wait(trans->shrd, &calib_wait,
|
||||||
CALIBRATION_COMPLETE_NOTIFICATION,
|
CALIBRATION_COMPLETE_NOTIFICATION,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
|
||||||
/* Will also start the device */
|
/* Will also start the device */
|
||||||
ret = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
|
ret = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
ret = iwlagn_init_alive_start(priv);
|
ret = iwl_init_alive_start(trans);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -743,15 +744,15 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
|
|||||||
* Some things may run in the background now, but we
|
* Some things may run in the background now, but we
|
||||||
* just wait for the calibration complete notification.
|
* just wait for the calibration complete notification.
|
||||||
*/
|
*/
|
||||||
ret = iwl_wait_notification(priv->shrd, &calib_wait,
|
ret = iwl_wait_notification(trans->shrd, &calib_wait,
|
||||||
UCODE_CALIB_TIMEOUT);
|
UCODE_CALIB_TIMEOUT);
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
iwl_remove_notification(priv->shrd, &calib_wait);
|
iwl_remove_notification(trans->shrd, &calib_wait);
|
||||||
out:
|
out:
|
||||||
/* Whatever happened, stop the device */
|
/* Whatever happened, stop the device */
|
||||||
iwl_trans_stop_device(trans(priv));
|
iwl_trans_stop_device(trans);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
74
drivers/net/wireless/iwlwifi/iwl-wifi.h
Normal file
74
drivers/net/wireless/iwlwifi/iwl-wifi.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||||
|
* redistributing this file, you may do so under either license.
|
||||||
|
*
|
||||||
|
* GPL LICENSE SUMMARY
|
||||||
|
*
|
||||||
|
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* The full GNU General Public License is included in this distribution
|
||||||
|
* in the file called LICENSE.GPL.
|
||||||
|
*
|
||||||
|
* Contact Information:
|
||||||
|
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||||
|
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||||
|
*
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __iwl_wifi_h__
|
||||||
|
#define __iwl_wifi_h__
|
||||||
|
|
||||||
|
#include "iwl-shared.h"
|
||||||
|
|
||||||
|
int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type);
|
||||||
|
void iwl_send_prio_tbl(struct iwl_trans *trans);
|
||||||
|
int iwl_init_alive_start(struct iwl_trans *trans);
|
||||||
|
int iwl_run_init_ucode(struct iwl_trans *trans);
|
||||||
|
int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
|
||||||
|
enum iwl_ucode_type ucode_type);
|
||||||
|
#endif /* __iwl_wifi_h__ */
|
Loading…
x
Reference in New Issue
Block a user