mirror of https://gitee.com/openkylin/linux.git
Merge branch 'wireless-next-2.6' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6
This commit is contained in:
commit
486699532e
|
@ -130,7 +130,7 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
|
|||
sizeof(struct iwlagn_scd_bc_tbl);
|
||||
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
|
||||
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
|
||||
priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
|
||||
|
||||
priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
|
||||
priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
|
||||
|
@ -217,7 +217,7 @@ static struct iwl_lib_ops iwl1000_lib = {
|
|||
.set_ct_kill = iwl1000_set_ct_threshold,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_station = iwl_update_bcast_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
|
|
|
@ -226,6 +226,7 @@ struct iwl3945_eeprom {
|
|||
|
||||
/* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */
|
||||
#define IWL39_NUM_QUEUES 5
|
||||
#define IWL39_CMD_QUEUE_NUM 4
|
||||
|
||||
#define IWL_DEFAULT_TX_RETRY 15
|
||||
|
||||
|
|
|
@ -343,7 +343,7 @@ void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 s
|
|||
int i;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "enter\n");
|
||||
if (sta_id == priv->hw_params.bcast_sta_id)
|
||||
if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
|
||||
goto out;
|
||||
|
||||
psta = (struct iwl3945_sta_priv *) sta->drv_priv;
|
||||
|
@ -932,7 +932,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
|
|||
|
||||
rcu_read_lock();
|
||||
|
||||
sta = ieee80211_find_sta(priv->vif,
|
||||
sta = ieee80211_find_sta(priv->contexts[IWL_RXON_CTX_BSS].vif,
|
||||
priv->stations[sta_id].sta.sta.addr);
|
||||
if (!sta) {
|
||||
IWL_DEBUG_RATE(priv, "Unable to find station to initialize rate scaling.\n");
|
||||
|
@ -949,7 +949,8 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
|
|||
switch (priv->band) {
|
||||
case IEEE80211_BAND_2GHZ:
|
||||
/* TODO: this always does G, not a regression */
|
||||
if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) {
|
||||
if (priv->contexts[IWL_RXON_CTX_BSS].active.flags &
|
||||
RXON_FLG_TGG_PROTECT_MSK) {
|
||||
rs_sta->tgg = 1;
|
||||
rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
|
||||
} else
|
||||
|
|
|
@ -245,7 +245,7 @@ int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate)
|
|||
break;
|
||||
case IEEE80211_BAND_2GHZ:
|
||||
if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
|
||||
iwl_is_associated(priv)) {
|
||||
iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
|
||||
if (rate == IWL_RATE_11M_INDEX)
|
||||
next_rate = IWL_RATE_5M_INDEX;
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
|
|||
struct iwl_queue *q = &txq->q;
|
||||
struct iwl_tx_info *tx_info;
|
||||
|
||||
BUG_ON(txq_id == IWL_CMD_QUEUE_NUM);
|
||||
BUG_ON(txq_id == IWL39_CMD_QUEUE_NUM);
|
||||
|
||||
for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
|
||||
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
|
||||
|
@ -285,7 +285,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
|
|||
}
|
||||
|
||||
if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) &&
|
||||
(txq_id != IWL_CMD_QUEUE_NUM) &&
|
||||
(txq_id != IWL39_CMD_QUEUE_NUM) &&
|
||||
priv->mac80211_registered)
|
||||
iwl_wake_queue(priv, txq_id);
|
||||
}
|
||||
|
@ -760,7 +760,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
|
|||
data_retry_limit = IWL_DEFAULT_TX_RETRY;
|
||||
tx_cmd->data_retry_limit = data_retry_limit;
|
||||
|
||||
if (tx_id >= IWL_CMD_QUEUE_NUM)
|
||||
if (tx_id >= IWL39_CMD_QUEUE_NUM)
|
||||
rts_retry_limit = 3;
|
||||
else
|
||||
rts_retry_limit = 7;
|
||||
|
@ -909,7 +909,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
|
|||
|
||||
/* Tx queue(s) */
|
||||
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
|
||||
slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
|
||||
slots_num = (txq_id == IWL39_CMD_QUEUE_NUM) ?
|
||||
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
|
||||
rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
|
||||
txq_id);
|
||||
|
@ -1072,7 +1072,7 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv)
|
|||
if (priv->txq)
|
||||
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num;
|
||||
txq_id++)
|
||||
if (txq_id == IWL_CMD_QUEUE_NUM)
|
||||
if (txq_id == IWL39_CMD_QUEUE_NUM)
|
||||
iwl_cmd_queue_free(priv);
|
||||
else
|
||||
iwl_tx_queue_free(priv, txq_id);
|
||||
|
@ -1439,17 +1439,18 @@ static int iwl3945_send_tx_power(struct iwl_priv *priv)
|
|||
int rate_idx, i;
|
||||
const struct iwl_channel_info *ch_info = NULL;
|
||||
struct iwl3945_txpowertable_cmd txpower = {
|
||||
.channel = priv->active_rxon.channel,
|
||||
.channel = priv->contexts[IWL_RXON_CTX_BSS].active.channel,
|
||||
};
|
||||
u16 chan;
|
||||
|
||||
chan = le16_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.channel);
|
||||
|
||||
txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
|
||||
ch_info = iwl_get_channel_info(priv,
|
||||
priv->band,
|
||||
le16_to_cpu(priv->active_rxon.channel));
|
||||
ch_info = iwl_get_channel_info(priv, priv->band, chan);
|
||||
if (!ch_info) {
|
||||
IWL_ERR(priv,
|
||||
"Failed to get channel info for channel %d [%d]\n",
|
||||
le16_to_cpu(priv->active_rxon.channel), priv->band);
|
||||
chan, priv->band);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1710,7 +1711,8 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
|
||||
static int iwl3945_send_rxon_assoc(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
int rc = 0;
|
||||
struct iwl_rx_packet *pkt;
|
||||
|
@ -1721,8 +1723,8 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
|
|||
.flags = CMD_WANT_SKB,
|
||||
.data = &rxon_assoc,
|
||||
};
|
||||
const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
|
||||
const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
|
||||
const struct iwl_rxon_cmd *rxon1 = &ctx->staging;
|
||||
const struct iwl_rxon_cmd *rxon2 = &ctx->active;
|
||||
|
||||
if ((rxon1->flags == rxon2->flags) &&
|
||||
(rxon1->filter_flags == rxon2->filter_flags) &&
|
||||
|
@ -1732,10 +1734,10 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
rxon_assoc.flags = priv->staging_rxon.flags;
|
||||
rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
|
||||
rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
|
||||
rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
|
||||
rxon_assoc.flags = ctx->staging.flags;
|
||||
rxon_assoc.filter_flags = ctx->staging.filter_flags;
|
||||
rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
|
||||
rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
|
||||
rxon_assoc.reserved = 0;
|
||||
|
||||
rc = iwl_send_cmd_sync(priv, &cmd);
|
||||
|
@ -1761,14 +1763,14 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
|
|||
* function correctly transitions out of the RXON_ASSOC_MSK state if
|
||||
* a HW tune is required based on the RXON structure changes.
|
||||
*/
|
||||
static int iwl3945_commit_rxon(struct iwl_priv *priv)
|
||||
static int iwl3945_commit_rxon(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
/* cast away the const for active_rxon in this function */
|
||||
struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
|
||||
struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon;
|
||||
struct iwl3945_rxon_cmd *active_rxon = (void *)&ctx->active;
|
||||
struct iwl3945_rxon_cmd *staging_rxon = (void *)&ctx->staging;
|
||||
int rc = 0;
|
||||
bool new_assoc =
|
||||
!!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
|
||||
bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK);
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return -1;
|
||||
|
@ -1781,7 +1783,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
|
|||
~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
|
||||
staging_rxon->flags |= iwl3945_get_antenna_flags(priv);
|
||||
|
||||
rc = iwl_check_rxon_cmd(priv);
|
||||
rc = iwl_check_rxon_cmd(priv, ctx);
|
||||
if (rc) {
|
||||
IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
|
||||
return -EINVAL;
|
||||
|
@ -1790,8 +1792,9 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
|
|||
/* If we don't need to send a full RXON, we can use
|
||||
* iwl3945_rxon_assoc_cmd which is used to reconfigure filter
|
||||
* and other flags for the current radio configuration. */
|
||||
if (!iwl_full_rxon_required(priv)) {
|
||||
rc = iwl_send_rxon_assoc(priv);
|
||||
if (!iwl_full_rxon_required(priv, &priv->contexts[IWL_RXON_CTX_BSS])) {
|
||||
rc = iwl_send_rxon_assoc(priv,
|
||||
&priv->contexts[IWL_RXON_CTX_BSS]);
|
||||
if (rc) {
|
||||
IWL_ERR(priv, "Error setting RXON_ASSOC "
|
||||
"configuration (%d).\n", rc);
|
||||
|
@ -1807,7 +1810,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
|
|||
* an RXON_ASSOC and the new config wants the associated mask enabled,
|
||||
* we must clear the associated from the active configuration
|
||||
* before we apply the new config */
|
||||
if (iwl_is_associated(priv) && new_assoc) {
|
||||
if (iwl_is_associated(priv, IWL_RXON_CTX_BSS) && new_assoc) {
|
||||
IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
|
||||
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
|
||||
|
@ -1819,7 +1822,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
|
|||
active_rxon->reserved5 = 0;
|
||||
rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
|
||||
sizeof(struct iwl3945_rxon_cmd),
|
||||
&priv->active_rxon);
|
||||
&priv->contexts[IWL_RXON_CTX_BSS].active);
|
||||
|
||||
/* If the mask clearing failed then we set
|
||||
* active_rxon back to what it was previously */
|
||||
|
@ -1829,8 +1832,9 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
|
|||
"configuration (%d).\n", rc);
|
||||
return rc;
|
||||
}
|
||||
iwl_clear_ucode_stations(priv);
|
||||
iwl_restore_stations(priv);
|
||||
iwl_clear_ucode_stations(priv,
|
||||
&priv->contexts[IWL_RXON_CTX_BSS]);
|
||||
iwl_restore_stations(priv, &priv->contexts[IWL_RXON_CTX_BSS]);
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Sending RXON\n"
|
||||
|
@ -1848,7 +1852,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
|
|||
staging_rxon->reserved4 = 0;
|
||||
staging_rxon->reserved5 = 0;
|
||||
|
||||
iwl_set_rxon_hwcrypto(priv, !iwl3945_mod_params.sw_crypto);
|
||||
iwl_set_rxon_hwcrypto(priv, ctx, !iwl3945_mod_params.sw_crypto);
|
||||
|
||||
/* Apply the new configuration */
|
||||
rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
|
||||
|
@ -1862,8 +1866,9 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
|
|||
memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
|
||||
|
||||
if (!new_assoc) {
|
||||
iwl_clear_ucode_stations(priv);
|
||||
iwl_restore_stations(priv);
|
||||
iwl_clear_ucode_stations(priv,
|
||||
&priv->contexts[IWL_RXON_CTX_BSS]);
|
||||
iwl_restore_stations(priv, &priv->contexts[IWL_RXON_CTX_BSS]);
|
||||
}
|
||||
|
||||
/* If we issue a new RXON command which required a tune then we must
|
||||
|
@ -2302,8 +2307,10 @@ static int iwl3945_manage_ibss_station(struct iwl_priv *priv,
|
|||
int ret;
|
||||
|
||||
if (add) {
|
||||
ret = iwl_add_bssid_station(priv, vif->bss_conf.bssid, false,
|
||||
&vif_priv->ibss_bssid_sta_id);
|
||||
ret = iwl_add_bssid_station(
|
||||
priv, &priv->contexts[IWL_RXON_CTX_BSS],
|
||||
vif->bss_conf.bssid, false,
|
||||
&vif_priv->ibss_bssid_sta_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -2366,7 +2373,7 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
|
|||
* 1M CCK rates */
|
||||
|
||||
if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
|
||||
iwl_is_associated(priv)) {
|
||||
iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
|
||||
|
||||
index = IWL_FIRST_CCK_RATE;
|
||||
for (i = IWL_RATE_6M_INDEX_TABLE;
|
||||
|
@ -2421,7 +2428,9 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
|
|||
priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
|
||||
priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
|
||||
priv->hw_params.max_stations = IWL3945_STATION_COUNT;
|
||||
priv->hw_params.bcast_sta_id = IWL3945_BROADCAST_ID;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL3945_BROADCAST_ID;
|
||||
|
||||
priv->sta_key_max_num = STA_KEY_MAX_NUM;
|
||||
|
||||
priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR;
|
||||
priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL;
|
||||
|
@ -2439,7 +2448,8 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
|
|||
tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u;
|
||||
memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
|
||||
|
||||
tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id;
|
||||
tx_beacon_cmd->tx.sta_id =
|
||||
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
|
||||
tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
|
||||
|
||||
frame_size = iwl3945_fill_beacon_frame(priv,
|
||||
|
|
|
@ -347,7 +347,7 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv)
|
|||
struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
|
||||
|
||||
if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
|
||||
iwl_is_associated(priv)) {
|
||||
iwl_is_any_associated(priv)) {
|
||||
struct iwl_calib_diff_gain_cmd cmd;
|
||||
|
||||
/* clear data for chain noise calibration algorithm */
|
||||
|
@ -576,7 +576,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
|
|||
/* Activate all Tx DMA/FIFO channels */
|
||||
priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 6));
|
||||
|
||||
iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
|
||||
iwl4965_set_wr_ptrs(priv, IWL_DEFAULT_CMD_QUEUE_NUM, 0);
|
||||
|
||||
/* make sure all queue are not stopped */
|
||||
memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
|
||||
|
@ -587,6 +587,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
|
|||
priv->txq_ctx_active_msk = 0;
|
||||
/* Map each Tx/cmd queue to its corresponding fifo */
|
||||
BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
|
||||
int ac = default_queue_to_tx_fifo[i];
|
||||
|
||||
|
@ -656,7 +657,7 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
|
|||
sizeof(struct iwl4965_scd_bc_tbl);
|
||||
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
|
||||
priv->hw_params.max_stations = IWL4965_STATION_COUNT;
|
||||
priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL4965_BROADCAST_ID;
|
||||
priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
|
||||
priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE;
|
||||
priv->hw_params.max_bsm_size = BSM_SRAM_SIZE;
|
||||
|
@ -1374,6 +1375,7 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
|
|||
u8 band = 0;
|
||||
bool is_ht40 = false;
|
||||
u8 ctrl_chan_high = 0;
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
if (test_bit(STATUS_SCANNING, &priv->status)) {
|
||||
/* If this gets hit a lot, switch it to a BUG() and catch
|
||||
|
@ -1385,17 +1387,16 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
|
|||
|
||||
band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
|
||||
is_ht40 = is_ht40_channel(priv->active_rxon.flags);
|
||||
is_ht40 = is_ht40_channel(ctx->active.flags);
|
||||
|
||||
if (is_ht40 &&
|
||||
(priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
|
||||
if (is_ht40 && (ctx->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
|
||||
ctrl_chan_high = 1;
|
||||
|
||||
cmd.band = band;
|
||||
cmd.channel = priv->active_rxon.channel;
|
||||
cmd.channel = ctx->active.channel;
|
||||
|
||||
ret = iwl4965_fill_txpower_tbl(priv, band,
|
||||
le16_to_cpu(priv->active_rxon.channel),
|
||||
le16_to_cpu(ctx->active.channel),
|
||||
is_ht40, ctrl_chan_high, &cmd.tx_power);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
@ -1406,12 +1407,13 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
|
||||
static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
struct iwl4965_rxon_assoc_cmd rxon_assoc;
|
||||
const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
|
||||
const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
|
||||
const struct iwl_rxon_cmd *rxon1 = &ctx->staging;
|
||||
const struct iwl_rxon_cmd *rxon2 = &ctx->active;
|
||||
|
||||
if ((rxon1->flags == rxon2->flags) &&
|
||||
(rxon1->filter_flags == rxon2->filter_flags) &&
|
||||
|
@ -1426,16 +1428,16 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
rxon_assoc.flags = priv->staging_rxon.flags;
|
||||
rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
|
||||
rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
|
||||
rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
|
||||
rxon_assoc.flags = ctx->staging.flags;
|
||||
rxon_assoc.filter_flags = ctx->staging.filter_flags;
|
||||
rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
|
||||
rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
|
||||
rxon_assoc.reserved = 0;
|
||||
rxon_assoc.ofdm_ht_single_stream_basic_rates =
|
||||
priv->staging_rxon.ofdm_ht_single_stream_basic_rates;
|
||||
ctx->staging.ofdm_ht_single_stream_basic_rates;
|
||||
rxon_assoc.ofdm_ht_dual_stream_basic_rates =
|
||||
priv->staging_rxon.ofdm_ht_dual_stream_basic_rates;
|
||||
rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain;
|
||||
ctx->staging.ofdm_ht_dual_stream_basic_rates;
|
||||
rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
|
||||
|
||||
ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
|
||||
sizeof(rxon_assoc), &rxon_assoc, NULL);
|
||||
|
@ -1448,6 +1450,7 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
|
|||
static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
{
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
int rc;
|
||||
u8 band = 0;
|
||||
bool is_ht40 = false;
|
||||
|
@ -1458,22 +1461,22 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
|
|||
u16 ch;
|
||||
u32 tsf_low;
|
||||
u8 switch_count;
|
||||
u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval);
|
||||
struct ieee80211_vif *vif = priv->vif;
|
||||
u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
|
||||
struct ieee80211_vif *vif = ctx->vif;
|
||||
band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
|
||||
is_ht40 = is_ht40_channel(priv->staging_rxon.flags);
|
||||
is_ht40 = is_ht40_channel(ctx->staging.flags);
|
||||
|
||||
if (is_ht40 &&
|
||||
(priv->staging_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
|
||||
(ctx->staging.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
|
||||
ctrl_chan_high = 1;
|
||||
|
||||
cmd.band = band;
|
||||
cmd.expect_beacon = 0;
|
||||
ch = ch_switch->channel->hw_value;
|
||||
cmd.channel = cpu_to_le16(ch);
|
||||
cmd.rxon_flags = priv->staging_rxon.flags;
|
||||
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
|
||||
cmd.rxon_flags = ctx->staging.flags;
|
||||
cmd.rxon_filter_flags = ctx->staging.filter_flags;
|
||||
switch_count = ch_switch->count;
|
||||
tsf_low = ch_switch->timestamp & 0x0ffffffff;
|
||||
/*
|
||||
|
@ -1508,7 +1511,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
|
|||
cmd.expect_beacon = is_channel_radar(ch_info);
|
||||
else {
|
||||
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
||||
priv->active_rxon.channel, ch);
|
||||
ctx->active.channel, ch);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
@ -2007,7 +2010,7 @@ static u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
|
|||
start = IWL_STA_ID;
|
||||
|
||||
if (is_broadcast_ether_addr(addr))
|
||||
return priv->hw_params.bcast_sta_id;
|
||||
return priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
for (i = start; i < priv->hw_params.max_stations; i++)
|
||||
|
@ -2280,7 +2283,7 @@ static struct iwl_lib_ops iwl4965_lib = {
|
|||
.set_ct_kill = iwl4965_set_ct_threshold,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_station = iwl_update_bcast_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
|
|
|
@ -180,7 +180,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
|
|||
sizeof(struct iwlagn_scd_bc_tbl);
|
||||
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
|
||||
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
|
||||
priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
|
||||
|
||||
priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
|
||||
priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
|
||||
|
@ -227,7 +227,7 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
|
|||
sizeof(struct iwlagn_scd_bc_tbl);
|
||||
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
|
||||
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
|
||||
priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
|
||||
|
||||
priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
|
||||
priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
|
||||
|
@ -275,14 +275,19 @@ static void iwl5150_temperature(struct iwl_priv *priv)
|
|||
static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
{
|
||||
/*
|
||||
* MULTI-FIXME
|
||||
* See iwl_mac_channel_switch.
|
||||
*/
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
struct iwl5000_channel_switch_cmd cmd;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
u32 switch_time_in_usec, ucode_switch_time;
|
||||
u16 ch;
|
||||
u32 tsf_low;
|
||||
u8 switch_count;
|
||||
u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval);
|
||||
struct ieee80211_vif *vif = priv->vif;
|
||||
u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
|
||||
struct ieee80211_vif *vif = ctx->vif;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = REPLY_CHANNEL_SWITCH,
|
||||
.len = sizeof(cmd),
|
||||
|
@ -293,10 +298,10 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
|
|||
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
ch = ch_switch->channel->hw_value;
|
||||
IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
|
||||
priv->active_rxon.channel, ch);
|
||||
ctx->active.channel, ch);
|
||||
cmd.channel = cpu_to_le16(ch);
|
||||
cmd.rxon_flags = priv->staging_rxon.flags;
|
||||
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
|
||||
cmd.rxon_flags = ctx->staging.flags;
|
||||
cmd.rxon_filter_flags = ctx->staging.filter_flags;
|
||||
switch_count = ch_switch->count;
|
||||
tsf_low = ch_switch->timestamp & 0x0ffffffff;
|
||||
/*
|
||||
|
@ -331,7 +336,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
|
|||
cmd.expect_beacon = is_channel_radar(ch_info);
|
||||
else {
|
||||
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
||||
priv->active_rxon.channel, ch);
|
||||
ctx->active.channel, ch);
|
||||
return -EFAULT;
|
||||
}
|
||||
priv->switch_rxon.channel = cmd.channel;
|
||||
|
@ -393,7 +398,7 @@ static struct iwl_lib_ops iwl5000_lib = {
|
|||
.set_ct_kill = iwl5000_set_ct_threshold,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_station = iwl_update_bcast_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
|
@ -464,7 +469,7 @@ static struct iwl_lib_ops iwl5150_lib = {
|
|||
.set_ct_kill = iwl5150_set_ct_threshold,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_station = iwl_update_bcast_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
|
|
|
@ -161,7 +161,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
|||
sizeof(struct iwlagn_scd_bc_tbl);
|
||||
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
|
||||
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
|
||||
priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
|
||||
|
||||
priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE;
|
||||
priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE;
|
||||
|
@ -198,14 +198,19 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
|||
static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
{
|
||||
/*
|
||||
* MULTI-FIXME
|
||||
* See iwl_mac_channel_switch.
|
||||
*/
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
struct iwl6000_channel_switch_cmd cmd;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
u32 switch_time_in_usec, ucode_switch_time;
|
||||
u16 ch;
|
||||
u32 tsf_low;
|
||||
u8 switch_count;
|
||||
u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval);
|
||||
struct ieee80211_vif *vif = priv->vif;
|
||||
u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
|
||||
struct ieee80211_vif *vif = ctx->vif;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = REPLY_CHANNEL_SWITCH,
|
||||
.len = sizeof(cmd),
|
||||
|
@ -216,10 +221,10 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
|||
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
ch = ch_switch->channel->hw_value;
|
||||
IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
|
||||
priv->active_rxon.channel, ch);
|
||||
ctx->active.channel, ch);
|
||||
cmd.channel = cpu_to_le16(ch);
|
||||
cmd.rxon_flags = priv->staging_rxon.flags;
|
||||
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
|
||||
cmd.rxon_flags = ctx->staging.flags;
|
||||
cmd.rxon_filter_flags = ctx->staging.filter_flags;
|
||||
switch_count = ch_switch->count;
|
||||
tsf_low = ch_switch->timestamp & 0x0ffffffff;
|
||||
/*
|
||||
|
@ -254,7 +259,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
|||
cmd.expect_beacon = is_channel_radar(ch_info);
|
||||
else {
|
||||
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
||||
priv->active_rxon.channel, ch);
|
||||
ctx->active.channel, ch);
|
||||
return -EFAULT;
|
||||
}
|
||||
priv->switch_rxon.channel = cmd.channel;
|
||||
|
@ -318,7 +323,7 @@ static struct iwl_lib_ops iwl6000_lib = {
|
|||
.set_calib_version = iwl6000_set_calib_version,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_station = iwl_update_bcast_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
|
@ -393,7 +398,7 @@ static struct iwl_lib_ops iwl6000g2b_lib = {
|
|||
.set_calib_version = iwl6000_set_calib_version,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_station = iwl_update_bcast_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
|
|
|
@ -625,7 +625,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp)
|
|||
|
||||
data = &(priv->sensitivity_data);
|
||||
|
||||
if (!iwl_is_associated(priv)) {
|
||||
if (!iwl_is_any_associated(priv)) {
|
||||
IWL_DEBUG_CALIB(priv, "<< - not associated\n");
|
||||
return;
|
||||
}
|
||||
|
@ -763,6 +763,12 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
|
|||
unsigned long flags;
|
||||
struct statistics_rx_non_phy *rx_info;
|
||||
u8 first_chain;
|
||||
/*
|
||||
* MULTI-FIXME:
|
||||
* When we support multiple interfaces on different channels,
|
||||
* this must be modified/fixed.
|
||||
*/
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
if (priv->disable_chain_noise_cal)
|
||||
return;
|
||||
|
@ -793,8 +799,8 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
|
|||
return;
|
||||
}
|
||||
|
||||
rxon_band24 = !!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK);
|
||||
rxon_chnum = le16_to_cpu(priv->staging_rxon.channel);
|
||||
rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK);
|
||||
rxon_chnum = le16_to_cpu(ctx->staging.channel);
|
||||
if (priv->cfg->bt_statistics) {
|
||||
stat_band24 = !!(((struct iwl_bt_notif_statistics *)
|
||||
stat_resp)->flag &
|
||||
|
|
|
@ -37,12 +37,13 @@
|
|||
#include "iwl-io.h"
|
||||
#include "iwl-agn.h"
|
||||
|
||||
int iwlagn_send_rxon_assoc(struct iwl_priv *priv)
|
||||
int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
struct iwl5000_rxon_assoc_cmd rxon_assoc;
|
||||
const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
|
||||
const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
|
||||
const struct iwl_rxon_cmd *rxon1 = &ctx->staging;
|
||||
const struct iwl_rxon_cmd *rxon2 = &ctx->active;
|
||||
|
||||
if ((rxon1->flags == rxon2->flags) &&
|
||||
(rxon1->filter_flags == rxon2->filter_flags) &&
|
||||
|
@ -60,23 +61,23 @@ int iwlagn_send_rxon_assoc(struct iwl_priv *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
rxon_assoc.flags = priv->staging_rxon.flags;
|
||||
rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
|
||||
rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
|
||||
rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
|
||||
rxon_assoc.flags = ctx->staging.flags;
|
||||
rxon_assoc.filter_flags = ctx->staging.filter_flags;
|
||||
rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
|
||||
rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
|
||||
rxon_assoc.reserved1 = 0;
|
||||
rxon_assoc.reserved2 = 0;
|
||||
rxon_assoc.reserved3 = 0;
|
||||
rxon_assoc.ofdm_ht_single_stream_basic_rates =
|
||||
priv->staging_rxon.ofdm_ht_single_stream_basic_rates;
|
||||
ctx->staging.ofdm_ht_single_stream_basic_rates;
|
||||
rxon_assoc.ofdm_ht_dual_stream_basic_rates =
|
||||
priv->staging_rxon.ofdm_ht_dual_stream_basic_rates;
|
||||
rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain;
|
||||
ctx->staging.ofdm_ht_dual_stream_basic_rates;
|
||||
rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
|
||||
rxon_assoc.ofdm_ht_triple_stream_basic_rates =
|
||||
priv->staging_rxon.ofdm_ht_triple_stream_basic_rates;
|
||||
rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data;
|
||||
ctx->staging.ofdm_ht_triple_stream_basic_rates;
|
||||
rxon_assoc.acquisition_data = ctx->staging.acquisition_data;
|
||||
|
||||
ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
|
||||
ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd,
|
||||
sizeof(rxon_assoc), &rxon_assoc, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -184,7 +185,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
|
|||
int ret;
|
||||
|
||||
if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
|
||||
iwl_is_associated(priv)) {
|
||||
iwl_is_any_associated(priv)) {
|
||||
struct iwl_calib_chain_noise_reset_cmd cmd;
|
||||
|
||||
/* clear data for chain noise calibration algorithm */
|
||||
|
@ -269,12 +270,86 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv,
|
|||
return max_rssi - agc - IWLAGN_RSSI_OFFSET;
|
||||
}
|
||||
|
||||
static int iwlagn_set_pan_params(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_wipan_params_cmd cmd;
|
||||
struct iwl_rxon_context *ctx_bss, *ctx_pan;
|
||||
int slot0 = 300, slot1 = 0;
|
||||
int ret;
|
||||
|
||||
if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS))
|
||||
return 0;
|
||||
|
||||
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN];
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
/* only 2 slots are currently allowed */
|
||||
cmd.num_slots = 2;
|
||||
|
||||
cmd.slots[0].type = 0; /* BSS */
|
||||
cmd.slots[1].type = 1; /* PAN */
|
||||
|
||||
if (ctx_bss->vif && ctx_pan->vif) {
|
||||
int bcnint = ctx_pan->vif->bss_conf.beacon_int;
|
||||
|
||||
/* should be set, but seems unused?? */
|
||||
cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE);
|
||||
|
||||
if (ctx_pan->vif->type == NL80211_IFTYPE_AP &&
|
||||
bcnint &&
|
||||
bcnint != ctx_bss->vif->bss_conf.beacon_int) {
|
||||
IWL_ERR(priv,
|
||||
"beacon intervals don't match (%d, %d)\n",
|
||||
ctx_bss->vif->bss_conf.beacon_int,
|
||||
ctx_pan->vif->bss_conf.beacon_int);
|
||||
} else
|
||||
bcnint = max_t(int, bcnint,
|
||||
ctx_bss->vif->bss_conf.beacon_int);
|
||||
if (!bcnint)
|
||||
bcnint = 100;
|
||||
slot0 = bcnint / 2;
|
||||
slot1 = bcnint - slot0;
|
||||
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->status) ||
|
||||
(!ctx_bss->vif->bss_conf.idle &&
|
||||
!ctx_bss->vif->bss_conf.assoc)) {
|
||||
slot0 = bcnint * 3 - 20;
|
||||
slot1 = 20;
|
||||
} else if (!ctx_pan->vif->bss_conf.idle &&
|
||||
!ctx_pan->vif->bss_conf.assoc) {
|
||||
slot1 = bcnint * 3 - 20;
|
||||
slot0 = 20;
|
||||
}
|
||||
} else if (ctx_pan->vif) {
|
||||
slot0 = 0;
|
||||
slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) *
|
||||
ctx_pan->vif->bss_conf.beacon_int;
|
||||
slot1 = max_t(int, 100, slot1);
|
||||
}
|
||||
|
||||
cmd.slots[0].width = cpu_to_le16(slot0);
|
||||
cmd.slots[1].width = cpu_to_le16(slot1);
|
||||
|
||||
ret = iwl_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, sizeof(cmd), &cmd);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct iwl_hcmd_ops iwlagn_hcmd = {
|
||||
.rxon_assoc = iwlagn_send_rxon_assoc,
|
||||
.commit_rxon = iwl_commit_rxon,
|
||||
.set_rxon_chain = iwl_set_rxon_chain,
|
||||
.set_tx_ant = iwlagn_send_tx_ant_config,
|
||||
.send_bt_config = iwl_send_bt_config,
|
||||
.set_pan_params = iwlagn_set_pan_params,
|
||||
};
|
||||
|
||||
struct iwl_hcmd_ops iwlagn_bt_hcmd = {
|
||||
|
@ -283,6 +358,7 @@ struct iwl_hcmd_ops iwlagn_bt_hcmd = {
|
|||
.set_rxon_chain = iwl_set_rxon_chain,
|
||||
.set_tx_ant = iwlagn_send_tx_ant_config,
|
||||
.send_bt_config = iwlagn_send_advance_bt_config,
|
||||
.set_pan_params = iwlagn_set_pan_params,
|
||||
};
|
||||
|
||||
struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {
|
||||
|
|
|
@ -1163,6 +1163,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
};
|
||||
struct iwl_scan_cmd *scan;
|
||||
struct ieee80211_conf *conf = NULL;
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
u32 rate_flags = 0;
|
||||
u16 cmd_len;
|
||||
u16 rx_chain = 0;
|
||||
|
@ -1175,6 +1176,9 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
u8 active_chains;
|
||||
u8 scan_tx_antennas = priv->hw_params.valid_tx_ant;
|
||||
|
||||
if (vif)
|
||||
ctx = iwl_rxon_ctx_from_vif(vif);
|
||||
|
||||
conf = ieee80211_get_hw_conf(priv->hw);
|
||||
|
||||
cancel_delayed_work(&priv->scan_check);
|
||||
|
@ -1232,7 +1236,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
|
||||
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
|
||||
|
||||
if (iwl_is_associated(priv)) {
|
||||
if (iwl_is_any_associated(priv)) {
|
||||
u16 interval = 0;
|
||||
u32 extra;
|
||||
u32 suspend_time = 100;
|
||||
|
@ -1283,13 +1287,15 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
|
||||
|
||||
scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
|
||||
scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
|
||||
scan->tx_cmd.sta_id = ctx->bcast_sta_id;
|
||||
scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
|
||||
|
||||
switch (priv->scan_band) {
|
||||
case IEEE80211_BAND_2GHZ:
|
||||
scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
|
||||
chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK)
|
||||
chan_mod = le32_to_cpu(
|
||||
priv->contexts[IWL_RXON_CTX_BSS].active.flags &
|
||||
RXON_FLG_CHANNEL_MODE_MSK)
|
||||
>> RXON_FLG_CHANNEL_MODE_POS;
|
||||
if (chan_mod == CHANNEL_MODE_PURE_40) {
|
||||
rate = IWL_RATE_6M_PLCP;
|
||||
|
@ -1418,6 +1424,11 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
scan->len = cpu_to_le16(cmd.len);
|
||||
|
||||
set_bit(STATUS_SCAN_HW, &priv->status);
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_pan_params &&
|
||||
priv->cfg->ops->hcmd->set_pan_params(priv))
|
||||
goto done;
|
||||
|
||||
if (iwl_send_cmd_sync(priv, &cmd))
|
||||
goto done;
|
||||
|
||||
|
@ -1444,7 +1455,8 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
|
|||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
|
||||
if (add)
|
||||
return iwl_add_bssid_station(priv, vif->bss_conf.bssid, true,
|
||||
return iwl_add_bssid_station(priv, vif_priv->ctx,
|
||||
vif->bss_conf.bssid, true,
|
||||
&vif_priv->ibss_bssid_sta_id);
|
||||
return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id,
|
||||
vif->bss_conf.bssid);
|
||||
|
@ -1477,7 +1489,7 @@ int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv)
|
|||
|
||||
/* waiting for all the tx frames complete might take a while */
|
||||
for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
|
||||
if (cnt == IWL_CMD_QUEUE_NUM)
|
||||
if (cnt == priv->cmd_queue)
|
||||
continue;
|
||||
txq = &priv->txq[cnt];
|
||||
q = &txq->q;
|
||||
|
@ -1713,6 +1725,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
|
|||
{
|
||||
struct iwl_priv *priv =
|
||||
container_of(work, struct iwl_priv, bt_traffic_change_work);
|
||||
struct iwl_rxon_context *ctx;
|
||||
int smps_request = -1;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n",
|
||||
|
@ -1740,9 +1753,12 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
|
|||
if (priv->cfg->ops->lib->update_chain_flags)
|
||||
priv->cfg->ops->lib->update_chain_flags(priv);
|
||||
|
||||
if (smps_request != -1 &&
|
||||
priv->vif && priv->vif->type == NL80211_IFTYPE_STATION)
|
||||
ieee80211_request_smps(priv->vif, smps_request);
|
||||
if (smps_request != -1) {
|
||||
for_each_context(priv, ctx) {
|
||||
if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION)
|
||||
ieee80211_request_smps(ctx->vif, smps_request);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
|
|
@ -602,11 +602,13 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
|
|||
* Green-field mode is valid if the station supports it and
|
||||
* there are no non-GF stations present in the BSS.
|
||||
*/
|
||||
static inline u8 rs_use_green(struct ieee80211_sta *sta,
|
||||
struct iwl_ht_config *ht_conf)
|
||||
static bool rs_use_green(struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
struct iwl_rxon_context *ctx = sta_priv->common.ctx;
|
||||
|
||||
return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) &&
|
||||
!(ht_conf->non_GF_STA_present);
|
||||
!(ctx->ht.non_gf_sta_present);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -758,8 +760,8 @@ static bool table_type_matches(struct iwl_scale_tbl_info *a,
|
|||
(a->is_SGI == b->is_SGI);
|
||||
}
|
||||
|
||||
static void rs_bt_update_lq(struct iwl_priv *priv,
|
||||
struct iwl_lq_sta *lq_sta)
|
||||
static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct iwl_lq_sta *lq_sta)
|
||||
{
|
||||
struct iwl_scale_tbl_info *tbl;
|
||||
bool full_concurrent;
|
||||
|
@ -778,7 +780,7 @@ static void rs_bt_update_lq(struct iwl_priv *priv,
|
|||
/* Update uCode's rate table. */
|
||||
tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
|
||||
rs_fill_link_cmd(priv, lq_sta, tbl->current_rate);
|
||||
iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false);
|
||||
iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
|
||||
|
||||
queue_work(priv->workqueue, &priv->bt_full_concurrency);
|
||||
}
|
||||
|
@ -803,6 +805,8 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
|||
u32 tx_rate;
|
||||
struct iwl_scale_tbl_info tbl_type;
|
||||
struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
struct iwl_rxon_context *ctx = sta_priv->common.ctx;
|
||||
|
||||
IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n");
|
||||
|
||||
|
@ -869,7 +873,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
|||
lq_sta->missed_rate_counter++;
|
||||
if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) {
|
||||
lq_sta->missed_rate_counter = 0;
|
||||
iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false);
|
||||
iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
|
||||
}
|
||||
/* Regardless, ignore this status info for outdated rate */
|
||||
return;
|
||||
|
@ -969,7 +973,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
|||
|
||||
/* Is there a need to switch between full concurrency and 3-wire? */
|
||||
if (priv->bt_ant_couple_ok)
|
||||
rs_bt_update_lq(priv, lq_sta);
|
||||
rs_bt_update_lq(priv, ctx, lq_sta);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1163,6 +1167,8 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
|
|||
u16 rate_mask;
|
||||
s32 rate;
|
||||
s8 is_green = lq_sta->is_green;
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
struct iwl_rxon_context *ctx = sta_priv->common.ctx;
|
||||
|
||||
if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
|
||||
return -1;
|
||||
|
@ -1183,7 +1189,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
|
|||
tbl->max_search = IWL_MAX_SEARCH;
|
||||
rate_mask = lq_sta->active_mimo2_rate;
|
||||
|
||||
if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
|
||||
if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
|
||||
tbl->is_ht40 = 1;
|
||||
else
|
||||
tbl->is_ht40 = 0;
|
||||
|
@ -1217,6 +1223,8 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
|
|||
u16 rate_mask;
|
||||
s32 rate;
|
||||
s8 is_green = lq_sta->is_green;
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
struct iwl_rxon_context *ctx = sta_priv->common.ctx;
|
||||
|
||||
if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
|
||||
return -1;
|
||||
|
@ -1237,7 +1245,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
|
|||
tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
|
||||
rate_mask = lq_sta->active_mimo3_rate;
|
||||
|
||||
if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
|
||||
if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
|
||||
tbl->is_ht40 = 1;
|
||||
else
|
||||
tbl->is_ht40 = 0;
|
||||
|
@ -1272,6 +1280,8 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
|
|||
u16 rate_mask;
|
||||
u8 is_green = lq_sta->is_green;
|
||||
s32 rate;
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
struct iwl_rxon_context *ctx = sta_priv->common.ctx;
|
||||
|
||||
if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
|
||||
return -1;
|
||||
|
@ -1284,7 +1294,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
|
|||
tbl->max_search = IWL_MAX_SEARCH;
|
||||
rate_mask = lq_sta->active_siso_rate;
|
||||
|
||||
if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
|
||||
if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
|
||||
tbl->is_ht40 = 1;
|
||||
else
|
||||
tbl->is_ht40 = 0;
|
||||
|
@ -2086,6 +2096,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
|
|||
* return rate_n_flags as used in the table
|
||||
*/
|
||||
static u32 rs_update_rate_tbl(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct iwl_lq_sta *lq_sta,
|
||||
struct iwl_scale_tbl_info *tbl,
|
||||
int index, u8 is_green)
|
||||
|
@ -2095,7 +2106,7 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv,
|
|||
/* Update uCode's rate table. */
|
||||
rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
|
||||
rs_fill_link_cmd(priv, lq_sta, rate);
|
||||
iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false);
|
||||
iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
@ -2134,6 +2145,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
|
|||
s32 sr;
|
||||
u8 tid = MAX_TID_COUNT;
|
||||
struct iwl_tid_data *tid_data;
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
struct iwl_rxon_context *ctx = sta_priv->common.ctx;
|
||||
|
||||
IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n");
|
||||
|
||||
|
@ -2172,7 +2185,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
|
|||
if (is_legacy(tbl->lq_type))
|
||||
lq_sta->is_green = 0;
|
||||
else
|
||||
lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config);
|
||||
lq_sta->is_green = rs_use_green(sta);
|
||||
is_green = lq_sta->is_green;
|
||||
|
||||
/* current tx rate */
|
||||
|
@ -2211,7 +2224,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
|
|||
tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
|
||||
/* get "active" rate info */
|
||||
index = iwl_hwrate_to_plcp_idx(tbl->current_rate);
|
||||
rate = rs_update_rate_tbl(priv, lq_sta,
|
||||
rate = rs_update_rate_tbl(priv, ctx, lq_sta,
|
||||
tbl, index, is_green);
|
||||
}
|
||||
return;
|
||||
|
@ -2453,7 +2466,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
|
|||
lq_update:
|
||||
/* Replace uCode's rate table for the destination station. */
|
||||
if (update_lq)
|
||||
rate = rs_update_rate_tbl(priv, lq_sta,
|
||||
rate = rs_update_rate_tbl(priv, ctx, lq_sta,
|
||||
tbl, index, is_green);
|
||||
|
||||
if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) {
|
||||
|
@ -2495,7 +2508,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
|
|||
IWL_DEBUG_RATE(priv, "Switch current mcs: %X index: %d\n",
|
||||
tbl->current_rate, index);
|
||||
rs_fill_link_cmd(priv, lq_sta, tbl->current_rate);
|
||||
iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false);
|
||||
iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
|
||||
} else
|
||||
done_search = 1;
|
||||
}
|
||||
|
@ -2565,12 +2578,17 @@ static void rs_initialize_lq(struct iwl_priv *priv,
|
|||
int rate_idx;
|
||||
int i;
|
||||
u32 rate;
|
||||
u8 use_green = rs_use_green(sta, &priv->current_ht_config);
|
||||
u8 use_green = rs_use_green(sta);
|
||||
u8 active_tbl = 0;
|
||||
u8 valid_tx_ant;
|
||||
struct iwl_station_priv *sta_priv;
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
if (!sta || !lq_sta)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
sta_priv = (void *)sta->drv_priv;
|
||||
ctx = sta_priv->common.ctx;
|
||||
|
||||
i = lq_sta->last_txrate_idx;
|
||||
|
||||
|
@ -2602,9 +2620,7 @@ static void rs_initialize_lq(struct iwl_priv *priv,
|
|||
rs_set_expected_tpt_table(lq_sta, tbl);
|
||||
rs_fill_link_cmd(NULL, lq_sta, rate);
|
||||
priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq;
|
||||
iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_SYNC, true);
|
||||
out:
|
||||
return;
|
||||
iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_SYNC, true);
|
||||
}
|
||||
|
||||
static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
|
||||
|
@ -2732,7 +2748,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
|
|||
lq_sta->is_dup = 0;
|
||||
lq_sta->max_rate_idx = -1;
|
||||
lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
|
||||
lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config);
|
||||
lq_sta->is_green = rs_use_green(sta);
|
||||
lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
|
||||
lq_sta->band = priv->band;
|
||||
/*
|
||||
|
@ -2992,6 +3008,9 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
|
|||
char buf[64];
|
||||
int buf_size;
|
||||
u32 parsed_rate;
|
||||
struct iwl_station_priv *sta_priv =
|
||||
container_of(lq_sta, struct iwl_station_priv, lq_sta);
|
||||
struct iwl_rxon_context *ctx = sta_priv->common.ctx;
|
||||
|
||||
priv = lq_sta->drv;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
@ -3014,7 +3033,8 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
|
|||
|
||||
if (lq_sta->dbg_fixed_rate) {
|
||||
rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate);
|
||||
iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false);
|
||||
iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC,
|
||||
false);
|
||||
}
|
||||
|
||||
return count;
|
||||
|
|
|
@ -416,18 +416,26 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
|
|||
/* stop ct_kill_waiting_tm timer */
|
||||
del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
|
||||
if (changed) {
|
||||
struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
|
||||
|
||||
if (tt->state >= IWL_TI_1) {
|
||||
/* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */
|
||||
tt->tt_power_mode = IWL_POWER_INDEX_5;
|
||||
if (!iwl_ht_enabled(priv))
|
||||
/* disable HT */
|
||||
rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
|
||||
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
|
||||
RXON_FLG_HT40_PROT_MSK |
|
||||
RXON_FLG_HT_PROT_MSK);
|
||||
else {
|
||||
|
||||
if (!iwl_ht_enabled(priv)) {
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
for_each_context(priv, ctx) {
|
||||
struct iwl_rxon_cmd *rxon;
|
||||
|
||||
rxon = &ctx->staging;
|
||||
|
||||
/* disable HT */
|
||||
rxon->flags &= ~(
|
||||
RXON_FLG_CHANNEL_MODE_MSK |
|
||||
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
|
||||
RXON_FLG_HT40_PROT_MSK |
|
||||
RXON_FLG_HT_PROT_MSK);
|
||||
}
|
||||
} else {
|
||||
/* check HT capability and set
|
||||
* according to the system HT capability
|
||||
* in case get disabled before */
|
||||
|
|
|
@ -71,18 +71,6 @@ static const u8 tid_to_ac[] = {
|
|||
2, 3, 3, 2, 1, 1, 0, 0
|
||||
};
|
||||
|
||||
static const u8 ac_to_fifo[] = {
|
||||
IWL_TX_FIFO_VO,
|
||||
IWL_TX_FIFO_VI,
|
||||
IWL_TX_FIFO_BE,
|
||||
IWL_TX_FIFO_BK,
|
||||
};
|
||||
|
||||
static inline int get_fifo_from_ac(u8 ac)
|
||||
{
|
||||
return ac_to_fifo[ac];
|
||||
}
|
||||
|
||||
static inline int get_ac_from_tid(u16 tid)
|
||||
{
|
||||
if (likely(tid < ARRAY_SIZE(tid_to_ac)))
|
||||
|
@ -92,10 +80,10 @@ static inline int get_ac_from_tid(u16 tid)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int get_fifo_from_tid(u16 tid)
|
||||
static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid)
|
||||
{
|
||||
if (likely(tid < ARRAY_SIZE(tid_to_ac)))
|
||||
return get_fifo_from_ac(tid_to_ac[tid]);
|
||||
return ctx->ac_to_fifo[tid_to_ac[tid]];
|
||||
|
||||
/* no support for TIDs 8-15 yet */
|
||||
return -EINVAL;
|
||||
|
@ -118,7 +106,7 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
|
|||
|
||||
WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
|
||||
|
||||
if (txq_id != IWL_CMD_QUEUE_NUM) {
|
||||
if (txq_id != priv->cmd_queue) {
|
||||
sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
|
||||
sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
|
||||
|
||||
|
@ -155,7 +143,7 @@ void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
|
|||
|
||||
WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
|
||||
|
||||
if (txq_id != IWL_CMD_QUEUE_NUM)
|
||||
if (txq_id != priv->cmd_queue)
|
||||
sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
|
||||
|
||||
bc_ent = cpu_to_le16(1 | (sta_id << 12));
|
||||
|
@ -333,11 +321,6 @@ void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask)
|
|||
iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask);
|
||||
}
|
||||
|
||||
static inline int get_queue_from_ac(u16 ac)
|
||||
{
|
||||
return ac;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle build REPLY_TX command notification.
|
||||
*/
|
||||
|
@ -531,6 +514,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
struct iwl_device_cmd *out_cmd;
|
||||
struct iwl_cmd_meta *out_meta;
|
||||
struct iwl_tx_cmd *tx_cmd;
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
int swq_id, txq_id;
|
||||
dma_addr_t phys_addr;
|
||||
dma_addr_t txcmd_phys;
|
||||
|
@ -545,6 +529,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
u8 *qc = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
if (info->control.vif)
|
||||
ctx = iwl_rxon_ctx_from_vif(info->control.vif);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
if (iwl_is_rfkill(priv)) {
|
||||
IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
|
||||
|
@ -565,7 +552,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
hdr_len = ieee80211_hdrlen(fc);
|
||||
|
||||
/* Find index into station table for destination station */
|
||||
sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta);
|
||||
sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
|
||||
hdr->addr1);
|
||||
|
@ -577,8 +564,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
if (sta)
|
||||
sta_priv = (void *)sta->drv_priv;
|
||||
|
||||
if (sta_priv && sta_id != priv->hw_params.bcast_sta_id &&
|
||||
sta_priv->asleep) {
|
||||
if (sta_priv && sta_priv->asleep) {
|
||||
WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE));
|
||||
/*
|
||||
* This sends an asynchronous command to the device,
|
||||
|
@ -592,7 +578,20 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
|
||||
}
|
||||
|
||||
txq_id = get_queue_from_ac(skb_get_queue_mapping(skb));
|
||||
/*
|
||||
* Send this frame after DTIM -- there's a special queue
|
||||
* reserved for this for contexts that support AP mode.
|
||||
*/
|
||||
if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
|
||||
txq_id = ctx->mcast_queue;
|
||||
/*
|
||||
* The microcode will clear the more data
|
||||
* bit in the last frame it transmits.
|
||||
*/
|
||||
hdr->frame_control |=
|
||||
cpu_to_le16(IEEE80211_FCTL_MOREDATA);
|
||||
} else
|
||||
txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)];
|
||||
|
||||
/* irqs already disabled/saved above when locking priv->lock */
|
||||
spin_lock(&priv->sta_lock);
|
||||
|
@ -637,6 +636,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
/* Set up driver data for this TFD */
|
||||
memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
|
||||
txq->txb[q->write_ptr].skb = skb;
|
||||
txq->txb[q->write_ptr].ctx = ctx;
|
||||
|
||||
/* Set up first empty entry in queue's array of Tx/cmd buffers */
|
||||
out_cmd = txq->cmd[q->write_ptr];
|
||||
|
@ -825,7 +825,7 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv)
|
|||
/* Tx queues */
|
||||
if (priv->txq) {
|
||||
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
|
||||
if (txq_id == IWL_CMD_QUEUE_NUM)
|
||||
if (txq_id == priv->cmd_queue)
|
||||
iwl_cmd_queue_free(priv);
|
||||
else
|
||||
iwl_tx_queue_free(priv, txq_id);
|
||||
|
@ -882,9 +882,9 @@ int iwlagn_txq_ctx_alloc(struct iwl_priv *priv)
|
|||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
/* Alloc and init all Tx queues, including the command queue (#4) */
|
||||
/* Alloc and init all Tx queues, including the command queue (#4/#9) */
|
||||
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
|
||||
slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
|
||||
slots_num = (txq_id == priv->cmd_queue) ?
|
||||
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
|
||||
ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
|
||||
txq_id);
|
||||
|
@ -922,7 +922,7 @@ void iwlagn_txq_ctx_reset(struct iwl_priv *priv)
|
|||
|
||||
/* Alloc and init all Tx queues, including the command queue (#4) */
|
||||
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
|
||||
slots_num = txq_id == IWL_CMD_QUEUE_NUM ?
|
||||
slots_num = txq_id == priv->cmd_queue ?
|
||||
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
|
||||
iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id);
|
||||
}
|
||||
|
@ -980,7 +980,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
|||
unsigned long flags;
|
||||
struct iwl_tid_data *tid_data;
|
||||
|
||||
tx_fifo = get_fifo_from_tid(tid);
|
||||
tx_fifo = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid);
|
||||
if (unlikely(tx_fifo < 0))
|
||||
return tx_fifo;
|
||||
|
||||
|
@ -1041,7 +1041,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
|||
int write_ptr, read_ptr;
|
||||
unsigned long flags;
|
||||
|
||||
tx_fifo_id = get_fifo_from_tid(tid);
|
||||
tx_fifo_id = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid);
|
||||
if (unlikely(tx_fifo_id < 0))
|
||||
return tx_fifo_id;
|
||||
|
||||
|
@ -1116,6 +1116,9 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
|
|||
struct iwl_queue *q = &priv->txq[txq_id].q;
|
||||
u8 *addr = priv->stations[sta_id].sta.sta.addr;
|
||||
struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid];
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
ctx = &priv->contexts[priv->stations[sta_id].ctxid];
|
||||
|
||||
lockdep_assert_held(&priv->sta_lock);
|
||||
|
||||
|
@ -1126,12 +1129,12 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
|
|||
if ((txq_id == tid_data->agg.txq_id) &&
|
||||
(q->read_ptr == q->write_ptr)) {
|
||||
u16 ssn = SEQ_TO_SN(tid_data->seq_number);
|
||||
int tx_fifo = get_fifo_from_tid(tid);
|
||||
int tx_fifo = get_fifo_from_tid(ctx, tid);
|
||||
IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n");
|
||||
priv->cfg->ops->lib->txq_agg_disable(priv, txq_id,
|
||||
ssn, tx_fifo);
|
||||
tid_data->agg.state = IWL_AGG_OFF;
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid);
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
|
||||
}
|
||||
break;
|
||||
case IWL_EMPTYING_HW_QUEUE_ADDBA:
|
||||
|
@ -1139,7 +1142,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
|
|||
if (tid_data->tfds_in_queue == 0) {
|
||||
IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n");
|
||||
tid_data->agg.state = IWL_AGG_ON;
|
||||
ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid);
|
||||
ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1147,14 +1150,14 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data;
|
||||
struct ieee80211_sta *sta;
|
||||
struct iwl_station_priv *sta_priv;
|
||||
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(priv->vif, hdr->addr1);
|
||||
sta = ieee80211_find_sta(tx_info->ctx->vif, hdr->addr1);
|
||||
if (sta) {
|
||||
sta_priv = (void *)sta->drv_priv;
|
||||
/* avoid atomic ops if this isn't a client */
|
||||
|
@ -1164,7 +1167,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
ieee80211_tx_status_irqsafe(priv->hw, skb);
|
||||
ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb);
|
||||
}
|
||||
|
||||
int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
|
||||
|
@ -1187,7 +1190,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
|
|||
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
|
||||
|
||||
tx_info = &txq->txb[txq->q.read_ptr];
|
||||
iwlagn_tx_status(priv, tx_info->skb);
|
||||
iwlagn_tx_status(priv, tx_info);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)tx_info->skb->data;
|
||||
if (hdr && ieee80211_is_data_qos(hdr->frame_control))
|
||||
|
|
|
@ -52,6 +52,19 @@ static const s8 iwlagn_default_queue_to_tx_fifo[] = {
|
|||
IWL_TX_FIFO_UNUSED,
|
||||
};
|
||||
|
||||
static const s8 iwlagn_ipan_queue_to_tx_fifo[] = {
|
||||
IWL_TX_FIFO_VO,
|
||||
IWL_TX_FIFO_VI,
|
||||
IWL_TX_FIFO_BE,
|
||||
IWL_TX_FIFO_BK,
|
||||
IWL_TX_FIFO_BK_IPAN,
|
||||
IWL_TX_FIFO_BE_IPAN,
|
||||
IWL_TX_FIFO_VI_IPAN,
|
||||
IWL_TX_FIFO_VO_IPAN,
|
||||
IWL_TX_FIFO_BE_IPAN,
|
||||
IWLAGN_CMD_FIFO_NUM,
|
||||
};
|
||||
|
||||
static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
|
||||
{COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
|
||||
0, COEX_UNASSOC_IDLE_FLAGS},
|
||||
|
@ -376,6 +389,7 @@ static void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
|
|||
|
||||
int iwlagn_alive_notify(struct iwl_priv *priv)
|
||||
{
|
||||
const s8 *queues;
|
||||
u32 a;
|
||||
unsigned long flags;
|
||||
int i, chan;
|
||||
|
@ -410,7 +424,7 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
|
|||
reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
|
||||
|
||||
iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL,
|
||||
IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num));
|
||||
IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv));
|
||||
iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0);
|
||||
|
||||
/* initiate the queues */
|
||||
|
@ -436,7 +450,13 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
|
|||
/* Activate all Tx DMA/FIFO channels */
|
||||
priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7));
|
||||
|
||||
iwlagn_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
|
||||
/* map queues to FIFOs */
|
||||
if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
|
||||
queues = iwlagn_ipan_queue_to_tx_fifo;
|
||||
else
|
||||
queues = iwlagn_default_queue_to_tx_fifo;
|
||||
|
||||
iwlagn_set_wr_ptrs(priv, priv->cmd_queue, 0);
|
||||
|
||||
/* make sure all queue are not stopped */
|
||||
memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
|
||||
|
@ -445,11 +465,12 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
|
|||
|
||||
/* reset to 0 to enable all the queue first */
|
||||
priv->txq_ctx_active_msk = 0;
|
||||
/* map qos queues to fifos one-to-one */
|
||||
BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); i++) {
|
||||
int ac = iwlagn_default_queue_to_tx_fifo[i];
|
||||
BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10);
|
||||
BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
int ac = queues[i];
|
||||
|
||||
iwl_txq_ctx_activate(priv, i);
|
||||
|
||||
|
|
|
@ -98,21 +98,22 @@ static bool iwlagn_bt_ch_announce = 1;
|
|||
* function correctly transitions out of the RXON_ASSOC_MSK state if
|
||||
* a HW tune is required based on the RXON structure changes.
|
||||
*/
|
||||
int iwl_commit_rxon(struct iwl_priv *priv)
|
||||
int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
{
|
||||
/* cast away the const for active_rxon in this function */
|
||||
struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
|
||||
struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active;
|
||||
int ret;
|
||||
bool new_assoc =
|
||||
!!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
|
||||
!!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
|
||||
bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK);
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EBUSY;
|
||||
|
||||
/* always get timestamp with Rx frame */
|
||||
priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
|
||||
ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
|
||||
|
||||
ret = iwl_check_rxon_cmd(priv);
|
||||
ret = iwl_check_rxon_cmd(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
|
||||
return -EINVAL;
|
||||
|
@ -123,7 +124,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
|||
* abort any previous channel switch if still in process
|
||||
*/
|
||||
if (priv->switch_rxon.switch_in_progress &&
|
||||
(priv->switch_rxon.channel != priv->staging_rxon.channel)) {
|
||||
(priv->switch_rxon.channel != ctx->staging.channel)) {
|
||||
IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
|
||||
le16_to_cpu(priv->switch_rxon.channel));
|
||||
iwl_chswitch_done(priv, false);
|
||||
|
@ -132,15 +133,15 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
|||
/* If we don't need to send a full RXON, we can use
|
||||
* iwl_rxon_assoc_cmd which is used to reconfigure filter
|
||||
* and other flags for the current radio configuration. */
|
||||
if (!iwl_full_rxon_required(priv)) {
|
||||
ret = iwl_send_rxon_assoc(priv);
|
||||
if (!iwl_full_rxon_required(priv, ctx)) {
|
||||
ret = iwl_send_rxon_assoc(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
|
||||
iwl_print_rx_config_cmd(priv);
|
||||
memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
|
||||
iwl_print_rx_config_cmd(priv, ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -148,13 +149,13 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
|||
* an RXON_ASSOC and the new config wants the associated mask enabled,
|
||||
* we must clear the associated from the active configuration
|
||||
* before we apply the new config */
|
||||
if (iwl_is_associated(priv) && new_assoc) {
|
||||
if (iwl_is_associated_ctx(ctx) && new_assoc) {
|
||||
IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
|
||||
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
|
||||
ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
|
||||
sizeof(struct iwl_rxon_cmd),
|
||||
&priv->active_rxon);
|
||||
ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
|
||||
sizeof(struct iwl_rxon_cmd),
|
||||
active_rxon);
|
||||
|
||||
/* If the mask clearing failed then we set
|
||||
* active_rxon back to what it was previously */
|
||||
|
@ -163,9 +164,9 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
|||
IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
iwl_clear_ucode_stations(priv);
|
||||
iwl_restore_stations(priv);
|
||||
ret = iwl_restore_default_wep_keys(priv);
|
||||
iwl_clear_ucode_stations(priv, ctx);
|
||||
iwl_restore_stations(priv, ctx);
|
||||
ret = iwl_restore_default_wep_keys(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
|
||||
return ret;
|
||||
|
@ -177,27 +178,46 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
|||
"* channel = %d\n"
|
||||
"* bssid = %pM\n",
|
||||
(new_assoc ? "" : "out"),
|
||||
le16_to_cpu(priv->staging_rxon.channel),
|
||||
priv->staging_rxon.bssid_addr);
|
||||
le16_to_cpu(ctx->staging.channel),
|
||||
ctx->staging.bssid_addr);
|
||||
|
||||
iwl_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto);
|
||||
iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
|
||||
|
||||
if (!old_assoc) {
|
||||
/*
|
||||
* First of all, before setting associated, we need to
|
||||
* send RXON timing so the device knows about the DTIM
|
||||
* period and other timing values
|
||||
*/
|
||||
ret = iwl_send_rxon_timing(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error setting RXON timing!\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_pan_params) {
|
||||
ret = priv->cfg->ops->hcmd->set_pan_params(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Apply the new configuration
|
||||
* RXON unassoc clears the station table in uCode so restoration of
|
||||
* stations is needed after it (the RXON command) completes
|
||||
*/
|
||||
if (!new_assoc) {
|
||||
ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
|
||||
sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
|
||||
ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
|
||||
sizeof(struct iwl_rxon_cmd), &ctx->staging);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
|
||||
memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
|
||||
iwl_clear_ucode_stations(priv);
|
||||
iwl_restore_stations(priv);
|
||||
ret = iwl_restore_default_wep_keys(priv);
|
||||
memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
|
||||
iwl_clear_ucode_stations(priv, ctx);
|
||||
iwl_restore_stations(priv, ctx);
|
||||
ret = iwl_restore_default_wep_keys(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
|
||||
return ret;
|
||||
|
@ -209,15 +229,15 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
|||
/* Apply the new configuration
|
||||
* RXON assoc doesn't clear the station table in uCode,
|
||||
*/
|
||||
ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
|
||||
sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
|
||||
ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
|
||||
sizeof(struct iwl_rxon_cmd), &ctx->staging);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
|
||||
memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
|
||||
}
|
||||
iwl_print_rx_config_cmd(priv);
|
||||
iwl_print_rx_config_cmd(priv, ctx);
|
||||
|
||||
iwl_init_sensitivity(priv);
|
||||
|
||||
|
@ -234,10 +254,14 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
|||
|
||||
void iwl_update_chain_flags(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
iwlcore_commit_rxon(priv);
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain) {
|
||||
for_each_context(priv, ctx) {
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_clear_free_frames(struct iwl_priv *priv)
|
||||
|
@ -341,6 +365,13 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
|
|||
* beacon contents.
|
||||
*/
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (!priv->beacon_ctx) {
|
||||
IWL_ERR(priv, "trying to build beacon w/o beacon context!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Initialize memory */
|
||||
tx_beacon_cmd = &frame->u.beacon;
|
||||
memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
|
||||
|
@ -353,7 +384,7 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
|
|||
|
||||
/* Set up TX command fields */
|
||||
tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
|
||||
tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id;
|
||||
tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id;
|
||||
tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
|
||||
tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK |
|
||||
TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK;
|
||||
|
@ -363,7 +394,7 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
|
|||
frame_size);
|
||||
|
||||
/* Set up packet rate and flags */
|
||||
rate = iwl_rate_get_lowest_plcp(priv);
|
||||
rate = iwl_rate_get_lowest_plcp(priv, priv->beacon_ctx);
|
||||
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
|
||||
priv->hw_params.valid_tx_ant);
|
||||
rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
|
||||
|
@ -596,23 +627,38 @@ static void iwl_bg_beacon_update(struct work_struct *work)
|
|||
container_of(work, struct iwl_priv, beacon_update);
|
||||
struct sk_buff *beacon;
|
||||
|
||||
/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
|
||||
beacon = ieee80211_beacon_get(priv->hw, priv->vif);
|
||||
|
||||
if (!beacon) {
|
||||
IWL_ERR(priv, "update beacon failed\n");
|
||||
return;
|
||||
mutex_lock(&priv->mutex);
|
||||
if (!priv->beacon_ctx) {
|
||||
IWL_ERR(priv, "updating beacon w/o beacon context!\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (priv->beacon_ctx->vif->type != NL80211_IFTYPE_AP) {
|
||||
/*
|
||||
* The ucode will send beacon notifications even in
|
||||
* IBSS mode, but we don't want to process them. But
|
||||
* we need to defer the type check to here due to
|
||||
* requiring locking around the beacon_ctx access.
|
||||
*/
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
|
||||
beacon = ieee80211_beacon_get(priv->hw, priv->beacon_ctx->vif);
|
||||
if (!beacon) {
|
||||
IWL_ERR(priv, "update beacon failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
/* new beacon skb is allocated every time; dispose previous.*/
|
||||
if (priv->ibss_beacon)
|
||||
dev_kfree_skb(priv->ibss_beacon);
|
||||
|
||||
priv->ibss_beacon = beacon;
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
iwl_send_beacon_cmd(priv);
|
||||
out:
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
static void iwl_bg_bt_runtime_config(struct work_struct *work)
|
||||
|
@ -633,6 +679,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
|
|||
{
|
||||
struct iwl_priv *priv =
|
||||
container_of(work, struct iwl_priv, bt_full_concurrency);
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
@ -649,9 +696,13 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
|
|||
* LQ & RXON updated cmds must be sent before BT Config cmd
|
||||
* to avoid 3-wire collisions
|
||||
*/
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
iwlcore_commit_rxon(priv);
|
||||
mutex_lock(&priv->mutex);
|
||||
for_each_context(priv, ctx) {
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
}
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
priv->cfg->ops->hcmd->send_bt_config(priv);
|
||||
}
|
||||
|
@ -825,8 +876,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
|
|||
|
||||
priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
|
||||
|
||||
if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
|
||||
(!test_bit(STATUS_EXIT_PENDING, &priv->status)))
|
||||
if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
queue_work(priv->workqueue, &priv->beacon_update);
|
||||
}
|
||||
|
||||
|
@ -1697,6 +1747,7 @@ static void iwl_nic_start(struct iwl_priv *priv)
|
|||
struct iwlagn_ucode_capabilities {
|
||||
u32 max_probe_length;
|
||||
u32 standard_phy_calibration_size;
|
||||
bool pan;
|
||||
};
|
||||
|
||||
static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
|
||||
|
@ -1934,6 +1985,11 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
|
|||
capa->max_probe_length =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_PAN:
|
||||
if (tlv_len)
|
||||
goto invalid_tlv_len;
|
||||
capa->pan = true;
|
||||
break;
|
||||
case IWL_UCODE_TLV_INIT_EVTLOG_PTR:
|
||||
if (tlv_len != sizeof(u32))
|
||||
goto invalid_tlv_len;
|
||||
|
@ -2209,6 +2265,12 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size;
|
||||
priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr;
|
||||
|
||||
if (ucode_capa.pan) {
|
||||
priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN);
|
||||
priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
|
||||
} else
|
||||
priv->sta_key_max_num = STA_KEY_MAX_NUM;
|
||||
|
||||
/* Copy images into buffers for card's bus-master reads ... */
|
||||
|
||||
/* Runtime instructions (first block of data in file) */
|
||||
|
@ -2710,6 +2772,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
|
|||
static void iwl_alive_start(struct iwl_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
|
||||
|
||||
|
@ -2758,18 +2821,20 @@ static void iwl_alive_start(struct iwl_priv *priv)
|
|||
if (priv->cfg->ops->hcmd->set_tx_ant)
|
||||
priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant);
|
||||
|
||||
if (iwl_is_associated(priv)) {
|
||||
if (iwl_is_associated_ctx(ctx)) {
|
||||
struct iwl_rxon_cmd *active_rxon =
|
||||
(struct iwl_rxon_cmd *)&priv->active_rxon;
|
||||
(struct iwl_rxon_cmd *)&ctx->active;
|
||||
/* apply any changes in staging */
|
||||
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
} else {
|
||||
struct iwl_rxon_context *tmp;
|
||||
/* Initialize our rx_config data */
|
||||
iwl_connection_init_rx_config(priv, NULL);
|
||||
for_each_context(priv, tmp)
|
||||
iwl_connection_init_rx_config(priv, tmp);
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
|
||||
}
|
||||
|
||||
if (!priv->cfg->advanced_bt_coexist) {
|
||||
|
@ -2780,7 +2845,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
|
|||
iwl_reset_run_time_calib(priv);
|
||||
|
||||
/* Configure the adapter for unassociated operation */
|
||||
iwlcore_commit_rxon(priv);
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
/* At this point, the NIC is initialized and operational */
|
||||
iwl_rf_kill_ct_config(priv);
|
||||
|
@ -2818,8 +2883,8 @@ static void __iwl_down(struct iwl_priv *priv)
|
|||
if (priv->cfg->ops->lib->recover_from_tx_stall)
|
||||
del_timer_sync(&priv->monitor_recover);
|
||||
|
||||
iwl_clear_ucode_stations(priv);
|
||||
iwl_dealloc_bcast_station(priv);
|
||||
iwl_clear_ucode_stations(priv, NULL);
|
||||
iwl_dealloc_bcast_stations(priv);
|
||||
iwl_clear_driver_stations(priv);
|
||||
|
||||
/* reset BT coex data */
|
||||
|
@ -2961,6 +3026,7 @@ static int iwl_prepare_card_hw(struct iwl_priv *priv)
|
|||
|
||||
static int __iwl_up(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
|
@ -2974,9 +3040,13 @@ static int __iwl_up(struct iwl_priv *priv)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
ret = iwl_alloc_bcast_station(priv, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
for_each_context(priv, ctx) {
|
||||
ret = iwl_alloc_bcast_station(priv, ctx, true);
|
||||
if (ret) {
|
||||
iwl_dealloc_bcast_stations(priv);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
iwl_prepare_card_hw(priv);
|
||||
|
||||
|
@ -3001,6 +3071,12 @@ static int __iwl_up(struct iwl_priv *priv)
|
|||
|
||||
iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
|
||||
|
||||
/* must be initialised before iwl_hw_nic_init */
|
||||
if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
|
||||
priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
|
||||
else
|
||||
priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
|
||||
|
||||
ret = iwlagn_hw_nic_init(priv);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Unable to init nic\n");
|
||||
|
@ -3131,13 +3207,15 @@ static void iwl_bg_restart(struct work_struct *data)
|
|||
return;
|
||||
|
||||
if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
|
||||
struct iwl_rxon_context *ctx;
|
||||
bool bt_sco, bt_full_concurrent;
|
||||
u8 bt_ci_compliance;
|
||||
u8 bt_load;
|
||||
u8 bt_status;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
priv->vif = NULL;
|
||||
for_each_context(priv, ctx)
|
||||
ctx->vif = NULL;
|
||||
priv->is_open = 0;
|
||||
|
||||
/*
|
||||
|
@ -3195,12 +3273,15 @@ static void iwl_bg_rx_replenish(struct work_struct *data)
|
|||
|
||||
void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_rxon_context *ctx;
|
||||
struct ieee80211_conf *conf = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!vif || !priv->is_open)
|
||||
return;
|
||||
|
||||
ctx = iwl_rxon_ctx_from_vif(vif);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
|
||||
return;
|
||||
|
@ -3213,42 +3294,42 @@ void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
|
||||
conf = ieee80211_get_hw_conf(priv->hw);
|
||||
|
||||
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv);
|
||||
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
ret = iwl_send_rxon_timing(priv, vif);
|
||||
ret = iwl_send_rxon_timing(priv, ctx);
|
||||
if (ret)
|
||||
IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
|
||||
IWL_WARN(priv, "RXON timing - "
|
||||
"Attempting to continue.\n");
|
||||
|
||||
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
|
||||
iwl_set_rxon_ht(priv, &priv->current_ht_config);
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
|
||||
|
||||
priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid);
|
||||
ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
|
||||
vif->bss_conf.aid, vif->bss_conf.beacon_int);
|
||||
|
||||
if (vif->bss_conf.use_short_preamble)
|
||||
priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (vif->bss_conf.use_short_slot)
|
||||
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
||||
ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
}
|
||||
|
||||
iwlcore_commit_rxon(priv);
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
|
||||
vif->bss_conf.aid, priv->active_rxon.bssid_addr);
|
||||
vif->bss_conf.aid, ctx->active.bssid_addr);
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
|
@ -3291,11 +3372,14 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
|
|||
{
|
||||
int ret;
|
||||
struct ieee80211_hw *hw = priv->hw;
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
hw->rate_control_algorithm = "iwl-agn-rs";
|
||||
|
||||
/* Tell mac80211 our characteristics */
|
||||
hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_NEED_DTIM_PERIOD |
|
||||
IEEE80211_HW_SPECTRUM_MGMT;
|
||||
|
||||
if (!priv->cfg->broken_powersave)
|
||||
|
@ -3309,9 +3393,10 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
|
|||
hw->sta_data_size = sizeof(struct iwl_station_priv);
|
||||
hw->vif_data_size = sizeof(struct iwl_vif_priv);
|
||||
|
||||
hw->wiphy->interface_modes =
|
||||
BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
for_each_context(priv, ctx) {
|
||||
hw->wiphy->interface_modes |= ctx->interface_modes;
|
||||
hw->wiphy->interface_modes |= ctx->exclusive_interface_modes;
|
||||
}
|
||||
|
||||
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
|
||||
WIPHY_FLAG_DISABLE_BEACON_HINTS;
|
||||
|
@ -3439,22 +3524,25 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
|
||||
void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
/* The following should be done only at AP bring up */
|
||||
if (!iwl_is_associated(priv)) {
|
||||
if (!iwl_is_associated_ctx(ctx)) {
|
||||
|
||||
/* RXON - unassoc (to set timing command) */
|
||||
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv);
|
||||
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
/* RXON Timing */
|
||||
ret = iwl_send_rxon_timing(priv, vif);
|
||||
ret = iwl_send_rxon_timing(priv, ctx);
|
||||
if (ret)
|
||||
IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
|
||||
IWL_WARN(priv, "RXON timing failed - "
|
||||
"Attempting to continue.\n");
|
||||
|
||||
/* AP has all antennas */
|
||||
|
@ -3462,28 +3550,30 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
priv->hw_params.valid_rx_ant;
|
||||
iwl_set_rxon_ht(priv, &priv->current_ht_config);
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
|
||||
|
||||
priv->staging_rxon.assoc_id = 0;
|
||||
ctx->staging.assoc_id = 0;
|
||||
|
||||
if (vif->bss_conf.use_short_preamble)
|
||||
priv->staging_rxon.flags |=
|
||||
ctx->staging.flags |=
|
||||
RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &=
|
||||
ctx->staging.flags &=
|
||||
~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (vif->bss_conf.use_short_slot)
|
||||
priv->staging_rxon.flags |=
|
||||
ctx->staging.flags |=
|
||||
RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &=
|
||||
ctx->staging.flags &=
|
||||
~RXON_FLG_SHORT_SLOT_MSK;
|
||||
}
|
||||
/* need to send beacon cmd before committing assoc RXON! */
|
||||
iwl_send_beacon_cmd(priv);
|
||||
/* restore RXON assoc */
|
||||
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv);
|
||||
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
}
|
||||
iwl_send_beacon_cmd(priv);
|
||||
|
||||
|
@ -3500,9 +3590,11 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
|
|||
{
|
||||
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
|
||||
iwl_update_tkip_key(priv, keyconf, sta,
|
||||
iwl_update_tkip_key(priv, vif_priv->ctx, keyconf, sta,
|
||||
iv32, phase1key);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
@ -3514,6 +3606,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
struct iwl_rxon_context *ctx = vif_priv->ctx;
|
||||
int ret;
|
||||
u8 sta_id;
|
||||
bool is_default_wep_key = false;
|
||||
|
@ -3525,7 +3619,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
sta_id = iwl_sta_id_or_broadcast(priv, sta);
|
||||
sta_id = iwl_sta_id_or_broadcast(priv, vif_priv->ctx, sta);
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -3542,7 +3636,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
|
||||
!sta) {
|
||||
if (cmd == SET_KEY)
|
||||
is_default_wep_key = !priv->key_mapping_key;
|
||||
is_default_wep_key = !ctx->key_mapping_keys;
|
||||
else
|
||||
is_default_wep_key =
|
||||
(key->hw_key_idx == HW_KEY_DEFAULT);
|
||||
|
@ -3551,17 +3645,18 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
switch (cmd) {
|
||||
case SET_KEY:
|
||||
if (is_default_wep_key)
|
||||
ret = iwl_set_default_wep_key(priv, key);
|
||||
ret = iwl_set_default_wep_key(priv, vif_priv->ctx, key);
|
||||
else
|
||||
ret = iwl_set_dynamic_key(priv, key, sta_id);
|
||||
ret = iwl_set_dynamic_key(priv, vif_priv->ctx,
|
||||
key, sta_id);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n");
|
||||
break;
|
||||
case DISABLE_KEY:
|
||||
if (is_default_wep_key)
|
||||
ret = iwl_remove_default_wep_key(priv, key);
|
||||
ret = iwl_remove_default_wep_key(priv, ctx, key);
|
||||
else
|
||||
ret = iwl_remove_dynamic_key(priv, key, sta_id);
|
||||
ret = iwl_remove_dynamic_key(priv, ctx, key, sta_id);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
|
||||
break;
|
||||
|
@ -3630,8 +3725,8 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
|
|||
|
||||
sta_priv->lq_sta.lq.general_params.flags &=
|
||||
~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
|
||||
iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq,
|
||||
CMD_ASYNC, false);
|
||||
iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
|
||||
&sta_priv->lq_sta.lq, CMD_ASYNC, false);
|
||||
}
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||
|
@ -3646,8 +3741,8 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
|
|||
|
||||
sta_priv->lq_sta.lq.general_params.flags |=
|
||||
LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
|
||||
iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq,
|
||||
CMD_ASYNC, false);
|
||||
iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
|
||||
&sta_priv->lq_sta.lq, CMD_ASYNC, false);
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
|
@ -3693,6 +3788,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
bool is_ap = vif->type == NL80211_IFTYPE_STATION;
|
||||
int ret;
|
||||
u8 sta_id;
|
||||
|
@ -3708,8 +3804,8 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
|
|||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
sta_priv->client = true;
|
||||
|
||||
ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap,
|
||||
&sta_id);
|
||||
ret = iwl_add_station_common(priv, vif_priv->ctx, sta->addr,
|
||||
is_ap, sta, &sta_id);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Unable to add station %pM (%d)\n",
|
||||
sta->addr, ret);
|
||||
|
@ -3737,6 +3833,15 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
|
|||
struct ieee80211_conf *conf = &hw->conf;
|
||||
struct ieee80211_channel *channel = ch_switch->channel;
|
||||
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
|
||||
/*
|
||||
* MULTI-FIXME
|
||||
* When we add support for multiple interfaces, we need to
|
||||
* revisit this. The channel switch command in the device
|
||||
* only affects the BSS context, but what does that really
|
||||
* mean? And what if we get a CSA on the second interface?
|
||||
* This needs a lot of work.
|
||||
*/
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
u16 ch;
|
||||
unsigned long flags = 0;
|
||||
|
||||
|
@ -3749,7 +3854,7 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
|
|||
test_bit(STATUS_SCANNING, &priv->status))
|
||||
goto out_exit;
|
||||
|
||||
if (!iwl_is_associated(priv))
|
||||
if (!iwl_is_associated_ctx(ctx))
|
||||
goto out_exit;
|
||||
|
||||
/* channel switch in progress */
|
||||
|
@ -3760,7 +3865,7 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
|
|||
if (priv->cfg->ops->lib->set_channel_switch) {
|
||||
|
||||
ch = channel->hw_value;
|
||||
if (le16_to_cpu(priv->active_rxon.channel) != ch) {
|
||||
if (le16_to_cpu(ctx->active.channel) != ch) {
|
||||
ch_info = iwl_get_channel_info(priv,
|
||||
channel->band,
|
||||
ch);
|
||||
|
@ -3773,31 +3878,31 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
|
|||
priv->current_ht_config.smps = conf->smps_mode;
|
||||
|
||||
/* Configure HT40 channels */
|
||||
ht_conf->is_ht = conf_is_ht(conf);
|
||||
if (ht_conf->is_ht) {
|
||||
ctx->ht.enabled = conf_is_ht(conf);
|
||||
if (ctx->ht.enabled) {
|
||||
if (conf_is_ht40_minus(conf)) {
|
||||
ht_conf->extension_chan_offset =
|
||||
ctx->ht.extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_BELOW;
|
||||
ht_conf->is_40mhz = true;
|
||||
ctx->ht.is_40mhz = true;
|
||||
} else if (conf_is_ht40_plus(conf)) {
|
||||
ht_conf->extension_chan_offset =
|
||||
ctx->ht.extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
|
||||
ht_conf->is_40mhz = true;
|
||||
ctx->ht.is_40mhz = true;
|
||||
} else {
|
||||
ht_conf->extension_chan_offset =
|
||||
ctx->ht.extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_NONE;
|
||||
ht_conf->is_40mhz = false;
|
||||
ctx->ht.is_40mhz = false;
|
||||
}
|
||||
} else
|
||||
ht_conf->is_40mhz = false;
|
||||
ctx->ht.is_40mhz = false;
|
||||
|
||||
if (le16_to_cpu(priv->staging_rxon.channel) != ch)
|
||||
priv->staging_rxon.flags = 0;
|
||||
if ((le16_to_cpu(ctx->staging.channel) != ch))
|
||||
ctx->staging.flags = 0;
|
||||
|
||||
iwl_set_rxon_channel(priv, channel);
|
||||
iwl_set_rxon_channel(priv, channel, ctx);
|
||||
iwl_set_rxon_ht(priv, ht_conf);
|
||||
iwl_set_flags_for_band(priv, channel->band,
|
||||
priv->vif);
|
||||
iwl_set_flags_for_band(priv, ctx, channel->band,
|
||||
ctx->vif);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
iwl_set_rate(priv);
|
||||
|
@ -3814,7 +3919,7 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
|
|||
mutex_unlock(&priv->mutex);
|
||||
out_exit:
|
||||
if (!priv->switch_rxon.switch_in_progress)
|
||||
ieee80211_chswitch_done(priv->vif, false);
|
||||
ieee80211_chswitch_done(ctx->vif, false);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
|
||||
|
@ -3825,6 +3930,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
__le32 filter_or = 0, filter_nand = 0;
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
#define CHK(test, flag) do { \
|
||||
if (*total_flags & (test)) \
|
||||
|
@ -3844,10 +3950,11 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
priv->staging_rxon.filter_flags &= ~filter_nand;
|
||||
priv->staging_rxon.filter_flags |= filter_or;
|
||||
|
||||
iwlcore_commit_rxon(priv);
|
||||
for_each_context(priv, ctx) {
|
||||
ctx->staging.filter_flags &= ~filter_nand;
|
||||
ctx->staging.filter_flags |= filter_or;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
|
@ -4018,7 +4125,8 @@ static int iwl_init_drv(struct iwl_priv *priv)
|
|||
|
||||
/* Choose which receivers/antennas to use */
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv,
|
||||
&priv->contexts[IWL_RXON_CTX_BSS]);
|
||||
|
||||
iwl_init_scan_params(priv);
|
||||
|
||||
|
@ -4116,9 +4224,31 @@ static int iwl_set_hw_params(struct iwl_priv *priv)
|
|||
return priv->cfg->ops->lib->set_hw_params(priv);
|
||||
}
|
||||
|
||||
static const u8 iwlagn_bss_ac_to_fifo[] = {
|
||||
IWL_TX_FIFO_VO,
|
||||
IWL_TX_FIFO_VI,
|
||||
IWL_TX_FIFO_BE,
|
||||
IWL_TX_FIFO_BK,
|
||||
};
|
||||
|
||||
static const u8 iwlagn_bss_ac_to_queue[] = {
|
||||
0, 1, 2, 3,
|
||||
};
|
||||
|
||||
static const u8 iwlagn_pan_ac_to_fifo[] = {
|
||||
IWL_TX_FIFO_VO_IPAN,
|
||||
IWL_TX_FIFO_VI_IPAN,
|
||||
IWL_TX_FIFO_BE_IPAN,
|
||||
IWL_TX_FIFO_BK_IPAN,
|
||||
};
|
||||
|
||||
static const u8 iwlagn_pan_ac_to_queue[] = {
|
||||
7, 6, 5, 4,
|
||||
};
|
||||
|
||||
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
int err = 0;
|
||||
int err = 0, i;
|
||||
struct iwl_priv *priv;
|
||||
struct ieee80211_hw *hw;
|
||||
struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
|
||||
|
@ -4146,6 +4276,51 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
priv = hw->priv;
|
||||
/* At this point both hw and priv are allocated. */
|
||||
|
||||
/*
|
||||
* The default context is always valid,
|
||||
* more may be discovered when firmware
|
||||
* is loaded.
|
||||
*/
|
||||
priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
|
||||
|
||||
for (i = 0; i < NUM_IWL_RXON_CTX; i++)
|
||||
priv->contexts[i].ctxid = i;
|
||||
|
||||
priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwlagn_bss_ac_to_fifo;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwlagn_bss_ac_to_queue;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes =
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
|
||||
BIT(NL80211_IFTYPE_STATION);
|
||||
priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
|
||||
|
||||
priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON;
|
||||
priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = REPLY_WIPAN_RXON_TIMING;
|
||||
priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd = REPLY_WIPAN_RXON_ASSOC;
|
||||
priv->contexts[IWL_RXON_CTX_PAN].qos_cmd = REPLY_WIPAN_QOS_PARAM;
|
||||
priv->contexts[IWL_RXON_CTX_PAN].ap_sta_id = IWL_AP_ID_PAN;
|
||||
priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY;
|
||||
priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID;
|
||||
priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION;
|
||||
priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo = iwlagn_pan_ac_to_fifo;
|
||||
priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue = iwlagn_pan_ac_to_queue;
|
||||
priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE;
|
||||
priv->contexts[IWL_RXON_CTX_PAN].interface_modes =
|
||||
BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
|
||||
priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP;
|
||||
priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA;
|
||||
priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
|
||||
|
||||
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
|
||||
|
||||
SET_IEEE80211_DEV(hw, &pdev->dev);
|
||||
|
||||
IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
|
||||
|
|
|
@ -224,7 +224,8 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
|
|||
struct ieee80211_vif *vif, bool add);
|
||||
|
||||
/* hcmd */
|
||||
int iwlagn_send_rxon_assoc(struct iwl_priv *priv);
|
||||
int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx);
|
||||
int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant);
|
||||
|
||||
/* bt coex */
|
||||
|
|
|
@ -180,6 +180,16 @@ enum {
|
|||
REPLY_BT_COEX_PROFILE_NOTIF = 0xce,
|
||||
REPLY_BT_COEX_SCO = 0xcf,
|
||||
|
||||
/* PAN commands */
|
||||
REPLY_WIPAN_PARAMS = 0xb2,
|
||||
REPLY_WIPAN_RXON = 0xb3, /* use REPLY_RXON structure */
|
||||
REPLY_WIPAN_RXON_TIMING = 0xb4, /* use REPLY_RXON_TIMING structure */
|
||||
REPLY_WIPAN_RXON_ASSOC = 0xb6, /* use REPLY_RXON_ASSOC structure */
|
||||
REPLY_WIPAN_QOS_PARAM = 0xb7, /* use REPLY_QOS_PARAM structure */
|
||||
REPLY_WIPAN_WEPKEY = 0xb8, /* use REPLY_WEPKEY structure */
|
||||
REPLY_WIPAN_P2P_CHANNEL_SWITCH = 0xb9,
|
||||
REPLY_WIPAN_NOA_NOTIFICATION = 0xbc,
|
||||
|
||||
REPLY_MAX = 0xff
|
||||
};
|
||||
|
||||
|
@ -607,6 +617,9 @@ enum {
|
|||
RXON_DEV_TYPE_ESS = 3,
|
||||
RXON_DEV_TYPE_IBSS = 4,
|
||||
RXON_DEV_TYPE_SNIFFER = 6,
|
||||
RXON_DEV_TYPE_CP = 7,
|
||||
RXON_DEV_TYPE_2STA = 8,
|
||||
RXON_DEV_TYPE_P2P = 9,
|
||||
};
|
||||
|
||||
|
||||
|
@ -823,7 +836,8 @@ struct iwl_rxon_time_cmd {
|
|||
__le16 atim_window;
|
||||
__le32 beacon_init_val;
|
||||
__le16 listen_interval;
|
||||
__le16 reserved;
|
||||
u8 dtim_period;
|
||||
u8 delta_cp_bss_tbtts;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
|
@ -960,11 +974,13 @@ struct iwl_qosparam_cmd {
|
|||
|
||||
/* Special, dedicated locations within device's station table */
|
||||
#define IWL_AP_ID 0
|
||||
#define IWL_AP_ID_PAN 1
|
||||
#define IWL_STA_ID 2
|
||||
#define IWL3945_BROADCAST_ID 24
|
||||
#define IWL3945_STATION_COUNT 25
|
||||
#define IWL4965_BROADCAST_ID 31
|
||||
#define IWL4965_STATION_COUNT 32
|
||||
#define IWLAGN_PAN_BCAST_ID 14
|
||||
#define IWLAGN_BROADCAST_ID 15
|
||||
#define IWLAGN_STATION_COUNT 16
|
||||
|
||||
|
@ -973,6 +989,7 @@ struct iwl_qosparam_cmd {
|
|||
|
||||
#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2)
|
||||
#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8)
|
||||
#define STA_FLG_PAN_STATION cpu_to_le32(1 << 13)
|
||||
#define STA_FLG_RTS_MIMO_PROT_MSK cpu_to_le32(1 << 17)
|
||||
#define STA_FLG_AGG_MPDU_8US_MSK cpu_to_le32(1 << 18)
|
||||
#define STA_FLG_MAX_AGG_SIZE_POS (19)
|
||||
|
@ -1001,6 +1018,7 @@ struct iwl_qosparam_cmd {
|
|||
#define STA_KEY_FLG_KEY_SIZE_MSK cpu_to_le16(0x1000)
|
||||
#define STA_KEY_MULTICAST_MSK cpu_to_le16(0x4000)
|
||||
#define STA_KEY_MAX_NUM 8
|
||||
#define STA_KEY_MAX_NUM_PAN 16
|
||||
|
||||
/* Flags indicate whether to modify vs. don't change various station params */
|
||||
#define STA_MODIFY_KEY_MASK 0x01
|
||||
|
@ -4308,4 +4326,94 @@ struct iwl_rx_packet {
|
|||
|
||||
int iwl_agn_check_rxon_cmd(struct iwl_priv *priv);
|
||||
|
||||
/*
|
||||
* REPLY_WIPAN_PARAMS = 0xb2 (Commands and Notification)
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct iwl_wipan_slot
|
||||
* @width: Time in TU
|
||||
* @type:
|
||||
* 0 - BSS
|
||||
* 1 - PAN
|
||||
*/
|
||||
struct iwl_wipan_slot {
|
||||
__le16 width;
|
||||
u8 type;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
#define IWL_WIPAN_PARAMS_FLG_LEAVE_CHANNEL_CTS BIT(1) /* reserved */
|
||||
#define IWL_WIPAN_PARAMS_FLG_LEAVE_CHANNEL_QUIET BIT(2) /* reserved */
|
||||
#define IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE BIT(3) /* reserved */
|
||||
#define IWL_WIPAN_PARAMS_FLG_FILTER_BEACON_NOTIF BIT(4)
|
||||
#define IWL_WIPAN_PARAMS_FLG_FULL_SLOTTED_MODE BIT(5)
|
||||
|
||||
/**
|
||||
* struct iwl_wipan_params_cmd
|
||||
* @flags:
|
||||
* bit0: reserved
|
||||
* bit1: CP leave channel with CTS
|
||||
* bit2: CP leave channel qith Quiet
|
||||
* bit3: slotted mode
|
||||
* 1 - work in slotted mode
|
||||
* 0 - work in non slotted mode
|
||||
* bit4: filter beacon notification
|
||||
* bit5: full tx slotted mode. if this flag is set,
|
||||
* uCode will perform leaving channel methods in context switch
|
||||
* also when working in same channel mode
|
||||
* @num_slots: 1 - 10
|
||||
*/
|
||||
struct iwl_wipan_params_cmd {
|
||||
__le16 flags;
|
||||
u8 reserved;
|
||||
u8 num_slots;
|
||||
struct iwl_wipan_slot slots[10];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* REPLY_WIPAN_P2P_CHANNEL_SWITCH = 0xb9
|
||||
*
|
||||
* TODO: Figure out what this is used for,
|
||||
* it can only switch between 2.4 GHz
|
||||
* channels!!
|
||||
*/
|
||||
|
||||
struct iwl_wipan_p2p_channel_switch_cmd {
|
||||
__le16 channel;
|
||||
__le16 reserved;
|
||||
};
|
||||
|
||||
/*
|
||||
* REPLY_WIPAN_NOA_NOTIFICATION = 0xbc
|
||||
*
|
||||
* This is used by the device to notify us of the
|
||||
* NoA schedule it determined so we can forward it
|
||||
* to userspace for inclusion in probe responses.
|
||||
*
|
||||
* In beacons, the NoA schedule is simply appended
|
||||
* to the frame we give the device.
|
||||
*/
|
||||
|
||||
struct iwl_wipan_noa_descriptor {
|
||||
u8 count;
|
||||
__le32 duration;
|
||||
__le32 interval;
|
||||
__le32 starttime;
|
||||
} __packed;
|
||||
|
||||
struct iwl_wipan_noa_attribute {
|
||||
u8 id;
|
||||
__le16 length;
|
||||
u8 index;
|
||||
u8 ct_window;
|
||||
struct iwl_wipan_noa_descriptor descr0, descr1;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
struct iwl_wipan_noa_notification {
|
||||
u32 noa_active;
|
||||
struct iwl_wipan_noa_attribute noa_attribute;
|
||||
} __packed;
|
||||
|
||||
#endif /* __iwl_commands_h__ */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -88,11 +88,13 @@ struct iwl_cmd;
|
|||
#define IWL_CMD(x) case x: return #x
|
||||
|
||||
struct iwl_hcmd_ops {
|
||||
int (*rxon_assoc)(struct iwl_priv *priv);
|
||||
int (*commit_rxon)(struct iwl_priv *priv);
|
||||
void (*set_rxon_chain)(struct iwl_priv *priv);
|
||||
int (*rxon_assoc)(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
int (*commit_rxon)(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
void (*set_rxon_chain)(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx);
|
||||
int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant);
|
||||
void (*send_bt_config)(struct iwl_priv *priv);
|
||||
int (*set_pan_params)(struct iwl_priv *priv);
|
||||
};
|
||||
|
||||
struct iwl_hcmd_utils_ops {
|
||||
|
@ -205,7 +207,7 @@ struct iwl_lib_ops {
|
|||
/* station management */
|
||||
int (*manage_ibss_station)(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif, bool add);
|
||||
int (*update_bcast_station)(struct iwl_priv *priv);
|
||||
int (*update_bcast_stations)(struct iwl_priv *priv);
|
||||
/* recover from tx queue stall */
|
||||
void (*recover_from_tx_stall)(unsigned long data);
|
||||
/* check for plcp health */
|
||||
|
@ -374,21 +376,25 @@ void iwl_activate_qos(struct iwl_priv *priv);
|
|||
int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
const struct ieee80211_tx_queue_params *params);
|
||||
int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw);
|
||||
void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt);
|
||||
int iwl_check_rxon_cmd(struct iwl_priv *priv);
|
||||
int iwl_full_rxon_required(struct iwl_priv *priv);
|
||||
void iwl_set_rxon_chain(struct iwl_priv *priv);
|
||||
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
|
||||
void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
int hw_decrypt);
|
||||
int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
void iwl_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
|
||||
struct iwl_rxon_context *ctx);
|
||||
void iwl_set_flags_for_band(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
enum ieee80211_band band,
|
||||
struct ieee80211_vif *vif);
|
||||
u8 iwl_get_single_channel_number(struct iwl_priv *priv,
|
||||
enum ieee80211_band band);
|
||||
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf);
|
||||
u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
|
||||
struct ieee80211_sta_ht_cap *sta_ht_inf);
|
||||
bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_sta_ht_cap *ht_cap);
|
||||
void iwl_connection_init_rx_config(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif);
|
||||
struct iwl_rxon_context *ctx);
|
||||
void iwl_set_rate(struct iwl_priv *priv);
|
||||
int iwl_set_decrypted_flag(struct iwl_priv *priv,
|
||||
struct ieee80211_hdr *hdr,
|
||||
|
@ -400,7 +406,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
|||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
u32 changes);
|
||||
int iwl_commit_rxon(struct iwl_priv *priv);
|
||||
int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
int iwl_mac_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
void iwl_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
|
@ -518,7 +524,8 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
|
|||
|
||||
int iwl_hwrate_to_plcp_idx(u32 rate_n_flags);
|
||||
|
||||
u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv);
|
||||
u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx);
|
||||
|
||||
u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
|
||||
|
||||
|
@ -632,9 +639,11 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv,
|
|||
void iwl_dump_csr(struct iwl_priv *priv);
|
||||
int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
void iwl_print_rx_config_cmd(struct iwl_priv *priv);
|
||||
void iwl_print_rx_config_cmd(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx);
|
||||
#else
|
||||
static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv)
|
||||
static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
@ -714,19 +723,21 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv)
|
|||
extern void iwl_send_bt_config(struct iwl_priv *priv);
|
||||
extern int iwl_send_statistics_request(struct iwl_priv *priv,
|
||||
u8 flags, bool clear);
|
||||
extern int iwl_send_lq_cmd(struct iwl_priv *priv,
|
||||
extern int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct iwl_link_quality_cmd *lq, u8 flags, bool init);
|
||||
void iwl_apm_stop(struct iwl_priv *priv);
|
||||
int iwl_apm_init(struct iwl_priv *priv);
|
||||
|
||||
int iwl_send_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif);
|
||||
static inline int iwl_send_rxon_assoc(struct iwl_priv *priv)
|
||||
int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
static inline int iwl_send_rxon_assoc(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
return priv->cfg->ops->hcmd->rxon_assoc(priv);
|
||||
return priv->cfg->ops->hcmd->rxon_assoc(priv, ctx);
|
||||
}
|
||||
static inline int iwlcore_commit_rxon(struct iwl_priv *priv)
|
||||
static inline int iwlcore_commit_rxon(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
return priv->cfg->ops->hcmd->commit_rxon(priv);
|
||||
return priv->cfg->ops->hcmd->commit_rxon(priv, ctx);
|
||||
}
|
||||
static inline void iwlcore_config_ap(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif)
|
||||
|
|
|
@ -643,19 +643,25 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
struct iwl_rxon_context *ctx;
|
||||
int pos = 0, i;
|
||||
char buf[256];
|
||||
char buf[256 * NUM_IWL_RXON_CTX];
|
||||
const size_t bufsz = sizeof(buf);
|
||||
|
||||
for (i = 0; i < AC_NUM; i++) {
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tcw_min\tcw_max\taifsn\ttxop\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
for_each_context(priv, ctx) {
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n",
|
||||
ctx->ctxid);
|
||||
for (i = 0; i < AC_NUM; i++) {
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tcw_min\tcw_max\taifsn\ttxop\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"AC[%d]\t%u\t%u\t%u\t%u\n", i,
|
||||
priv->qos_data.def_qos_parm.ac[i].cw_min,
|
||||
priv->qos_data.def_qos_parm.ac[i].cw_max,
|
||||
priv->qos_data.def_qos_parm.ac[i].aifsn,
|
||||
priv->qos_data.def_qos_parm.ac[i].edca_txop);
|
||||
ctx->qos_data.def_qos_parm.ac[i].cw_min,
|
||||
ctx->qos_data.def_qos_parm.ac[i].cw_max,
|
||||
ctx->qos_data.def_qos_parm.ac[i].aifsn,
|
||||
ctx->qos_data.def_qos_parm.ac[i].edca_txop);
|
||||
}
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "\n");
|
||||
}
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
@ -730,7 +736,7 @@ static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,
|
|||
return -EFAULT;
|
||||
if (sscanf(buf, "%d", &ht40) != 1)
|
||||
return -EFAULT;
|
||||
if (!iwl_is_associated(priv))
|
||||
if (!iwl_is_any_associated(priv))
|
||||
priv->disable_ht40 = ht40 ? true : false;
|
||||
else {
|
||||
IWL_ERR(priv, "Sta associated with AP - "
|
||||
|
@ -1319,7 +1325,8 @@ static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file,
|
|||
int len = 0;
|
||||
char buf[20];
|
||||
|
||||
len = sprintf(buf, "0x%04X\n", le32_to_cpu(priv->active_rxon.flags));
|
||||
len = sprintf(buf, "0x%04X\n",
|
||||
le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.flags));
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
|
@ -1332,7 +1339,7 @@ static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file,
|
|||
char buf[20];
|
||||
|
||||
len = sprintf(buf, "0x%04X\n",
|
||||
le32_to_cpu(priv->active_rxon.filter_flags));
|
||||
le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags));
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
|
|
|
@ -144,6 +144,7 @@ struct iwl_queue {
|
|||
/* One for each TFD */
|
||||
struct iwl_tx_info {
|
||||
struct sk_buff *skb;
|
||||
struct iwl_rxon_context *ctx;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -253,10 +254,14 @@ struct iwl_channel_info {
|
|||
struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES];
|
||||
};
|
||||
|
||||
#define IWL_TX_FIFO_BK 0
|
||||
#define IWL_TX_FIFO_BK 0 /* shared */
|
||||
#define IWL_TX_FIFO_BE 1
|
||||
#define IWL_TX_FIFO_VI 2
|
||||
#define IWL_TX_FIFO_VI 2 /* shared */
|
||||
#define IWL_TX_FIFO_VO 3
|
||||
#define IWL_TX_FIFO_BK_IPAN IWL_TX_FIFO_BK
|
||||
#define IWL_TX_FIFO_BE_IPAN 4
|
||||
#define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI
|
||||
#define IWL_TX_FIFO_VO_IPAN 5
|
||||
#define IWL_TX_FIFO_UNUSED -1
|
||||
|
||||
/* Minimum number of queues. MAX_NUM is defined in hw specific files.
|
||||
|
@ -265,11 +270,17 @@ struct iwl_channel_info {
|
|||
#define IWL_MIN_NUM_QUEUES 10
|
||||
|
||||
/*
|
||||
* Queue #4 is the command queue for 3945/4965/5x00/1000/6x00,
|
||||
* the driver maps it into the appropriate device FIFO for the
|
||||
* uCode.
|
||||
* Command queue depends on iPAN support.
|
||||
*/
|
||||
#define IWL_CMD_QUEUE_NUM 4
|
||||
#define IWL_DEFAULT_CMD_QUEUE_NUM 4
|
||||
#define IWL_IPAN_CMD_QUEUE_NUM 9
|
||||
|
||||
/*
|
||||
* This queue number is required for proper operation
|
||||
* because the ucode will stop/start the scheduler as
|
||||
* required.
|
||||
*/
|
||||
#define IWL_IPAN_MCAST_QUEUE 8
|
||||
|
||||
/* Power management (not Tx power) structures */
|
||||
|
||||
|
@ -459,15 +470,8 @@ union iwl_ht_rate_supp {
|
|||
#define CFG_HT_MPDU_DENSITY_MIN (0x1)
|
||||
|
||||
struct iwl_ht_config {
|
||||
/* self configuration data */
|
||||
bool is_ht;
|
||||
bool is_40mhz;
|
||||
bool single_chain_sufficient;
|
||||
enum ieee80211_smps_mode smps; /* current smps mode */
|
||||
/* BSS related data */
|
||||
u8 extension_chan_offset;
|
||||
u8 ht_protection;
|
||||
u8 non_GF_STA_present;
|
||||
};
|
||||
|
||||
/* QoS structures */
|
||||
|
@ -485,12 +489,13 @@ struct iwl_qos_info {
|
|||
struct iwl_station_entry {
|
||||
struct iwl_addsta_cmd sta;
|
||||
struct iwl_tid_data tid[MAX_TID_COUNT];
|
||||
u8 used;
|
||||
u8 used, ctxid;
|
||||
struct iwl_hw_key keyinfo;
|
||||
struct iwl_link_quality_cmd *lq;
|
||||
};
|
||||
|
||||
struct iwl_station_priv_common {
|
||||
struct iwl_rxon_context *ctx;
|
||||
u8 sta_id;
|
||||
};
|
||||
|
||||
|
@ -519,6 +524,7 @@ struct iwl_station_priv {
|
|||
* space for us to put data into.
|
||||
*/
|
||||
struct iwl_vif_priv {
|
||||
struct iwl_rxon_context *ctx;
|
||||
u8 ibss_bssid_sta_id;
|
||||
};
|
||||
|
||||
|
@ -576,6 +582,7 @@ enum iwl_ucode_tlv_type {
|
|||
IWL_UCODE_TLV_INIT_DATA = 4,
|
||||
IWL_UCODE_TLV_BOOT = 5,
|
||||
IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */
|
||||
IWL_UCODE_TLV_PAN = 7,
|
||||
IWL_UCODE_TLV_RUNT_EVTLOG_PTR = 8,
|
||||
IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9,
|
||||
IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10,
|
||||
|
@ -670,7 +677,6 @@ struct iwl_sensitivity_ranges {
|
|||
* @rx_page_order: Rx buffer page order
|
||||
* @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
|
||||
* @max_stations:
|
||||
* @bcast_sta_id:
|
||||
* @ht40_channel: is 40MHz width possible in band 2.4
|
||||
* BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ)
|
||||
* @sw_crypto: 0 for hw, 1 for sw
|
||||
|
@ -694,7 +700,6 @@ struct iwl_hw_params {
|
|||
u32 rx_page_order;
|
||||
u32 rx_wrt_ptr_reg;
|
||||
u8 max_stations;
|
||||
u8 bcast_sta_id;
|
||||
u8 ht40_channel;
|
||||
u8 max_beacon_itrvl; /* in 1024 ms */
|
||||
u32 max_inst_size;
|
||||
|
@ -1097,6 +1102,57 @@ struct iwl_force_reset {
|
|||
*/
|
||||
#define IWLAGN_EXT_BEACON_TIME_POS 22
|
||||
|
||||
enum iwl_rxon_context_id {
|
||||
IWL_RXON_CTX_BSS,
|
||||
IWL_RXON_CTX_PAN,
|
||||
|
||||
NUM_IWL_RXON_CTX
|
||||
};
|
||||
|
||||
struct iwl_rxon_context {
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
const u8 *ac_to_fifo;
|
||||
const u8 *ac_to_queue;
|
||||
u8 mcast_queue;
|
||||
|
||||
enum iwl_rxon_context_id ctxid;
|
||||
|
||||
u32 interface_modes, exclusive_interface_modes;
|
||||
u8 unused_devtype, ap_devtype, ibss_devtype, station_devtype;
|
||||
|
||||
/*
|
||||
* We declare this const so it can only be
|
||||
* changed via explicit cast within the
|
||||
* routines that actually update the physical
|
||||
* hardware.
|
||||
*/
|
||||
const struct iwl_rxon_cmd active;
|
||||
struct iwl_rxon_cmd staging;
|
||||
|
||||
struct iwl_rxon_time_cmd timing;
|
||||
|
||||
struct iwl_qos_info qos_data;
|
||||
|
||||
u8 bcast_sta_id, ap_sta_id;
|
||||
|
||||
u8 rxon_cmd, rxon_assoc_cmd, rxon_timing_cmd;
|
||||
u8 qos_cmd;
|
||||
u8 wep_key_cmd;
|
||||
|
||||
struct iwl_wep_key wep_keys[WEP_KEYS_MAX];
|
||||
u8 key_mapping_keys;
|
||||
|
||||
__le32 station_flags;
|
||||
|
||||
struct {
|
||||
bool non_gf_sta_present;
|
||||
u8 protection;
|
||||
bool enabled, is_40mhz;
|
||||
u8 extension_chan_offset;
|
||||
} ht;
|
||||
};
|
||||
|
||||
struct iwl_priv {
|
||||
|
||||
/* ieee device used by generic ieee processing code */
|
||||
|
@ -1173,6 +1229,15 @@ struct iwl_priv {
|
|||
u32 hw_wa_rev;
|
||||
u8 rev_id;
|
||||
|
||||
/* microcode/device supports multiple contexts */
|
||||
u8 valid_contexts;
|
||||
|
||||
/* command queue number */
|
||||
u8 cmd_queue;
|
||||
|
||||
/* max number of station keys */
|
||||
u8 sta_key_max_num;
|
||||
|
||||
/* EEPROM MAC addresses */
|
||||
struct mac_address addresses[2];
|
||||
|
||||
|
@ -1190,15 +1255,7 @@ struct iwl_priv {
|
|||
u8 ucode_write_complete; /* the image write is complete */
|
||||
char firmware_name[25];
|
||||
|
||||
|
||||
struct iwl_rxon_time_cmd rxon_timing;
|
||||
|
||||
/* We declare this const so it can only be
|
||||
* changed via explicit cast within the
|
||||
* routines that actually update the physical
|
||||
* hardware */
|
||||
const struct iwl_rxon_cmd active_rxon;
|
||||
struct iwl_rxon_cmd staging_rxon;
|
||||
struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX];
|
||||
|
||||
struct iwl_switch_rxon switch_rxon;
|
||||
|
||||
|
@ -1260,8 +1317,6 @@ struct iwl_priv {
|
|||
spinlock_t sta_lock;
|
||||
int num_stations;
|
||||
struct iwl_station_entry stations[IWL_STATION_COUNT];
|
||||
struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; /* protected by mutex */
|
||||
u8 key_mapping_key;
|
||||
unsigned long ucode_key_table;
|
||||
|
||||
/* queue refcounts */
|
||||
|
@ -1286,7 +1341,6 @@ struct iwl_priv {
|
|||
|
||||
/* Last Rx'd beacon timestamp */
|
||||
u64 timestamp;
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
union {
|
||||
#if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE)
|
||||
|
@ -1387,8 +1441,6 @@ struct iwl_priv {
|
|||
|
||||
u32 inta_mask;
|
||||
|
||||
struct iwl_qos_info qos_data;
|
||||
|
||||
struct workqueue_struct *workqueue;
|
||||
|
||||
struct work_struct restart;
|
||||
|
@ -1396,6 +1448,8 @@ struct iwl_priv {
|
|||
struct work_struct rx_replenish;
|
||||
struct work_struct abort_scan;
|
||||
struct work_struct beacon_update;
|
||||
struct iwl_rxon_context *beacon_ctx;
|
||||
|
||||
struct work_struct tt_work;
|
||||
struct work_struct ct_enter;
|
||||
struct work_struct ct_exit;
|
||||
|
@ -1490,10 +1544,34 @@ static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static inline int iwl_is_associated(struct iwl_priv *priv)
|
||||
static inline struct iwl_rxon_context *
|
||||
iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif)
|
||||
{
|
||||
return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
|
||||
return vif_priv->ctx;
|
||||
}
|
||||
|
||||
#define for_each_context(priv, ctx) \
|
||||
for (ctx = &priv->contexts[IWL_RXON_CTX_BSS]; \
|
||||
ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++) \
|
||||
if (priv->valid_contexts & BIT(ctx->ctxid))
|
||||
|
||||
static inline int iwl_is_associated(struct iwl_priv *priv,
|
||||
enum iwl_rxon_context_id ctxid)
|
||||
{
|
||||
return (priv->contexts[ctxid].active.filter_flags &
|
||||
RXON_FILTER_ASSOC_MSK) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline int iwl_is_any_associated(struct iwl_priv *priv)
|
||||
{
|
||||
return iwl_is_associated(priv, IWL_RXON_CTX_BSS);
|
||||
}
|
||||
|
||||
static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx)
|
||||
{
|
||||
return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline int is_channel_valid(const struct iwl_channel_info *ch_info)
|
||||
|
|
|
@ -100,6 +100,14 @@ const char *get_cmd_string(u8 cmd)
|
|||
IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF);
|
||||
IWL_CMD(REPLY_BT_COEX_PRIO_TABLE);
|
||||
IWL_CMD(REPLY_BT_COEX_PROT_ENV);
|
||||
IWL_CMD(REPLY_WIPAN_PARAMS);
|
||||
IWL_CMD(REPLY_WIPAN_RXON);
|
||||
IWL_CMD(REPLY_WIPAN_RXON_TIMING);
|
||||
IWL_CMD(REPLY_WIPAN_RXON_ASSOC);
|
||||
IWL_CMD(REPLY_WIPAN_QOS_PARAM);
|
||||
IWL_CMD(REPLY_WIPAN_WEPKEY);
|
||||
IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH);
|
||||
IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION);
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
|
||||
|
@ -232,7 +240,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
|||
* in later, it will possibly set an invalid
|
||||
* address (cmd->meta.source).
|
||||
*/
|
||||
priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_idx].flags &=
|
||||
priv->txq[priv->cmd_queue].meta[cmd_idx].flags &=
|
||||
~CMD_WANT_SKB;
|
||||
}
|
||||
fail:
|
||||
|
|
|
@ -306,7 +306,7 @@
|
|||
* at a time, until receiving ACK from receiving station, or reaching
|
||||
* retry limit and giving up.
|
||||
*
|
||||
* The command queue (#4) must use this mode!
|
||||
* The command queue (#4/#9) must use this mode!
|
||||
* This mode does not require use of the Byte Count table in host DRAM.
|
||||
*
|
||||
* Driver controls scheduler operation via 3 means:
|
||||
|
@ -322,7 +322,7 @@
|
|||
* (1024 bytes for each queue).
|
||||
*
|
||||
* After receiving "Alive" response from uCode, driver must initialize
|
||||
* the scheduler (especially for queue #4, the command queue, otherwise
|
||||
* the scheduler (especially for queue #4/#9, the command queue, otherwise
|
||||
* the driver can't issue commands!):
|
||||
*/
|
||||
|
||||
|
@ -555,8 +555,9 @@
|
|||
#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
|
||||
((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc)
|
||||
|
||||
#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(x) (((1<<(x)) - 1) &\
|
||||
(~(1<<IWL_CMD_QUEUE_NUM)))
|
||||
#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv) \
|
||||
(((1<<(priv)->hw_params.max_txq_num) - 1) &\
|
||||
(~(1<<(priv)->cmd_queue)))
|
||||
|
||||
#define IWLAGN_SCD_BASE (PRPH_BASE + 0xa02c00)
|
||||
|
||||
|
|
|
@ -228,7 +228,7 @@ void iwl_recover_from_statistics(struct iwl_priv *priv,
|
|||
{
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
if (iwl_is_associated(priv)) {
|
||||
if (iwl_is_any_associated(priv)) {
|
||||
if (priv->cfg->ops->lib->check_ack_health) {
|
||||
if (!priv->cfg->ops->lib->check_ack_health(
|
||||
priv, pkt)) {
|
||||
|
@ -266,7 +266,12 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv,
|
|||
{
|
||||
u16 fc = le16_to_cpu(hdr->frame_control);
|
||||
|
||||
if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK)
|
||||
/*
|
||||
* All contexts have the same setting here due to it being
|
||||
* a module parameter, so OK to check any context.
|
||||
*/
|
||||
if (priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags &
|
||||
RXON_FILTER_DIS_DECRYPT_MSK)
|
||||
return 0;
|
||||
|
||||
if (!(fc & IEEE80211_FCTL_PROTECTED))
|
||||
|
|
|
@ -286,18 +286,28 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
|
|||
enum ieee80211_band band,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_rxon_context *ctx;
|
||||
u16 passive = (band == IEEE80211_BAND_2GHZ) ?
|
||||
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
|
||||
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
|
||||
|
||||
if (iwl_is_associated(priv)) {
|
||||
/* If we're associated, we clamp the maximum passive
|
||||
* dwell time to be 98% of the beacon interval (minus
|
||||
* 2 * channel tune time) */
|
||||
passive = vif ? vif->bss_conf.beacon_int : 0;
|
||||
if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive)
|
||||
passive = IWL_PASSIVE_DWELL_BASE;
|
||||
passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
|
||||
if (iwl_is_any_associated(priv)) {
|
||||
/*
|
||||
* If we're associated, we clamp the maximum passive
|
||||
* dwell time to be 98% of the smallest beacon interval
|
||||
* (minus 2 * channel tune time)
|
||||
*/
|
||||
for_each_context(priv, ctx) {
|
||||
u16 value;
|
||||
|
||||
if (!iwl_is_associated_ctx(ctx))
|
||||
continue;
|
||||
value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0;
|
||||
if ((value > IWL_PASSIVE_DWELL_BASE) || !value)
|
||||
value = IWL_PASSIVE_DWELL_BASE;
|
||||
value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
|
||||
passive = min(value, passive);
|
||||
}
|
||||
}
|
||||
|
||||
return passive;
|
||||
|
@ -527,6 +537,7 @@ static void iwl_bg_scan_completed(struct work_struct *work)
|
|||
container_of(work, struct iwl_priv, scan_completed);
|
||||
bool internal = false;
|
||||
bool scan_completed = false;
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "SCAN complete scan\n");
|
||||
|
||||
|
@ -557,11 +568,13 @@ static void iwl_bg_scan_completed(struct work_struct *work)
|
|||
* Since setting the RXON may have been deferred while
|
||||
* performing the scan, fire one off if needed
|
||||
*/
|
||||
if (memcmp(&priv->active_rxon,
|
||||
&priv->staging_rxon, sizeof(priv->staging_rxon)))
|
||||
iwlcore_commit_rxon(priv);
|
||||
for_each_context(priv, ctx)
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
out:
|
||||
if (priv->cfg->ops->hcmd->set_pan_params)
|
||||
priv->cfg->ops->hcmd->set_pan_params(priv);
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
/*
|
||||
|
|
|
@ -172,12 +172,14 @@ int iwl_send_add_sta(struct iwl_priv *priv,
|
|||
EXPORT_SYMBOL(iwl_send_add_sta);
|
||||
|
||||
static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
|
||||
struct ieee80211_sta_ht_cap *sta_ht_inf)
|
||||
struct ieee80211_sta *sta,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap;
|
||||
__le32 sta_flags;
|
||||
u8 mimo_ps_mode;
|
||||
|
||||
if (!sta_ht_inf || !sta_ht_inf->ht_supported)
|
||||
if (!sta || !sta_ht_inf->ht_supported)
|
||||
goto done;
|
||||
|
||||
mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
|
||||
|
@ -211,7 +213,7 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
|
|||
sta_flags |= cpu_to_le32(
|
||||
(u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
|
||||
|
||||
if (iwl_is_ht40_tx_allowed(priv, sta_ht_inf))
|
||||
if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
|
||||
sta_flags |= STA_FLG_HT40_EN_MSK;
|
||||
else
|
||||
sta_flags &= ~STA_FLG_HT40_EN_MSK;
|
||||
|
@ -226,9 +228,9 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
|
|||
*
|
||||
* should be called with sta_lock held
|
||||
*/
|
||||
static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr,
|
||||
bool is_ap,
|
||||
struct ieee80211_sta_ht_cap *ht_info)
|
||||
static u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
const u8 *addr, bool is_ap,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_station_entry *station;
|
||||
int i;
|
||||
|
@ -236,9 +238,9 @@ static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr,
|
|||
u16 rate;
|
||||
|
||||
if (is_ap)
|
||||
sta_id = IWL_AP_ID;
|
||||
sta_id = ctx->ap_sta_id;
|
||||
else if (is_broadcast_ether_addr(addr))
|
||||
sta_id = priv->hw_params.bcast_sta_id;
|
||||
sta_id = ctx->bcast_sta_id;
|
||||
else
|
||||
for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
|
||||
if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
|
||||
|
@ -289,14 +291,22 @@ static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr,
|
|||
memcpy(station->sta.sta.addr, addr, ETH_ALEN);
|
||||
station->sta.mode = 0;
|
||||
station->sta.sta.sta_id = sta_id;
|
||||
station->sta.station_flags = 0;
|
||||
station->sta.station_flags = ctx->station_flags;
|
||||
station->ctxid = ctx->ctxid;
|
||||
|
||||
if (sta) {
|
||||
struct iwl_station_priv_common *sta_priv;
|
||||
|
||||
sta_priv = (void *)sta->drv_priv;
|
||||
sta_priv->ctx = ctx;
|
||||
}
|
||||
|
||||
/*
|
||||
* OK to call unconditionally, since local stations (IBSS BSSID
|
||||
* STA and broadcast STA) pass in a NULL ht_info, and mac80211
|
||||
* STA and broadcast STA) pass in a NULL sta, and mac80211
|
||||
* doesn't allow HT IBSS.
|
||||
*/
|
||||
iwl_set_ht_add_station(priv, sta_id, ht_info);
|
||||
iwl_set_ht_add_station(priv, sta_id, sta, ctx);
|
||||
|
||||
/* 3945 only */
|
||||
rate = (priv->band == IEEE80211_BAND_5GHZ) ?
|
||||
|
@ -313,10 +323,9 @@ static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr,
|
|||
/**
|
||||
* iwl_add_station_common -
|
||||
*/
|
||||
int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
|
||||
bool is_ap,
|
||||
struct ieee80211_sta_ht_cap *ht_info,
|
||||
u8 *sta_id_r)
|
||||
int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
const u8 *addr, bool is_ap,
|
||||
struct ieee80211_sta *sta, u8 *sta_id_r)
|
||||
{
|
||||
unsigned long flags_spin;
|
||||
int ret = 0;
|
||||
|
@ -325,7 +334,7 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
|
|||
|
||||
*sta_id_r = 0;
|
||||
spin_lock_irqsave(&priv->sta_lock, flags_spin);
|
||||
sta_id = iwl_prep_station(priv, addr, is_ap, ht_info);
|
||||
sta_id = iwl_prep_station(priv, ctx, addr, is_ap, sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_ERR(priv, "Unable to prepare station %pM for addition\n",
|
||||
addr);
|
||||
|
@ -431,8 +440,8 @@ static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv,
|
|||
*
|
||||
* Function sleeps.
|
||||
*/
|
||||
int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs,
|
||||
u8 *sta_id_r)
|
||||
int iwl_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
const u8 *addr, bool init_rs, u8 *sta_id_r)
|
||||
{
|
||||
int ret;
|
||||
u8 sta_id;
|
||||
|
@ -442,7 +451,7 @@ int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs,
|
|||
if (sta_id_r)
|
||||
*sta_id_r = IWL_INVALID_STATION;
|
||||
|
||||
ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id);
|
||||
ret = iwl_add_station_common(priv, ctx, addr, 0, NULL, &sta_id);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Unable to add station %pM\n", addr);
|
||||
return ret;
|
||||
|
@ -464,7 +473,7 @@ int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = iwl_send_lq_cmd(priv, link_cmd, CMD_SYNC, true);
|
||||
ret = iwl_send_lq_cmd(priv, ctx, link_cmd, CMD_SYNC, true);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
|
||||
|
||||
|
@ -616,7 +625,8 @@ EXPORT_SYMBOL_GPL(iwl_remove_station);
|
|||
* other than explicit station management would cause this in
|
||||
* the ucode, e.g. unassociated RXON.
|
||||
*/
|
||||
void iwl_clear_ucode_stations(struct iwl_priv *priv)
|
||||
void iwl_clear_ucode_stations(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags_spin;
|
||||
|
@ -626,6 +636,9 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv)
|
|||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags_spin);
|
||||
for (i = 0; i < priv->hw_params.max_stations; i++) {
|
||||
if (ctx && ctx->ctxid != priv->stations[i].ctxid)
|
||||
continue;
|
||||
|
||||
if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) {
|
||||
IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i);
|
||||
priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
|
||||
|
@ -647,7 +660,7 @@ EXPORT_SYMBOL(iwl_clear_ucode_stations);
|
|||
*
|
||||
* Function sleeps.
|
||||
*/
|
||||
void iwl_restore_stations(struct iwl_priv *priv)
|
||||
void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
{
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
struct iwl_link_quality_cmd lq;
|
||||
|
@ -665,6 +678,8 @@ void iwl_restore_stations(struct iwl_priv *priv)
|
|||
IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n");
|
||||
spin_lock_irqsave(&priv->sta_lock, flags_spin);
|
||||
for (i = 0; i < priv->hw_params.max_stations; i++) {
|
||||
if (ctx->ctxid != priv->stations[i].ctxid)
|
||||
continue;
|
||||
if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) &&
|
||||
!(priv->stations[i].used & IWL_STA_UCODE_ACTIVE)) {
|
||||
IWL_DEBUG_ASSOC(priv, "Restoring sta %pM\n",
|
||||
|
@ -700,7 +715,7 @@ void iwl_restore_stations(struct iwl_priv *priv)
|
|||
* current LQ command
|
||||
*/
|
||||
if (send_lq)
|
||||
iwl_send_lq_cmd(priv, &lq, CMD_SYNC, true);
|
||||
iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
|
||||
spin_lock_irqsave(&priv->sta_lock, flags_spin);
|
||||
priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
|
||||
}
|
||||
|
@ -718,7 +733,7 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < STA_KEY_MAX_NUM; i++)
|
||||
for (i = 0; i < priv->sta_key_max_num; i++)
|
||||
if (!test_and_set_bit(i, &priv->ucode_key_table))
|
||||
return i;
|
||||
|
||||
|
@ -726,7 +741,9 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_get_free_ucode_key_index);
|
||||
|
||||
static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
|
||||
static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
bool send_if_empty)
|
||||
{
|
||||
int i, not_empty = 0;
|
||||
u8 buff[sizeof(struct iwl_wep_cmd) +
|
||||
|
@ -734,7 +751,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
|
|||
struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff;
|
||||
size_t cmd_size = sizeof(struct iwl_wep_cmd);
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_WEPKEY,
|
||||
.id = ctx->wep_key_cmd,
|
||||
.data = wep_cmd,
|
||||
.flags = CMD_SYNC,
|
||||
};
|
||||
|
@ -746,16 +763,16 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
|
|||
|
||||
for (i = 0; i < WEP_KEYS_MAX ; i++) {
|
||||
wep_cmd->key[i].key_index = i;
|
||||
if (priv->wep_keys[i].key_size) {
|
||||
if (ctx->wep_keys[i].key_size) {
|
||||
wep_cmd->key[i].key_offset = i;
|
||||
not_empty = 1;
|
||||
} else {
|
||||
wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
|
||||
}
|
||||
|
||||
wep_cmd->key[i].key_size = priv->wep_keys[i].key_size;
|
||||
memcpy(&wep_cmd->key[i].key[3], priv->wep_keys[i].key,
|
||||
priv->wep_keys[i].key_size);
|
||||
wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size;
|
||||
memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key,
|
||||
ctx->wep_keys[i].key_size);
|
||||
}
|
||||
|
||||
wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
|
||||
|
@ -771,15 +788,17 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int iwl_restore_default_wep_keys(struct iwl_priv *priv)
|
||||
int iwl_restore_default_wep_keys(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
return iwl_send_static_wepkey_cmd(priv, 0);
|
||||
return iwl_send_static_wepkey_cmd(priv, ctx, false);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_restore_default_wep_keys);
|
||||
|
||||
int iwl_remove_default_wep_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf)
|
||||
{
|
||||
int ret;
|
||||
|
@ -789,13 +808,13 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
|
|||
IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
|
||||
keyconf->keyidx);
|
||||
|
||||
memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0]));
|
||||
memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
|
||||
if (iwl_is_rfkill(priv)) {
|
||||
IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n");
|
||||
/* but keys in device are clear anyway so return success */
|
||||
return 0;
|
||||
}
|
||||
ret = iwl_send_static_wepkey_cmd(priv, 1);
|
||||
ret = iwl_send_static_wepkey_cmd(priv, ctx, 1);
|
||||
IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
|
||||
keyconf->keyidx, ret);
|
||||
|
||||
|
@ -804,6 +823,7 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
|
|||
EXPORT_SYMBOL(iwl_remove_default_wep_key);
|
||||
|
||||
int iwl_set_default_wep_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf)
|
||||
{
|
||||
int ret;
|
||||
|
@ -818,13 +838,13 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
|
|||
|
||||
keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
keyconf->hw_key_idx = HW_KEY_DEFAULT;
|
||||
priv->stations[IWL_AP_ID].keyinfo.cipher = keyconf->cipher;
|
||||
priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher;
|
||||
|
||||
priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
|
||||
memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key,
|
||||
ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
|
||||
memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key,
|
||||
keyconf->keylen);
|
||||
|
||||
ret = iwl_send_static_wepkey_cmd(priv, 0);
|
||||
ret = iwl_send_static_wepkey_cmd(priv, ctx, false);
|
||||
IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n",
|
||||
keyconf->keylen, keyconf->keyidx, ret);
|
||||
|
||||
|
@ -833,8 +853,9 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
|
|||
EXPORT_SYMBOL(iwl_set_default_wep_key);
|
||||
|
||||
static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
__le16 key_flags = 0;
|
||||
|
@ -851,7 +872,7 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
|
|||
if (keyconf->keylen == WEP_KEY_LEN_128)
|
||||
key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
|
||||
|
||||
if (sta_id == priv->hw_params.bcast_sta_id)
|
||||
if (sta_id == ctx->bcast_sta_id)
|
||||
key_flags |= STA_KEY_MULTICAST_MSK;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
|
@ -887,8 +908,9 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
|
|||
}
|
||||
|
||||
static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
__le16 key_flags = 0;
|
||||
|
@ -900,7 +922,7 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
|
|||
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
|
||||
key_flags &= ~STA_KEY_FLG_INVALID;
|
||||
|
||||
if (sta_id == priv->hw_params.bcast_sta_id)
|
||||
if (sta_id == ctx->bcast_sta_id)
|
||||
key_flags |= STA_KEY_MULTICAST_MSK;
|
||||
|
||||
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
|
@ -936,8 +958,9 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
|
|||
}
|
||||
|
||||
static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
@ -947,7 +970,7 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
|
|||
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
|
||||
key_flags &= ~STA_KEY_FLG_INVALID;
|
||||
|
||||
if (sta_id == priv->hw_params.bcast_sta_id)
|
||||
if (sta_id == ctx->bcast_sta_id)
|
||||
key_flags |= STA_KEY_MULTICAST_MSK;
|
||||
|
||||
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
|
@ -982,8 +1005,9 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
|
|||
}
|
||||
|
||||
void iwl_update_tkip_key(struct iwl_priv *priv,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
|
||||
{
|
||||
u8 sta_id;
|
||||
unsigned long flags;
|
||||
|
@ -995,7 +1019,7 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
|
|||
return;
|
||||
}
|
||||
|
||||
sta_id = iwl_sta_id_or_broadcast(priv, sta);
|
||||
sta_id = iwl_sta_id_or_broadcast(priv, ctx, sta);
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return;
|
||||
|
||||
|
@ -1018,8 +1042,9 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
|
|||
EXPORT_SYMBOL(iwl_update_tkip_key);
|
||||
|
||||
int iwl_remove_dynamic_key(struct iwl_priv *priv,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
u8 sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
u16 key_flags;
|
||||
|
@ -1028,7 +1053,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
|
|||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
priv->key_mapping_key--;
|
||||
ctx->key_mapping_keys--;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
|
||||
|
@ -1080,26 +1105,26 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_remove_dynamic_key);
|
||||
|
||||
int iwl_set_dynamic_key(struct iwl_priv *priv,
|
||||
struct ieee80211_key_conf *keyconf, u8 sta_id)
|
||||
int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf, u8 sta_id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
priv->key_mapping_key++;
|
||||
ctx->key_mapping_keys++;
|
||||
keyconf->hw_key_idx = HW_KEY_DYNAMIC;
|
||||
|
||||
switch (keyconf->cipher) {
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
ret = iwl_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
|
||||
ret = iwl_set_ccmp_dynamic_key_info(priv, ctx, keyconf, sta_id);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
ret = iwl_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
|
||||
ret = iwl_set_tkip_dynamic_key_info(priv, ctx, keyconf, sta_id);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id);
|
||||
ret = iwl_set_wep_dynamic_key_info(priv, ctx, keyconf, sta_id);
|
||||
break;
|
||||
default:
|
||||
IWL_ERR(priv,
|
||||
|
@ -1149,16 +1174,16 @@ static inline void iwl_dump_lq_cmd(struct iwl_priv *priv,
|
|||
* RXON flags are updated and when LQ command is updated.
|
||||
*/
|
||||
static bool is_lq_table_valid(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct iwl_link_quality_cmd *lq)
|
||||
{
|
||||
int i;
|
||||
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
|
||||
|
||||
if (ht_conf->is_ht)
|
||||
if (ctx->ht.enabled)
|
||||
return true;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n",
|
||||
priv->active_rxon.channel);
|
||||
ctx->active.channel);
|
||||
for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
|
||||
if (le32_to_cpu(lq->rs_table[i].rate_n_flags) & RATE_MCS_HT_MSK) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
|
@ -1180,7 +1205,7 @@ static bool is_lq_table_valid(struct iwl_priv *priv,
|
|||
* this case to clear the state indicating that station creation is in
|
||||
* progress.
|
||||
*/
|
||||
int iwl_send_lq_cmd(struct iwl_priv *priv,
|
||||
int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct iwl_link_quality_cmd *lq, u8 flags, bool init)
|
||||
{
|
||||
int ret = 0;
|
||||
|
@ -1199,7 +1224,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
|
|||
iwl_dump_lq_cmd(priv, lq);
|
||||
BUG_ON(init && (cmd.flags & CMD_ASYNC));
|
||||
|
||||
if (is_lq_table_valid(priv, lq))
|
||||
if (is_lq_table_valid(priv, ctx, lq))
|
||||
ret = iwl_send_cmd(priv, &cmd);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
@ -1225,14 +1250,15 @@ EXPORT_SYMBOL(iwl_send_lq_cmd);
|
|||
* and marks it driver active, so that it will be restored to the
|
||||
* device at the next best time.
|
||||
*/
|
||||
int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq)
|
||||
int iwl_alloc_bcast_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
bool init_lq)
|
||||
{
|
||||
struct iwl_link_quality_cmd *link_cmd;
|
||||
unsigned long flags;
|
||||
u8 sta_id;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
sta_id = iwl_prep_station(priv, iwl_bcast_addr, false, NULL);
|
||||
sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_ERR(priv, "Unable to prepare broadcast station\n");
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
@ -1267,11 +1293,12 @@ EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station);
|
|||
* Only used by iwlagn. Placed here to have all bcast station management
|
||||
* code together.
|
||||
*/
|
||||
int iwl_update_bcast_station(struct iwl_priv *priv)
|
||||
static int iwl_update_bcast_station(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iwl_link_quality_cmd *link_cmd;
|
||||
u8 sta_id = priv->hw_params.bcast_sta_id;
|
||||
u8 sta_id = ctx->bcast_sta_id;
|
||||
|
||||
link_cmd = iwl_sta_alloc_lq(priv, sta_id);
|
||||
if (!link_cmd) {
|
||||
|
@ -1289,9 +1316,23 @@ int iwl_update_bcast_station(struct iwl_priv *priv)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_update_bcast_station);
|
||||
|
||||
void iwl_dealloc_bcast_station(struct iwl_priv *priv)
|
||||
int iwl_update_bcast_stations(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx;
|
||||
int ret = 0;
|
||||
|
||||
for_each_context(priv, ctx) {
|
||||
ret = iwl_update_bcast_station(priv, ctx);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_update_bcast_stations);
|
||||
|
||||
void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
@ -1309,7 +1350,7 @@ void iwl_dealloc_bcast_station(struct iwl_priv *priv)
|
|||
}
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station);
|
||||
EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_stations);
|
||||
|
||||
/**
|
||||
* iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
|
||||
|
|
|
@ -44,32 +44,37 @@
|
|||
|
||||
|
||||
int iwl_remove_default_wep_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *key);
|
||||
int iwl_set_default_wep_key(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *key);
|
||||
int iwl_restore_default_wep_keys(struct iwl_priv *priv);
|
||||
int iwl_set_dynamic_key(struct iwl_priv *priv,
|
||||
int iwl_restore_default_wep_keys(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx);
|
||||
int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *key, u8 sta_id);
|
||||
int iwl_remove_dynamic_key(struct iwl_priv *priv,
|
||||
int iwl_remove_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *key, u8 sta_id);
|
||||
void iwl_update_tkip_key(struct iwl_priv *priv,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
struct ieee80211_sta *sta, u32 iv32, u16 *phase1key);
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
struct ieee80211_sta *sta, u32 iv32, u16 *phase1key);
|
||||
|
||||
void iwl_restore_stations(struct iwl_priv *priv);
|
||||
void iwl_clear_ucode_stations(struct iwl_priv *priv);
|
||||
int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq);
|
||||
void iwl_dealloc_bcast_station(struct iwl_priv *priv);
|
||||
int iwl_update_bcast_station(struct iwl_priv *priv);
|
||||
void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
void iwl_clear_ucode_stations(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx);
|
||||
int iwl_alloc_bcast_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
bool init_lq);
|
||||
void iwl_dealloc_bcast_stations(struct iwl_priv *priv);
|
||||
int iwl_update_bcast_stations(struct iwl_priv *priv);
|
||||
int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
|
||||
int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
struct iwl_addsta_cmd *sta, u8 flags);
|
||||
int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs,
|
||||
u8 *sta_id_r);
|
||||
int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
|
||||
bool is_ap,
|
||||
struct ieee80211_sta_ht_cap *ht_info,
|
||||
u8 *sta_id_r);
|
||||
int iwl_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
const u8 *addr, bool init_rs, u8 *sta_id_r);
|
||||
int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
const u8 *addr, bool is_ap,
|
||||
struct ieee80211_sta *sta, u8 *sta_id_r);
|
||||
int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
|
||||
const u8 *addr);
|
||||
int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
@ -94,20 +99,25 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
|
|||
static inline void iwl_clear_driver_stations(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
memset(priv->stations, 0, sizeof(priv->stations));
|
||||
priv->num_stations = 0;
|
||||
|
||||
/*
|
||||
* Remove all key information that is not stored as part of station
|
||||
* information since mac80211 may not have had a
|
||||
* chance to remove all the keys. When device is reconfigured by
|
||||
* mac80211 after an error all keys will be reconfigured.
|
||||
*/
|
||||
priv->ucode_key_table = 0;
|
||||
priv->key_mapping_key = 0;
|
||||
memset(priv->wep_keys, 0, sizeof(priv->wep_keys));
|
||||
|
||||
for_each_context(priv, ctx) {
|
||||
/*
|
||||
* Remove all key information that is not stored as part
|
||||
* of station information since mac80211 may not have had
|
||||
* a chance to remove all the keys. When device is
|
||||
* reconfigured by mac80211 after an error all keys will
|
||||
* be reconfigured.
|
||||
*/
|
||||
memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
|
||||
ctx->key_mapping_keys = 0;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
}
|
||||
|
@ -123,6 +133,7 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta)
|
|||
/**
|
||||
* iwl_sta_id_or_broadcast - return sta_id or broadcast sta
|
||||
* @priv: iwl priv
|
||||
* @context: the current context
|
||||
* @sta: mac80211 station
|
||||
*
|
||||
* In certain circumstances mac80211 passes a station pointer
|
||||
|
@ -131,12 +142,13 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta)
|
|||
* inline wraps that pattern.
|
||||
*/
|
||||
static inline int iwl_sta_id_or_broadcast(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *context,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
int sta_id;
|
||||
|
||||
if (!sta)
|
||||
return priv->hw_params.bcast_sta_id;
|
||||
return context->bcast_sta_id;
|
||||
|
||||
sta_id = iwl_sta_id(sta);
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ EXPORT_SYMBOL(iwl_tx_queue_free);
|
|||
*/
|
||||
void iwl_cmd_queue_free(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
|
||||
struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
|
||||
struct iwl_queue *q = &txq->q;
|
||||
struct device *dev = &priv->pci_dev->dev;
|
||||
int i;
|
||||
|
@ -271,7 +271,7 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,
|
|||
|
||||
/* Driver private data, only for Tx (not command) queues,
|
||||
* not shared with device. */
|
||||
if (id != IWL_CMD_QUEUE_NUM) {
|
||||
if (id != priv->cmd_queue) {
|
||||
txq->txb = kzalloc(sizeof(txq->txb[0]) *
|
||||
TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
|
||||
if (!txq->txb) {
|
||||
|
@ -314,13 +314,13 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
|
|||
|
||||
/*
|
||||
* Alloc buffer array for commands (Tx or other types of commands).
|
||||
* For the command queue (#4), allocate command space + one big
|
||||
* For the command queue (#4/#9), allocate command space + one big
|
||||
* command for scan, since scan command is very huge; the system will
|
||||
* not have two scans at the same time, so only one is needed.
|
||||
* For normal Tx queues (all other queues), no super-size command
|
||||
* space is needed.
|
||||
*/
|
||||
if (txq_id == IWL_CMD_QUEUE_NUM)
|
||||
if (txq_id == priv->cmd_queue)
|
||||
actual_slots++;
|
||||
|
||||
txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots,
|
||||
|
@ -355,7 +355,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
|
|||
* need an swq_id so don't set one to catch errors, all others can
|
||||
* be set up to the identity mapping.
|
||||
*/
|
||||
if (txq_id != IWL_CMD_QUEUE_NUM)
|
||||
if (txq_id != priv->cmd_queue)
|
||||
txq->swq_id = txq_id;
|
||||
|
||||
/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
|
||||
|
@ -385,7 +385,7 @@ void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
|
|||
{
|
||||
int actual_slots = slots_num;
|
||||
|
||||
if (txq_id == IWL_CMD_QUEUE_NUM)
|
||||
if (txq_id == priv->cmd_queue)
|
||||
actual_slots++;
|
||||
|
||||
memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots);
|
||||
|
@ -413,7 +413,7 @@ EXPORT_SYMBOL(iwl_tx_queue_reset);
|
|||
*/
|
||||
int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
||||
{
|
||||
struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
|
||||
struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
|
||||
struct iwl_queue *q = &txq->q;
|
||||
struct iwl_device_cmd *out_cmd;
|
||||
struct iwl_cmd_meta *out_meta;
|
||||
|
@ -483,7 +483,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
|||
* information */
|
||||
|
||||
out_cmd->hdr.flags = 0;
|
||||
out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) |
|
||||
out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) |
|
||||
INDEX_TO_SEQ(q->write_ptr));
|
||||
if (cmd->flags & CMD_SIZE_HUGE)
|
||||
out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
|
||||
|
@ -500,15 +500,15 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
|||
get_cmd_string(out_cmd->hdr.cmd),
|
||||
out_cmd->hdr.cmd,
|
||||
le16_to_cpu(out_cmd->hdr.sequence), fix_size,
|
||||
q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
|
||||
break;
|
||||
q->write_ptr, idx, priv->cmd_queue);
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, "
|
||||
"%d bytes at %d[%d]:%d\n",
|
||||
get_cmd_string(out_cmd->hdr.cmd),
|
||||
out_cmd->hdr.cmd,
|
||||
le16_to_cpu(out_cmd->hdr.sequence), fix_size,
|
||||
q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
|
||||
q->write_ptr, idx, priv->cmd_queue);
|
||||
}
|
||||
#endif
|
||||
txq->need_update = 1;
|
||||
|
@ -587,16 +587,16 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
|||
bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
|
||||
struct iwl_device_cmd *cmd;
|
||||
struct iwl_cmd_meta *meta;
|
||||
struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
|
||||
struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
|
||||
|
||||
/* If a Tx command is being handled and it isn't in the actual
|
||||
* command queue then there a command routing bug has been introduced
|
||||
* in the queue management code. */
|
||||
if (WARN(txq_id != IWL_CMD_QUEUE_NUM,
|
||||
"wrong command queue %d, sequence 0x%X readp=%d writep=%d\n",
|
||||
txq_id, sequence,
|
||||
priv->txq[IWL_CMD_QUEUE_NUM].q.read_ptr,
|
||||
priv->txq[IWL_CMD_QUEUE_NUM].q.write_ptr)) {
|
||||
if (WARN(txq_id != priv->cmd_queue,
|
||||
"wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
|
||||
txq_id, priv->cmd_queue, sequence,
|
||||
priv->txq[priv->cmd_queue].q.read_ptr,
|
||||
priv->txq[priv->cmd_queue].q.write_ptr)) {
|
||||
iwl_print_hex_error(priv, pkt, 32);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
|
|||
key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
|
||||
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
|
||||
|
||||
if (sta_id == priv->hw_params.bcast_sta_id)
|
||||
if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
|
||||
key_flags |= STA_KEY_MULTICAST_MSK;
|
||||
|
||||
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
|
@ -317,7 +317,7 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
|
|||
int left)
|
||||
{
|
||||
|
||||
if (!iwl_is_associated(priv) || !priv->ibss_beacon)
|
||||
if (!iwl_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->ibss_beacon)
|
||||
return 0;
|
||||
|
||||
if (priv->ibss_beacon->len > left)
|
||||
|
@ -343,7 +343,8 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rate = iwl_rate_get_lowest_plcp(priv);
|
||||
rate = iwl_rate_get_lowest_plcp(priv,
|
||||
&priv->contexts[IWL_RXON_CTX_BSS]);
|
||||
|
||||
frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
|
||||
|
||||
|
@ -512,7 +513,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
hdr_len = ieee80211_hdrlen(fc);
|
||||
|
||||
/* Find index into station table for destination station */
|
||||
sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta);
|
||||
sta_id = iwl_sta_id_or_broadcast(
|
||||
priv, &priv->contexts[IWL_RXON_CTX_BSS],
|
||||
info->control.sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
|
||||
hdr->addr1);
|
||||
|
@ -542,6 +545,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
/* Set up driver data for this TFD */
|
||||
memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
|
||||
txq->txb[q->write_ptr].skb = skb;
|
||||
txq->txb[q->write_ptr].ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
/* Init first empty entry in queue's array of Tx/cmd buffers */
|
||||
out_cmd = txq->cmd[idx];
|
||||
|
@ -683,11 +687,12 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
|
|||
int rc;
|
||||
int spectrum_resp_status;
|
||||
int duration = le16_to_cpu(params->duration);
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
if (iwl_is_associated(priv))
|
||||
if (iwl_is_associated(priv, IWL_RXON_CTX_BSS))
|
||||
add_time = iwl_usecs_to_beacons(priv,
|
||||
le64_to_cpu(params->start_time) - priv->_3945.last_tsf,
|
||||
le16_to_cpu(priv->rxon_timing.beacon_interval));
|
||||
le16_to_cpu(ctx->timing.beacon_interval));
|
||||
|
||||
memset(&spectrum, 0, sizeof(spectrum));
|
||||
|
||||
|
@ -698,18 +703,18 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
|
|||
cmd.len = sizeof(spectrum);
|
||||
spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
|
||||
|
||||
if (iwl_is_associated(priv))
|
||||
if (iwl_is_associated(priv, IWL_RXON_CTX_BSS))
|
||||
spectrum.start_time =
|
||||
iwl_add_beacon_time(priv,
|
||||
priv->_3945.last_beacon_time, add_time,
|
||||
le16_to_cpu(priv->rxon_timing.beacon_interval));
|
||||
le16_to_cpu(ctx->timing.beacon_interval));
|
||||
else
|
||||
spectrum.start_time = 0;
|
||||
|
||||
spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
|
||||
spectrum.channels[0].channel = params->channel;
|
||||
spectrum.channels[0].type = type;
|
||||
if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)
|
||||
if (ctx->active.flags & RXON_FLG_BAND_24G_MSK)
|
||||
spectrum.flags |= RXON_FLG_BAND_24G_MSK |
|
||||
RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
|
||||
|
||||
|
@ -798,7 +803,8 @@ static void iwl3945_bg_beacon_update(struct work_struct *work)
|
|||
struct sk_buff *beacon;
|
||||
|
||||
/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
|
||||
beacon = ieee80211_beacon_get(priv->hw, priv->vif);
|
||||
beacon = ieee80211_beacon_get(priv->hw,
|
||||
priv->contexts[IWL_RXON_CTX_BSS].vif);
|
||||
|
||||
if (!beacon) {
|
||||
IWL_ERR(priv, "update beacon failed\n");
|
||||
|
@ -2468,6 +2474,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
|
|||
{
|
||||
int thermal_spin = 0;
|
||||
u32 rfkill;
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
|
||||
|
||||
|
@ -2525,22 +2532,22 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
|
|||
|
||||
iwl_power_update_mode(priv, true);
|
||||
|
||||
if (iwl_is_associated(priv)) {
|
||||
if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
|
||||
struct iwl3945_rxon_cmd *active_rxon =
|
||||
(struct iwl3945_rxon_cmd *)(&priv->active_rxon);
|
||||
(struct iwl3945_rxon_cmd *)(&ctx->active);
|
||||
|
||||
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
} else {
|
||||
/* Initialize our rx_config data */
|
||||
iwl_connection_init_rx_config(priv, NULL);
|
||||
iwl_connection_init_rx_config(priv, ctx);
|
||||
}
|
||||
|
||||
/* Configure Bluetooth device coexistence support */
|
||||
priv->cfg->ops->hcmd->send_bt_config(priv);
|
||||
|
||||
/* Configure the adapter for unassociated operation */
|
||||
iwlcore_commit_rxon(priv);
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
iwl3945_reg_txpower_periodic(priv);
|
||||
|
||||
|
@ -2577,8 +2584,8 @@ static void __iwl3945_down(struct iwl_priv *priv)
|
|||
del_timer_sync(&priv->monitor_recover);
|
||||
|
||||
/* Station information will now be cleared in device */
|
||||
iwl_clear_ucode_stations(priv);
|
||||
iwl_dealloc_bcast_station(priv);
|
||||
iwl_clear_ucode_stations(priv, NULL);
|
||||
iwl_dealloc_bcast_stations(priv);
|
||||
iwl_clear_driver_stations(priv);
|
||||
|
||||
/* Unblock any waiting calls */
|
||||
|
@ -2660,7 +2667,8 @@ static int __iwl3945_up(struct iwl_priv *priv)
|
|||
{
|
||||
int rc, i;
|
||||
|
||||
rc = iwl_alloc_bcast_station(priv, false);
|
||||
rc = iwl_alloc_bcast_station(priv, &priv->contexts[IWL_RXON_CTX_BSS],
|
||||
false);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -2883,7 +2891,7 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
|
||||
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
|
||||
|
||||
if (iwl_is_associated(priv)) {
|
||||
if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
|
||||
u16 interval = 0;
|
||||
u32 extra;
|
||||
u32 suspend_time = 100;
|
||||
|
@ -2944,7 +2952,7 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
/* We don't build a direct scan probe request; the uCode will do
|
||||
* that based on the direct_mask added to each channel entry */
|
||||
scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
|
||||
scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
|
||||
scan->tx_cmd.sta_id = priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
|
||||
scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
|
||||
|
||||
/* flags + rate selection */
|
||||
|
@ -3042,8 +3050,10 @@ static void iwl3945_bg_restart(struct work_struct *data)
|
|||
return;
|
||||
|
||||
if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
|
||||
struct iwl_rxon_context *ctx;
|
||||
mutex_lock(&priv->mutex);
|
||||
priv->vif = NULL;
|
||||
for_each_context(priv, ctx)
|
||||
ctx->vif = NULL;
|
||||
priv->is_open = 0;
|
||||
mutex_unlock(&priv->mutex);
|
||||
iwl3945_down(priv);
|
||||
|
@ -3077,6 +3087,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
{
|
||||
int rc = 0;
|
||||
struct ieee80211_conf *conf = NULL;
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
if (!vif || !priv->is_open)
|
||||
return;
|
||||
|
@ -3087,7 +3098,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
}
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
|
||||
vif->bss_conf.aid, priv->active_rxon.bssid_addr);
|
||||
vif->bss_conf.aid, ctx->active.bssid_addr);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
@ -3096,34 +3107,34 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
|
||||
conf = ieee80211_get_hw_conf(priv->hw);
|
||||
|
||||
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv);
|
||||
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
rc = iwl_send_rxon_timing(priv, vif);
|
||||
rc = iwl_send_rxon_timing(priv, ctx);
|
||||
if (rc)
|
||||
IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
|
||||
"Attempting to continue.\n");
|
||||
|
||||
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
|
||||
priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid);
|
||||
ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
|
||||
vif->bss_conf.aid, vif->bss_conf.beacon_int);
|
||||
|
||||
if (vif->bss_conf.use_short_preamble)
|
||||
priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (vif->bss_conf.use_short_slot)
|
||||
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
||||
ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
}
|
||||
|
||||
iwlcore_commit_rxon(priv);
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
|
@ -3260,44 +3271,45 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
|
||||
void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
int rc = 0;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
/* The following should be done only at AP bring up */
|
||||
if (!(iwl_is_associated(priv))) {
|
||||
if (!(iwl_is_associated(priv, IWL_RXON_CTX_BSS))) {
|
||||
|
||||
/* RXON - unassoc (to set timing command) */
|
||||
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv);
|
||||
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
/* RXON Timing */
|
||||
rc = iwl_send_rxon_timing(priv, vif);
|
||||
rc = iwl_send_rxon_timing(priv, ctx);
|
||||
if (rc)
|
||||
IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
|
||||
"Attempting to continue.\n");
|
||||
|
||||
priv->staging_rxon.assoc_id = 0;
|
||||
ctx->staging.assoc_id = 0;
|
||||
|
||||
if (vif->bss_conf.use_short_preamble)
|
||||
priv->staging_rxon.flags |=
|
||||
ctx->staging.flags |=
|
||||
RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &=
|
||||
ctx->staging.flags &=
|
||||
~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (vif->bss_conf.use_short_slot)
|
||||
priv->staging_rxon.flags |=
|
||||
ctx->staging.flags |=
|
||||
RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &=
|
||||
ctx->staging.flags &=
|
||||
~RXON_FLG_SHORT_SLOT_MSK;
|
||||
}
|
||||
/* restore RXON assoc */
|
||||
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv);
|
||||
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
}
|
||||
iwl3945_send_beacon_cmd(priv);
|
||||
|
||||
|
@ -3323,10 +3335,11 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static_key = !iwl_is_associated(priv);
|
||||
static_key = !iwl_is_associated(priv, IWL_RXON_CTX_BSS);
|
||||
|
||||
if (!static_key) {
|
||||
sta_id = iwl_sta_id_or_broadcast(priv, sta);
|
||||
sta_id = iwl_sta_id_or_broadcast(
|
||||
priv, &priv->contexts[IWL_RXON_CTX_BSS], sta);
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -3377,8 +3390,8 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
|
|||
sta_priv->common.sta_id = IWL_INVALID_STATION;
|
||||
|
||||
|
||||
ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap,
|
||||
&sta_id);
|
||||
ret = iwl_add_station_common(priv, &priv->contexts[IWL_RXON_CTX_BSS],
|
||||
sta->addr, is_ap, sta, &sta_id);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Unable to add station %pM (%d)\n",
|
||||
sta->addr, ret);
|
||||
|
@ -3405,6 +3418,7 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
__le32 filter_or = 0, filter_nand = 0;
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
#define CHK(test, flag) do { \
|
||||
if (*total_flags & (test)) \
|
||||
|
@ -3424,8 +3438,8 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
priv->staging_rxon.filter_flags &= ~filter_nand;
|
||||
priv->staging_rxon.filter_flags |= filter_or;
|
||||
ctx->staging.filter_flags &= ~filter_nand;
|
||||
ctx->staging.filter_flags |= filter_or;
|
||||
|
||||
/*
|
||||
* Committing directly here breaks for some reason,
|
||||
|
@ -3539,8 +3553,9 @@ static ssize_t show_flags(struct device *d,
|
|||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
|
||||
return sprintf(buf, "0x%04X\n", ctx->active.flags);
|
||||
}
|
||||
|
||||
static ssize_t store_flags(struct device *d,
|
||||
|
@ -3549,17 +3564,18 @@ static ssize_t store_flags(struct device *d,
|
|||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
u32 flags = simple_strtoul(buf, NULL, 0);
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
if (le32_to_cpu(priv->staging_rxon.flags) != flags) {
|
||||
if (le32_to_cpu(ctx->staging.flags) != flags) {
|
||||
/* Cancel any currently running scans... */
|
||||
if (iwl_scan_cancel_timeout(priv, 100))
|
||||
IWL_WARN(priv, "Could not cancel scan.\n");
|
||||
else {
|
||||
IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n",
|
||||
flags);
|
||||
priv->staging_rxon.flags = cpu_to_le32(flags);
|
||||
iwlcore_commit_rxon(priv);
|
||||
ctx->staging.flags = cpu_to_le32(flags);
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
@ -3573,9 +3589,10 @@ static ssize_t show_filter_flags(struct device *d,
|
|||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
return sprintf(buf, "0x%04X\n",
|
||||
le32_to_cpu(priv->active_rxon.filter_flags));
|
||||
le32_to_cpu(ctx->active.filter_flags));
|
||||
}
|
||||
|
||||
static ssize_t store_filter_flags(struct device *d,
|
||||
|
@ -3583,19 +3600,20 @@ static ssize_t store_filter_flags(struct device *d,
|
|||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
u32 filter_flags = simple_strtoul(buf, NULL, 0);
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) {
|
||||
if (le32_to_cpu(ctx->staging.filter_flags) != filter_flags) {
|
||||
/* Cancel any currently running scans... */
|
||||
if (iwl_scan_cancel_timeout(priv, 100))
|
||||
IWL_WARN(priv, "Could not cancel scan.\n");
|
||||
else {
|
||||
IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = "
|
||||
"0x%04X\n", filter_flags);
|
||||
priv->staging_rxon.filter_flags =
|
||||
ctx->staging.filter_flags =
|
||||
cpu_to_le32(filter_flags);
|
||||
iwlcore_commit_rxon(priv);
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
@ -3643,8 +3661,9 @@ static ssize_t store_measurement(struct device *d,
|
|||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
struct ieee80211_measurement_params params = {
|
||||
.channel = le16_to_cpu(priv->active_rxon.channel),
|
||||
.channel = le16_to_cpu(ctx->active.channel),
|
||||
.start_time = cpu_to_le64(priv->_3945.last_tsf),
|
||||
.duration = cpu_to_le16(1),
|
||||
};
|
||||
|
@ -3936,8 +3955,7 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
|
|||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
|
||||
|
||||
hw->wiphy->interface_modes =
|
||||
BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
priv->contexts[IWL_RXON_CTX_BSS].interface_modes;
|
||||
|
||||
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
|
||||
WIPHY_FLAG_DISABLE_BEACON_HINTS;
|
||||
|
@ -3969,7 +3987,7 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
|
|||
|
||||
static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
int err = 0;
|
||||
int err = 0, i;
|
||||
struct iwl_priv *priv;
|
||||
struct ieee80211_hw *hw;
|
||||
struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
|
||||
|
@ -3991,6 +4009,27 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
|||
priv = hw->priv;
|
||||
SET_IEEE80211_DEV(hw, &pdev->dev);
|
||||
|
||||
priv->cmd_queue = IWL39_CMD_QUEUE_NUM;
|
||||
|
||||
/* 3945 has only one valid context */
|
||||
priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
|
||||
|
||||
for (i = 0; i < NUM_IWL_RXON_CTX; i++)
|
||||
priv->contexts[i].ctxid = i;
|
||||
|
||||
priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
|
||||
BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
|
||||
|
||||
/*
|
||||
* Disabling hardware scan means that mac80211 will perform scans
|
||||
* "the hard way", rather than using device's scan.
|
||||
|
@ -4126,7 +4165,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
|||
}
|
||||
|
||||
iwl_set_rxon_channel(priv,
|
||||
&priv->bands[IEEE80211_BAND_2GHZ].channels[5]);
|
||||
&priv->bands[IEEE80211_BAND_2GHZ].channels[5],
|
||||
&priv->contexts[IWL_RXON_CTX_BSS]);
|
||||
iwl3945_setup_deferred_work(priv);
|
||||
iwl3945_setup_rx_handlers(priv);
|
||||
iwl_power_initialize(priv);
|
||||
|
|
Loading…
Reference in New Issue