aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
diff options
context:
space:
mode:
authorSara Sharon <sara.sharon@intel.com>2018-08-21 08:23:39 -0400
committerLuca Coelho <luciano.coelho@intel.com>2019-01-25 13:57:19 -0500
commitcfbc6c4c5b91c7725ef14465b98ac347d31f2334 (patch)
treeec174a10264bd09381be46580078739dd2d83ef4 /drivers/net/wireless/intel/iwlwifi/mvm/ops.c
parentc281f13792f64372f49b63eab4c1ce88282448d2 (diff)
iwlwifi: mvm: support mac80211 TXQs model
Move to use the new mac80211 TXQs implementation. This has quite a few benefits for us. We can get rid of the awkward mapping of DQA to mac80211 queues. We can stop buffering traffic while waiting for the queue to be allocated. We can also use mac80211 AMSDUs instead of building it ourselves. The usage is pretty simple: Each ieee80211_txq contains iwl_mvm_txq. There is such a queue for each TID, and one for management frames. We keep having static AP queues for probes and non-bufferable MMPDUs, along with broadcast and multicast queues. Those are being used from the "old" TX invocation path - iwl_mvm_mac_tx. When there is a new frame in a TXQ, iwl_mvm_mac_wake_tx is being called, and either invokes the TX path, or allocates the queue if it does not exist. Most of the TX path is left untouched, although we can consider cleaning it up some more, for example get rid of the duplication of txq_id in both iwl_mvm_txq and iwl_mvm_dqa_txq_info. Signed-off-by: Sara Sharon <sara.sharon@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/ops.c')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c87
1 files changed, 49 insertions, 38 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 30c5127034a0..d257c143e624 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -685,6 +685,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
685 INIT_DELAYED_WORK(&mvm->tdls_cs.dwork, iwl_mvm_tdls_ch_switch_work); 685 INIT_DELAYED_WORK(&mvm->tdls_cs.dwork, iwl_mvm_tdls_ch_switch_work);
686 INIT_DELAYED_WORK(&mvm->scan_timeout_dwork, iwl_mvm_scan_timeout_wk); 686 INIT_DELAYED_WORK(&mvm->scan_timeout_dwork, iwl_mvm_scan_timeout_wk);
687 INIT_WORK(&mvm->add_stream_wk, iwl_mvm_add_new_dqa_stream_wk); 687 INIT_WORK(&mvm->add_stream_wk, iwl_mvm_add_new_dqa_stream_wk);
688 INIT_LIST_HEAD(&mvm->add_stream_txqs);
688 689
689 spin_lock_init(&mvm->d0i3_tx_lock); 690 spin_lock_init(&mvm->d0i3_tx_lock);
690 spin_lock_init(&mvm->refs_lock); 691 spin_lock_init(&mvm->refs_lock);
@@ -1079,24 +1080,6 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode,
1079 iwl_mvm_rx_common(mvm, rxb, pkt); 1080 iwl_mvm_rx_common(mvm, rxb, pkt);
1080} 1081}
1081 1082
1082void iwl_mvm_stop_mac_queues(struct iwl_mvm *mvm, unsigned long mq)
1083{
1084 int q;
1085
1086 if (WARN_ON_ONCE(!mq))
1087 return;
1088
1089 for_each_set_bit(q, &mq, IEEE80211_MAX_QUEUES) {
1090 if (atomic_inc_return(&mvm->mac80211_queue_stop_count[q]) > 1) {
1091 IWL_DEBUG_TX_QUEUES(mvm,
1092 "mac80211 %d already stopped\n", q);
1093 continue;
1094 }
1095
1096 ieee80211_stop_queue(mvm->hw, q);
1097 }
1098}
1099
1100static void iwl_mvm_async_cb(struct iwl_op_mode *op_mode, 1083static void iwl_mvm_async_cb(struct iwl_op_mode *op_mode,
1101 const struct iwl_device_cmd *cmd) 1084 const struct iwl_device_cmd *cmd)
1102{ 1085{
@@ -1109,38 +1092,66 @@ static void iwl_mvm_async_cb(struct iwl_op_mode *op_mode,
1109 iwl_trans_block_txq_ptrs(mvm->trans, false); 1092 iwl_trans_block_txq_ptrs(mvm->trans, false);
1110} 1093}
1111 1094
1112static void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int hw_queue) 1095static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode,
1096 int hw_queue, bool start)
1113{ 1097{
1114 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 1098 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
1115 unsigned long mq = mvm->hw_queue_to_mac80211[hw_queue]; 1099 struct ieee80211_sta *sta;
1100 struct ieee80211_txq *txq;
1101 struct iwl_mvm_txq *mvmtxq;
1102 int i;
1103 unsigned long tid_bitmap;
1104 struct iwl_mvm_sta *mvmsta;
1105 u8 sta_id;
1116 1106
1117 iwl_mvm_stop_mac_queues(mvm, mq); 1107 sta_id = iwl_mvm_has_new_tx_api(mvm) ?
1118} 1108 mvm->tvqm_info[hw_queue].sta_id :
1109 mvm->queue_info[hw_queue].ra_sta_id;
1119 1110
1120void iwl_mvm_start_mac_queues(struct iwl_mvm *mvm, unsigned long mq) 1111 if (WARN_ON_ONCE(sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id)))
1121{
1122 int q;
1123
1124 if (WARN_ON_ONCE(!mq))
1125 return; 1112 return;
1126 1113
1127 for_each_set_bit(q, &mq, IEEE80211_MAX_QUEUES) { 1114 rcu_read_lock();
1128 if (atomic_dec_return(&mvm->mac80211_queue_stop_count[q]) > 0) {
1129 IWL_DEBUG_TX_QUEUES(mvm,
1130 "mac80211 %d still stopped\n", q);
1131 continue;
1132 }
1133 1115
1134 ieee80211_wake_queue(mvm->hw, q); 1116 sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
1117 if (IS_ERR_OR_NULL(sta))
1118 goto out;
1119 mvmsta = iwl_mvm_sta_from_mac80211(sta);
1120
1121 if (iwl_mvm_has_new_tx_api(mvm)) {
1122 int tid = mvm->tvqm_info[hw_queue].txq_tid;
1123
1124 tid_bitmap = BIT(tid);
1125 } else {
1126 tid_bitmap = mvm->queue_info[hw_queue].tid_bitmap;
1127 }
1128
1129 for_each_set_bit(i, &tid_bitmap, IWL_MAX_TID_COUNT + 1) {
1130 int tid = i;
1131
1132 if (tid == IWL_MAX_TID_COUNT)
1133 tid = IEEE80211_NUM_TIDS;
1134
1135 txq = sta->txq[tid];
1136 mvmtxq = iwl_mvm_txq_from_mac80211(txq);
1137 mvmtxq->stopped = !start;
1138
1139 if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST)
1140 iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
1135 } 1141 }
1142
1143out:
1144 rcu_read_unlock();
1136} 1145}
1137 1146
1138static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int hw_queue) 1147static void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int hw_queue)
1139{ 1148{
1140 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 1149 iwl_mvm_queue_state_change(op_mode, hw_queue, false);
1141 unsigned long mq = mvm->hw_queue_to_mac80211[hw_queue]; 1150}
1142 1151
1143 iwl_mvm_start_mac_queues(mvm, mq); 1152static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int hw_queue)
1153{
1154 iwl_mvm_queue_state_change(op_mode, hw_queue, true);
1144} 1155}
1145 1156
1146static void iwl_mvm_set_rfkill_state(struct iwl_mvm *mvm) 1157static void iwl_mvm_set_rfkill_state(struct iwl_mvm *mvm)