aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToke Høiland-Jørgensen <toke@toke.dk>2016-09-12 09:55:43 -0400
committerJohannes Berg <johannes.berg@intel.com>2016-09-13 02:20:16 -0400
commit8d51dbb8c7fb5412f0935c20f66e27d2c63ef4a0 (patch)
tree7df8c29f5beab637b79d31a9cd4d6775e900d5c5
parent53f249747d5ec6434415a6895b5690bf4f1d5d7d (diff)
mac80211: Re-structure aqm debugfs output and keep CoDel stats per txq
Currently the 'aqm' stats in mac80211 only keeps overlimit drop stats, not CoDel stats. This moves the CoDel stats into the txqi structure to keep them per txq in order to show them in debugfs. In addition, the aqm debugfs output is restructured by splitting it up into three files: One global per phy, one per netdev and one per station, in the appropriate directories. The files are all called aqm, and are only created if the driver supports the wake_tx_queue op (rather than emitting an error on open as previously). Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/debugfs.c151
-rw-r--r--net/mac80211/debugfs_netdev.c37
-rw-r--r--net/mac80211/debugfs_sta.c52
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/tx.c4
5 files changed, 117 insertions, 129 deletions
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 2906c1004e1a..5bbb470f335f 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -71,138 +71,39 @@ DEBUGFS_READONLY_FILE(wep_iv, "%#08x",
71DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s", 71DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s",
72 local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver"); 72 local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver");
73 73
74struct aqm_info { 74static ssize_t aqm_read(struct file *file,
75 struct ieee80211_local *local; 75 char __user *user_buf,
76 size_t size; 76 size_t count,
77 size_t len; 77 loff_t *ppos)
78 unsigned char buf[0];
79};
80
81#define AQM_HDR_LEN 200
82#define AQM_HW_ENTRY_LEN 40
83#define AQM_TXQ_ENTRY_LEN 110
84
85static int aqm_open(struct inode *inode, struct file *file)
86{ 78{
87 struct ieee80211_local *local = inode->i_private; 79 struct ieee80211_local *local = file->private_data;
88 struct ieee80211_sub_if_data *sdata;
89 struct sta_info *sta;
90 struct txq_info *txqi;
91 struct fq *fq = &local->fq; 80 struct fq *fq = &local->fq;
92 struct aqm_info *info = NULL; 81 char buf[200];
93 int len = 0; 82 int len = 0;
94 int i;
95
96 if (!local->ops->wake_tx_queue)
97 return -EOPNOTSUPP;
98
99 len += AQM_HDR_LEN;
100 len += 6 * AQM_HW_ENTRY_LEN;
101
102 rcu_read_lock();
103 list_for_each_entry_rcu(sdata, &local->interfaces, list)
104 len += AQM_TXQ_ENTRY_LEN;
105 list_for_each_entry_rcu(sta, &local->sta_list, list)
106 len += AQM_TXQ_ENTRY_LEN * ARRAY_SIZE(sta->sta.txq);
107 rcu_read_unlock();
108
109 info = vmalloc(len);
110 if (!info)
111 return -ENOMEM;
112 83
113 spin_lock_bh(&local->fq.lock); 84 spin_lock_bh(&local->fq.lock);
114 rcu_read_lock(); 85 rcu_read_lock();
115 86
116 file->private_data = info; 87 len = scnprintf(buf, sizeof(buf),
117 info->local = local; 88 "access name value\n"
118 info->size = len; 89 "R fq_flows_cnt %u\n"
119 len = 0; 90 "R fq_backlog %u\n"
120 91 "R fq_overlimit %u\n"
121 len += scnprintf(info->buf + len, info->size - len, 92 "R fq_collisions %u\n"
122 "* hw\n" 93 "RW fq_limit %u\n"
123 "access name value\n" 94 "RW fq_quantum %u\n",
124 "R fq_flows_cnt %u\n" 95 fq->flows_cnt,
125 "R fq_backlog %u\n" 96 fq->backlog,
126 "R fq_overlimit %u\n" 97 fq->overlimit,
127 "R fq_collisions %u\n" 98 fq->collisions,
128 "RW fq_limit %u\n" 99 fq->limit,
129 "RW fq_quantum %u\n", 100 fq->quantum);
130 fq->flows_cnt,
131 fq->backlog,
132 fq->overlimit,
133 fq->collisions,
134 fq->limit,
135 fq->quantum);
136
137 len += scnprintf(info->buf + len,
138 info->size - len,
139 "* vif\n"
140 "ifname addr ac backlog-bytes backlog-packets flows overlimit collisions tx-bytes tx-packets\n");
141
142 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
143 txqi = to_txq_info(sdata->vif.txq);
144 len += scnprintf(info->buf + len, info->size - len,
145 "%s %pM %u %u %u %u %u %u %u %u\n",
146 sdata->name,
147 sdata->vif.addr,
148 txqi->txq.ac,
149 txqi->tin.backlog_bytes,
150 txqi->tin.backlog_packets,
151 txqi->tin.flows,
152 txqi->tin.overlimit,
153 txqi->tin.collisions,
154 txqi->tin.tx_bytes,
155 txqi->tin.tx_packets);
156 }
157
158 len += scnprintf(info->buf + len,
159 info->size - len,
160 "* sta\n"
161 "ifname addr tid ac backlog-bytes backlog-packets flows overlimit collisions tx-bytes tx-packets\n");
162
163 list_for_each_entry_rcu(sta, &local->sta_list, list) {
164 sdata = sta->sdata;
165 for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
166 txqi = to_txq_info(sta->sta.txq[i]);
167 len += scnprintf(info->buf + len, info->size - len,
168 "%s %pM %d %d %u %u %u %u %u %u %u\n",
169 sdata->name,
170 sta->sta.addr,
171 txqi->txq.tid,
172 txqi->txq.ac,
173 txqi->tin.backlog_bytes,
174 txqi->tin.backlog_packets,
175 txqi->tin.flows,
176 txqi->tin.overlimit,
177 txqi->tin.collisions,
178 txqi->tin.tx_bytes,
179 txqi->tin.tx_packets);
180 }
181 }
182
183 info->len = len;
184 101
185 rcu_read_unlock(); 102 rcu_read_unlock();
186 spin_unlock_bh(&local->fq.lock); 103 spin_unlock_bh(&local->fq.lock);
187 104
188 return 0;
189}
190
191static int aqm_release(struct inode *inode, struct file *file)
192{
193 vfree(file->private_data);
194 return 0;
195}
196
197static ssize_t aqm_read(struct file *file,
198 char __user *user_buf,
199 size_t count,
200 loff_t *ppos)
201{
202 struct aqm_info *info = file->private_data;
203
204 return simple_read_from_buffer(user_buf, count, ppos, 105 return simple_read_from_buffer(user_buf, count, ppos,
205 info->buf, info->len); 106 buf, len);
206} 107}
207 108
208static ssize_t aqm_write(struct file *file, 109static ssize_t aqm_write(struct file *file,
@@ -210,8 +111,7 @@ static ssize_t aqm_write(struct file *file,
210 size_t count, 111 size_t count,
211 loff_t *ppos) 112 loff_t *ppos)
212{ 113{
213 struct aqm_info *info = file->private_data; 114 struct ieee80211_local *local = file->private_data;
214 struct ieee80211_local *local = info->local;
215 char buf[100]; 115 char buf[100];
216 size_t len; 116 size_t len;
217 117
@@ -237,8 +137,7 @@ static ssize_t aqm_write(struct file *file,
237static const struct file_operations aqm_ops = { 137static const struct file_operations aqm_ops = {
238 .write = aqm_write, 138 .write = aqm_write,
239 .read = aqm_read, 139 .read = aqm_read,
240 .open = aqm_open, 140 .open = simple_open,
241 .release = aqm_release,
242 .llseek = default_llseek, 141 .llseek = default_llseek,
243}; 142};
244 143
@@ -428,7 +327,9 @@ void debugfs_hw_add(struct ieee80211_local *local)
428 DEBUGFS_ADD(hwflags); 327 DEBUGFS_ADD(hwflags);
429 DEBUGFS_ADD(user_power); 328 DEBUGFS_ADD(user_power);
430 DEBUGFS_ADD(power); 329 DEBUGFS_ADD(power);
431 DEBUGFS_ADD_MODE(aqm, 0600); 330
331 if (local->ops->wake_tx_queue)
332 DEBUGFS_ADD_MODE(aqm, 0600);
432 333
433 statsd = debugfs_create_dir("statistics", phyd); 334 statsd = debugfs_create_dir("statistics", phyd);
434 335
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index a5ba739cd2a7..5d35c0f37bb7 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -30,7 +30,7 @@ static ssize_t ieee80211_if_read(
30 size_t count, loff_t *ppos, 30 size_t count, loff_t *ppos,
31 ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int)) 31 ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int))
32{ 32{
33 char buf[70]; 33 char buf[200];
34 ssize_t ret = -EINVAL; 34 ssize_t ret = -EINVAL;
35 35
36 read_lock(&dev_base_lock); 36 read_lock(&dev_base_lock);
@@ -486,6 +486,38 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast(
486} 486}
487IEEE80211_IF_FILE_R(num_buffered_multicast); 487IEEE80211_IF_FILE_R(num_buffered_multicast);
488 488
489static ssize_t ieee80211_if_fmt_aqm(
490 const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
491{
492 struct ieee80211_local *local = sdata->local;
493 struct txq_info *txqi = to_txq_info(sdata->vif.txq);
494 int len;
495
496 spin_lock_bh(&local->fq.lock);
497 rcu_read_lock();
498
499 len = scnprintf(buf,
500 buflen,
501 "ac backlog-bytes backlog-packets new-flows drops marks overlimit collisions tx-bytes tx-packets\n"
502 "%u %u %u %u %u %u %u %u %u %u\n",
503 txqi->txq.ac,
504 txqi->tin.backlog_bytes,
505 txqi->tin.backlog_packets,
506 txqi->tin.flows,
507 txqi->cstats.drop_count,
508 txqi->cstats.ecn_mark,
509 txqi->tin.overlimit,
510 txqi->tin.collisions,
511 txqi->tin.tx_bytes,
512 txqi->tin.tx_packets);
513
514 rcu_read_unlock();
515 spin_unlock_bh(&local->fq.lock);
516
517 return len;
518}
519IEEE80211_IF_FILE_R(aqm);
520
489/* IBSS attributes */ 521/* IBSS attributes */
490static ssize_t ieee80211_if_fmt_tsf( 522static ssize_t ieee80211_if_fmt_tsf(
491 const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) 523 const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
@@ -618,6 +650,9 @@ static void add_common_files(struct ieee80211_sub_if_data *sdata)
618 DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_2ghz); 650 DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_2ghz);
619 DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_5ghz); 651 DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_5ghz);
620 DEBUGFS_ADD(hw_queues); 652 DEBUGFS_ADD(hw_queues);
653
654 if (sdata->local->ops->wake_tx_queue)
655 DEBUGFS_ADD(aqm);
621} 656}
622 657
623static void add_sta_files(struct ieee80211_sub_if_data *sdata) 658static void add_sta_files(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index fd334133ff45..fb2693582e40 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -133,6 +133,55 @@ static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf,
133} 133}
134STA_OPS(last_seq_ctrl); 134STA_OPS(last_seq_ctrl);
135 135
136#define AQM_TXQ_ENTRY_LEN 130
137
138static ssize_t sta_aqm_read(struct file *file, char __user *userbuf,
139 size_t count, loff_t *ppos)
140{
141 struct sta_info *sta = file->private_data;
142 struct ieee80211_local *local = sta->local;
143 size_t bufsz = AQM_TXQ_ENTRY_LEN*(IEEE80211_NUM_TIDS+1);
144 char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
145 struct txq_info *txqi;
146 ssize_t rv;
147 int i;
148
149 if (!buf)
150 return -ENOMEM;
151
152 spin_lock_bh(&local->fq.lock);
153 rcu_read_lock();
154
155 p += scnprintf(p,
156 bufsz+buf-p,
157 "tid ac backlog-bytes backlog-packets new-flows drops marks overlimit collisions tx-bytes tx-packets\n");
158
159 for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
160 txqi = to_txq_info(sta->sta.txq[i]);
161 p += scnprintf(p, bufsz+buf-p,
162 "%d %d %u %u %u %u %u %u %u %u %u\n",
163 txqi->txq.tid,
164 txqi->txq.ac,
165 txqi->tin.backlog_bytes,
166 txqi->tin.backlog_packets,
167 txqi->tin.flows,
168 txqi->cstats.drop_count,
169 txqi->cstats.ecn_mark,
170 txqi->tin.overlimit,
171 txqi->tin.collisions,
172 txqi->tin.tx_bytes,
173 txqi->tin.tx_packets);
174 }
175
176 rcu_read_unlock();
177 spin_unlock_bh(&local->fq.lock);
178
179 rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
180 kfree(buf);
181 return rv;
182}
183STA_OPS(aqm);
184
136static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, 185static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
137 size_t count, loff_t *ppos) 186 size_t count, loff_t *ppos)
138{ 187{
@@ -478,6 +527,9 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
478 DEBUGFS_ADD_COUNTER(rx_fragments, rx_stats.fragments); 527 DEBUGFS_ADD_COUNTER(rx_fragments, rx_stats.fragments);
479 DEBUGFS_ADD_COUNTER(tx_filtered, status_stats.filtered); 528 DEBUGFS_ADD_COUNTER(tx_filtered, status_stats.filtered);
480 529
530 if (local->ops->wake_tx_queue)
531 DEBUGFS_ADD(aqm);
532
481 if (sizeof(sta->driver_buffered_tids) == sizeof(u32)) 533 if (sizeof(sta->driver_buffered_tids) == sizeof(u32))
482 debugfs_create_x32("driver_buffered_tids", 0400, 534 debugfs_create_x32("driver_buffered_tids", 0400,
483 sta->debugfs_dir, 535 sta->debugfs_dir,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 75761686a98b..c71c73594790 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -818,6 +818,7 @@ struct txq_info {
818 struct fq_tin tin; 818 struct fq_tin tin;
819 struct fq_flow def_flow; 819 struct fq_flow def_flow;
820 struct codel_vars def_cvars; 820 struct codel_vars def_cvars;
821 struct codel_stats cstats;
821 unsigned long flags; 822 unsigned long flags;
822 823
823 /* keep last! */ 824 /* keep last! */
@@ -1117,7 +1118,6 @@ struct ieee80211_local {
1117 struct fq fq; 1118 struct fq fq;
1118 struct codel_vars *cvars; 1119 struct codel_vars *cvars;
1119 struct codel_params cparams; 1120 struct codel_params cparams;
1120 struct codel_stats cstats;
1121 1121
1122 const struct ieee80211_ops *ops; 1122 const struct ieee80211_ops *ops;
1123 1123
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index efc38e7b90b9..ee9e7d60cb78 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1343,7 +1343,7 @@ static struct sk_buff *fq_tin_dequeue_func(struct fq *fq,
1343 local = container_of(fq, struct ieee80211_local, fq); 1343 local = container_of(fq, struct ieee80211_local, fq);
1344 txqi = container_of(tin, struct txq_info, tin); 1344 txqi = container_of(tin, struct txq_info, tin);
1345 cparams = &local->cparams; 1345 cparams = &local->cparams;
1346 cstats = &local->cstats; 1346 cstats = &txqi->cstats;
1347 1347
1348 if (flow == &txqi->def_flow) 1348 if (flow == &txqi->def_flow)
1349 cvars = &txqi->def_cvars; 1349 cvars = &txqi->def_cvars;
@@ -1403,6 +1403,7 @@ void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata,
1403 fq_tin_init(&txqi->tin); 1403 fq_tin_init(&txqi->tin);
1404 fq_flow_init(&txqi->def_flow); 1404 fq_flow_init(&txqi->def_flow);
1405 codel_vars_init(&txqi->def_cvars); 1405 codel_vars_init(&txqi->def_cvars);
1406 codel_stats_init(&txqi->cstats);
1406 1407
1407 txqi->txq.vif = &sdata->vif; 1408 txqi->txq.vif = &sdata->vif;
1408 1409
@@ -1441,7 +1442,6 @@ int ieee80211_txq_setup_flows(struct ieee80211_local *local)
1441 return ret; 1442 return ret;
1442 1443
1443 codel_params_init(&local->cparams); 1444 codel_params_init(&local->cparams);
1444 codel_stats_init(&local->cstats);
1445 local->cparams.interval = MS2TIME(100); 1445 local->cparams.interval = MS2TIME(100);
1446 local->cparams.target = MS2TIME(20); 1446 local->cparams.target = MS2TIME(20);
1447 local->cparams.ecn = true; 1447 local->cparams.ecn = true;