Commit 1479177b authored by Johannes Berg's avatar Johannes Berg Committed by Wey-Yi Guy

iwlwifi: use new mac80211 queue scheme

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarWey-Yi Guy <wey-yi.w.guy@intel.com>
parent 65de7e84
...@@ -463,6 +463,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ...@@ -463,6 +463,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
else else
txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)];
WARN_ON_ONCE(!is_agg && txq_id != info->hw_queue);
WARN_ON_ONCE(is_agg &&
priv->queue_to_mac80211[txq_id] != info->hw_queue);
if (iwl_trans_tx(priv->trans, skb, dev_cmd, txq_id)) if (iwl_trans_tx(priv->trans, skb, dev_cmd, txq_id))
goto drop_unlock_sta; goto drop_unlock_sta;
...@@ -492,14 +496,14 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ...@@ -492,14 +496,14 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
return -1; return -1;
} }
static int iwlagn_alloc_agg_txq(struct iwl_priv *priv, int ac) static int iwlagn_alloc_agg_txq(struct iwl_priv *priv, int mq)
{ {
int q; int q;
for (q = IWLAGN_FIRST_AMPDU_QUEUE; for (q = IWLAGN_FIRST_AMPDU_QUEUE;
q < priv->cfg->base_params->num_of_queues; q++) { q < priv->cfg->base_params->num_of_queues; q++) {
if (!test_and_set_bit(q, priv->agg_q_alloc)) { if (!test_and_set_bit(q, priv->agg_q_alloc)) {
priv->queue_to_ac[q] = ac; priv->queue_to_mac80211[q] = mq;
return q; return q;
} }
} }
...@@ -510,7 +514,7 @@ static int iwlagn_alloc_agg_txq(struct iwl_priv *priv, int ac) ...@@ -510,7 +514,7 @@ static int iwlagn_alloc_agg_txq(struct iwl_priv *priv, int ac)
static void iwlagn_dealloc_agg_txq(struct iwl_priv *priv, int q) static void iwlagn_dealloc_agg_txq(struct iwl_priv *priv, int q)
{ {
clear_bit(q, priv->agg_q_alloc); clear_bit(q, priv->agg_q_alloc);
priv->queue_to_ac[q] = IWL_INVALID_AC; priv->queue_to_mac80211[q] = IWL_INVALID_MAC80211_QUEUE;
} }
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
...@@ -602,6 +606,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, ...@@ -602,6 +606,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid, u16 *ssn) struct ieee80211_sta *sta, u16 tid, u16 *ssn)
{ {
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
struct iwl_tid_data *tid_data; struct iwl_tid_data *tid_data;
int sta_id, txq_id, ret; int sta_id, txq_id, ret;
...@@ -621,7 +626,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, ...@@ -621,7 +626,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
return -ENXIO; return -ENXIO;
} }
txq_id = iwlagn_alloc_agg_txq(priv, tid_to_ac[tid]); txq_id = iwlagn_alloc_agg_txq(priv, ctx->ac_to_queue[tid_to_ac[tid]]);
if (txq_id < 0) { if (txq_id < 0) {
IWL_DEBUG_TX_QUEUES(priv, IWL_DEBUG_TX_QUEUES(priv,
"No free aggregation queue for %pM/%d\n", "No free aggregation queue for %pM/%d\n",
......
...@@ -578,24 +578,6 @@ static const u8 iwlagn_pan_ac_to_queue[] = { ...@@ -578,24 +578,6 @@ static const u8 iwlagn_pan_ac_to_queue[] = {
7, 6, 5, 4, 7, 6, 5, 4,
}; };
static const u8 iwlagn_bss_queue_to_ac[] = {
IEEE80211_AC_VO,
IEEE80211_AC_VI,
IEEE80211_AC_BE,
IEEE80211_AC_BK,
};
static const u8 iwlagn_pan_queue_to_ac[] = {
IEEE80211_AC_VO,
IEEE80211_AC_VI,
IEEE80211_AC_BE,
IEEE80211_AC_BK,
IEEE80211_AC_BK,
IEEE80211_AC_BE,
IEEE80211_AC_VI,
IEEE80211_AC_VO,
};
void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
{ {
int i; int i;
...@@ -1030,12 +1012,12 @@ void iwlagn_prepare_restart(struct iwl_priv *priv) ...@@ -1030,12 +1012,12 @@ void iwlagn_prepare_restart(struct iwl_priv *priv)
priv->bt_status = bt_status; priv->bt_status = bt_status;
priv->bt_is_sco = bt_is_sco; priv->bt_is_sco = bt_is_sco;
/* reset all queues */ /* reset aggregation queues */
for (i = 0; i < IEEE80211_NUM_ACS; i++)
atomic_set(&priv->ac_stop_count[i], 0);
for (i = IWLAGN_FIRST_AMPDU_QUEUE; i < IWL_MAX_HW_QUEUES; i++) for (i = IWLAGN_FIRST_AMPDU_QUEUE; i < IWL_MAX_HW_QUEUES; i++)
priv->queue_to_ac[i] = IWL_INVALID_AC; priv->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE;
/* and stop counts */
for (i = 0; i < IWL_MAX_HW_QUEUES; i++)
atomic_set(&priv->queue_stop_count[i], 0);
memset(priv->agg_q_alloc, 0, sizeof(priv->agg_q_alloc)); memset(priv->agg_q_alloc, 0, sizeof(priv->agg_q_alloc));
} }
...@@ -1491,8 +1473,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, ...@@ -1491,8 +1473,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
STATISTICS_NOTIFICATION, STATISTICS_NOTIFICATION,
REPLY_TX, REPLY_TX,
}; };
const u8 *q_to_ac;
int n_q_to_ac;
int i; int i;
/************************ /************************
...@@ -1575,16 +1555,12 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, ...@@ -1575,16 +1555,12 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
trans_cfg.queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo; trans_cfg.queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo;
trans_cfg.n_queue_to_fifo = trans_cfg.n_queue_to_fifo =
ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo); ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo);
q_to_ac = iwlagn_pan_queue_to_ac;
n_q_to_ac = ARRAY_SIZE(iwlagn_pan_queue_to_ac);
} else { } else {
priv->sta_key_max_num = STA_KEY_MAX_NUM; priv->sta_key_max_num = STA_KEY_MAX_NUM;
trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
trans_cfg.queue_to_fifo = iwlagn_default_queue_to_tx_fifo; trans_cfg.queue_to_fifo = iwlagn_default_queue_to_tx_fifo;
trans_cfg.n_queue_to_fifo = trans_cfg.n_queue_to_fifo =
ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo);
q_to_ac = iwlagn_bss_queue_to_ac;
n_q_to_ac = ARRAY_SIZE(iwlagn_bss_queue_to_ac);
} }
/* Configure transport layer */ /* Configure transport layer */
...@@ -1670,8 +1646,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, ...@@ -1670,8 +1646,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
trans_cfg.queue_to_fifo = iwlagn_default_queue_to_tx_fifo; trans_cfg.queue_to_fifo = iwlagn_default_queue_to_tx_fifo;
trans_cfg.n_queue_to_fifo = trans_cfg.n_queue_to_fifo =
ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo);
q_to_ac = iwlagn_bss_queue_to_ac;
n_q_to_ac = ARRAY_SIZE(iwlagn_bss_queue_to_ac);
/* Configure transport layer again*/ /* Configure transport layer again*/
iwl_trans_configure(priv->trans, &trans_cfg); iwl_trans_configure(priv->trans, &trans_cfg);
...@@ -1680,14 +1654,13 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, ...@@ -1680,14 +1654,13 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
/******************* /*******************
* 5. Setup priv * 5. Setup priv
*******************/ *******************/
for (i = 0; i < IEEE80211_NUM_ACS; i++)
atomic_set(&priv->ac_stop_count[i], 0);
for (i = 0; i < IWL_MAX_HW_QUEUES; i++) { for (i = 0; i < IWL_MAX_HW_QUEUES; i++) {
if (i < n_q_to_ac) priv->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE;
priv->queue_to_ac[i] = q_to_ac[i]; if (i < IWLAGN_FIRST_AMPDU_QUEUE &&
else i != IWL_DEFAULT_CMD_QUEUE_NUM &&
priv->queue_to_ac[i] = IWL_INVALID_AC; i != IWL_IPAN_CMD_QUEUE_NUM)
priv->queue_to_mac80211[i] = i;
atomic_set(&priv->queue_stop_count[i], 0);
} }
WARN_ON(trans_cfg.queue_to_fifo[trans_cfg.cmd_queue] != WARN_ON(trans_cfg.queue_to_fifo[trans_cfg.cmd_queue] !=
...@@ -2256,56 +2229,56 @@ static void iwl_wimax_active(struct iwl_op_mode *op_mode) ...@@ -2256,56 +2229,56 @@ static void iwl_wimax_active(struct iwl_op_mode *op_mode)
void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue)
{ {
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
int ac = priv->queue_to_ac[queue]; int mq = priv->queue_to_mac80211[queue];
if (WARN_ON_ONCE(ac == IWL_INVALID_AC)) if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE))
return; return;
if (atomic_inc_return(&priv->ac_stop_count[ac]) > 1) { if (atomic_inc_return(&priv->queue_stop_count[mq]) > 1) {
IWL_DEBUG_TX_QUEUES(priv, IWL_DEBUG_TX_QUEUES(priv,
"queue %d (AC %d) already stopped\n", "queue %d (mac80211 %d) already stopped\n",
queue, ac); queue, mq);
return; return;
} }
set_bit(ac, &priv->transport_queue_stop); set_bit(mq, &priv->transport_queue_stop);
ieee80211_stop_queue(priv->hw, ac); ieee80211_stop_queue(priv->hw, mq);
} }
void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue)
{ {
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
int ac = priv->queue_to_ac[queue]; int mq = priv->queue_to_mac80211[queue];
if (WARN_ON_ONCE(ac == IWL_INVALID_AC)) if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE))
return; return;
if (atomic_dec_return(&priv->ac_stop_count[ac]) > 0) { if (atomic_dec_return(&priv->queue_stop_count[mq]) > 0) {
IWL_DEBUG_TX_QUEUES(priv, IWL_DEBUG_TX_QUEUES(priv,
"queue %d (AC %d) already awake\n", "queue %d (mac80211 %d) already awake\n",
queue, ac); queue, mq);
return; return;
} }
clear_bit(ac, &priv->transport_queue_stop); clear_bit(mq, &priv->transport_queue_stop);
if (!priv->passive_no_rx) if (!priv->passive_no_rx)
ieee80211_wake_queue(priv->hw, ac); ieee80211_wake_queue(priv->hw, mq);
} }
void iwlagn_lift_passive_no_rx(struct iwl_priv *priv) void iwlagn_lift_passive_no_rx(struct iwl_priv *priv)
{ {
int ac; int mq;
if (!priv->passive_no_rx) if (!priv->passive_no_rx)
return; return;
for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++) { for (mq = 0; mq < IWLAGN_FIRST_AMPDU_QUEUE; mq++) {
if (!test_bit(ac, &priv->transport_queue_stop)) { if (!test_bit(mq, &priv->transport_queue_stop)) {
IWL_DEBUG_TX_QUEUES(priv, "Wake queue %d"); IWL_DEBUG_TX_QUEUES(priv, "Wake queue %d", mq);
ieee80211_wake_queue(priv->hw, ac); ieee80211_wake_queue(priv->hw, mq);
} else { } else {
IWL_DEBUG_TX_QUEUES(priv, "Don't wake queue %d"); IWL_DEBUG_TX_QUEUES(priv, "Don't wake queue %d", mq);
} }
} }
......
...@@ -727,9 +727,9 @@ struct iwl_priv { ...@@ -727,9 +727,9 @@ struct iwl_priv {
unsigned long transport_queue_stop; unsigned long transport_queue_stop;
bool passive_no_rx; bool passive_no_rx;
#define IWL_INVALID_AC 0xff #define IWL_INVALID_MAC80211_QUEUE 0xff
u8 queue_to_ac[IWL_MAX_HW_QUEUES]; u8 queue_to_mac80211[IWL_MAX_HW_QUEUES];
atomic_t ac_stop_count[IEEE80211_NUM_ACS]; atomic_t queue_stop_count[IWL_MAX_HW_QUEUES];
unsigned long agg_q_alloc[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; unsigned long agg_q_alloc[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
......
...@@ -146,7 +146,13 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, ...@@ -146,7 +146,13 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_AMPDU_AGGREGATION |
IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_NEED_DTIM_PERIOD |
IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_SPECTRUM_MGMT |
IEEE80211_HW_REPORTS_TX_ACK_STATUS; IEEE80211_HW_REPORTS_TX_ACK_STATUS |
IEEE80211_HW_QUEUE_CONTROL |
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
IEEE80211_HW_SCAN_WHILE_IDLE;
hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE;
/* /*
* Including the following line will crash some AP's. This * Including the following line will crash some AP's. This
...@@ -155,10 +161,6 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, ...@@ -155,10 +161,6 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF; hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
*/ */
hw->flags |= IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
IEEE80211_HW_SCAN_WHILE_IDLE;
if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE) if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE)
hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
IEEE80211_HW_SUPPORTS_STATIC_SMPS; IEEE80211_HW_SUPPORTS_STATIC_SMPS;
...@@ -224,8 +226,11 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, ...@@ -224,8 +226,11 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
/* we create the 802.11 header and a zero-length SSID element */ /* we create the 802.11 header and a zero-length SSID element */
hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 2; hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 2;
/* Default value; 4 EDCA QOS priorities */ /*
hw->queues = 4; * We don't use all queues: 4 and 9 are unused and any
* aggregation queue gets mapped down to the AC queue.
*/
hw->queues = IWLAGN_FIRST_AMPDU_QUEUE;
hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
...@@ -1218,7 +1223,7 @@ static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx) ...@@ -1218,7 +1223,7 @@ static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
int iwl_setup_interface(struct iwl_priv *priv, struct iwl_rxon_context *ctx) int iwl_setup_interface(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{ {
struct ieee80211_vif *vif = ctx->vif; struct ieee80211_vif *vif = ctx->vif;
int err; int err, ac;
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->mutex);
...@@ -1248,11 +1253,20 @@ int iwl_setup_interface(struct iwl_priv *priv, struct iwl_rxon_context *ctx) ...@@ -1248,11 +1253,20 @@ int iwl_setup_interface(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH; priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
} }
/* set up queue mappings */
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
vif->hw_queue[ac] = ctx->ac_to_queue[ac];
if (vif->type == NL80211_IFTYPE_AP)
vif->cab_queue = ctx->mcast_queue;
else
vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
return 0; return 0;
} }
static int iwlagn_mac_add_interface(struct ieee80211_hw *hw, static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
......
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