Commit abfbc3af authored by Johannes Berg's avatar Johannes Berg
Browse files

mac80211: remove TX latency measurement code

Revert commit ad38bfc9

 ("mac80211: Tx frame latency statistics")
(along with some follow-up fixes).

This code turned out not to be as useful in the current form as we
thought, and we've internally hacked it up more, but that's not
very suitable for upstream (for now), and we might just do that
with tracing instead.

Therefore, for now at least, remove this code. We might also need
to use the skb->tstamp field for the TCP performance issue, which
is more important than the debugging.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 31f909a2
...@@ -18,172 +18,6 @@ ...@@ -18,172 +18,6 @@
#define DEBUGFS_FORMAT_BUFFER_SIZE 100 #define DEBUGFS_FORMAT_BUFFER_SIZE 100
#define TX_LATENCY_BIN_DELIMTER_C ','
#define TX_LATENCY_BIN_DELIMTER_S ","
#define TX_LATENCY_BINS_DISABLED "enable(bins disabled)\n"
#define TX_LATENCY_DISABLED "disable\n"
/*
* Display if Tx latency statistics & bins are enabled/disabled
*/
static ssize_t sta_tx_latency_stat_read(struct file *file,
char __user *userbuf,
size_t count, loff_t *ppos)
{
struct ieee80211_local *local = file->private_data;
struct ieee80211_tx_latency_bin_ranges *tx_latency;
char *buf;
int bufsz, i, ret;
int pos = 0;
rcu_read_lock();
tx_latency = rcu_dereference(local->tx_latency);
if (tx_latency && tx_latency->n_ranges) {
bufsz = tx_latency->n_ranges * 15;
buf = kzalloc(bufsz, GFP_ATOMIC);
if (!buf)
goto err;
for (i = 0; i < tx_latency->n_ranges; i++)
pos += scnprintf(buf + pos, bufsz - pos, "%d,",
tx_latency->ranges[i]);
pos += scnprintf(buf + pos, bufsz - pos, "\n");
} else if (tx_latency) {
bufsz = sizeof(TX_LATENCY_BINS_DISABLED) + 1;
buf = kzalloc(bufsz, GFP_ATOMIC);
if (!buf)
goto err;
pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
TX_LATENCY_BINS_DISABLED);
} else {
bufsz = sizeof(TX_LATENCY_DISABLED) + 1;
buf = kzalloc(bufsz, GFP_ATOMIC);
if (!buf)
goto err;
pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
TX_LATENCY_DISABLED);
}
rcu_read_unlock();
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
kfree(buf);
return ret;
err:
rcu_read_unlock();
return -ENOMEM;
}
/*
* Receive input from user regarding Tx latency statistics
* The input should indicate if Tx latency statistics and bins are
* enabled/disabled.
* If bins are enabled input should indicate the amount of different bins and
* their ranges. Each bin will count how many Tx frames transmitted within the
* appropriate latency.
* Legal input is:
* a) "enable(bins disabled)" - to enable only general statistics
* b) "a,b,c,d,...z" - to enable general statistics and bins, where all are
* numbers and a < b < c < d.. < z
* c) "disable" - disable all statistics
* NOTE: must configure Tx latency statistics bins before stations connected.
*/
static ssize_t sta_tx_latency_stat_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct ieee80211_local *local = file->private_data;
char buf[128] = {};
char *bins = buf;
char *token;
int buf_size, i, alloc_size;
int prev_bin = 0;
int n_ranges = 0;
int ret = count;
struct ieee80211_tx_latency_bin_ranges *tx_latency;
if (sizeof(buf) <= count)
return -EINVAL;
buf_size = count;
if (copy_from_user(buf, userbuf, buf_size))
return -EFAULT;
mutex_lock(&local->sta_mtx);
/* cannot change config once we have stations */
if (local->num_sta)
goto unlock;
tx_latency =
rcu_dereference_protected(local->tx_latency,
lockdep_is_held(&local->sta_mtx));
/* disable Tx statistics */
if (!strcmp(buf, TX_LATENCY_DISABLED)) {
if (!tx_latency)
goto unlock;
RCU_INIT_POINTER(local->tx_latency, NULL);
synchronize_rcu();
kfree(tx_latency);
goto unlock;
}
/* Tx latency already enabled */
if (tx_latency)
goto unlock;
if (strcmp(TX_LATENCY_BINS_DISABLED, buf)) {
/* check how many bins and between what ranges user requested */
token = buf;
while (*token != '\0') {
if (*token == TX_LATENCY_BIN_DELIMTER_C)
n_ranges++;
token++;
}
n_ranges++;
}
alloc_size = sizeof(struct ieee80211_tx_latency_bin_ranges) +
n_ranges * sizeof(u32);
tx_latency = kzalloc(alloc_size, GFP_ATOMIC);
if (!tx_latency) {
ret = -ENOMEM;
goto unlock;
}
tx_latency->n_ranges = n_ranges;
for (i = 0; i < n_ranges; i++) { /* setting bin ranges */
token = strsep(&bins, TX_LATENCY_BIN_DELIMTER_S);
sscanf(token, "%d", &tx_latency->ranges[i]);
/* bins values should be in ascending order */
if (prev_bin >= tx_latency->ranges[i]) {
ret = -EINVAL;
kfree(tx_latency);
goto unlock;
}
prev_bin = tx_latency->ranges[i];
}
rcu_assign_pointer(local->tx_latency, tx_latency);
unlock:
mutex_unlock(&local->sta_mtx);
return ret;
}
static const struct file_operations stats_tx_latency_ops = {
.write = sta_tx_latency_stat_write,
.read = sta_tx_latency_stat_read,
.open = simple_open,
.llseek = generic_file_llseek,
};
int mac80211_format_buffer(char __user *userbuf, size_t count, int mac80211_format_buffer(char __user *userbuf, size_t count,
loff_t *ppos, char *fmt, ...) loff_t *ppos, char *fmt, ...)
{ {
...@@ -475,6 +309,4 @@ void debugfs_hw_add(struct ieee80211_local *local) ...@@ -475,6 +309,4 @@ void debugfs_hw_add(struct ieee80211_local *local)
DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount); DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount);
DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount); DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount);
DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount); DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount);
DEBUGFS_DEVSTATS_ADD(tx_latency);
} }
...@@ -39,13 +39,6 @@ static const struct file_operations sta_ ##name## _ops = { \ ...@@ -39,13 +39,6 @@ static const struct file_operations sta_ ##name## _ops = { \
.llseek = generic_file_llseek, \ .llseek = generic_file_llseek, \
} }
#define STA_OPS_W(name) \
static const struct file_operations sta_ ##name## _ops = { \
.write = sta_##name##_write, \
.open = simple_open, \
.llseek = generic_file_llseek, \
}
#define STA_OPS_RW(name) \ #define STA_OPS_RW(name) \
static const struct file_operations sta_ ##name## _ops = { \ static const struct file_operations sta_ ##name## _ops = { \
.read = sta_##name##_read, \ .read = sta_##name##_read, \
...@@ -398,131 +391,6 @@ static ssize_t sta_last_rx_rate_read(struct file *file, char __user *userbuf, ...@@ -398,131 +391,6 @@ static ssize_t sta_last_rx_rate_read(struct file *file, char __user *userbuf,
} }
STA_OPS(last_rx_rate); STA_OPS(last_rx_rate);
static int
sta_tx_latency_stat_header(struct ieee80211_tx_latency_bin_ranges *tx_latency,
char *buf, int pos, int bufsz)
{
int i;
int range_count = tx_latency->n_ranges;
u32 *bin_ranges = tx_latency->ranges;
pos += scnprintf(buf + pos, bufsz - pos,
"Station\t\t\tTID\tMax\tAvg");
if (range_count) {
pos += scnprintf(buf + pos, bufsz - pos,
"\t<=%d", bin_ranges[0]);
for (i = 0; i < range_count - 1; i++)
pos += scnprintf(buf + pos, bufsz - pos, "\t%d-%d",
bin_ranges[i], bin_ranges[i+1]);
pos += scnprintf(buf + pos, bufsz - pos,
"\t%d<", bin_ranges[range_count - 1]);
}
pos += scnprintf(buf + pos, bufsz - pos, "\n");
return pos;
}
static int
sta_tx_latency_stat_table(struct ieee80211_tx_latency_bin_ranges *tx_lat_range,
struct ieee80211_tx_latency_stat *tx_lat,
char *buf, int pos, int bufsz, int tid)
{
u32 avg = 0;
int j;
int bin_count = tx_lat->bin_count;
pos += scnprintf(buf + pos, bufsz - pos, "\t\t\t%d", tid);
/* make sure you don't divide in 0 */
if (tx_lat->counter)
avg = tx_lat->sum / tx_lat->counter;
pos += scnprintf(buf + pos, bufsz - pos, "\t%d\t%d",
tx_lat->max, avg);
if (tx_lat_range->n_ranges && tx_lat->bins)
for (j = 0; j < bin_count; j++)
pos += scnprintf(buf + pos, bufsz - pos,
"\t%d", tx_lat->bins[j]);
pos += scnprintf(buf + pos, bufsz - pos, "\n");
return pos;
}
/*
* Output Tx latency statistics station && restart all statistics information
*/
static ssize_t sta_tx_latency_stat_read(struct file *file,
char __user *userbuf,
size_t count, loff_t *ppos)
{
struct sta_info *sta = file->private_data;
struct ieee80211_local *local = sta->local;
struct ieee80211_tx_latency_bin_ranges *tx_latency;
char *buf;
int bufsz, ret, i;
int pos = 0;
bufsz = 20 * IEEE80211_NUM_TIDS *
sizeof(struct ieee80211_tx_latency_stat);
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf)
return -ENOMEM;
rcu_read_lock();
tx_latency = rcu_dereference(local->tx_latency);
if (!sta->tx_lat) {
pos += scnprintf(buf + pos, bufsz - pos,
"Tx latency statistics are not enabled\n");
goto unlock;
}
pos = sta_tx_latency_stat_header(tx_latency, buf, pos, bufsz);
pos += scnprintf(buf + pos, bufsz - pos, "%pM\n", sta->sta.addr);
for (i = 0; i < IEEE80211_NUM_TIDS; i++)
pos = sta_tx_latency_stat_table(tx_latency, &sta->tx_lat[i],
buf, pos, bufsz, i);
unlock:
rcu_read_unlock();
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
kfree(buf);
return ret;
}
STA_OPS(tx_latency_stat);
static ssize_t sta_tx_latency_stat_reset_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
u32 *bins;
int bin_count;
struct sta_info *sta = file->private_data;
int i;
if (!sta->tx_lat)
return -EINVAL;
for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
bins = sta->tx_lat[i].bins;
bin_count = sta->tx_lat[i].bin_count;
sta->tx_lat[i].max = 0;
sta->tx_lat[i].sum = 0;
sta->tx_lat[i].counter = 0;
if (bin_count)
memset(bins, 0, bin_count * sizeof(u32));
}
return count;
}
STA_OPS_W(tx_latency_stat_reset);
#define DEBUGFS_ADD(name) \ #define DEBUGFS_ADD(name) \
debugfs_create_file(#name, 0400, \ debugfs_create_file(#name, 0400, \
sta->debugfs.dir, sta, &sta_ ##name## _ops); sta->debugfs.dir, sta, &sta_ ##name## _ops);
...@@ -576,8 +444,6 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) ...@@ -576,8 +444,6 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
DEBUGFS_ADD(last_ack_signal); DEBUGFS_ADD(last_ack_signal);
DEBUGFS_ADD(current_tx_rate); DEBUGFS_ADD(current_tx_rate);
DEBUGFS_ADD(last_rx_rate); DEBUGFS_ADD(last_rx_rate);
DEBUGFS_ADD(tx_latency_stat);
DEBUGFS_ADD(tx_latency_stat_reset);
DEBUGFS_ADD_COUNTER(rx_packets, rx_packets); DEBUGFS_ADD_COUNTER(rx_packets, rx_packets);
DEBUGFS_ADD_COUNTER(tx_packets, tx_packets); DEBUGFS_ADD_COUNTER(tx_packets, tx_packets);
......
...@@ -1030,24 +1030,6 @@ struct tpt_led_trigger { ...@@ -1030,24 +1030,6 @@ struct tpt_led_trigger {
}; };
#endif #endif
/*
* struct ieee80211_tx_latency_bin_ranges - Tx latency statistics bins ranges
*
* Measuring Tx latency statistics. Counts how many Tx frames transmitted in a
* certain latency range (in Milliseconds). Each station that uses these
* ranges will have bins to count the amount of frames received in that range.
* The user can configure the ranges via debugfs.
* If ranges is NULL then Tx latency statistics bins are disabled for all
* stations.
*
* @n_ranges: number of ranges that are taken in account
* @ranges: the ranges that the user requested or NULL if disabled.
*/
struct ieee80211_tx_latency_bin_ranges {
int n_ranges;
u32 ranges[];
};
/** /**
* mac80211 scan flags - currently active scan mode * mac80211 scan flags - currently active scan mode
* *
...@@ -1199,12 +1181,6 @@ struct ieee80211_local { ...@@ -1199,12 +1181,6 @@ struct ieee80211_local {
struct timer_list sta_cleanup; struct timer_list sta_cleanup;
int sta_generation; int sta_generation;
/*
* Tx latency statistics parameters for all stations.
* Can enable via debugfs (NULL when disabled).
*/
struct ieee80211_tx_latency_bin_ranges __rcu *tx_latency;
struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; struct sk_buff_head pending[IEEE80211_MAX_QUEUES];
struct tasklet_struct tx_pending_tasklet; struct tasklet_struct tx_pending_tasklet;
......
...@@ -1201,8 +1201,6 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) ...@@ -1201,8 +1201,6 @@ void ieee80211_free_hw(struct ieee80211_hw *hw)
ieee80211_free_ack_frame, NULL); ieee80211_free_ack_frame, NULL);
idr_destroy(&local->ack_status_frames); idr_destroy(&local->ack_status_frames);
kfree(rcu_access_pointer(local->tx_latency));
sta_info_stop(local); sta_info_stop(local);
wiphy_free(local->hw.wiphy); wiphy_free(local->hw.wiphy);
......
...@@ -229,17 +229,9 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, ...@@ -229,17 +229,9 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
*/ */
void sta_info_free(struct ieee80211_local *local, struct sta_info *sta) void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
{ {
int i;
if (sta->rate_ctrl) if (sta->rate_ctrl)
rate_control_free_sta(sta); rate_control_free_sta(sta);
if (sta->tx_lat) {
for (i = 0; i < IEEE80211_NUM_TIDS; i++)
kfree(sta->tx_lat[i].bins);
kfree(sta->tx_lat);
}
sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr); sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
kfree(rcu_dereference_raw(sta->sta.rates)); kfree(rcu_dereference_raw(sta->sta.rates));
...@@ -295,42 +287,12 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, ...@@ -295,42 +287,12 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct sta_info *sta; struct sta_info *sta;
struct timespec uptime; struct timespec uptime;
struct ieee80211_tx_latency_bin_ranges *tx_latency;
int i; int i;
sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp); sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp);
if (!sta) if (!sta)
return NULL; return NULL;
rcu_read_lock();
tx_latency = rcu_dereference(local->tx_latency);
/* init stations Tx latency statistics && TID bins */
if (tx_latency) {
sta->tx_lat = kzalloc(IEEE80211_NUM_TIDS *
sizeof(struct ieee80211_tx_latency_stat),
GFP_ATOMIC);
if (!sta->tx_lat) {
rcu_read_unlock();
goto free;
}
if (tx_latency->n_ranges) {
for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
/* size of bins is size of the ranges +1 */
sta->tx_lat[i].bin_count =
tx_latency->n_ranges + 1;
sta->tx_lat[i].bins =
kcalloc(sta->tx_lat[i].bin_count,
sizeof(u32), GFP_ATOMIC);
if (!sta->tx_lat[i].bins) {
rcu_read_unlock();
goto free;
}
}
}
}
rcu_read_unlock();
spin_lock_init(&sta->lock); spin_lock_init(&sta->lock);
spin_lock_init(&sta->ps_lock); spin_lock_init(&sta->ps_lock);
INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames); INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
...@@ -359,8 +321,10 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, ...@@ -359,8 +321,10 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++) for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++)
ewma_init(&sta->chain_signal_avg[i], 1024, 8); ewma_init(&sta->chain_signal_avg[i], 1024, 8);
if (sta_prepare_rate_control(local, sta, gfp)) if (sta_prepare_rate_control(local, sta, gfp)) {
goto free; kfree(sta);
return NULL;
}
for (i = 0; i < IEEE80211_NUM_TIDS; i++) { for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
/* /*
...@@ -405,16 +369,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, ...@@ -405,16 +369,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
} }
sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
return sta;
free: return sta;
if (sta->tx_lat) {
for (i = 0; i < IEEE80211_NUM_TIDS; i++)
kfree(sta->tx_lat[i].bins);
kfree(sta->tx_lat);
}
kfree(sta);
return NULL;
} }
static int sta_info_insert_check(struct sta_info *sta) static int sta_info_insert_check(struct sta_info *sta)
......
...@@ -234,25 +234,6 @@ struct sta_ampdu_mlme { ...@@ -234,25 +234,6 @@ struct sta_ampdu_mlme {
u8 dialog_token_allocator; u8 dialog_token_allocator;
}; };
/*
* struct ieee80211_tx_latency_stat - Tx latency statistics
*
* Measures TX latency and jitter for a station per TID.
*
* @max: worst case latency
* @sum: sum of all latencies
* @counter: amount of Tx frames sent from interface
* @bins: each bin counts how many frames transmitted within a certain
* latency range. when disabled it is NULL.
* @bin_count: amount of bins.
*/
struct ieee80211_tx_latency_stat {
u32 max;
u32 sum;
u32 counter;
u32 *bins;
u32 bin_count;
};
/* Value to indicate no TID reservation */ /* Value to indicate no TID reservation */
#define IEEE80211_TID_UNRESERVED 0xff #define IEEE80211_TID_UNRESERVED 0xff
...@@ -314,7 +295,6 @@ struct ieee80211_tx_latency_stat { ...@@ -314,7 +295,6 @@ struct ieee80211_tx_latency_stat {
* @tid_seq: per-TID sequence numbers for sending to this STA * @tid_seq: per-TID sequence numbers for sending to this STA
* @ampdu_mlme: A-MPDU state machine state * @ampdu_mlme: A-MPDU state machine state
* @timer_to_tid: identity mapping to ID timers * @timer_to_tid: identity mapping to ID timers
* @tx_lat: Tx latency statistics
* @llid: Local link ID * @llid: Local link ID
* @plid: Peer link ID * @plid: Peer link ID
* @reason: Cancel reason on PLINK_HOLDING state * @reason: Cancel reason on PLINK_HOLDING state
...@@ -435,8 +415,6 @@ struct sta_info { ...@@ -435,8 +415,6 @@ struct sta_info {
struct sta_ampdu_mlme ampdu_mlme; struct sta_ampdu_mlme ampdu_mlme;
u8 timer_to_tid[IEEE80211_NUM_TIDS]; u8 timer_to_tid[IEEE80211_NUM_TIDS];
struct ieee80211_tx_latency_stat *tx_lat;
#ifdef CONFIG_MAC80211_MESH #ifdef CONFIG_MAC80211_MESH
/* /*
* Mesh peer link attributes * Mesh peer link attributes
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/time.h>
#include <net/mac80211.h> #include <net/mac80211.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include "ieee80211_i.h" #include "ieee80211_i.h"
...@@ -514,73 +513,6 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local, ...@@ -514,73 +513,6 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local,
} }
} }
/*
* Measure Tx frame completion and removal time for Tx latency statistics
* calculation. A single Tx frame latency should be measured from when it
* is entering the Kernel until we receive Tx complete confirmation indication
* and remove the skb.
*/
static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local,
struct sk_buff *skb,
struct sta_info *sta,
struct ieee80211_hdr *hdr)
{
u32 msrmnt;