Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 236759
b: refs/heads/master
c: 60f2d1d
h: refs/heads/master
i:
  236757: 67158a4
  236755: bc45307
  236751: 5b20287
v: v3
  • Loading branch information
Ben Greear authored and John W. Linville committed Jan 21, 2011
1 parent 09786bc commit cb195fa
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 30 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 71e025a5a630681ad8b37d4426a994d199976ec9
refs/heads/master: 60f2d1d506195803fa6e1dcf3972637b740fdd60
9 changes: 8 additions & 1 deletion trunk/drivers/net/wireless/ath/ath9k/ath9k.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ enum ATH_AGGR_STATUS {

#define ATH_TXFIFO_DEPTH 8
struct ath_txq {
u32 axq_qnum;
int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
u32 axq_qnum; /* ath9k hardware queue number */
u32 *axq_link;
struct list_head axq_q;
spinlock_t axq_lock;
Expand Down Expand Up @@ -280,6 +281,11 @@ struct ath_tx_control {
#define ATH_TX_XRETRY 0x02
#define ATH_TX_BAR 0x04

/**
* @txq_map: Index is mac80211 queue number. This is
* not necessarily the same as the hardware queue number
* (axq_qnum).
*/
struct ath_tx {
u16 seq_no;
u32 txqsetup;
Expand Down Expand Up @@ -643,6 +649,7 @@ struct ath_softc {
struct ath9k_debug debug;
spinlock_t nodes_lock;
struct list_head nodes; /* basically, stations */
unsigned int tx_complete_poll_work_seen;
#endif
struct ath_beacon_config cur_beacon_conf;
struct delayed_work tx_complete_work;
Expand Down
4 changes: 3 additions & 1 deletion trunk/drivers/net/wireless/ath/ath9k/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -629,9 +629,11 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
if (buf == NULL)
return -ENOMEM;

len += sprintf(buf, "Num-Tx-Queues: %i tx-queues-setup: 0x%x\n"
len += sprintf(buf, "Num-Tx-Queues: %i tx-queues-setup: 0x%x"
" poll-work-seen: %u\n"
"%30s %10s%10s%10s\n\n",
ATH9K_NUM_TX_QUEUES, sc->tx.txqsetup,
sc->tx_complete_poll_work_seen,
"BE", "BK", "VI", "VO");

PR("MPDUs Queued: ", queued);
Expand Down
5 changes: 3 additions & 2 deletions trunk/drivers/net/wireless/ath/ath9k/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,9 +442,10 @@ static int ath9k_init_queues(struct ath_softc *sc)
sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
ath_cabq_update(sc);

for (i = 0; i < WME_NUM_AC; i++)
for (i = 0; i < WME_NUM_AC; i++) {
sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);

sc->tx.txq_map[i]->mac80211_qnum = i;
}
return 0;
}

Expand Down
79 changes: 54 additions & 25 deletions trunk/drivers/net/wireless/ath/ath9k/xmit.c
Original file line number Diff line number Diff line change
Expand Up @@ -945,7 +945,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
[WME_AC_VI] = ATH_TXQ_AC_VI,
[WME_AC_VO] = ATH_TXQ_AC_VO,
};
int qnum, i;
int axq_qnum, i;

memset(&qi, 0, sizeof(qi));
qi.tqi_subtype = subtype_txq_to_hwq[subtype];
Expand Down Expand Up @@ -979,39 +979,40 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
TXQ_FLAG_TXDESCINT_ENABLE;
}
qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
if (qnum == -1) {
axq_qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
if (axq_qnum == -1) {
/*
* NB: don't print a message, this happens
* normally on parts with too few tx queues
*/
return NULL;
}
if (qnum >= ARRAY_SIZE(sc->tx.txq)) {
if (axq_qnum >= ARRAY_SIZE(sc->tx.txq)) {
ath_err(common, "qnum %u out of range, max %zu!\n",
qnum, ARRAY_SIZE(sc->tx.txq));
ath9k_hw_releasetxqueue(ah, qnum);
axq_qnum, ARRAY_SIZE(sc->tx.txq));
ath9k_hw_releasetxqueue(ah, axq_qnum);
return NULL;
}
if (!ATH_TXQ_SETUP(sc, qnum)) {
struct ath_txq *txq = &sc->tx.txq[qnum];
if (!ATH_TXQ_SETUP(sc, axq_qnum)) {
struct ath_txq *txq = &sc->tx.txq[axq_qnum];

txq->axq_qnum = qnum;
txq->axq_qnum = axq_qnum;
txq->mac80211_qnum = -1;
txq->axq_link = NULL;
INIT_LIST_HEAD(&txq->axq_q);
INIT_LIST_HEAD(&txq->axq_acq);
spin_lock_init(&txq->axq_lock);
txq->axq_depth = 0;
txq->axq_ampdu_depth = 0;
txq->axq_tx_inprogress = false;
sc->tx.txqsetup |= 1<<qnum;
sc->tx.txqsetup |= 1<<axq_qnum;

txq->txq_headidx = txq->txq_tailidx = 0;
for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
INIT_LIST_HEAD(&txq->txq_fifo[i]);
INIT_LIST_HEAD(&txq->txq_fifo_pending);
}
return &sc->tx.txq[qnum];
return &sc->tx.txq[axq_qnum];
}

int ath_txq_update(struct ath_softc *sc, int qnum,
Expand Down Expand Up @@ -1973,17 +1974,16 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
}

static void ath_wake_mac80211_queue(struct ath_softc *sc, int qnum)
/* Has no locking. Must hold spin_lock_bh(&txq->axq_lock)
* before calling this.
*/
static void __ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
{
struct ath_txq *txq;

txq = sc->tx.txq_map[qnum];
spin_lock_bh(&txq->axq_lock);
if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
if (ath_mac80211_start_queue(sc, qnum))
if (txq->mac80211_qnum >= 0 &&
txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
if (ath_mac80211_start_queue(sc, txq->mac80211_qnum))
txq->stopped = 0;
}
spin_unlock_bh(&txq->axq_lock);
}

static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
Expand Down Expand Up @@ -2086,10 +2086,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
else
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);

if (txq == sc->tx.txq_map[qnum])
ath_wake_mac80211_queue(sc, qnum);

spin_lock_bh(&txq->axq_lock);
__ath_wake_mac80211_queue(sc, txq);

if (sc->sc_flags & SC_OP_TXAGGR)
ath_txq_schedule(sc, txq);
spin_unlock_bh(&txq->axq_lock);
Expand All @@ -2103,6 +2102,9 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
struct ath_txq *txq;
int i;
bool needreset = false;
#ifdef CONFIG_ATH9K_DEBUGFS
sc->tx_complete_poll_work_seen++;
#endif

for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
if (ATH_TXQ_SETUP(sc, i)) {
Expand All @@ -2116,6 +2118,34 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
} else {
txq->axq_tx_inprogress = true;
}
} else {
/* If the queue has pending buffers, then it
* should be doing tx work (and have axq_depth).
* Shouldn't get to this state I think..but
* we do.
*/
if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) &&
(txq->pending_frames > 0 ||
!list_empty(&txq->axq_acq) ||
txq->stopped)) {
ath_err(ath9k_hw_common(sc->sc_ah),
"txq: %p axq_qnum: %u,"
" mac80211_qnum: %i"
" axq_link: %p"
" pending frames: %i"
" axq_acq empty: %i"
" stopped: %i"
" axq_depth: 0 Attempting to"
" restart tx logic.\n",
txq, txq->axq_qnum,
txq->mac80211_qnum,
txq->axq_link,
txq->pending_frames,
list_empty(&txq->axq_acq),
txq->stopped);
__ath_wake_mac80211_queue(sc, txq);
ath_txq_schedule(sc, txq);
}
}
spin_unlock_bh(&txq->axq_lock);
}
Expand Down Expand Up @@ -2212,10 +2242,9 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
ath_tx_complete_buf(sc, bf, txq, &bf_head,
&txs, txok, 0);

if (txq == sc->tx.txq_map[qnum])
ath_wake_mac80211_queue(sc, qnum);

spin_lock_bh(&txq->axq_lock);
__ath_wake_mac80211_queue(sc, txq);

if (!list_empty(&txq->txq_fifo_pending)) {
INIT_LIST_HEAD(&bf_head);
bf = list_first_entry(&txq->txq_fifo_pending,
Expand Down

0 comments on commit cb195fa

Please sign in to comment.