aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/debugfs_netdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/debugfs_netdev.c')
-rw-r--r--net/mac80211/debugfs_netdev.c212
1 files changed, 136 insertions, 76 deletions
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 472b2039906c..9affe2cd185f 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -41,6 +41,30 @@ static ssize_t ieee80211_if_read(
41 return ret; 41 return ret;
42} 42}
43 43
44static ssize_t ieee80211_if_write(
45 struct ieee80211_sub_if_data *sdata,
46 const char __user *userbuf,
47 size_t count, loff_t *ppos,
48 ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int))
49{
50 u8 *buf;
51 ssize_t ret = -ENODEV;
52
53 buf = kzalloc(count, GFP_KERNEL);
54 if (!buf)
55 return -ENOMEM;
56
57 if (copy_from_user(buf, userbuf, count))
58 return -EFAULT;
59
60 rtnl_lock();
61 if (sdata->dev->reg_state == NETREG_REGISTERED)
62 ret = (*write)(sdata, buf, count);
63 rtnl_unlock();
64
65 return ret;
66}
67
44#define IEEE80211_IF_FMT(name, field, format_string) \ 68#define IEEE80211_IF_FMT(name, field, format_string) \
45static ssize_t ieee80211_if_fmt_##name( \ 69static ssize_t ieee80211_if_fmt_##name( \
46 const struct ieee80211_sub_if_data *sdata, char *buf, \ 70 const struct ieee80211_sub_if_data *sdata, char *buf, \
@@ -71,7 +95,7 @@ static ssize_t ieee80211_if_fmt_##name( \
71 return scnprintf(buf, buflen, "%pM\n", sdata->field); \ 95 return scnprintf(buf, buflen, "%pM\n", sdata->field); \
72} 96}
73 97
74#define __IEEE80211_IF_FILE(name) \ 98#define __IEEE80211_IF_FILE(name, _write) \
75static ssize_t ieee80211_if_read_##name(struct file *file, \ 99static ssize_t ieee80211_if_read_##name(struct file *file, \
76 char __user *userbuf, \ 100 char __user *userbuf, \
77 size_t count, loff_t *ppos) \ 101 size_t count, loff_t *ppos) \
@@ -82,22 +106,99 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \
82} \ 106} \
83static const struct file_operations name##_ops = { \ 107static const struct file_operations name##_ops = { \
84 .read = ieee80211_if_read_##name, \ 108 .read = ieee80211_if_read_##name, \
109 .write = (_write), \
85 .open = mac80211_open_file_generic, \ 110 .open = mac80211_open_file_generic, \
86} 111}
87 112
113#define __IEEE80211_IF_FILE_W(name) \
114static ssize_t ieee80211_if_write_##name(struct file *file, \
115 const char __user *userbuf, \
116 size_t count, loff_t *ppos) \
117{ \
118 return ieee80211_if_write(file->private_data, userbuf, count, \
119 ppos, ieee80211_if_parse_##name); \
120} \
121__IEEE80211_IF_FILE(name, ieee80211_if_write_##name)
122
123
88#define IEEE80211_IF_FILE(name, field, format) \ 124#define IEEE80211_IF_FILE(name, field, format) \
89 IEEE80211_IF_FMT_##format(name, field) \ 125 IEEE80211_IF_FMT_##format(name, field) \
90 __IEEE80211_IF_FILE(name) 126 __IEEE80211_IF_FILE(name, NULL)
91 127
92/* common attributes */ 128/* common attributes */
93IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); 129IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
94IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC); 130IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ],
95IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC); 131 HEX);
132IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ],
133 HEX);
96 134
97/* STA attributes */ 135/* STA attributes */
98IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); 136IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
99IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); 137IEEE80211_IF_FILE(aid, u.mgd.aid, DEC);
100IEEE80211_IF_FILE(capab, u.mgd.capab, HEX); 138
139static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
140 enum ieee80211_smps_mode smps_mode)
141{
142 struct ieee80211_local *local = sdata->local;
143 int err;
144
145 if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) &&
146 smps_mode == IEEE80211_SMPS_STATIC)
147 return -EINVAL;
148
149 /* auto should be dynamic if in PS mode */
150 if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) &&
151 (smps_mode == IEEE80211_SMPS_DYNAMIC ||
152 smps_mode == IEEE80211_SMPS_AUTOMATIC))
153 return -EINVAL;
154
155 /* supported only on managed interfaces for now */
156 if (sdata->vif.type != NL80211_IFTYPE_STATION)
157 return -EOPNOTSUPP;
158
159 mutex_lock(&local->iflist_mtx);
160 err = __ieee80211_request_smps(sdata, smps_mode);
161 mutex_unlock(&local->iflist_mtx);
162
163 return err;
164}
165
166static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = {
167 [IEEE80211_SMPS_AUTOMATIC] = "auto",
168 [IEEE80211_SMPS_OFF] = "off",
169 [IEEE80211_SMPS_STATIC] = "static",
170 [IEEE80211_SMPS_DYNAMIC] = "dynamic",
171};
172
173static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata,
174 char *buf, int buflen)
175{
176 if (sdata->vif.type != NL80211_IFTYPE_STATION)
177 return -EOPNOTSUPP;
178
179 return snprintf(buf, buflen, "request: %s\nused: %s\n",
180 smps_modes[sdata->u.mgd.req_smps],
181 smps_modes[sdata->u.mgd.ap_smps]);
182}
183
184static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata,
185 const char *buf, int buflen)
186{
187 enum ieee80211_smps_mode mode;
188
189 for (mode = 0; mode < IEEE80211_SMPS_NUM_MODES; mode++) {
190 if (strncmp(buf, smps_modes[mode], buflen) == 0) {
191 int err = ieee80211_set_smps(sdata, mode);
192 if (!err)
193 return buflen;
194 return err;
195 }
196 }
197
198 return -EINVAL;
199}
200
201__IEEE80211_IF_FILE_W(smps);
101 202
102/* AP attributes */ 203/* AP attributes */
103IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); 204IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
@@ -109,7 +210,7 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast(
109 return scnprintf(buf, buflen, "%u\n", 210 return scnprintf(buf, buflen, "%u\n",
110 skb_queue_len(&sdata->u.ap.ps_bc_buf)); 211 skb_queue_len(&sdata->u.ap.ps_bc_buf));
111} 212}
112__IEEE80211_IF_FILE(num_buffered_multicast); 213__IEEE80211_IF_FILE(num_buffered_multicast, NULL);
113 214
114/* WDS attributes */ 215/* WDS attributes */
115IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); 216IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
@@ -154,46 +255,50 @@ IEEE80211_IF_FILE(dot11MeshHWMPRootMode,
154#endif 255#endif
155 256
156 257
157#define DEBUGFS_ADD(name, type) \ 258#define DEBUGFS_ADD(name) \
158 debugfs_create_file(#name, 0400, sdata->debugfs.dir, \ 259 debugfs_create_file(#name, 0400, sdata->debugfs.dir, \
159 sdata, &name##_ops); 260 sdata, &name##_ops);
160 261
262#define DEBUGFS_ADD_MODE(name, mode) \
263 debugfs_create_file(#name, mode, sdata->debugfs.dir, \
264 sdata, &name##_ops);
265
161static void add_sta_files(struct ieee80211_sub_if_data *sdata) 266static void add_sta_files(struct ieee80211_sub_if_data *sdata)
162{ 267{
163 DEBUGFS_ADD(drop_unencrypted, sta); 268 DEBUGFS_ADD(drop_unencrypted);
164 DEBUGFS_ADD(force_unicast_rateidx, sta); 269 DEBUGFS_ADD(rc_rateidx_mask_2ghz);
165 DEBUGFS_ADD(max_ratectrl_rateidx, sta); 270 DEBUGFS_ADD(rc_rateidx_mask_5ghz);
166 271
167 DEBUGFS_ADD(bssid, sta); 272 DEBUGFS_ADD(bssid);
168 DEBUGFS_ADD(aid, sta); 273 DEBUGFS_ADD(aid);
169 DEBUGFS_ADD(capab, sta); 274 DEBUGFS_ADD_MODE(smps, 0600);
170} 275}
171 276
172static void add_ap_files(struct ieee80211_sub_if_data *sdata) 277static void add_ap_files(struct ieee80211_sub_if_data *sdata)
173{ 278{
174 DEBUGFS_ADD(drop_unencrypted, ap); 279 DEBUGFS_ADD(drop_unencrypted);
175 DEBUGFS_ADD(force_unicast_rateidx, ap); 280 DEBUGFS_ADD(rc_rateidx_mask_2ghz);
176 DEBUGFS_ADD(max_ratectrl_rateidx, ap); 281 DEBUGFS_ADD(rc_rateidx_mask_5ghz);
177 282
178 DEBUGFS_ADD(num_sta_ps, ap); 283 DEBUGFS_ADD(num_sta_ps);
179 DEBUGFS_ADD(dtim_count, ap); 284 DEBUGFS_ADD(dtim_count);
180 DEBUGFS_ADD(num_buffered_multicast, ap); 285 DEBUGFS_ADD(num_buffered_multicast);
181} 286}
182 287
183static void add_wds_files(struct ieee80211_sub_if_data *sdata) 288static void add_wds_files(struct ieee80211_sub_if_data *sdata)
184{ 289{
185 DEBUGFS_ADD(drop_unencrypted, wds); 290 DEBUGFS_ADD(drop_unencrypted);
186 DEBUGFS_ADD(force_unicast_rateidx, wds); 291 DEBUGFS_ADD(rc_rateidx_mask_2ghz);
187 DEBUGFS_ADD(max_ratectrl_rateidx, wds); 292 DEBUGFS_ADD(rc_rateidx_mask_5ghz);
188 293
189 DEBUGFS_ADD(peer, wds); 294 DEBUGFS_ADD(peer);
190} 295}
191 296
192static void add_vlan_files(struct ieee80211_sub_if_data *sdata) 297static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
193{ 298{
194 DEBUGFS_ADD(drop_unencrypted, vlan); 299 DEBUGFS_ADD(drop_unencrypted);
195 DEBUGFS_ADD(force_unicast_rateidx, vlan); 300 DEBUGFS_ADD(rc_rateidx_mask_2ghz);
196 DEBUGFS_ADD(max_ratectrl_rateidx, vlan); 301 DEBUGFS_ADD(rc_rateidx_mask_5ghz);
197} 302}
198 303
199static void add_monitor_files(struct ieee80211_sub_if_data *sdata) 304static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
@@ -280,16 +385,11 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
280 } 385 }
281} 386}
282 387
283static int notif_registered;
284
285void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) 388void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
286{ 389{
287 char buf[10+IFNAMSIZ]; 390 char buf[10+IFNAMSIZ];
288 391
289 if (!notif_registered) 392 sprintf(buf, "netdev:%s", sdata->name);
290 return;
291
292 sprintf(buf, "netdev:%s", sdata->dev->name);
293 sdata->debugfs.dir = debugfs_create_dir(buf, 393 sdata->debugfs.dir = debugfs_create_dir(buf,
294 sdata->local->hw.wiphy->debugfsdir); 394 sdata->local->hw.wiphy->debugfsdir);
295 add_files(sdata); 395 add_files(sdata);
@@ -304,58 +404,18 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
304 sdata->debugfs.dir = NULL; 404 sdata->debugfs.dir = NULL;
305} 405}
306 406
307static int netdev_notify(struct notifier_block *nb, 407void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
308 unsigned long state,
309 void *ndev)
310{ 408{
311 struct net_device *dev = ndev;
312 struct dentry *dir; 409 struct dentry *dir;
313 struct ieee80211_sub_if_data *sdata; 410 char buf[10 + IFNAMSIZ];
314 char buf[10+IFNAMSIZ];
315
316 if (state != NETDEV_CHANGENAME)
317 return 0;
318
319 if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
320 return 0;
321
322 if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
323 return 0;
324
325 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
326 411
327 dir = sdata->debugfs.dir; 412 dir = sdata->debugfs.dir;
328 413
329 if (!dir) 414 if (!dir)
330 return 0; 415 return;
331 416
332 sprintf(buf, "netdev:%s", dev->name); 417 sprintf(buf, "netdev:%s", sdata->name);
333 if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) 418 if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf))
334 printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " 419 printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs "
335 "dir to %s\n", buf); 420 "dir to %s\n", buf);
336
337 return 0;
338}
339
340static struct notifier_block mac80211_debugfs_netdev_notifier = {
341 .notifier_call = netdev_notify,
342};
343
344void ieee80211_debugfs_netdev_init(void)
345{
346 int err;
347
348 err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
349 if (err) {
350 printk(KERN_ERR
351 "mac80211: failed to install netdev notifier,"
352 " disabling per-netdev debugfs!\n");
353 } else
354 notif_registered = 1;
355}
356
357void ieee80211_debugfs_netdev_exit(void)
358{
359 unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
360 notif_registered = 0;
361} 421}