Commit 48669953 authored by John W. Linville's avatar John W. Linville

Merge branch 'wireless-next-2.6' of...

Merge branch 'wireless-next-2.6' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6
parents 5b714c6a d0fe478c
...@@ -130,7 +130,7 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) ...@@ -130,7 +130,7 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
sizeof(struct iwlagn_scd_bc_tbl); sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd); priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWLAGN_STATION_COUNT; 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_data_size = IWLAGN_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
...@@ -217,7 +217,7 @@ static struct iwl_lib_ops iwl1000_lib = { ...@@ -217,7 +217,7 @@ static struct iwl_lib_ops iwl1000_lib = {
.set_ct_kill = iwl1000_set_ct_threshold, .set_ct_kill = iwl1000_set_ct_threshold,
}, },
.manage_ibss_station = iwlagn_manage_ibss_station, .manage_ibss_station = iwlagn_manage_ibss_station,
.update_bcast_station = iwl_update_bcast_station, .update_bcast_stations = iwl_update_bcast_stations,
.debugfs_ops = { .debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read, .rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read,
......
...@@ -226,6 +226,7 @@ struct iwl3945_eeprom { ...@@ -226,6 +226,7 @@ struct iwl3945_eeprom {
/* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */ /* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */
#define IWL39_NUM_QUEUES 5 #define IWL39_NUM_QUEUES 5
#define IWL39_CMD_QUEUE_NUM 4
#define IWL_DEFAULT_TX_RETRY 15 #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 ...@@ -343,7 +343,7 @@ void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 s
int i; int i;
IWL_DEBUG_INFO(priv, "enter\n"); 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; goto out;
psta = (struct iwl3945_sta_priv *) sta->drv_priv; psta = (struct iwl3945_sta_priv *) sta->drv_priv;
...@@ -932,7 +932,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) ...@@ -932,7 +932,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
rcu_read_lock(); 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); priv->stations[sta_id].sta.sta.addr);
if (!sta) { if (!sta) {
IWL_DEBUG_RATE(priv, "Unable to find station to initialize rate scaling.\n"); 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) ...@@ -949,7 +949,8 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
switch (priv->band) { switch (priv->band) {
case IEEE80211_BAND_2GHZ: case IEEE80211_BAND_2GHZ:
/* TODO: this always does G, not a regression */ /* 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->tgg = 1;
rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot; rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
} else } else
......
...@@ -245,7 +245,7 @@ int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate) ...@@ -245,7 +245,7 @@ int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate)
break; break;
case IEEE80211_BAND_2GHZ: case IEEE80211_BAND_2GHZ:
if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) && 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) if (rate == IWL_RATE_11M_INDEX)
next_rate = IWL_RATE_5M_INDEX; next_rate = IWL_RATE_5M_INDEX;
} }
...@@ -273,7 +273,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, ...@@ -273,7 +273,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
struct iwl_queue *q = &txq->q; struct iwl_queue *q = &txq->q;
struct iwl_tx_info *tx_info; 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; 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)) { 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, ...@@ -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) && 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) priv->mac80211_registered)
iwl_wake_queue(priv, txq_id); iwl_wake_queue(priv, txq_id);
} }
...@@ -760,7 +760,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, ...@@ -760,7 +760,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
data_retry_limit = IWL_DEFAULT_TX_RETRY; data_retry_limit = IWL_DEFAULT_TX_RETRY;
tx_cmd->data_retry_limit = data_retry_limit; 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; rts_retry_limit = 3;
else else
rts_retry_limit = 7; rts_retry_limit = 7;
...@@ -909,7 +909,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) ...@@ -909,7 +909,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
/* Tx queue(s) */ /* Tx queue(s) */
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { 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; TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
txq_id); txq_id);
...@@ -1072,7 +1072,7 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv) ...@@ -1072,7 +1072,7 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv)
if (priv->txq) if (priv->txq)
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; for (txq_id = 0; txq_id < priv->hw_params.max_txq_num;
txq_id++) txq_id++)
if (txq_id == IWL_CMD_QUEUE_NUM) if (txq_id == IWL39_CMD_QUEUE_NUM)
iwl_cmd_queue_free(priv); iwl_cmd_queue_free(priv);
else else
iwl_tx_queue_free(priv, txq_id); iwl_tx_queue_free(priv, txq_id);
...@@ -1439,17 +1439,18 @@ static int iwl3945_send_tx_power(struct iwl_priv *priv) ...@@ -1439,17 +1439,18 @@ static int iwl3945_send_tx_power(struct iwl_priv *priv)
int rate_idx, i; int rate_idx, i;
const struct iwl_channel_info *ch_info = NULL; const struct iwl_channel_info *ch_info = NULL;
struct iwl3945_txpowertable_cmd txpower = { 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; txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
ch_info = iwl_get_channel_info(priv, ch_info = iwl_get_channel_info(priv, priv->band, chan);
priv->band,
le16_to_cpu(priv->active_rxon.channel));
if (!ch_info) { if (!ch_info) {
IWL_ERR(priv, IWL_ERR(priv,
"Failed to get channel info for channel %d [%d]\n", "Failed to get channel info for channel %d [%d]\n",
le16_to_cpu(priv->active_rxon.channel), priv->band); chan, priv->band);
return -EINVAL; return -EINVAL;
} }
...@@ -1710,7 +1711,8 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power) ...@@ -1710,7 +1711,8 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
return 0; 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; int rc = 0;
struct iwl_rx_packet *pkt; struct iwl_rx_packet *pkt;
...@@ -1721,8 +1723,8 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) ...@@ -1721,8 +1723,8 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
.flags = CMD_WANT_SKB, .flags = CMD_WANT_SKB,
.data = &rxon_assoc, .data = &rxon_assoc,
}; };
const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; const struct iwl_rxon_cmd *rxon1 = &ctx->staging;
const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; const struct iwl_rxon_cmd *rxon2 = &ctx->active;
if ((rxon1->flags == rxon2->flags) && if ((rxon1->flags == rxon2->flags) &&
(rxon1->filter_flags == rxon2->filter_flags) && (rxon1->filter_flags == rxon2->filter_flags) &&
...@@ -1732,10 +1734,10 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) ...@@ -1732,10 +1734,10 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
return 0; return 0;
} }
rxon_assoc.flags = priv->staging_rxon.flags; rxon_assoc.flags = ctx->staging.flags;
rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; rxon_assoc.filter_flags = ctx->staging.filter_flags;
rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
rxon_assoc.reserved = 0; rxon_assoc.reserved = 0;
rc = iwl_send_cmd_sync(priv, &cmd); rc = iwl_send_cmd_sync(priv, &cmd);
...@@ -1761,14 +1763,14 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) ...@@ -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 * function correctly transitions out of the RXON_ASSOC_MSK state if
* a HW tune is required based on the RXON structure changes. * 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 */ /* cast away the const for active_rxon in this function */
struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon; struct iwl3945_rxon_cmd *active_rxon = (void *)&ctx->active;
struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon; struct iwl3945_rxon_cmd *staging_rxon = (void *)&ctx->staging;
int rc = 0; int rc = 0;
bool new_assoc = bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK);
!!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
if (!iwl_is_alive(priv)) if (!iwl_is_alive(priv))
return -1; return -1;
...@@ -1781,7 +1783,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) ...@@ -1781,7 +1783,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK); ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
staging_rxon->flags |= iwl3945_get_antenna_flags(priv); staging_rxon->flags |= iwl3945_get_antenna_flags(priv);
rc = iwl_check_rxon_cmd(priv); rc = iwl_check_rxon_cmd(priv, ctx);
if (rc) { if (rc) {
IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
return -EINVAL; return -EINVAL;
...@@ -1790,8 +1792,9 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) ...@@ -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 /* If we don't need to send a full RXON, we can use
* iwl3945_rxon_assoc_cmd which is used to reconfigure filter * iwl3945_rxon_assoc_cmd which is used to reconfigure filter
* and other flags for the current radio configuration. */ * and other flags for the current radio configuration. */
if (!iwl_full_rxon_required(priv)) { if (!iwl_full_rxon_required(priv, &priv->contexts[IWL_RXON_CTX_BSS])) {
rc = iwl_send_rxon_assoc(priv); rc = iwl_send_rxon_assoc(priv,
&priv->contexts[IWL_RXON_CTX_BSS]);
if (rc) { if (rc) {
IWL_ERR(priv, "Error setting RXON_ASSOC " IWL_ERR(priv, "Error setting RXON_ASSOC "
"configuration (%d).\n", rc); "configuration (%d).\n", rc);
...@@ -1807,7 +1810,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) ...@@ -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, * an RXON_ASSOC and the new config wants the associated mask enabled,
* we must clear the associated from the active configuration * we must clear the associated from the active configuration
* before we apply the new config */ * 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"); IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
...@@ -1819,7 +1822,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) ...@@ -1819,7 +1822,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
active_rxon->reserved5 = 0; active_rxon->reserved5 = 0;
rc = iwl_send_cmd_pdu(priv, REPLY_RXON, rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
sizeof(struct iwl3945_rxon_cmd), sizeof(struct iwl3945_rxon_cmd),
&priv->active_rxon); &priv->contexts[IWL_RXON_CTX_BSS].active);
/* If the mask clearing failed then we set /* If the mask clearing failed then we set
* active_rxon back to what it was previously */ * active_rxon back to what it was previously */
...@@ -1829,8 +1832,9 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) ...@@ -1829,8 +1832,9 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
"configuration (%d).\n", rc); "configuration (%d).\n", rc);
return rc; return rc;
} }
iwl_clear_ucode_stations(priv); iwl_clear_ucode_stations(priv,
iwl_restore_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" IWL_DEBUG_INFO(priv, "Sending RXON\n"
...@@ -1848,7 +1852,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) ...@@ -1848,7 +1852,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
staging_rxon->reserved4 = 0; staging_rxon->reserved4 = 0;
staging_rxon->reserved5 = 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 */ /* Apply the new configuration */
rc = iwl_send_cmd_pdu(priv, REPLY_RXON, rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
...@@ -1862,8 +1866,9 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) ...@@ -1862,8 +1866,9 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
if (!new_assoc) { if (!new_assoc) {
iwl_clear_ucode_stations(priv); iwl_clear_ucode_stations(priv,
iwl_restore_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 /* 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, ...@@ -2302,8 +2307,10 @@ static int iwl3945_manage_ibss_station(struct iwl_priv *priv,
int ret; int ret;
if (add) { if (add) {
ret = iwl_add_bssid_station(priv, vif->bss_conf.bssid, false, ret = iwl_add_bssid_station(
&vif_priv->ibss_bssid_sta_id); priv, &priv->contexts[IWL_RXON_CTX_BSS],
vif->bss_conf.bssid, false,
&vif_priv->ibss_bssid_sta_id);
if (ret) if (ret)
return ret; return ret;
...@@ -2366,7 +2373,7 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv) ...@@ -2366,7 +2373,7 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
* 1M CCK rates */ * 1M CCK rates */
if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) && 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; index = IWL_FIRST_CCK_RATE;
for (i = IWL_RATE_6M_INDEX_TABLE; for (i = IWL_RATE_6M_INDEX_TABLE;
...@@ -2421,7 +2428,9 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) ...@@ -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_size = RX_QUEUE_SIZE;
priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
priv->hw_params.max_stations = IWL3945_STATION_COUNT; 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.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR;
priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL; 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, ...@@ -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; tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u;
memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); 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; tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
frame_size = iwl3945_fill_beacon_frame(priv, frame_size = iwl3945_fill_beacon_frame(priv,
......
...@@ -347,7 +347,7 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *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); struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
if ((data->state == IWL_CHAIN_NOISE_ALIVE) && if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
iwl_is_associated(priv)) { iwl_is_any_associated(priv)) {
struct iwl_calib_diff_gain_cmd cmd; struct iwl_calib_diff_gain_cmd cmd;
/* clear data for chain noise calibration algorithm */ /* clear data for chain noise calibration algorithm */
...@@ -576,7 +576,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) ...@@ -576,7 +576,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
/* Activate all Tx DMA/FIFO channels */ /* Activate all Tx DMA/FIFO channels */
priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 6)); 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 */ /* make sure all queue are not stopped */
memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
...@@ -587,6 +587,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) ...@@ -587,6 +587,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
priv->txq_ctx_active_msk = 0; priv->txq_ctx_active_msk = 0;
/* Map each Tx/cmd queue to its corresponding fifo */ /* Map each Tx/cmd queue to its corresponding fifo */
BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7); BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
int ac = 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) ...@@ -656,7 +657,7 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
sizeof(struct iwl4965_scd_bc_tbl); sizeof(struct iwl4965_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd); priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWL4965_STATION_COUNT; 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_data_size = IWL49_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE; priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE;
priv->hw_params.max_bsm_size = BSM_SRAM_SIZE; priv->hw_params.max_bsm_size = BSM_SRAM_SIZE;
...@@ -1374,6 +1375,7 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv) ...@@ -1374,6 +1375,7 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
u8 band = 0; u8 band = 0;
bool is_ht40 = false; bool is_ht40 = false;
u8 ctrl_chan_high = 0; u8 ctrl_chan_high = 0;
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
if (test_bit(STATUS_SCANNING, &priv->status)) { if (test_bit(STATUS_SCANNING, &priv->status)) {
/* If this gets hit a lot, switch it to a BUG() and catch /* 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) ...@@ -1385,17 +1387,16 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
band = priv->band == IEEE80211_BAND_2GHZ; 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 && if (is_ht40 && (ctx->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
(priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
ctrl_chan_high = 1; ctrl_chan_high = 1;
cmd.band = band; cmd.band = band;
cmd.channel = priv->active_rxon.channel; cmd.channel = ctx->active.channel;
ret = iwl4965_fill_txpower_tbl(priv, band, 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); is_ht40, ctrl_chan_high, &cmd.tx_power);
if (ret) if (ret)
goto out; goto out;
...@@ -1406,12 +1407,13 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv) ...@@ -1406,12 +1407,13 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
return ret; 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; int ret = 0;
struct iwl4965_rxon_assoc_cmd rxon_assoc; struct iwl4965_rxon_assoc_cmd rxon_assoc;
const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; const struct iwl_rxon_cmd *rxon1 = &ctx->staging;
const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; const struct iwl_rxon_cmd *rxon2 = &ctx->active;
if ((rxon1->flags == rxon2->flags) && if ((rxon1->flags == rxon2->flags) &&
(rxon1->filter_flags == rxon2->filter_flags) && (rxon1->filter_flags == rxon2->filter_flags) &&
...@@ -1426,16 +1428,16 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) ...@@ -1426,16 +1428,16 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
return 0; return 0;
} }
rxon_assoc.flags = priv->staging_rxon.flags; rxon_assoc.flags = ctx->staging.flags;
rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; rxon_assoc.filter_flags = ctx->staging.filter_flags;
rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
rxon_assoc.reserved = 0; rxon_assoc.reserved = 0;
rxon_assoc.ofdm_ht_single_stream_basic_rates = 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 = rxon_assoc.ofdm_ht_dual_stream_basic_rates =
priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; ctx->staging.ofdm_ht_dual_stream_basic_rates;
rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
sizeof(rxon_assoc), &rxon_assoc, NULL); sizeof(rxon_assoc), &rxon_assoc, NULL);
...@@ -1448,6 +1450,7 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) ...@@ -1448,6 +1450,7 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
static int iwl4965_hw_channel_switch(struct iwl_priv *priv, static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
struct ieee80211_channel_switch *ch_switch) struct ieee80211_channel_switch *ch_switch)
{ {
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
int rc; int rc;
u8 band = 0; u8 band = 0;
bool is_ht40 = false; bool is_ht40 = false;
...@@ -1458,22 +1461,22 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, ...@@ -1458,22 +1461,22 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
u16 ch; u16 ch;
u32 tsf_low; u32 tsf_low;
u8 switch_count; u8 switch_count;
u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval); u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
struct ieee80211_vif *vif = priv->vif; struct ieee80211_vif *vif = ctx->vif;
band = priv->band == IEEE80211_BAND_2GHZ; 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 && 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; ctrl_chan_high = 1;
cmd.band = band; cmd.band = band;
cmd.expect_beacon = 0; cmd.expect_beacon = 0;
ch = ch_switch->channel->hw_value; ch = ch_switch->channel->hw_value;
cmd.channel = cpu_to_le16(ch); cmd.channel = cpu_to_le16(ch);
cmd.rxon_flags = priv->staging_rxon.flags; cmd.rxon_flags = ctx->staging.flags;
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; cmd.rxon_filter_flags = ctx->staging.filter_flags;
switch_count = ch_switch->count; switch_count = ch_switch->count;
tsf_low = ch_switch->timestamp & 0x0ffffffff; tsf_low = ch_switch->timestamp & 0x0ffffffff;
/* /*
...@@ -1508,7 +1511,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, ...@@ -1508,7 +1511,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
cmd.expect_beacon = is_channel_radar(ch_info); cmd.expect_beacon = is_channel_radar(ch_info);
else { else {
IWL_ERR(priv, "invalid channel switch from %u to %u\n", IWL_ERR(priv, "invalid channel switch from %u to %u\n",
priv->active_rxon.channel, ch); ctx->active.channel, ch);
return -EFAULT; return -EFAULT;
} }
...@@ -2007,7 +2010,7 @@ static u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) ...@@ -2007,7 +2010,7 @@ static u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
start = IWL_STA_ID; start = IWL_STA_ID;
if (is_broadcast_ether_addr(addr)) 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); spin_lock_irqsave(&priv->sta_lock, flags);
for (i = start; i < priv->hw_params.max_stations; i++) for (i = start; i < priv->hw_params.max_stations; i++)
...@@ -2280,7 +2283,7 @@ static struct iwl_lib_ops iwl4965_lib = { ...@@ -2280,7 +2283,7 @@ static struct iwl_lib_ops iwl4965_lib = {
.set_ct_kill = iwl4965_set_ct_threshold, .set_ct_kill = iwl4965_set_ct_threshold,
}, },
.manage_ibss_station = iwlagn_manage_ibss_station, .manage_ibss_station = iwlagn_manage_ibss_station,
.update_bcast_station = iwl_update_bcast_station, .update_bcast_stations = iwl_update_bcast_stations,
.debugfs_ops = { .debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read, .rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_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) ...@@ -180,7 +180,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
sizeof(struct iwlagn_scd_bc_tbl); sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd); priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWLAGN_STATION_COUNT; 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_data_size = IWLAGN_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWLAGN_RTC_INST_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) ...@@ -227,7 +227,7 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
sizeof(struct iwlagn_scd_bc_tbl); sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd); priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWLAGN_STATION_COUNT; 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_data_size = IWLAGN_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
...@@ -275,14 +275,19 @@ static void iwl5150_temperature(struct iwl_priv *priv) ...@@ -275,14 +275,19 @@ static void iwl5150_temperature(struct iwl_priv *priv)
static int iwl5000_hw_channel_switch(struct iwl_priv *priv, static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
struct ieee80211_channel_switch *ch_switch) 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; struct iwl5000_channel_switch_cmd cmd;
const struct iwl_channel_info *ch_info; const struct iwl_channel_info *ch_info;
u32 switch_time_in_usec, ucode_switch_time; u32 switch_time_in_usec, ucode_switch_time;
u16 ch; u16 ch;
u32 tsf_low; u32 tsf_low;
u8 switch_count; u8 switch_count;
u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval); u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
struct ieee80211_vif *vif = priv->vif; struct ieee80211_vif *vif = ctx->vif;
struct iwl_host_cmd hcmd = { struct iwl_host_cmd hcmd = {
.id = REPLY_CHANNEL_SWITCH, .id = REPLY_CHANNEL_SWITCH,
.len = sizeof(cmd), .len = sizeof(cmd),
...@@ -293,10 +298,10 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, ...@@ -293,10 +298,10 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
cmd.band = priv->band == IEEE80211_BAND_2GHZ; cmd.band = priv->band == IEEE80211_BAND_2GHZ;
ch = ch_switch->channel->hw_value; ch = ch_switch->channel->hw_value;
IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", 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.channel = cpu_to_le16(ch);
cmd.rxon_flags = priv->staging_rxon.flags; cmd.rxon_flags = ctx->staging.flags;
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; cmd.rxon_filter_flags = ctx->staging.filter_flags;
switch_count = ch_switch->count; switch_count = ch_switch->count;
tsf_low = ch_switch->timestamp & 0x0ffffffff; tsf_low = ch_switch->timestamp & 0x0ffffffff;
/* /*
...@@ -331,7 +336,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, ...@@ -331,7 +336,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
cmd.expect_beacon = is_channel_radar(ch_info); cmd.expect_beacon = is_channel_radar(ch_info);
else { else {
IWL_ERR(priv, "invalid channel switch from %u to %u\n", IWL_ERR(priv, "invalid channel switch from %u to %u\n",
priv->active_rxon.channel, ch); ctx->active.channel, ch);
return -EFAULT; return -EFAULT;
} }
priv->switch_rxon.channel = cmd.channel; priv->switch_rxon.channel = cmd.channel;
...@@ -393,7 +398,7 @@ static struct iwl_lib_ops iwl5000_lib = { ...@@ -393,7 +398,7 @@ static struct iwl_lib_ops iwl5000_lib = {
.set_ct_kill = iwl5000_set_ct_threshold, .set_ct_kill = iwl5000_set_ct_threshold,
}, },
.manage_ibss_station = iwlagn_manage_ibss_station, .manage_ibss_station = iwlagn_manage_ibss_station,
.update_bcast_station = iwl_update_bcast_station, .update_bcast_stations = iwl_update_bcast_stations,
.debugfs_ops = { .debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read, .rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read,
...@@ -464,7 +469,7 @@ static struct iwl_lib_ops iwl5150_lib = { ...@@ -464,7 +469,7 @@ static struct iwl_lib_ops iwl5150_lib = {
.set_ct_kill = iwl5150_set_ct_threshold, .set_ct_kill = iwl5150_set_ct_threshold,
}, },
.manage_ibss_station = iwlagn_manage_ibss_station, .manage_ibss_station = iwlagn_manage_ibss_station,
.update_bcast_station = iwl_update_bcast_station, .update_bcast_stations = iwl_update_bcast_stations,
.debugfs_ops = { .debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read, .rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_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) ...@@ -161,7 +161,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
sizeof(struct iwlagn_scd_bc_tbl); sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd); priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWLAGN_STATION_COUNT; 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_data_size = IWL60_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWL60_RTC_INST_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) ...@@ -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, static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
struct ieee80211_channel_switch *ch_switch) 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; struct iwl6000_channel_switch_cmd cmd;
const struct iwl_channel_info *ch_info; const struct iwl_channel_info *ch_info;
u32 switch_time_in_usec, ucode_switch_time; u32 switch_time_in_usec, ucode_switch_time;
u16 ch; u16 ch;
u32 tsf_low; u32 tsf_low;
u8 switch_count; u8 switch_count;
u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval); u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
struct ieee80211_vif *vif = priv->vif; struct ieee80211_vif *vif = ctx->vif;
struct iwl_host_cmd hcmd = { struct iwl_host_cmd hcmd = {
.id = REPLY_CHANNEL_SWITCH, .id = REPLY_CHANNEL_SWITCH,
.len = sizeof(cmd), .len = sizeof(cmd),
...@@ -216,10 +221,10 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, ...@@ -216,10 +221,10 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
cmd.band = priv->band == IEEE80211_BAND_2GHZ; cmd.band = priv->band == IEEE80211_BAND_2GHZ;
ch = ch_switch->channel->hw_value; ch = ch_switch->channel->hw_value;
IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", 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.channel = cpu_to_le16(ch);
cmd.rxon_flags = priv->staging_rxon.flags; cmd.rxon_flags = ctx->staging.flags;
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; cmd.rxon_filter_flags = ctx->staging.filter_flags;
switch_count = ch_switch->count; switch_count = ch_switch->count;
tsf_low = ch_switch->timestamp & 0x0ffffffff; tsf_low = ch_switch->timestamp & 0x0ffffffff;
/* /*
...@@ -254,7 +259,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, ...@@ -254,7 +259,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
cmd.expect_beacon = is_channel_radar(ch_info); cmd.expect_beacon = is_channel_radar(ch_info);
else { else {
IWL_ERR(priv, "invalid channel switch from %u to %u\n", IWL_ERR(priv, "invalid channel switch from %u to %u\n",
priv->active_rxon.channel, ch); ctx->active.channel, ch);
return -EFAULT; return -EFAULT;
} }
priv->switch_rxon.channel = cmd.channel; priv->switch_rxon.channel = cmd.channel;
...@@ -318,7 +323,7 @@ static struct iwl_lib_ops iwl6000_lib = { ...@@ -318,7 +323,7 @@ static struct iwl_lib_ops iwl6000_lib = {
.set_calib_version = iwl6000_set_calib_version, .set_calib_version = iwl6000_set_calib_version,
}, },
.manage_ibss_station = iwlagn_manage_ibss_station, .manage_ibss_station = iwlagn_manage_ibss_station,
.update_bcast_station = iwl_update_bcast_station, .update_bcast_stations = iwl_update_bcast_stations,
.debugfs_ops = { .debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read, .rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read,
...@@ -393,7 +398,7 @@ static struct iwl_lib_ops iwl6000g2b_lib = { ...@@ -393,7 +398,7 @@ static struct iwl_lib_ops iwl6000g2b_lib = {
.set_calib_version = iwl6000_set_calib_version, .set_calib_version = iwl6000_set_calib_version,
}, },
.manage_ibss_station = iwlagn_manage_ibss_station, .manage_ibss_station = iwlagn_manage_ibss_station,
.update_bcast_station = iwl_update_bcast_station, .update_bcast_stations = iwl_update_bcast_stations,
.debugfs_ops = { .debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read, .rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read,
......
...@@ -625,7 +625,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp) ...@@ -625,7 +625,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp)
data = &(priv->sensitivity_data); data = &(priv->sensitivity_data);
if (!iwl_is_associated(priv)) { if (!iwl_is_any_associated(priv)) {
IWL_DEBUG_CALIB(priv, "<< - not associated\n"); IWL_DEBUG_CALIB(priv, "<< - not associated\n");
return; return;
} }
...@@ -763,6 +763,12 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) ...@@ -763,6 +763,12 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
unsigned long flags; unsigned long flags;
struct statistics_rx_non_phy *rx_info; struct statistics_rx_non_phy *rx_info;
u8 first_chain; 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) if (priv->disable_chain_noise_cal)
return; return;
...@@ -793,8 +799,8 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) ...@@ -793,8 +799,8 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
return; return;
} }
rxon_band24 = !!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK); rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK);
rxon_chnum = le16_to_cpu(priv->staging_rxon.channel); rxon_chnum = le16_to_cpu(ctx->staging.channel);
if (priv->cfg->bt_statistics) { if (priv->cfg->bt_statistics) {
stat_band24 = !!(((struct iwl_bt_notif_statistics *) stat_band24 = !!(((struct iwl_bt_notif_statistics *)
stat_resp)->flag & stat_resp)->flag &
......
...@@ -37,12 +37,13 @@ ...@@ -37,12 +37,13 @@
#include "iwl-io.h" #include "iwl-io.h"
#include "iwl-agn.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; int ret = 0;
struct iwl5000_rxon_assoc_cmd rxon_assoc; struct iwl5000_rxon_assoc_cmd rxon_assoc;
const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; const struct iwl_rxon_cmd *rxon1 = &ctx->staging;
const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; const struct iwl_rxon_cmd *rxon2 = &ctx->active;
if ((rxon1->flags == rxon2->flags) && if ((rxon1->flags == rxon2->flags) &&
(rxon1->filter_flags == rxon2->filter_flags) && (rxon1->filter_flags == rxon2->filter_flags) &&
...@@ -60,23 +61,23 @@ int iwlagn_send_rxon_assoc(struct iwl_priv *priv) ...@@ -60,23 +61,23 @@ int iwlagn_send_rxon_assoc(struct iwl_priv *priv)
return 0; return 0;
} }
rxon_assoc.flags = priv->staging_rxon.flags; rxon_assoc.flags = ctx->staging.flags;
rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; rxon_assoc.filter_flags = ctx->staging.filter_flags;
rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
rxon_assoc.reserved1 = 0; rxon_assoc.reserved1 = 0;
rxon_assoc.reserved2 = 0; rxon_assoc.reserved2 = 0;
rxon_assoc.reserved3 = 0; rxon_assoc.reserved3 = 0;
rxon_assoc.ofdm_ht_single_stream_basic_rates = 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 = rxon_assoc.ofdm_ht_dual_stream_basic_rates =
priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; ctx->staging.ofdm_ht_dual_stream_basic_rates;
rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
rxon_assoc.ofdm_ht_triple_stream_basic_rates = rxon_assoc.ofdm_ht_triple_stream_basic_rates =
priv->staging_rxon.ofdm_ht_triple_stream_basic_rates; ctx->staging.ofdm_ht_triple_stream_basic_rates;
rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data; 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); sizeof(rxon_assoc), &rxon_assoc, NULL);
if (ret) if (ret)
return ret; return ret;
...@@ -184,7 +185,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) ...@@ -184,7 +185,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
int ret; int ret;
if ((data->state == IWL_CHAIN_NOISE_ALIVE) && if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
iwl_is_associated(priv)) { iwl_is_any_associated(priv)) {
struct iwl_calib_chain_noise_reset_cmd cmd; struct iwl_calib_chain_noise_reset_cmd cmd;
/* clear data for chain noise calibration algorithm */ /* clear data for chain noise calibration algorithm */
...@@ -269,12 +270,86 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, ...@@ -269,12 +270,86 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv,
return max_rssi - agc - IWLAGN_RSSI_OFFSET; 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 = { struct iwl_hcmd_ops iwlagn_hcmd = {
.rxon_assoc = iwlagn_send_rxon_assoc, .rxon_assoc = iwlagn_send_rxon_assoc,
.commit_rxon = iwl_commit_rxon, .commit_rxon = iwl_commit_rxon,
.set_rxon_chain = iwl_set_rxon_chain, .set_rxon_chain = iwl_set_rxon_chain,
.set_tx_ant = iwlagn_send_tx_ant_config, .set_tx_ant = iwlagn_send_tx_ant_config,
.send_bt_config = iwl_send_bt_config, .send_bt_config = iwl_send_bt_config,
.set_pan_params = iwlagn_set_pan_params,
}; };
struct iwl_hcmd_ops iwlagn_bt_hcmd = { struct iwl_hcmd_ops iwlagn_bt_hcmd = {
...@@ -283,6 +358,7 @@ 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_rxon_chain = iwl_set_rxon_chain,
.set_tx_ant = iwlagn_send_tx_ant_config, .set_tx_ant = iwlagn_send_tx_ant_config,
.send_bt_config = iwlagn_send_advance_bt_config, .send_bt_config = iwlagn_send_advance_bt_config,
.set_pan_params = iwlagn_set_pan_params,
}; };
struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {
......
...@@ -1163,6 +1163,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) ...@@ -1163,6 +1163,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
}; };
struct iwl_scan_cmd *scan; struct iwl_scan_cmd *scan;
struct ieee80211_conf *conf = NULL; struct ieee80211_conf *conf = NULL;
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
u32 rate_flags = 0; u32 rate_flags = 0;
u16 cmd_len; u16 cmd_len;
u16 rx_chain = 0; u16 rx_chain = 0;
...@@ -1175,6 +1176,9 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) ...@@ -1175,6 +1176,9 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
u8 active_chains; u8 active_chains;
u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; 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); conf = ieee80211_get_hw_conf(priv->hw);
cancel_delayed_work(&priv->scan_check); cancel_delayed_work(&priv->scan_check);
...@@ -1232,7 +1236,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) ...@@ -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_plcp_th = IWL_PLCP_QUIET_THRESH;
scan->quiet_time = IWL_ACTIVE_QUIET_TIME; scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
if (iwl_is_associated(priv)) { if (iwl_is_any_associated(priv)) {
u16 interval = 0; u16 interval = 0;
u32 extra; u32 extra;
u32 suspend_time = 100; u32 suspend_time = 100;
...@@ -1283,13 +1287,15 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) ...@@ -1283,13 +1287,15 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; 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; scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
switch (priv->scan_band) { switch (priv->scan_band) {
case IEEE80211_BAND_2GHZ: case IEEE80211_BAND_2GHZ:
scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; 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; >> RXON_FLG_CHANNEL_MODE_POS;
if (chan_mod == CHANNEL_MODE_PURE_40) { if (chan_mod == CHANNEL_MODE_PURE_40) {
rate = IWL_RATE_6M_PLCP; rate = IWL_RATE_6M_PLCP;
...@@ -1418,6 +1424,11 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) ...@@ -1418,6 +1424,11 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan->len = cpu_to_le16(cmd.len); scan->len = cpu_to_le16(cmd.len);
set_bit(STATUS_SCAN_HW, &priv->status); 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)) if (iwl_send_cmd_sync(priv, &cmd))
goto done; goto done;
...@@ -1444,7 +1455,8 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, ...@@ -1444,7 +1455,8 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
if (add) 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); &vif_priv->ibss_bssid_sta_id);
return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id,
vif->bss_conf.bssid); vif->bss_conf.bssid);
...@@ -1477,7 +1489,7 @@ int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv) ...@@ -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 */ /* waiting for all the tx frames complete might take a while */
for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
if (cnt == IWL_CMD_QUEUE_NUM) if (cnt == priv->cmd_queue)
continue; continue;
txq = &priv->txq[cnt]; txq = &priv->txq[cnt];
q = &txq->q; q = &txq->q;
...@@ -1713,6 +1725,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) ...@@ -1713,6 +1725,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
{ {
struct iwl_priv *priv = struct iwl_priv *priv =
container_of(work, struct iwl_priv, bt_traffic_change_work); container_of(work, struct iwl_priv, bt_traffic_change_work);
struct iwl_rxon_context *ctx;
int smps_request = -1; int smps_request = -1;
IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n", 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) ...@@ -1740,9 +1753,12 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
if (priv->cfg->ops->lib->update_chain_flags) if (priv->cfg->ops->lib->update_chain_flags)
priv->cfg->ops->lib->update_chain_flags(priv); priv->cfg->ops->lib->update_chain_flags(priv);
if (smps_request != -1 && if (smps_request != -1) {
priv->vif && priv->vif->type == NL80211_IFTYPE_STATION) for_each_context(priv, ctx) {
ieee80211_request_smps(priv->vif, smps_request); if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION)
ieee80211_request_smps(ctx->vif, smps_request);
}
}
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
} }
......
...@@ -602,11 +602,13 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, ...@@ -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 * Green-field mode is valid if the station supports it and
* there are no non-GF stations present in the BSS. * there are no non-GF stations present in the BSS.
*/ */
static inline u8 rs_use_green(struct ieee80211_sta *sta, static bool rs_use_green(struct ieee80211_sta *sta)
struct iwl_ht_config *ht_conf)
{ {
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) && 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, ...@@ -758,8 +760,8 @@ static bool table_type_matches(struct iwl_scale_tbl_info *a,
(a->is_SGI == b->is_SGI); (a->is_SGI == b->is_SGI);
} }
static void rs_bt_update_lq(struct iwl_priv *priv, static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
struct iwl_lq_sta *lq_sta) struct iwl_lq_sta *lq_sta)
{ {
struct iwl_scale_tbl_info *tbl; struct iwl_scale_tbl_info *tbl;
bool full_concurrent; bool full_concurrent;
...@@ -778,7 +780,7 @@ static void rs_bt_update_lq(struct iwl_priv *priv, ...@@ -778,7 +780,7 @@ static void rs_bt_update_lq(struct iwl_priv *priv,
/* Update uCode's rate table. */ /* Update uCode's rate table. */
tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); 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); 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, ...@@ -803,6 +805,8 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
u32 tx_rate; u32 tx_rate;
struct iwl_scale_tbl_info tbl_type; struct iwl_scale_tbl_info tbl_type;
struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; 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"); 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, ...@@ -869,7 +873,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
lq_sta->missed_rate_counter++; lq_sta->missed_rate_counter++;
if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) {
lq_sta->missed_rate_counter = 0; 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 */ /* Regardless, ignore this status info for outdated rate */
return; return;
...@@ -969,7 +973,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, ...@@ -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? */ /* Is there a need to switch between full concurrency and 3-wire? */
if (priv->bt_ant_couple_ok) 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, ...@@ -1163,6 +1167,8 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
u16 rate_mask; u16 rate_mask;
s32 rate; s32 rate;
s8 is_green = lq_sta->is_green; 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) if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
return -1; return -1;
...@@ -1183,7 +1189,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, ...@@ -1183,7 +1189,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
tbl->max_search = IWL_MAX_SEARCH; tbl->max_search = IWL_MAX_SEARCH;
rate_mask = lq_sta->active_mimo2_rate; 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; tbl->is_ht40 = 1;
else else
tbl->is_ht40 = 0; tbl->is_ht40 = 0;
...@@ -1217,6 +1223,8 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv, ...@@ -1217,6 +1223,8 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
u16 rate_mask; u16 rate_mask;
s32 rate; s32 rate;
s8 is_green = lq_sta->is_green; 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) if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
return -1; return -1;
...@@ -1237,7 +1245,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv, ...@@ -1237,7 +1245,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH; tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
rate_mask = lq_sta->active_mimo3_rate; 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; tbl->is_ht40 = 1;
else else
tbl->is_ht40 = 0; tbl->is_ht40 = 0;
...@@ -1272,6 +1280,8 @@ static int rs_switch_to_siso(struct iwl_priv *priv, ...@@ -1272,6 +1280,8 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
u16 rate_mask; u16 rate_mask;
u8 is_green = lq_sta->is_green; u8 is_green = lq_sta->is_green;
s32 rate; 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) if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
return -1; return -1;
...@@ -1284,7 +1294,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, ...@@ -1284,7 +1294,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
tbl->max_search = IWL_MAX_SEARCH; tbl->max_search = IWL_MAX_SEARCH;
rate_mask = lq_sta->active_siso_rate; 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; tbl->is_ht40 = 1;
else else
tbl->is_ht40 = 0; tbl->is_ht40 = 0;
...@@ -2086,6 +2096,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) ...@@ -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 * return rate_n_flags as used in the table
*/ */
static u32 rs_update_rate_tbl(struct iwl_priv *priv, static u32 rs_update_rate_tbl(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
struct iwl_lq_sta *lq_sta, struct iwl_lq_sta *lq_sta,
struct iwl_scale_tbl_info *tbl, struct iwl_scale_tbl_info *tbl,
int index, u8 is_green) int index, u8 is_green)
...@@ -2095,7 +2106,7 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv, ...@@ -2095,7 +2106,7 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv,
/* Update uCode's rate table. */ /* Update uCode's rate table. */
rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
rs_fill_link_cmd(priv, lq_sta, rate); 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; return rate;
} }
...@@ -2134,6 +2145,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -2134,6 +2145,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
s32 sr; s32 sr;
u8 tid = MAX_TID_COUNT; u8 tid = MAX_TID_COUNT;
struct iwl_tid_data *tid_data; 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"); 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, ...@@ -2172,7 +2185,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
if (is_legacy(tbl->lq_type)) if (is_legacy(tbl->lq_type))
lq_sta->is_green = 0; lq_sta->is_green = 0;
else 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; is_green = lq_sta->is_green;
/* current tx rate */ /* current tx rate */
...@@ -2211,7 +2224,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -2211,7 +2224,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
/* get "active" rate info */ /* get "active" rate info */
index = iwl_hwrate_to_plcp_idx(tbl->current_rate); 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); tbl, index, is_green);
} }
return; return;
...@@ -2453,7 +2466,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -2453,7 +2466,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
lq_update: lq_update:
/* Replace uCode's rate table for the destination station. */ /* Replace uCode's rate table for the destination station. */
if (update_lq) if (update_lq)
rate = rs_update_rate_tbl(priv, lq_sta, rate = rs_update_rate_tbl(priv, ctx, lq_sta,
tbl, index, is_green); tbl, index, is_green);
if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) { if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) {
...@@ -2495,7 +2508,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, ...@@ -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", IWL_DEBUG_RATE(priv, "Switch current mcs: %X index: %d\n",
tbl->current_rate, index); tbl->current_rate, index);
rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); 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 } else
done_search = 1; done_search = 1;
} }
...@@ -2565,12 +2578,17 @@ static void rs_initialize_lq(struct iwl_priv *priv, ...@@ -2565,12 +2578,17 @@ static void rs_initialize_lq(struct iwl_priv *priv,
int rate_idx; int rate_idx;
int i; int i;
u32 rate; 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 active_tbl = 0;
u8 valid_tx_ant; u8 valid_tx_ant;
struct iwl_station_priv *sta_priv;
struct iwl_rxon_context *ctx;
if (!sta || !lq_sta) if (!sta || !lq_sta)
goto out; return;
sta_priv = (void *)sta->drv_priv;
ctx = sta_priv->common.ctx;
i = lq_sta->last_txrate_idx; i = lq_sta->last_txrate_idx;
...@@ -2602,9 +2620,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, ...@@ -2602,9 +2620,7 @@ static void rs_initialize_lq(struct iwl_priv *priv,
rs_set_expected_tpt_table(lq_sta, tbl); rs_set_expected_tpt_table(lq_sta, tbl);
rs_fill_link_cmd(NULL, lq_sta, rate); rs_fill_link_cmd(NULL, lq_sta, rate);
priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq; priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq;
iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_SYNC, true); iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_SYNC, true);
out:
return;
} }
static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, 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 ...@@ -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->is_dup = 0;
lq_sta->max_rate_idx = -1; lq_sta->max_rate_idx = -1;
lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; 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->active_legacy_rate = priv->active_rate & ~(0x1000);
lq_sta->band = priv->band; lq_sta->band = priv->band;
/* /*
...@@ -2992,6 +3008,9 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, ...@@ -2992,6 +3008,9 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
char buf[64]; char buf[64];
int buf_size; int buf_size;
u32 parsed_rate; 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; priv = lq_sta->drv;
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
...@@ -3014,7 +3033,8 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, ...@@ -3014,7 +3033,8 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
if (lq_sta->dbg_fixed_rate) { if (lq_sta->dbg_fixed_rate) {
rs_fill_link_cmd(NULL, lq_sta, 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; return count;
......
...@@ -416,18 +416,26 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) ...@@ -416,18 +416,26 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
/* stop ct_kill_waiting_tm timer */ /* stop ct_kill_waiting_tm timer */
del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
if (changed) { if (changed) {
struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
if (tt->state >= IWL_TI_1) { if (tt->state >= IWL_TI_1) {
/* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */ /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */
tt->tt_power_mode = IWL_POWER_INDEX_5; tt->tt_power_mode = IWL_POWER_INDEX_5;
if (!iwl_ht_enabled(priv))
/* disable HT */ if (!iwl_ht_enabled(priv)) {
rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | struct iwl_rxon_context *ctx;
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
RXON_FLG_HT40_PROT_MSK | for_each_context(priv, ctx) {
RXON_FLG_HT_PROT_MSK); struct iwl_rxon_cmd *rxon;
else {
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 /* check HT capability and set
* according to the system HT capability * according to the system HT capability
* in case get disabled before */ * in case get disabled before */
......
...@@ -71,18 +71,6 @@ static const u8 tid_to_ac[] = { ...@@ -71,18 +71,6 @@ static const u8 tid_to_ac[] = {
2, 3, 3, 2, 1, 1, 0, 0 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) static inline int get_ac_from_tid(u16 tid)
{ {
if (likely(tid < ARRAY_SIZE(tid_to_ac))) if (likely(tid < ARRAY_SIZE(tid_to_ac)))
...@@ -92,10 +80,10 @@ static inline int get_ac_from_tid(u16 tid) ...@@ -92,10 +80,10 @@ static inline int get_ac_from_tid(u16 tid)
return -EINVAL; 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))) 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 */ /* no support for TIDs 8-15 yet */
return -EINVAL; return -EINVAL;
...@@ -118,7 +106,7 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, ...@@ -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); 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; sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; 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, ...@@ -155,7 +143,7 @@ void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); 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; sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
bc_ent = cpu_to_le16(1 | (sta_id << 12)); bc_ent = cpu_to_le16(1 | (sta_id << 12));
...@@ -333,11 +321,6 @@ void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask) ...@@ -333,11 +321,6 @@ void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask)
iwl_write_prph(priv, IWLAGN_SCD_TXFACT, 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. * handle build REPLY_TX command notification.
*/ */
...@@ -531,6 +514,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ...@@ -531,6 +514,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
struct iwl_device_cmd *out_cmd; struct iwl_device_cmd *out_cmd;
struct iwl_cmd_meta *out_meta; struct iwl_cmd_meta *out_meta;
struct iwl_tx_cmd *tx_cmd; struct iwl_tx_cmd *tx_cmd;
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
int swq_id, txq_id; int swq_id, txq_id;
dma_addr_t phys_addr; dma_addr_t phys_addr;
dma_addr_t txcmd_phys; dma_addr_t txcmd_phys;
...@@ -545,6 +529,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ...@@ -545,6 +529,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
u8 *qc = NULL; u8 *qc = NULL;
unsigned long flags; unsigned long flags;
if (info->control.vif)
ctx = iwl_rxon_ctx_from_vif(info->control.vif);
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
if (iwl_is_rfkill(priv)) { if (iwl_is_rfkill(priv)) {
IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
...@@ -565,7 +552,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ...@@ -565,7 +552,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
hdr_len = ieee80211_hdrlen(fc); hdr_len = ieee80211_hdrlen(fc);
/* Find index into station table for destination station */ /* 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) { if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
hdr->addr1); hdr->addr1);
...@@ -577,8 +564,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ...@@ -577,8 +564,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
if (sta) if (sta)
sta_priv = (void *)sta->drv_priv; sta_priv = (void *)sta->drv_priv;
if (sta_priv && sta_id != priv->hw_params.bcast_sta_id && if (sta_priv && sta_priv->asleep) {
sta_priv->asleep) {
WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)); WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE));
/* /*
* This sends an asynchronous command to the device, * This sends an asynchronous command to the device,
...@@ -592,7 +578,20 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ...@@ -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); 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 */ /* irqs already disabled/saved above when locking priv->lock */
spin_lock(&priv->sta_lock); spin_lock(&priv->sta_lock);
...@@ -637,6 +636,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ...@@ -637,6 +636,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* Set up driver data for this TFD */ /* Set up driver data for this TFD */
memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
txq->txb[q->write_ptr].skb = skb; 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 */ /* Set up first empty entry in queue's array of Tx/cmd buffers */
out_cmd = txq->cmd[q->write_ptr]; out_cmd = txq->cmd[q->write_ptr];
...@@ -825,7 +825,7 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv) ...@@ -825,7 +825,7 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv)
/* Tx queues */ /* Tx queues */
if (priv->txq) { if (priv->txq) {
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) 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); iwl_cmd_queue_free(priv);
else else
iwl_tx_queue_free(priv, txq_id); iwl_tx_queue_free(priv, txq_id);
...@@ -882,9 +882,9 @@ int iwlagn_txq_ctx_alloc(struct iwl_priv *priv) ...@@ -882,9 +882,9 @@ int iwlagn_txq_ctx_alloc(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags); 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++) { 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; TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
txq_id); txq_id);
...@@ -922,7 +922,7 @@ void iwlagn_txq_ctx_reset(struct iwl_priv *priv) ...@@ -922,7 +922,7 @@ void iwlagn_txq_ctx_reset(struct iwl_priv *priv)
/* Alloc and init all Tx queues, including the command queue (#4) */ /* 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++) { 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; TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); 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, ...@@ -980,7 +980,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
unsigned long flags; unsigned long flags;
struct iwl_tid_data *tid_data; 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)) if (unlikely(tx_fifo < 0))
return tx_fifo; return tx_fifo;
...@@ -1041,7 +1041,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, ...@@ -1041,7 +1041,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
int write_ptr, read_ptr; int write_ptr, read_ptr;
unsigned long flags; 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)) if (unlikely(tx_fifo_id < 0))
return tx_fifo_id; return tx_fifo_id;
...@@ -1116,6 +1116,9 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, ...@@ -1116,6 +1116,9 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
struct iwl_queue *q = &priv->txq[txq_id].q; struct iwl_queue *q = &priv->txq[txq_id].q;
u8 *addr = priv->stations[sta_id].sta.sta.addr; u8 *addr = priv->stations[sta_id].sta.sta.addr;
struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; 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); lockdep_assert_held(&priv->sta_lock);
...@@ -1126,12 +1129,12 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, ...@@ -1126,12 +1129,12 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
if ((txq_id == tid_data->agg.txq_id) && if ((txq_id == tid_data->agg.txq_id) &&
(q->read_ptr == q->write_ptr)) { (q->read_ptr == q->write_ptr)) {
u16 ssn = SEQ_TO_SN(tid_data->seq_number); 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"); IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n");
priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, priv->cfg->ops->lib->txq_agg_disable(priv, txq_id,
ssn, tx_fifo); ssn, tx_fifo);
tid_data->agg.state = IWL_AGG_OFF; 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; break;
case IWL_EMPTYING_HW_QUEUE_ADDBA: case IWL_EMPTYING_HW_QUEUE_ADDBA:
...@@ -1139,7 +1142,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, ...@@ -1139,7 +1142,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
if (tid_data->tfds_in_queue == 0) { if (tid_data->tfds_in_queue == 0) {
IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n");
tid_data->agg.state = IWL_AGG_ON; 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; break;
} }
...@@ -1147,14 +1150,14 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, ...@@ -1147,14 +1150,14 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
return 0; 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 ieee80211_sta *sta;
struct iwl_station_priv *sta_priv; struct iwl_station_priv *sta_priv;
rcu_read_lock(); rcu_read_lock();
sta = ieee80211_find_sta(priv->vif, hdr->addr1); sta = ieee80211_find_sta(tx_info->ctx->vif, hdr->addr1);
if (sta) { if (sta) {
sta_priv = (void *)sta->drv_priv; sta_priv = (void *)sta->drv_priv;
/* avoid atomic ops if this isn't a client */ /* 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) ...@@ -1164,7 +1167,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
} }
rcu_read_unlock(); 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) 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) ...@@ -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)) { q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
tx_info = &txq->txb[txq->q.read_ptr]; 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; hdr = (struct ieee80211_hdr *)tx_info->skb->data;
if (hdr && ieee80211_is_data_qos(hdr->frame_control)) if (hdr && ieee80211_is_data_qos(hdr->frame_control))
......
...@@ -52,6 +52,19 @@ static const s8 iwlagn_default_queue_to_tx_fifo[] = { ...@@ -52,6 +52,19 @@ static const s8 iwlagn_default_queue_to_tx_fifo[] = {
IWL_TX_FIFO_UNUSED, 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] = { static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
{COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
0, COEX_UNASSOC_IDLE_FLAGS}, 0, COEX_UNASSOC_IDLE_FLAGS},
...@@ -376,6 +389,7 @@ static void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) ...@@ -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) int iwlagn_alive_notify(struct iwl_priv *priv)
{ {
const s8 *queues;
u32 a; u32 a;
unsigned long flags; unsigned long flags;
int i, chan; int i, chan;
...@@ -410,7 +424,7 @@ int iwlagn_alive_notify(struct iwl_priv *priv) ...@@ -410,7 +424,7 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, 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); iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0);
/* initiate the queues */ /* initiate the queues */
...@@ -436,7 +450,13 @@ int iwlagn_alive_notify(struct iwl_priv *priv) ...@@ -436,7 +450,13 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
/* Activate all Tx DMA/FIFO channels */ /* Activate all Tx DMA/FIFO channels */
priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); 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 */ /* make sure all queue are not stopped */
memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
...@@ -445,11 +465,12 @@ int iwlagn_alive_notify(struct iwl_priv *priv) ...@@ -445,11 +465,12 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
/* reset to 0 to enable all the queue first */ /* reset to 0 to enable all the queue first */
priv->txq_ctx_active_msk = 0; 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); 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 < ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); i++) { for (i = 0; i < 10; i++) {
int ac = iwlagn_default_queue_to_tx_fifo[i]; int ac = queues[i];
iwl_txq_ctx_activate(priv, i); iwl_txq_ctx_activate(priv, i);
......
This diff is collapsed.
...@@ -224,7 +224,8 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, ...@@ -224,7 +224,8 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
struct ieee80211_vif *vif, bool add); struct ieee80211_vif *vif, bool add);
/* hcmd */ /* 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); int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant);
/* bt coex */ /* bt coex */
......
...@@ -180,6 +180,16 @@ enum { ...@@ -180,6 +180,16 @@ enum {
REPLY_BT_COEX_PROFILE_NOTIF = 0xce, REPLY_BT_COEX_PROFILE_NOTIF = 0xce,
REPLY_BT_COEX_SCO = 0xcf, 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 REPLY_MAX = 0xff
}; };
...@@ -607,6 +617,9 @@ enum { ...@@ -607,6 +617,9 @@ enum {
RXON_DEV_TYPE_ESS = 3, RXON_DEV_TYPE_ESS = 3,
RXON_DEV_TYPE_IBSS = 4, RXON_DEV_TYPE_IBSS = 4,
RXON_DEV_TYPE_SNIFFER = 6, 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 { ...@@ -823,7 +836,8 @@ struct iwl_rxon_time_cmd {
__le16 atim_window; __le16 atim_window;
__le32 beacon_init_val; __le32 beacon_init_val;
__le16 listen_interval; __le16 listen_interval;
__le16 reserved; u8 dtim_period;
u8 delta_cp_bss_tbtts;
} __packed; } __packed;
/* /*
...@@ -960,11 +974,13 @@ struct iwl_qosparam_cmd { ...@@ -960,11 +974,13 @@ struct iwl_qosparam_cmd {
/* Special, dedicated locations within device's station table */ /* Special, dedicated locations within device's station table */
#define IWL_AP_ID 0 #define IWL_AP_ID 0
#define IWL_AP_ID_PAN 1
#define IWL_STA_ID 2 #define IWL_STA_ID 2
#define IWL3945_BROADCAST_ID 24 #define IWL3945_BROADCAST_ID 24
#define IWL3945_STATION_COUNT 25 #define IWL3945_STATION_COUNT 25
#define IWL4965_BROADCAST_ID 31 #define IWL4965_BROADCAST_ID 31
#define IWL4965_STATION_COUNT 32 #define IWL4965_STATION_COUNT 32
#define IWLAGN_PAN_BCAST_ID 14
#define IWLAGN_BROADCAST_ID 15 #define IWLAGN_BROADCAST_ID 15
#define IWLAGN_STATION_COUNT 16 #define IWLAGN_STATION_COUNT 16
...@@ -973,6 +989,7 @@ struct iwl_qosparam_cmd { ...@@ -973,6 +989,7 @@ struct iwl_qosparam_cmd {
#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) #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_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_RTS_MIMO_PROT_MSK cpu_to_le32(1 << 17)
#define STA_FLG_AGG_MPDU_8US_MSK cpu_to_le32(1 << 18) #define STA_FLG_AGG_MPDU_8US_MSK cpu_to_le32(1 << 18)
#define STA_FLG_MAX_AGG_SIZE_POS (19) #define STA_FLG_MAX_AGG_SIZE_POS (19)
...@@ -1001,6 +1018,7 @@ struct iwl_qosparam_cmd { ...@@ -1001,6 +1018,7 @@ struct iwl_qosparam_cmd {
#define STA_KEY_FLG_KEY_SIZE_MSK cpu_to_le16(0x1000) #define STA_KEY_FLG_KEY_SIZE_MSK cpu_to_le16(0x1000)
#define STA_KEY_MULTICAST_MSK cpu_to_le16(0x4000) #define STA_KEY_MULTICAST_MSK cpu_to_le16(0x4000)
#define STA_KEY_MAX_NUM 8 #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 */ /* Flags indicate whether to modify vs. don't change various station params */
#define STA_MODIFY_KEY_MASK 0x01 #define STA_MODIFY_KEY_MASK 0x01
...@@ -4308,4 +4326,94 @@ struct iwl_rx_packet { ...@@ -4308,4 +4326,94 @@ struct iwl_rx_packet {
int iwl_agn_check_rxon_cmd(struct iwl_priv *priv); 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__ */ #endif /* __iwl_commands_h__ */
This diff is collapsed.
...@@ -88,11 +88,13 @@ struct iwl_cmd; ...@@ -88,11 +88,13 @@ struct iwl_cmd;
#define IWL_CMD(x) case x: return #x #define IWL_CMD(x) case x: return #x
struct iwl_hcmd_ops { struct iwl_hcmd_ops {
int (*rxon_assoc)(struct iwl_priv *priv); int (*rxon_assoc)(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
int (*commit_rxon)(struct iwl_priv *priv); int (*commit_rxon)(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
void (*set_rxon_chain)(struct iwl_priv *priv); 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); int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant);
void (*send_bt_config)(struct iwl_priv *priv); void (*send_bt_config)(struct iwl_priv *priv);
int (*set_pan_params)(struct iwl_priv *priv);
}; };
struct iwl_hcmd_utils_ops { struct iwl_hcmd_utils_ops {
...@@ -205,7 +207,7 @@ struct iwl_lib_ops { ...@@ -205,7 +207,7 @@ struct iwl_lib_ops {
/* station management */ /* station management */
int (*manage_ibss_station)(struct iwl_priv *priv, int (*manage_ibss_station)(struct iwl_priv *priv,
struct ieee80211_vif *vif, bool add); 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 */ /* recover from tx queue stall */
void (*recover_from_tx_stall)(unsigned long data); void (*recover_from_tx_stall)(unsigned long data);
/* check for plcp health */ /* check for plcp health */
...@@ -374,21 +376,25 @@ void iwl_activate_qos(struct iwl_priv *priv); ...@@ -374,21 +376,25 @@ void iwl_activate_qos(struct iwl_priv *priv);
int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params); const struct ieee80211_tx_queue_params *params);
int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw); int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw);
void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
int iwl_check_rxon_cmd(struct iwl_priv *priv); int hw_decrypt);
int iwl_full_rxon_required(struct iwl_priv *priv); int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
void iwl_set_rxon_chain(struct iwl_priv *priv); int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); 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, void iwl_set_flags_for_band(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
enum ieee80211_band band, enum ieee80211_band band,
struct ieee80211_vif *vif); struct ieee80211_vif *vif);
u8 iwl_get_single_channel_number(struct iwl_priv *priv, u8 iwl_get_single_channel_number(struct iwl_priv *priv,
enum ieee80211_band band); enum ieee80211_band band);
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); 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, bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
struct ieee80211_sta_ht_cap *sta_ht_inf); struct iwl_rxon_context *ctx,
struct ieee80211_sta_ht_cap *ht_cap);
void iwl_connection_init_rx_config(struct iwl_priv *priv, 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); void iwl_set_rate(struct iwl_priv *priv);
int iwl_set_decrypted_flag(struct iwl_priv *priv, int iwl_set_decrypted_flag(struct iwl_priv *priv,
struct ieee80211_hdr *hdr, struct ieee80211_hdr *hdr,
...@@ -400,7 +406,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, ...@@ -400,7 +406,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf, struct ieee80211_bss_conf *bss_conf,
u32 changes); 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, int iwl_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif); struct ieee80211_vif *vif);
void iwl_mac_remove_interface(struct ieee80211_hw *hw, 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); ...@@ -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); 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); 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, ...@@ -632,9 +639,11 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv,
void iwl_dump_csr(struct iwl_priv *priv); void iwl_dump_csr(struct iwl_priv *priv);
int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);
#ifdef CONFIG_IWLWIFI_DEBUG #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 #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 #endif
...@@ -714,19 +723,21 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv) ...@@ -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 void iwl_send_bt_config(struct iwl_priv *priv);
extern int iwl_send_statistics_request(struct iwl_priv *priv, extern int iwl_send_statistics_request(struct iwl_priv *priv,
u8 flags, bool clear); 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); struct iwl_link_quality_cmd *lq, u8 flags, bool init);
void iwl_apm_stop(struct iwl_priv *priv); void iwl_apm_stop(struct iwl_priv *priv);
int iwl_apm_init(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); 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) 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, static inline void iwlcore_config_ap(struct iwl_priv *priv,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
......
...@@ -643,19 +643,25 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, ...@@ -643,19 +643,25 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct iwl_priv *priv = file->private_data; struct iwl_priv *priv = file->private_data;
struct iwl_rxon_context *ctx;
int pos = 0, i; int pos = 0, i;
char buf[256]; char buf[256 * NUM_IWL_RXON_CTX];
const size_t bufsz = sizeof(buf); const size_t bufsz = sizeof(buf);
for (i = 0; i < AC_NUM; i++) { for_each_context(priv, ctx) {
pos += scnprintf(buf + pos, bufsz - pos, pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n",
"\tcw_min\tcw_max\taifsn\ttxop\n"); ctx->ctxid);
pos += scnprintf(buf + pos, bufsz - pos, 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, "AC[%d]\t%u\t%u\t%u\t%u\n", i,
priv->qos_data.def_qos_parm.ac[i].cw_min, ctx->qos_data.def_qos_parm.ac[i].cw_min,
priv->qos_data.def_qos_parm.ac[i].cw_max, ctx->qos_data.def_qos_parm.ac[i].cw_max,
priv->qos_data.def_qos_parm.ac[i].aifsn, ctx->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].edca_txop);
}
pos += scnprintf(buf + pos, bufsz - pos, "\n");
} }
return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 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, ...@@ -730,7 +736,7 @@ static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,
return -EFAULT; return -EFAULT;
if (sscanf(buf, "%d", &ht40) != 1) if (sscanf(buf, "%d", &ht40) != 1)
return -EFAULT; return -EFAULT;
if (!iwl_is_associated(priv)) if (!iwl_is_any_associated(priv))
priv->disable_ht40 = ht40 ? true : false; priv->disable_ht40 = ht40 ? true : false;
else { else {
IWL_ERR(priv, "Sta associated with AP - " IWL_ERR(priv, "Sta associated with AP - "
...@@ -1319,7 +1325,8 @@ static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file, ...@@ -1319,7 +1325,8 @@ static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file,
int len = 0; int len = 0;
char buf[20]; 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); 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, ...@@ -1332,7 +1339,7 @@ static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file,
char buf[20]; char buf[20];
len = sprintf(buf, "0x%04X\n", 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); return simple_read_from_buffer(user_buf, count, ppos, buf, len);
} }
......
...@@ -144,6 +144,7 @@ struct iwl_queue { ...@@ -144,6 +144,7 @@ struct iwl_queue {
/* One for each TFD */ /* One for each TFD */
struct iwl_tx_info { struct iwl_tx_info {
struct sk_buff *skb; struct sk_buff *skb;
struct iwl_rxon_context *ctx;
}; };
/** /**
...@@ -253,10 +254,14 @@ struct iwl_channel_info { ...@@ -253,10 +254,14 @@ struct iwl_channel_info {
struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; 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_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_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 #define IWL_TX_FIFO_UNUSED -1
/* Minimum number of queues. MAX_NUM is defined in hw specific files. /* Minimum number of queues. MAX_NUM is defined in hw specific files.
...@@ -265,11 +270,17 @@ struct iwl_channel_info { ...@@ -265,11 +270,17 @@ struct iwl_channel_info {
#define IWL_MIN_NUM_QUEUES 10 #define IWL_MIN_NUM_QUEUES 10
/* /*
* Queue #4 is the command queue for 3945/4965/5x00/1000/6x00, * Command queue depends on iPAN support.
* the driver maps it into the appropriate device FIFO for the
* uCode.
*/ */
#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 */ /* Power management (not Tx power) structures */
...@@ -459,15 +470,8 @@ union iwl_ht_rate_supp { ...@@ -459,15 +470,8 @@ union iwl_ht_rate_supp {
#define CFG_HT_MPDU_DENSITY_MIN (0x1) #define CFG_HT_MPDU_DENSITY_MIN (0x1)
struct iwl_ht_config { struct iwl_ht_config {
/* self configuration data */
bool is_ht;
bool is_40mhz;
bool single_chain_sufficient; bool single_chain_sufficient;
enum ieee80211_smps_mode smps; /* current smps mode */ 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 */ /* QoS structures */
...@@ -485,12 +489,13 @@ struct iwl_qos_info { ...@@ -485,12 +489,13 @@ struct iwl_qos_info {
struct iwl_station_entry { struct iwl_station_entry {
struct iwl_addsta_cmd sta; struct iwl_addsta_cmd sta;
struct iwl_tid_data tid[MAX_TID_COUNT]; struct iwl_tid_data tid[MAX_TID_COUNT];
u8 used; u8 used, ctxid;
struct iwl_hw_key keyinfo; struct iwl_hw_key keyinfo;
struct iwl_link_quality_cmd *lq; struct iwl_link_quality_cmd *lq;
}; };
struct iwl_station_priv_common { struct iwl_station_priv_common {
struct iwl_rxon_context *ctx;
u8 sta_id; u8 sta_id;
}; };
...@@ -519,6 +524,7 @@ struct iwl_station_priv { ...@@ -519,6 +524,7 @@ struct iwl_station_priv {
* space for us to put data into. * space for us to put data into.
*/ */
struct iwl_vif_priv { struct iwl_vif_priv {
struct iwl_rxon_context *ctx;
u8 ibss_bssid_sta_id; u8 ibss_bssid_sta_id;
}; };
...@@ -576,6 +582,7 @@ enum iwl_ucode_tlv_type { ...@@ -576,6 +582,7 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_INIT_DATA = 4, IWL_UCODE_TLV_INIT_DATA = 4,
IWL_UCODE_TLV_BOOT = 5, IWL_UCODE_TLV_BOOT = 5,
IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ 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_PTR = 8,
IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9, IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9,
IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10, IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10,
...@@ -670,7 +677,6 @@ struct iwl_sensitivity_ranges { ...@@ -670,7 +677,6 @@ struct iwl_sensitivity_ranges {
* @rx_page_order: Rx buffer page order * @rx_page_order: Rx buffer page order
* @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
* @max_stations: * @max_stations:
* @bcast_sta_id:
* @ht40_channel: is 40MHz width possible in band 2.4 * @ht40_channel: is 40MHz width possible in band 2.4
* BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ) * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ)
* @sw_crypto: 0 for hw, 1 for sw * @sw_crypto: 0 for hw, 1 for sw
...@@ -694,7 +700,6 @@ struct iwl_hw_params { ...@@ -694,7 +700,6 @@ struct iwl_hw_params {
u32 rx_page_order; u32 rx_page_order;
u32 rx_wrt_ptr_reg; u32 rx_wrt_ptr_reg;
u8 max_stations; u8 max_stations;
u8 bcast_sta_id;
u8 ht40_channel; u8 ht40_channel;
u8 max_beacon_itrvl; /* in 1024 ms */ u8 max_beacon_itrvl; /* in 1024 ms */
u32 max_inst_size; u32 max_inst_size;
...@@ -1097,6 +1102,57 @@ struct iwl_force_reset { ...@@ -1097,6 +1102,57 @@ struct iwl_force_reset {
*/ */
#define IWLAGN_EXT_BEACON_TIME_POS 22 #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 { struct iwl_priv {
/* ieee device used by generic ieee processing code */ /* ieee device used by generic ieee processing code */
...@@ -1173,6 +1229,15 @@ struct iwl_priv { ...@@ -1173,6 +1229,15 @@ struct iwl_priv {
u32 hw_wa_rev; u32 hw_wa_rev;
u8 rev_id; 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 */ /* EEPROM MAC addresses */
struct mac_address addresses[2]; struct mac_address addresses[2];
...@@ -1190,15 +1255,7 @@ struct iwl_priv { ...@@ -1190,15 +1255,7 @@ struct iwl_priv {
u8 ucode_write_complete; /* the image write is complete */ u8 ucode_write_complete; /* the image write is complete */
char firmware_name[25]; char firmware_name[25];
struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX];
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_switch_rxon switch_rxon; struct iwl_switch_rxon switch_rxon;
...@@ -1260,8 +1317,6 @@ struct iwl_priv { ...@@ -1260,8 +1317,6 @@ struct iwl_priv {
spinlock_t sta_lock; spinlock_t sta_lock;
int num_stations; int num_stations;
struct iwl_station_entry stations[IWL_STATION_COUNT]; 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; unsigned long ucode_key_table;
/* queue refcounts */ /* queue refcounts */
...@@ -1286,7 +1341,6 @@ struct iwl_priv { ...@@ -1286,7 +1341,6 @@ struct iwl_priv {
/* Last Rx'd beacon timestamp */ /* Last Rx'd beacon timestamp */
u64 timestamp; u64 timestamp;
struct ieee80211_vif *vif;
union { union {
#if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE) #if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE)
...@@ -1387,8 +1441,6 @@ struct iwl_priv { ...@@ -1387,8 +1441,6 @@ struct iwl_priv {
u32 inta_mask; u32 inta_mask;
struct iwl_qos_info qos_data;
struct workqueue_struct *workqueue; struct workqueue_struct *workqueue;
struct work_struct restart; struct work_struct restart;
...@@ -1396,6 +1448,8 @@ struct iwl_priv { ...@@ -1396,6 +1448,8 @@ struct iwl_priv {
struct work_struct rx_replenish; struct work_struct rx_replenish;
struct work_struct abort_scan; struct work_struct abort_scan;
struct work_struct beacon_update; struct work_struct beacon_update;
struct iwl_rxon_context *beacon_ctx;
struct work_struct tt_work; struct work_struct tt_work;
struct work_struct ct_enter; struct work_struct ct_enter;
struct work_struct ct_exit; struct work_struct ct_exit;
...@@ -1490,10 +1544,34 @@ static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv, ...@@ -1490,10 +1544,34 @@ static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv,
return NULL; return NULL;
} }
static inline struct iwl_rxon_context *
iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif)
{
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(struct iwl_priv *priv) static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx)
{ {
return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
} }
static inline int is_channel_valid(const struct iwl_channel_info *ch_info) static inline int is_channel_valid(const struct iwl_channel_info *ch_info)
......
...@@ -100,6 +100,14 @@ const char *get_cmd_string(u8 cmd) ...@@ -100,6 +100,14 @@ const char *get_cmd_string(u8 cmd)
IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF); IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF);
IWL_CMD(REPLY_BT_COEX_PRIO_TABLE); IWL_CMD(REPLY_BT_COEX_PRIO_TABLE);
IWL_CMD(REPLY_BT_COEX_PROT_ENV); 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: default:
return "UNKNOWN"; return "UNKNOWN";
...@@ -232,7 +240,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) ...@@ -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 * in later, it will possibly set an invalid
* address (cmd->meta.source). * 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; ~CMD_WANT_SKB;
} }
fail: fail:
......
...@@ -306,7 +306,7 @@ ...@@ -306,7 +306,7 @@
* at a time, until receiving ACK from receiving station, or reaching * at a time, until receiving ACK from receiving station, or reaching
* retry limit and giving up. * 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. * This mode does not require use of the Byte Count table in host DRAM.
* *
* Driver controls scheduler operation via 3 means: * Driver controls scheduler operation via 3 means:
...@@ -322,7 +322,7 @@ ...@@ -322,7 +322,7 @@
* (1024 bytes for each queue). * (1024 bytes for each queue).
* *
* After receiving "Alive" response from uCode, driver must initialize * 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!): * the driver can't issue commands!):
*/ */
...@@ -555,8 +555,9 @@ ...@@ -555,8 +555,9 @@
#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ #define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc) ((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc)
#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(x) (((1<<(x)) - 1) &\ #define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv) \
(~(1<<IWL_CMD_QUEUE_NUM))) (((1<<(priv)->hw_params.max_txq_num) - 1) &\
(~(1<<(priv)->cmd_queue)))
#define IWLAGN_SCD_BASE (PRPH_BASE + 0xa02c00) #define IWLAGN_SCD_BASE (PRPH_BASE + 0xa02c00)
......
...@@ -228,7 +228,7 @@ void iwl_recover_from_statistics(struct iwl_priv *priv, ...@@ -228,7 +228,7 @@ void iwl_recover_from_statistics(struct iwl_priv *priv,
{ {
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return; 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) {
if (!priv->cfg->ops->lib->check_ack_health( if (!priv->cfg->ops->lib->check_ack_health(
priv, pkt)) { priv, pkt)) {
...@@ -266,7 +266,12 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, ...@@ -266,7 +266,12 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv,
{ {
u16 fc = le16_to_cpu(hdr->frame_control); 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; return 0;
if (!(fc & IEEE80211_FCTL_PROTECTED)) if (!(fc & IEEE80211_FCTL_PROTECTED))
......
...@@ -286,18 +286,28 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, ...@@ -286,18 +286,28 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
enum ieee80211_band band, enum ieee80211_band band,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
struct iwl_rxon_context *ctx;
u16 passive = (band == IEEE80211_BAND_2GHZ) ? u16 passive = (band == IEEE80211_BAND_2GHZ) ?
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
if (iwl_is_associated(priv)) { if (iwl_is_any_associated(priv)) {
/* If we're associated, we clamp the maximum passive /*
* dwell time to be 98% of the beacon interval (minus * If we're associated, we clamp the maximum passive
* 2 * channel tune time) */ * dwell time to be 98% of the smallest beacon interval
passive = vif ? vif->bss_conf.beacon_int : 0; * (minus 2 * channel tune time)
if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive) */
passive = IWL_PASSIVE_DWELL_BASE; for_each_context(priv, ctx) {
passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; 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; return passive;
...@@ -527,6 +537,7 @@ static void iwl_bg_scan_completed(struct work_struct *work) ...@@ -527,6 +537,7 @@ static void iwl_bg_scan_completed(struct work_struct *work)
container_of(work, struct iwl_priv, scan_completed); container_of(work, struct iwl_priv, scan_completed);
bool internal = false; bool internal = false;
bool scan_completed = false; bool scan_completed = false;
struct iwl_rxon_context *ctx;
IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); IWL_DEBUG_SCAN(priv, "SCAN complete scan\n");
...@@ -557,11 +568,13 @@ static void iwl_bg_scan_completed(struct work_struct *work) ...@@ -557,11 +568,13 @@ static void iwl_bg_scan_completed(struct work_struct *work)
* Since setting the RXON may have been deferred while * Since setting the RXON may have been deferred while
* performing the scan, fire one off if needed * performing the scan, fire one off if needed
*/ */
if (memcmp(&priv->active_rxon, for_each_context(priv, ctx)
&priv->staging_rxon, sizeof(priv->staging_rxon))) iwlcore_commit_rxon(priv, ctx);
iwlcore_commit_rxon(priv);
out: out:
if (priv->cfg->ops->hcmd->set_pan_params)
priv->cfg->ops->hcmd->set_pan_params(priv);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
/* /*
......
This diff is collapsed.
...@@ -44,32 +44,37 @@ ...@@ -44,32 +44,37 @@
int iwl_remove_default_wep_key(struct iwl_priv *priv, int iwl_remove_default_wep_key(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
struct ieee80211_key_conf *key); struct ieee80211_key_conf *key);
int iwl_set_default_wep_key(struct iwl_priv *priv, int iwl_set_default_wep_key(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
struct ieee80211_key_conf *key); struct ieee80211_key_conf *key);
int iwl_restore_default_wep_keys(struct iwl_priv *priv); int iwl_restore_default_wep_keys(struct iwl_priv *priv,
int iwl_set_dynamic_key(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); 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); struct ieee80211_key_conf *key, u8 sta_id);
void iwl_update_tkip_key(struct iwl_priv *priv, void iwl_update_tkip_key(struct iwl_priv *priv,
struct ieee80211_key_conf *keyconf, struct iwl_rxon_context *ctx,
struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); 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); void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq); void iwl_clear_ucode_stations(struct iwl_priv *priv,
void iwl_dealloc_bcast_station(struct iwl_priv *priv); struct iwl_rxon_context *ctx);
int iwl_update_bcast_station(struct iwl_priv *priv); 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_get_free_ucode_key_index(struct iwl_priv *priv);
int iwl_send_add_sta(struct iwl_priv *priv, int iwl_send_add_sta(struct iwl_priv *priv,
struct iwl_addsta_cmd *sta, u8 flags); struct iwl_addsta_cmd *sta, u8 flags);
int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, int iwl_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
u8 *sta_id_r); const u8 *addr, bool init_rs, u8 *sta_id_r);
int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
bool is_ap, const u8 *addr, bool is_ap,
struct ieee80211_sta_ht_cap *ht_info, struct ieee80211_sta *sta, u8 *sta_id_r);
u8 *sta_id_r);
int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
const u8 *addr); const u8 *addr);
int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 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); ...@@ -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) static inline void iwl_clear_driver_stations(struct iwl_priv *priv)
{ {
unsigned long flags; unsigned long flags;
struct iwl_rxon_context *ctx;
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->sta_lock, flags);
memset(priv->stations, 0, sizeof(priv->stations)); memset(priv->stations, 0, sizeof(priv->stations));
priv->num_stations = 0; 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->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); spin_unlock_irqrestore(&priv->sta_lock, flags);
} }
...@@ -123,6 +133,7 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta) ...@@ -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 * iwl_sta_id_or_broadcast - return sta_id or broadcast sta
* @priv: iwl priv * @priv: iwl priv
* @context: the current context
* @sta: mac80211 station * @sta: mac80211 station
* *
* In certain circumstances mac80211 passes a station pointer * In certain circumstances mac80211 passes a station pointer
...@@ -131,12 +142,13 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta) ...@@ -131,12 +142,13 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta)
* inline wraps that pattern. * inline wraps that pattern.
*/ */
static inline int iwl_sta_id_or_broadcast(struct iwl_priv *priv, static inline int iwl_sta_id_or_broadcast(struct iwl_priv *priv,
struct iwl_rxon_context *context,
struct ieee80211_sta *sta) struct ieee80211_sta *sta)
{ {
int sta_id; int sta_id;
if (!sta) if (!sta)
return priv->hw_params.bcast_sta_id; return context->bcast_sta_id;
sta_id = iwl_sta_id(sta); sta_id = iwl_sta_id(sta);
......
...@@ -134,7 +134,7 @@ EXPORT_SYMBOL(iwl_tx_queue_free); ...@@ -134,7 +134,7 @@ EXPORT_SYMBOL(iwl_tx_queue_free);
*/ */
void iwl_cmd_queue_free(struct iwl_priv *priv) 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 iwl_queue *q = &txq->q;
struct device *dev = &priv->pci_dev->dev; struct device *dev = &priv->pci_dev->dev;
int i; int i;
...@@ -271,7 +271,7 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, ...@@ -271,7 +271,7 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,
/* Driver private data, only for Tx (not command) queues, /* Driver private data, only for Tx (not command) queues,
* not shared with device. */ * not shared with device. */
if (id != IWL_CMD_QUEUE_NUM) { if (id != priv->cmd_queue) {
txq->txb = kzalloc(sizeof(txq->txb[0]) * txq->txb = kzalloc(sizeof(txq->txb[0]) *
TFD_QUEUE_SIZE_MAX, GFP_KERNEL); TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
if (!txq->txb) { if (!txq->txb) {
...@@ -314,13 +314,13 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, ...@@ -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). * 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 * 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. * not have two scans at the same time, so only one is needed.
* For normal Tx queues (all other queues), no super-size command * For normal Tx queues (all other queues), no super-size command
* space is needed. * space is needed.
*/ */
if (txq_id == IWL_CMD_QUEUE_NUM) if (txq_id == priv->cmd_queue)
actual_slots++; actual_slots++;
txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * 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, ...@@ -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 * need an swq_id so don't set one to catch errors, all others can
* be set up to the identity mapping. * 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; txq->swq_id = txq_id;
/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise /* 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, ...@@ -385,7 +385,7 @@ void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
{ {
int actual_slots = slots_num; int actual_slots = slots_num;
if (txq_id == IWL_CMD_QUEUE_NUM) if (txq_id == priv->cmd_queue)
actual_slots++; actual_slots++;
memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots); memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots);
...@@ -413,7 +413,7 @@ EXPORT_SYMBOL(iwl_tx_queue_reset); ...@@ -413,7 +413,7 @@ EXPORT_SYMBOL(iwl_tx_queue_reset);
*/ */
int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) 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_queue *q = &txq->q;
struct iwl_device_cmd *out_cmd; struct iwl_device_cmd *out_cmd;
struct iwl_cmd_meta *out_meta; struct iwl_cmd_meta *out_meta;
...@@ -483,7 +483,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) ...@@ -483,7 +483,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
* information */ * information */
out_cmd->hdr.flags = 0; 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)); INDEX_TO_SEQ(q->write_ptr));
if (cmd->flags & CMD_SIZE_HUGE) if (cmd->flags & CMD_SIZE_HUGE)
out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
...@@ -500,15 +500,15 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) ...@@ -500,15 +500,15 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
get_cmd_string(out_cmd->hdr.cmd), get_cmd_string(out_cmd->hdr.cmd),
out_cmd->hdr.cmd, out_cmd->hdr.cmd,
le16_to_cpu(out_cmd->hdr.sequence), fix_size, le16_to_cpu(out_cmd->hdr.sequence), fix_size,
q->write_ptr, idx, IWL_CMD_QUEUE_NUM); q->write_ptr, idx, priv->cmd_queue);
break; break;
default: default:
IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, " IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, "
"%d bytes at %d[%d]:%d\n", "%d bytes at %d[%d]:%d\n",
get_cmd_string(out_cmd->hdr.cmd), get_cmd_string(out_cmd->hdr.cmd),
out_cmd->hdr.cmd, out_cmd->hdr.cmd,
le16_to_cpu(out_cmd->hdr.sequence), fix_size, 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 #endif
txq->need_update = 1; txq->need_update = 1;
...@@ -587,16 +587,16 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) ...@@ -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); bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
struct iwl_device_cmd *cmd; struct iwl_device_cmd *cmd;
struct iwl_cmd_meta *meta; 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 /* 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 * command queue then there a command routing bug has been introduced
* in the queue management code. */ * in the queue management code. */
if (WARN(txq_id != IWL_CMD_QUEUE_NUM, if (WARN(txq_id != priv->cmd_queue,
"wrong command queue %d, sequence 0x%X readp=%d writep=%d\n", "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
txq_id, sequence, txq_id, priv->cmd_queue, sequence,
priv->txq[IWL_CMD_QUEUE_NUM].q.read_ptr, priv->txq[priv->cmd_queue].q.read_ptr,
priv->txq[IWL_CMD_QUEUE_NUM].q.write_ptr)) { priv->txq[priv->cmd_queue].q.write_ptr)) {
iwl_print_hex_error(priv, pkt, 32); iwl_print_hex_error(priv, pkt, 32);
return; return;
} }
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment