Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

wlcore: add counters with reasons for aggr packet sending (DEBUG)

Count the reasons that triggered us to send the buffer to the firmware
for transmission.  Count buffer_full, fw_buffer_full, other reasons
and no_data left to send.

This is useful when debugging throughput issues.

To have a better understanding of what is going on in the TX data
path, we can count the number of times we sent n packets.  For
example, if we sent 10 times aggregations of 2 packets, we print [2] =
10.

Instead of counting the reasons as an overall value, we count the
reasons for each number of packets used in the aggregation.

Signed-off-by: Luciano Coelho <coelho@ti.com>
Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
  • Loading branch information...
commit 5204326efeea5edb1fed8c132a046e4d74291740 1 parent 1abe446
Luciano Coelho authored ariknem committed
View
86 drivers/net/wireless/ti/wlcore/debugfs.c
@@ -386,6 +386,91 @@ static const struct file_operations forced_ps_ops = {
.llseek = default_llseek,
};
+static ssize_t stats_tx_aggr_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+ char *buf;
+ int ret, i;
+ size_t len = 32768, size = 0;
+ u32 total_buffer_full = 0, total_fw_buffer_full= 0;
+ u32 total_no_data = 0, total_other = 0;
+
+ buf = kmalloc(len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ buf[0] = '\0';
+
+ mutex_lock(&wl->mutex);
+
+ for (i = 0; i < WLCORE_AGGR_MAX_PACKETS; i++) {
+ total_buffer_full += wl->aggr_pkts_reason[i].buffer_full;
+ total_fw_buffer_full += wl->aggr_pkts_reason[i].fw_buffer_full;
+ total_other += wl->aggr_pkts_reason[i].other;
+ total_no_data += wl->aggr_pkts_reason[i].no_data;
+ wl->aggr_pkts_reason[i].total =
+ wl->aggr_pkts_reason[i].buffer_full +
+ wl->aggr_pkts_reason[i].fw_buffer_full +
+ wl->aggr_pkts_reason[i].other +
+ wl->aggr_pkts_reason[i].no_data;
+ if (wl->aggr_pkts_reason[i].total)
+ snprintf(buf, len, "%s[%d] total %d\n"
+ "\tbuffer_full\t= %d\n"
+ "\tfw_buffer_full\t= %d\n"
+ "\tother\t\t= %d\n"
+ "\tno_data\t\t= %d\n", buf, i,
+ wl->aggr_pkts_reason[i].total,
+ wl->aggr_pkts_reason[i].buffer_full,
+ wl->aggr_pkts_reason[i].fw_buffer_full,
+ wl->aggr_pkts_reason[i].other,
+ wl->aggr_pkts_reason[i].no_data);
+ }
+
+ mutex_unlock(&wl->mutex);
+
+ size = snprintf(buf, len, "%sTotals:\n"
+ "\tbuffer_full\t= %d\n"
+ "\tfw_buffer_full\t= %d\n"
+ "\tother\t\t= %d\n"
+ "\tno_data\t\t= %d\n",
+ buf,
+ total_buffer_full,
+ total_fw_buffer_full,
+ total_other,
+ total_no_data);
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, size);
+
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t stats_tx_aggr_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+
+ mutex_lock(&wl->mutex);
+
+ if (wl->state == WL1271_STATE_OFF)
+ goto out;
+
+ memset(wl->aggr_pkts_reason, 0, sizeof(wl->aggr_pkts_reason));
+
+out:
+ mutex_unlock(&wl->mutex);
+ return count;
+}
+
+static const struct file_operations stats_tx_aggr_ops = {
+ .read = stats_tx_aggr_read,
+ .write = stats_tx_aggr_write,
+ .open = simple_open,
+ .llseek = default_llseek,
+};
+
static ssize_t split_scan_timeout_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -1244,6 +1329,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD(beacon_filtering, rootdir);
DEBUGFS_ADD(dynamic_ps_timeout, rootdir);
DEBUGFS_ADD(forced_ps, rootdir);
+ DEBUGFS_ADD(stats_tx_aggr, rootdir);
DEBUGFS_ADD(split_scan_timeout, rootdir);
DEBUGFS_ADD(irq_pkt_threshold, rootdir);
DEBUGFS_ADD(irq_blk_threshold, rootdir);
View
8 drivers/net/wireless/ti/wlcore/tx.c
@@ -684,6 +684,7 @@ int wlcore_tx_work_locked(struct wl1271 *wl)
struct wl1271_tx_hw_descr *desc;
u32 buf_offset = 0, last_len = 0;
bool sent_packets = false;
+ int n_aggr_packets = 0;
unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
int ret = 0;
int bus_ret = 0;
@@ -717,6 +718,7 @@ int wlcore_tx_work_locked(struct wl1271 *wl)
sent_packets = true;
buf_offset = 0;
+ wl->aggr_pkts_reason[n_aggr_packets].buffer_full++;
continue;
} else if (ret == -EBUSY) {
/*
@@ -726,6 +728,7 @@ int wlcore_tx_work_locked(struct wl1271 *wl)
wl1271_skb_queue_head(wl, wlvif, skb);
/* No work left, avoid scheduling redundant tx work */
set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
+ wl->aggr_pkts_reason[n_aggr_packets].fw_buffer_full++;
goto out_ack;
} else if (ret < 0) {
if (wl12xx_is_dummy_packet(wl, skb))
@@ -736,17 +739,22 @@ int wlcore_tx_work_locked(struct wl1271 *wl)
wl1271_skb_queue_head(wl, wlvif, skb);
else
ieee80211_free_txskb(wl->hw, skb);
+ wl->aggr_pkts_reason[n_aggr_packets].other++;
goto out_ack;
}
last_len = ret;
buf_offset += last_len;
wl->tx_packets_count++;
+ n_aggr_packets++;
if (has_data) {
desc = (struct wl1271_tx_hw_descr *) skb->data;
__set_bit(desc->hlid, active_hlids);
}
}
+ if (buf_offset)
+ wl->aggr_pkts_reason[n_aggr_packets].no_data++;
+
out_ack:
if (buf_offset) {
buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, last_len);
View
10 drivers/net/wireless/ti/wlcore/wlcore.h
@@ -138,6 +138,14 @@ struct wl1271_stats {
unsigned int excessive_retries;
};
+struct wlcore_aggr_reason {
+ u32 total;
+ u32 buffer_full;
+ u32 fw_buffer_full;
+ u32 other;
+ u32 no_data;
+};
+
struct wl1271 {
struct ieee80211_hw *hw;
bool mac80211_registered;
@@ -399,6 +407,8 @@ struct wl1271 {
/* the minimum FW version required for the driver to work */
unsigned int min_fw_ver[NUM_FW_VER];
+
+ struct wlcore_aggr_reason aggr_pkts_reason[WLCORE_AGGR_MAX_PACKETS];
};
int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
View
3  drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -88,6 +88,9 @@
#define WL1271_AGGR_BUFFER_SIZE (5 * PAGE_SIZE)
+#define WLCORE_AGGR_MAX_PACKETS (WL1271_AGGR_BUFFER_SIZE / \
+ sizeof(struct ieee80211_hdr))
+
enum wl1271_state {
WL1271_STATE_OFF,
WL1271_STATE_ON,
Please sign in to comment.
Something went wrong with that request. Please try again.