Skip to content

Commit

Permalink
mac80211: Add TXQ scheduling API
Browse files Browse the repository at this point in the history
This adds an API to mac80211 to handle scheduling of TXQs and changes the
interface between driver and mac80211 for TXQ handling as follows:

- The wake_tx_queue callback interface no longer includes the TXQ. Instead,
  the driver is expected to retrieve that from ieee80211_next_txq()

- Two new mac80211 functions are added: ieee80211_next_txq() and
  ieee80211_schedule_txq(). The former returns the next TXQ that should be
  scheduled, and is how the driver gets a queue to pull packets from. The
  latter is called internally by mac80211 to start scheduling a queue, and
  the driver is supposed to call it to re-schedule the TXQ after it is
  finished pulling packets from it (unless the queue emptied).

The ath9k and ath10k drivers are changed to use the new API.

Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Toke Høiland-Jørgensen authored and Johannes Berg committed Dec 11, 2017
1 parent 9de18d8 commit e937b8d
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 262 deletions.
2 changes: 0 additions & 2 deletions drivers/net/wireless/ath/ath10k/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2574,9 +2574,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,

mutex_init(&ar->conf_mutex);
spin_lock_init(&ar->data_lock);
spin_lock_init(&ar->txqs_lock);

INIT_LIST_HEAD(&ar->txqs);
INIT_LIST_HEAD(&ar->peers);
init_waitqueue_head(&ar->peer_mapping_wq);
init_waitqueue_head(&ar->htt.empty_tx_wq);
Expand Down
4 changes: 0 additions & 4 deletions drivers/net/wireless/ath/ath10k/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,6 @@ struct ath10k_peer {
};

struct ath10k_txq {
struct list_head list;
unsigned long num_fw_queued;
unsigned long num_push_allowed;
};
Expand Down Expand Up @@ -895,10 +894,7 @@ struct ath10k {

/* protects shared structure data */
spinlock_t data_lock;
/* protects: ar->txqs, artxq->list */
spinlock_t txqs_lock;

struct list_head txqs;
struct list_head arvifs;
struct list_head peers;
struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS];
Expand Down
55 changes: 16 additions & 39 deletions drivers/net/wireless/ath/ath10k/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -3830,25 +3830,17 @@ static void ath10k_mac_txq_init(struct ieee80211_txq *txq)
return;

artxq = (void *)txq->drv_priv;
INIT_LIST_HEAD(&artxq->list);
}

static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq)
{
struct ath10k_txq *artxq;
struct ath10k_skb_cb *cb;
struct sk_buff *msdu;
int msdu_id;

if (!txq)
return;

artxq = (void *)txq->drv_priv;
spin_lock_bh(&ar->txqs_lock);
if (!list_empty(&artxq->list))
list_del_init(&artxq->list);
spin_unlock_bh(&ar->txqs_lock);

spin_lock_bh(&ar->htt.tx_lock);
idr_for_each_entry(&ar->htt.pending_tx, msdu, msdu_id) {
cb = ATH10K_SKB_CB(msdu);
Expand Down Expand Up @@ -3978,23 +3970,17 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
void ath10k_mac_tx_push_pending(struct ath10k *ar)
{
struct ieee80211_hw *hw = ar->hw;
struct ieee80211_txq *txq;
struct ath10k_txq *artxq;
struct ath10k_txq *last;
struct ieee80211_txq *txq, *first = NULL;
int ret;
int max;

if (ar->htt.num_pending_tx >= (ar->htt.max_num_pending_tx / 2))
return;

spin_lock_bh(&ar->txqs_lock);
rcu_read_lock();

last = list_last_entry(&ar->txqs, struct ath10k_txq, list);
while (!list_empty(&ar->txqs)) {
artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list);
txq = container_of((void *)artxq, struct ieee80211_txq,
drv_priv);
txq = ieee80211_next_txq(hw);
while (txq) {

/* Prevent aggressive sta/tid taking over tx queue */
max = 16;
Expand All @@ -4005,18 +3991,21 @@ void ath10k_mac_tx_push_pending(struct ath10k *ar)
break;
}

list_del_init(&artxq->list);
if (ret != -ENOENT)
list_add_tail(&artxq->list, &ar->txqs);
ieee80211_schedule_txq(hw, txq);

ath10k_htt_tx_txq_update(hw, txq);

if (artxq == last || (ret < 0 && ret != -ENOENT))
if (first == txq || (ret < 0 && ret != -ENOENT))
break;

if (!first)
first = txq;

txq = ieee80211_next_txq(hw);
}

rcu_read_unlock();
spin_unlock_bh(&ar->txqs_lock);
}

/************/
Expand Down Expand Up @@ -4250,34 +4239,22 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
}
}

static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
struct ieee80211_txq *txq)
static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw)
{
struct ath10k *ar = hw->priv;
struct ath10k_txq *artxq = (void *)txq->drv_priv;
struct ieee80211_txq *f_txq;
struct ath10k_txq *f_artxq;
struct ieee80211_txq *txq;
int ret = 0;
int max = 16;

spin_lock_bh(&ar->txqs_lock);
if (list_empty(&artxq->list))
list_add_tail(&artxq->list, &ar->txqs);

f_artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list);
f_txq = container_of((void *)f_artxq, struct ieee80211_txq, drv_priv);
list_del_init(&f_artxq->list);
txq = ieee80211_next_txq(hw);

while (ath10k_mac_tx_can_push(hw, f_txq) && max--) {
ret = ath10k_mac_tx_push_txq(hw, f_txq);
while (ath10k_mac_tx_can_push(hw, txq) && max--) {
ret = ath10k_mac_tx_push_txq(hw, txq);
if (ret)
break;
}
if (ret != -ENOENT)
list_add_tail(&f_artxq->list, &ar->txqs);
spin_unlock_bh(&ar->txqs_lock);
ieee80211_schedule_txq(hw, txq);

ath10k_htt_tx_txq_update(hw, f_txq);
ath10k_htt_tx_txq_update(hw, txq);
}

Expand Down
9 changes: 2 additions & 7 deletions drivers/net/wireless/ath/ath9k/ath9k.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,8 @@ struct ath_atx_tid {
s8 bar_index;
bool active;
bool clear_ps_filter;
bool has_queued;
};

void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid);

struct ath_node {
struct ath_softc *sc;
struct ieee80211_sta *sta; /* station struct we're part of */
Expand Down Expand Up @@ -591,8 +587,7 @@ bool ath_drain_all_txq(struct ath_softc *sc);
void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq);
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
void ath_txq_schedule_all(struct ath_softc *sc);
void ath_txq_schedule(struct ath_softc *sc);
int ath_tx_init(struct ath_softc *sc, int nbufs);
int ath_txq_update(struct ath_softc *sc, int qnum,
struct ath9k_tx_queue_info *q);
Expand All @@ -618,7 +613,7 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
u16 tids, int nframes,
enum ieee80211_frame_release_type reason,
bool more_data);
void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue);
void ath9k_wake_tx_queue(struct ieee80211_hw *hw);

/********/
/* VIFs */
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/ath/ath9k/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
}
work:
ath_restart_work(sc);
ath_txq_schedule_all(sc);
ath_txq_schedule(sc);
}

sc->gtt_cnt = 0;
Expand Down
2 changes: 0 additions & 2 deletions drivers/net/wireless/ath/ath9k/recv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1057,8 +1057,6 @@ static void ath_rx_count_airtime(struct ath_softc *sc,
if (!!(sc->airtime_flags & AIRTIME_USE_RX)) {
spin_lock_bh(&acq->lock);
an->airtime_deficit[acno] -= airtime;
if (an->airtime_deficit[acno] <= 0)
__ath_tx_queue_tid(sc, ATH_AN_2_TID(an, tidno));
spin_unlock_bh(&acq->lock);
}
ath_debug_airtime(sc, an, airtime, 0);
Expand Down
Loading

0 comments on commit e937b8d

Please sign in to comment.