1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -137,6 +137,8 @@ void ath_descdma_cleanup(struct ath_soft
#define ATH_MAX_ANTENNA 3
#define ATH_RXBUF 512
#define ATH_TXBUF 512
+#define ATH_TXBUF_RESERVE 5
+#define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
#define ATH_TXMAXTRY 13
#define ATH_MGT_TXMAXTRY 4
@@ -205,6 +207,7 @@ struct ath_txq {
struct list_head txq_fifo_pending;
u8 txq_headidx;
u8 txq_tailidx;
+ int pending_frames;
};
struct ath_atx_ac {
@@ -242,6 +245,7 @@ struct ath_buf {
struct ath_buf_state bf_state;
dma_addr_t bf_dmacontext;
struct ath_wiphy *aphy;
+ struct ath_txq *txq;
};
struct ath_atx_tid {
@@ -331,7 +335,6 @@ void ath_tx_node_cleanup(struct ath_soft
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
int ath_tx_init(struct ath_softc *sc, int nbufs);
void ath_tx_cleanup(struct ath_softc *sc);
-struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb);
int ath_txq_update(struct ath_softc *sc, int qnum,
struct ath9k_tx_queue_info *q);
int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -986,32 +986,6 @@ int ath_tx_get_qnum(struct ath_softc *sc
return qnum;
}
-struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
-{
- struct ath_txq *txq = NULL;
- u16 skb_queue = skb_get_queue_mapping(skb);
- int qnum;
-
- qnum = ath_get_hal_qnum(skb_queue, sc);
- txq = &sc->tx.txq[qnum];
-
- spin_lock_bh(&txq->axq_lock);
-
- if (txq->axq_depth >= (ATH_TXBUF - 20)) {
- ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_XMIT,
- "TX queue: %d is full, depth: %d\n",
- qnum, txq->axq_depth);
- ath_mac80211_stop_queue(sc, skb_queue);
- txq->stopped = 1;
- spin_unlock_bh(&txq->axq_lock);
- return NULL;
- }
-
- spin_unlock_bh(&txq->axq_lock);
-
- return txq;
-}
-
int ath_txq_update(struct ath_softc *sc, int qnum,
struct ath9k_tx_queue_info *qinfo)
{
@@ -1811,6 +1785,7 @@ int ath_tx_start(struct ieee80211_hw *hw
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_txq *txq = txctl->txq;
struct ath_buf *bf;
int r;
@@ -1820,10 +1795,16 @@ int ath_tx_start(struct ieee80211_hw *hw
return -1;
}
+ bf->txq = txctl->txq;
+ spin_lock_bh(&bf->txq->axq_lock);
+ if (++bf->txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
+ ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
+ txq->stopped = 1;
+ }
+ spin_unlock_bh(&bf->txq->axq_lock);
+
r = ath_tx_setup_buffer(hw, bf, skb, txctl);
if (unlikely(r)) {
- struct ath_txq *txq = txctl->txq;
-
ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n");
/* upon ath_tx_processq() this TX queue will be resumed, we
@@ -1831,7 +1812,7 @@ int ath_tx_start(struct ieee80211_hw *hw
* we will at least have to run TX completionon one buffer
* on the queue */
spin_lock_bh(&txq->axq_lock);
- if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) {
+ if (!txq->stopped && txq->axq_depth > 1) {
ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
txq->stopped = 1;
}
@@ -1972,6 +1953,13 @@ static void ath_tx_complete_buf(struct a
tx_flags |= ATH_TX_XRETRY;
}
+ if (bf->txq) {
+ spin_lock_bh(&bf->txq->axq_lock);
+ bf->txq->pending_frames--;
+ spin_unlock_bh(&bf->txq->axq_lock);
+ bf->txq = NULL;
+ }
+
dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
ath_tx_complete(sc, skb, bf->aphy, tx_flags);
ath_debug_stat_tx(sc, txq, bf, ts);
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1026,6 +1026,7 @@ static int ath9k_tx(struct ieee80211_hw
struct ath_tx_control txctl;
int padpos, padsize;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ int qnum;
if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
ath_print(common, ATH_DBG_XMIT,
@@ -1098,11 +1099,8 @@ static int ath9k_tx(struct ieee80211_hw
memmove(skb->data, skb->data + padsize, padpos);
}
- /* Check if a tx queue is available */
-
- txctl.txq = ath_test_get_txq(sc, skb);
- if (!txctl.txq)
- goto exit;
+ qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
+ txctl.txq = &sc->tx.txq[qnum];
ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
|