summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/wl12xx/debugfs.c4
-rw-r--r--drivers/net/wireless/wl12xx/main.c7
-rw-r--r--drivers/net/wireless/wl12xx/tx.c71
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h2
4 files changed, 57 insertions, 27 deletions
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index 3102652c7625..d59354f53702 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -340,6 +340,10 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_INT(tx_blocks_available);
DRIVER_STATE_PRINT_INT(tx_allocated_blocks);
+ DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]);
+ DRIVER_STATE_PRINT_INT(tx_allocated_pkts[1]);
+ DRIVER_STATE_PRINT_INT(tx_allocated_pkts[2]);
+ DRIVER_STATE_PRINT_INT(tx_allocated_pkts[3]);
DRIVER_STATE_PRINT_INT(tx_frames_cnt);
DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]);
DRIVER_STATE_PRINT_INT(tx_queue_count[0]);
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 09cecb336d53..027b6742a151 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -827,7 +827,7 @@ static void wl12xx_fw_status(struct wl1271 *wl,
for (i = 0; i < NUM_TX_QUEUES; i++) {
/* prevent wrap-around in freed-packets counter */
- wl->tx_allocated_pkts -=
+ wl->tx_allocated_pkts[i] -=
(status->tx_released_pkts[i] -
wl->tx_pkts_freed[i]) & 0xff;
@@ -2060,9 +2060,10 @@ deinit:
wl->tx_blocks_freed = 0;
- wl->tx_allocated_pkts = 0;
- for (i = 0; i < NUM_TX_QUEUES; i++)
+ for (i = 0; i < NUM_TX_QUEUES; i++) {
wl->tx_pkts_freed[i] = 0;
+ wl->tx_allocated_pkts[i] = 0;
+ }
wl1271_debugfs_reset(wl);
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 7dd6d8b94f64..ccbcd0a4d2bf 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -205,7 +205,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
u32 len;
u32 total_blocks;
- int id, ret = -EBUSY;
+ int id, ret = -EBUSY, ac;
/* we use 1 spare block */
u32 spare_blocks = 1;
@@ -242,7 +242,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
wl->tx_blocks_available -= total_blocks;
wl->tx_allocated_blocks += total_blocks;
- wl->tx_allocated_pkts++;
+ ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
+ wl->tx_allocated_pkts[ac]++;
if (wl->bss_type == BSS_TYPE_AP_BSS)
wl->links[hlid].allocated_blks += total_blocks;
@@ -485,21 +486,45 @@ void wl1271_handle_tx_low_watermark(struct wl1271 *wl)
}
}
+static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl,
+ struct sk_buff_head *queues)
+{
+ int i, q = -1, ac;
+ u32 min_pkts = 0xffffffff;
+
+ /*
+ * Find a non-empty ac where:
+ * 1. There are packets to transmit
+ * 2. The FW has the least allocated blocks
+ *
+ * We prioritize the ACs according to VO>VI>BE>BK
+ */
+ for (i = 0; i < NUM_TX_QUEUES; i++) {
+ ac = wl1271_tx_get_queue(i);
+ if (!skb_queue_empty(&queues[ac]) &&
+ (wl->tx_allocated_pkts[ac] < min_pkts)) {
+ q = ac;
+ min_pkts = wl->tx_allocated_pkts[q];
+ }
+ }
+
+ if (q == -1)
+ return NULL;
+
+ return &queues[q];
+}
+
static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl)
{
struct sk_buff *skb = NULL;
unsigned long flags;
+ struct sk_buff_head *queue;
- skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VO]);
- if (skb)
+ queue = wl1271_select_queue(wl, wl->tx_queue);
+ if (!queue)
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]);
+
+ skb = skb_dequeue(queue);
out:
if (skb) {
@@ -517,6 +542,7 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)
struct sk_buff *skb = NULL;
unsigned long flags;
int i, h, start_hlid;
+ struct sk_buff_head *queue;
/* start from the link after the last one */
start_hlid = (wl->last_tx_hlid + 1) % AP_MAX_LINKS;
@@ -525,21 +551,20 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)
for (i = 0; i < AP_MAX_LINKS; i++) {
h = (start_hlid + i) % AP_MAX_LINKS;
- skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VO]);
- if (skb)
- goto out;
- skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VI]);
- if (skb)
- goto out;
- skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BE]);
- if (skb)
- goto out;
- skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BK]);
+ /* only consider connected stations */
+ if (h >= WL1271_AP_STA_HLID_START &&
+ !test_bit(h - WL1271_AP_STA_HLID_START, wl->ap_hlid_map))
+ continue;
+
+ queue = wl1271_select_queue(wl, wl->links[h].tx_queue);
+ if (!queue)
+ continue;
+
+ skb = skb_dequeue(queue);
if (skb)
- goto out;
+ break;
}
-out:
if (skb) {
int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
wl->last_tx_hlid = h;
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 24b40251535b..6118df5b742d 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -424,7 +424,7 @@ struct wl1271 {
/* Accounting for allocated / available Tx packets in HW */
u32 tx_pkts_freed[NUM_TX_QUEUES];
- u32 tx_allocated_pkts;
+ u32 tx_allocated_pkts[NUM_TX_QUEUES];
/* Transmitted TX packets counter for chipset interface */
u32 tx_packets_count;