@@ -35,6 +35,8 @@
#include "coredump.h"
unsigned int ath10k_debug_mask;
+unsigned int ath10k_wake_tx_queue_max = 16;
+unsigned int ath10k_prio_sta_aid = 0;
static unsigned int ath10k_cryptmode_param;
static bool uart_print;
static bool skip_otp;
@@ -47,6 +49,8 @@ unsigned long ath10k_coredump_mask = 0x3;
/* FIXME: most of these should be readonly */
module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);
+module_param_named(wake_tx_queue_max, ath10k_wake_tx_queue_max, uint, 0644);
+module_param_named(prio_sta_aid, ath10k_prio_sta_aid, uint, 0644);
module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644);
module_param(uart_print, bool, 0644);
module_param(skip_otp, bool, 0644);
@@ -54,6 +58,7 @@ module_param(rawmode, bool, 0644);
module_param_named(coredump_mask, ath10k_coredump_mask, ulong, 0444);
MODULE_PARM_DESC(debug_mask, "Debugging mask");
+MODULE_PARM_DESC(wake_tx_queue_max, "Max time for wake_tx_queue send txq");
MODULE_PARM_DESC(uart_print, "Uart target debugging");
MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");
@@ -2732,6 +2737,8 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
spin_lock_init(&ar->txqs_lock);
INIT_LIST_HEAD(&ar->txqs);
+ INIT_LIST_HEAD(&ar->txqs_prio_sta);
+ ar->is_txqs_prio_sta = 0;
INIT_LIST_HEAD(&ar->peers);
init_waitqueue_head(&ar->peer_mapping_wq);
init_waitqueue_head(&ar->htt.empty_tx_wq);
@@ -907,6 +907,8 @@ struct ath10k {
spinlock_t txqs_lock;
struct list_head txqs;
+ struct list_head txqs_prio_sta;
+ int is_txqs_prio_sta;
struct list_head arvifs;
struct list_head peers;
struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS];
@@ -33,6 +33,10 @@
#include "wmi-ops.h"
#include "wow.h"
+
+extern unsigned int ath10k_wake_tx_queue_max;
+extern unsigned int ath10k_prio_sta_aid;
+
/*********/
/* Rates */
/*********/
@@ -4260,23 +4264,45 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
struct ieee80211_txq *f_txq;
struct ath10k_txq *f_artxq;
int ret = 0;
- int max = 16;
+ unsigned max = 16;
+ int txqs_prio_sta = 0;
+ int txq_sta_aid = txq->sta ? txq->sta->aid : -1;
+
+ /* Claim there is an prio station txq */
+ if (txq_sta_aid == ath10k_prio_sta_aid)
+ ar->is_txqs_prio_sta = 1;
spin_lock_bh(&ar->txqs_lock);
- if (list_empty(&artxq->list))
- list_add_tail(&artxq->list, &ar->txqs);
+ max = ath10k_wake_tx_queue_max;
+ ar->is_txqs_prio_sta = 0;
+ if (list_empty(&artxq->list)) {
+ if (txq_sta_aid == ath10k_prio_sta_aid) {
+ list_add_tail(&artxq->list, &ar->txqs_prio_sta);
+ } else {
+ list_add_tail(&artxq->list, &ar->txqs);
+ }
+ }
- f_artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list);
+ txqs_prio_sta = !list_empty(&ar->txqs_prio_sta);
+ f_artxq = list_first_entry(txqs_prio_sta ? &ar->txqs_prio_sta : &ar->txqs, struct ath10k_txq, list);
f_txq = container_of((void *)f_artxq, struct ieee80211_txq, drv_priv);
list_del_init(&f_artxq->list);
+ ret = 0;
+ txq_sta_aid = f_txq->sta ? f_txq->sta->aid : -1;
+ ath10k_dbg(ar, ATH10K_DBG_MAC, "mac wake aid:%d ac:%d tid:%d\n",
+ txq_sta_aid, f_txq->ac, f_txq->tid);
while (ath10k_mac_tx_can_push(hw, f_txq) && max--) {
+ if (ar->is_txqs_prio_sta == 1 && txq_sta_aid != ath10k_prio_sta_aid)
+ break;
ret = ath10k_mac_tx_push_txq(hw, f_txq);
if (ret)
break;
}
- if (ret != -ENOENT)
- list_add_tail(&f_artxq->list, &ar->txqs);
+
+ if (ret != -ENOENT && ret) {
+ list_add_tail(&f_artxq->list, txqs_prio_sta ? &ar->txqs_prio_sta : &ar->txqs);
+ }
spin_unlock_bh(&ar->txqs_lock);
ath10k_htt_tx_txq_update(hw, f_txq);