Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 225323
b: refs/heads/master
c: 6742f55
h: refs/heads/master
i:
  225321: 661b44b
  225319: 8c90ed7
v: v3
  • Loading branch information
Juuso Oikarinen authored and Luciano Coelho committed Dec 15, 2010
1 parent 10bcda4 commit 3fbf888
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 18 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: 17c1755c24d83f9fd0509b64c76cc43fc60cc642
refs/heads/master: 6742f554db14da94172da9eb1875a1aa944a827f
2 changes: 1 addition & 1 deletion trunk/drivers/net/wireless/wl12xx/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
char buf[20];
int res;

queue_len = skb_queue_len(&wl->tx_queue);
queue_len = wl->tx_queue_count;

res = scnprintf(buf, sizeof(buf), "%u\n", queue_len);
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
Expand Down
12 changes: 8 additions & 4 deletions trunk/drivers/net/wireless/wl12xx/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ static void wl1271_irq_work(struct work_struct *work)

/* Check if any tx blocks were freed */
if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
!skb_queue_empty(&wl->tx_queue)) {
wl->tx_queue_count) {
/*
* In order to avoid starvation of the TX path,
* call the work function directly.
Expand Down Expand Up @@ -891,6 +891,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
struct ieee80211_sta *sta = txinfo->control.sta;
unsigned long flags;
int q;

/*
* peek into the rates configured in the STA entry.
Expand Down Expand Up @@ -918,10 +919,12 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags);
}
#endif
wl->tx_queue_count++;
spin_unlock_irqrestore(&wl->wl_lock, flags);

/* queue the packet */
skb_queue_tail(&wl->tx_queue, skb);
q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
skb_queue_tail(&wl->tx_queue[q], skb);

/*
* The chip specific setup must run before the first TX packet -
Expand All @@ -935,7 +938,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
* The workqueue is slow to process the tx_queue and we need stop
* the queue here, otherwise the queue will get too long.
*/
if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_HIGH_WATERMARK) {
if (wl->tx_queue_count >= WL1271_TX_QUEUE_HIGH_WATERMARK) {
wl1271_debug(DEBUG_TX, "op_tx: stopping queues");

spin_lock_irqsave(&wl->wl_lock, flags);
Expand Down Expand Up @@ -2719,7 +2722,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->hw = hw;
wl->plat_dev = plat_dev;

skb_queue_head_init(&wl->tx_queue);
for (i = 0; i < NUM_TX_QUEUES; i++)
skb_queue_head_init(&wl->tx_queue[i]);

INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work);
INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work);
Expand Down
60 changes: 49 additions & 11 deletions trunk/drivers/net/wireless/wl12xx/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
/* queue (we use same identifiers for tid's and ac's */
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
desc->tid = ac;

desc->aid = TX_HW_DEFAULT_AID;
desc->reserved = 0;

Expand Down Expand Up @@ -228,7 +227,7 @@ static void handle_tx_low_watermark(struct wl1271 *wl)
unsigned long flags;

if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) &&
skb_queue_len(&wl->tx_queue) <= WL1271_TX_QUEUE_LOW_WATERMARK) {
wl->tx_queue_count <= WL1271_TX_QUEUE_LOW_WATERMARK) {
/* firmware buffer has space, restart queues */
spin_lock_irqsave(&wl->wl_lock, flags);
ieee80211_wake_queues(wl->hw);
Expand All @@ -237,6 +236,43 @@ static void handle_tx_low_watermark(struct wl1271 *wl)
}
}

static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
{
struct sk_buff *skb = NULL;
unsigned long flags;

skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VO]);
if (skb)
goto out;
skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VI]);
if (skb)
goto out;
skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BE]);
if (skb)
goto out;
skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BK]);

out:
if (skb) {
spin_lock_irqsave(&wl->wl_lock, flags);
wl->tx_queue_count--;
spin_unlock_irqrestore(&wl->wl_lock, flags);
}

return skb;
}

static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
{
unsigned long flags;
int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));

skb_queue_head(&wl->tx_queue[q], skb);
spin_lock_irqsave(&wl->wl_lock, flags);
wl->tx_queue_count++;
spin_unlock_irqrestore(&wl->wl_lock, flags);
}

void wl1271_tx_work_locked(struct wl1271 *wl)
{
struct sk_buff *skb;
Expand Down Expand Up @@ -270,7 +306,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
wl1271_acx_rate_policies(wl);
}

while ((skb = skb_dequeue(&wl->tx_queue))) {
while ((skb = wl1271_skb_dequeue(wl))) {
if (!woken_up) {
ret = wl1271_ps_elp_wakeup(wl, false);
if (ret < 0)
Expand All @@ -284,9 +320,9 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
* Aggregation buffer is full.
* Flush buffer and try again.
*/
skb_queue_head(&wl->tx_queue, skb);
wl1271_skb_queue_head(wl, skb);
wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
buf_offset, true);
buf_offset, true);
sent_packets = true;
buf_offset = 0;
continue;
Expand All @@ -295,7 +331,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
* Firmware buffer is full.
* Queue back last skb, and stop aggregating.
*/
skb_queue_head(&wl->tx_queue, skb);
wl1271_skb_queue_head(wl, skb);
/* No work left, avoid scheduling redundant tx work */
set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
goto out_ack;
Expand Down Expand Up @@ -440,10 +476,13 @@ void wl1271_tx_reset(struct wl1271 *wl)
struct sk_buff *skb;

/* TX failure */
while ((skb = skb_dequeue(&wl->tx_queue))) {
wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
ieee80211_tx_status(wl->hw, skb);
for (i = 0; i < NUM_TX_QUEUES; i++) {
while ((skb = skb_dequeue(&wl->tx_queue[i]))) {
wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
ieee80211_tx_status(wl->hw, skb);
}
}
wl->tx_queue_count = 0;

/*
* Make sure the driver is at a consistent state, in case this
Expand Down Expand Up @@ -472,8 +511,7 @@ void wl1271_tx_flush(struct wl1271 *wl)
mutex_lock(&wl->mutex);
wl1271_debug(DEBUG_TX, "flushing tx buffer: %d",
wl->tx_frames_cnt);
if ((wl->tx_frames_cnt == 0) &&
skb_queue_empty(&wl->tx_queue)) {
if ((wl->tx_frames_cnt == 0) && (wl->tx_queue_count == 0)) {
mutex_unlock(&wl->mutex);
return;
}
Expand Down
3 changes: 2 additions & 1 deletion trunk/drivers/net/wireless/wl12xx/wl12xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ struct wl1271 {
int session_counter;

/* Frames scheduled for transmission, not handled yet */
struct sk_buff_head tx_queue;
struct sk_buff_head tx_queue[NUM_TX_QUEUES];
int tx_queue_count;

struct work_struct tx_work;

Expand Down

0 comments on commit 3fbf888

Please sign in to comment.