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.c216
1 files changed, 140 insertions, 76 deletions
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 472b2039906c..b4ddb2f83914 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -41,6 +41,34 @@ 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;
52
53 buf = kmalloc(count, GFP_KERNEL);
54 if (!buf)
55 return -ENOMEM;
56
57 ret = -EFAULT;
58 if (copy_from_user(buf, userbuf, count))
59 goto freebuf;
60
61 ret = -ENODEV;
62 rtnl_lock();
63 if (sdata->dev->reg_state == NETREG_REGISTERED)
64 ret = (*write)(sdata, buf, count);
65 rtnl_unlock();
66
67freebuf:
68 kfree(buf);
69 return ret;
70}
71
44#define IEEE80211_IF_FMT(name, field, format_string) \ 72#define IEEE80211_IF_FMT(name, field, format_string) \
45static ssize_t ieee80211_if_fmt_##name( \ 73static ssize_t ieee80211_if_fmt_##name( \
46 const struct ieee80211_sub_if_data *sdata, char *buf, \ 74 const struct ieee80211_sub_if_data *sdata, char *buf, \
@@ -71,7 +99,7 @@ static ssize_t ieee80211_if_fmt_##name( \
71 return scnprintf(buf, buflen, "%pM\n", sdata->field); \ 99 return scnprintf(buf, buflen, "%pM\n", sdata->field); \
72} 100}
73 101
74#define __IEEE80211_IF_FILE(name) \ 102#define __IEEE80211_IF_FILE(name, _write) \
75static ssize_t ieee80211_if_read_##name(struct file *file, \ 103static ssize_t ieee80211_if_read_##name(struct file *file, \
76 char __user *userbuf, \ 104 char __user *userbuf, \
77 size_t count, loff_t *ppos) \ 105 size_t count, loff_t *ppos) \
@@ -82,22 +110,99 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \
82} \ 110} \
83static const struct file_operations name##_ops = { \ 111static const struct file_operations name##_ops = { \
84 .read = ieee80211_if_read_##name, \ 112 .read = ieee80211_if_read_##name, \
113 .write = (_write), \
85 .open = mac80211_open_file_generic, \ 114 .open = mac80211_open_file_generic, \
86} 115}
87 116
117#define __IEEE80211_IF_FILE_W(name) \
118static ssize_t ieee80211_if_write_##name(struct file *file, \
119 const char __user *userbuf, \
120 size_t count, loff_t *ppos) \
121{ \
122 return ieee80211_if_write(file->private_data, userbuf, count, \
123 ppos, ieee80211_if_parse_##name); \
124} \
125__IEEE80211_IF_FILE(name, ieee80211_if_write_##name)
126
127
88#define IEEE80211_IF_FILE(name, field, format) \ 128#define IEEE80211_IF_FILE(name, field, format) \
89 IEEE80211_IF_FMT_##format(name, field) \ 129 IEEE80211_IF_FMT_##format(name, field) \
90 __IEEE80211_IF_FILE(name) 130 __IEEE80211_IF_FILE(name, NULL)
91 131
92/* common attributes */ 132/* common attributes */
93IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); 133IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
94IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC); 134IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ],
95IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC); 135 HEX);
136IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ],
137 HEX);
96 138
97/* STA attributes */ 139/* STA attributes */
98IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); 140IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
99IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); 141IEEE80211_IF_FILE(aid, u.mgd.aid, DEC);
100IEEE80211_IF_FILE(capab, u.mgd.capab, HEX); 142
143static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
144 enum ieee80211_smps_mode smps_mode)
145{
146 struct ieee80211_local *local = sdata->local;
147 int err;
148
149 if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) &&
150 smps_mode == IEEE80211_SMPS_STATIC)
151 return -EINVAL;
152
153 /* auto should be dynamic if in PS mode */
154 if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) &&
155 (smps_mode == IEEE80211_SMPS_DYNAMIC ||
156 smps_mode == IEEE80211_SMPS_AUTOMATIC))
157 return -EINVAL;
158
159 /* supported only on managed interfaces for now */
160 if (sdata->vif.type != NL80211_IFTYPE_STATION)
161 return -EOPNOTSUPP;
162
163 mutex_lock(&local->iflist_mtx);
164 err = __ieee80211_request_smps(sdata, smps_mode);
165 mutex_unlock(&local->iflist_mtx);
166
167 return err;
168}
169
170static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = {
171 [IEEE80211_SMPS_AUTOMATIC] = "auto",
172 [IEEE80211_SMPS_OFF] = "off",
173 [IEEE80211_SMPS_STATIC] = "static",
174 [IEEE80211_SMPS_DYNAMIC] = "dynamic",
175};
176
177static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata,
178 char *buf, int buflen)
179{
180 if (sdata->vif.type != NL80211_IFTYPE_STATION)
181 return -EOPNOTSUPP;
182
183 return snprintf(buf, buflen, "request: %s\nused: %s\n",
184 smps_modes[sdata->u.mgd.req_smps],
185 smps_modes[sdata->u.mgd.ap_smps]);
186}
187
188static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata,
189 const char *buf, int buflen)
190{
191 enum ieee80211_smps_mode mode;
192
193 for (mode = 0; mode < IEEE80211_SMPS_NUM_MODES; mode++) {
194 if (strncmp(buf, smps_modes[mode], buflen) == 0) {
195 int err = ieee80211_set_smps(sdata, mode);
196 if (!err)
197 return buflen;
198 return err;
199 }
200 }
201
202 return -EINVAL;
203}
204
205__IEEE80211_IF_FILE_W(smps);
101 206
102/* AP attributes */ 207/* AP attributes */
103IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); 208IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
@@ -109,7 +214,7 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast(
109 return scnprintf(buf, buflen, "%u\n", 214 return scnprintf(buf, buflen, "%u\n",
110 skb_queue_len(&sdata->u.ap.ps_bc_buf)); 215 skb_queue_len(&sdata->u.ap.ps_bc_buf));
111} 216}
112__IEEE80211_IF_FILE(num_buffered_multicast); 217__IEEE80211_IF_FILE(num_buffered_multicast, NULL);
113 218
114/* WDS attributes */ 219/* WDS attributes */
115IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); 220IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
@@ -154,46 +259,50 @@ IEEE80211_IF_FILE(dot11MeshHWMPRootMode,
154#endif 259#endif
155 260
156 261
157#define DEBUGFS_ADD(name, type) \ 262#define DEBUGFS_ADD(name) \
158 debugfs_create_file(#name, 0400, sdata->debugfs.dir, \ 263 debugfs_create_file(#name, 0400, sdata->debugfs.dir, \
159 sdata, &name##_ops); 264 sdata, &name##_ops);
160 265
266#define DEBUGFS_ADD_MODE(name, mode) \
267 debugfs_create_file(#name, mode, sdata->debugfs.dir, \
268 sdata, &name##_ops);
269
161static void add_sta_files(struct ieee80211_sub_if_data *sdata) 270static void add_sta_files(struct ieee80211_sub_if_data *sdata)
162{ 271{
163 DEBUGFS_ADD(drop_unencrypted, sta); 272 DEBUGFS_ADD(drop_unencrypted);
164 DEBUGFS_ADD(force_unicast_rateidx, sta); 273 DEBUGFS_ADD(rc_rateidx_mask_2ghz);
165 DEBUGFS_ADD(max_ratectrl_rateidx, sta); 274 DEBUGFS_ADD(rc_rateidx_mask_5ghz);
166 275
167 DEBUGFS_ADD(bssid, sta); 276 DEBUGFS_ADD(bssid);
168 DEBUGFS_ADD(aid, sta); 277 DEBUGFS_ADD(aid);
169 DEBUGFS_ADD(capab, sta); 278 DEBUGFS_ADD_MODE(smps, 0600);
170} 279}
171 280
172static void add_ap_files(struct ieee80211_sub_if_data *sdata) 281static void add_ap_files(struct ieee80211_sub_if_data *sdata)
173{ 282{
174 DEBUGFS_ADD(drop_unencrypted, ap); 283 DEBUGFS_ADD(drop_unencrypted);
175 DEBUGFS_ADD(force_unicast_rateidx, ap); 284 DEBUGFS_ADD(rc_rateidx_mask_2ghz);
176 DEBUGFS_ADD(max_ratectrl_rateidx, ap); 285 DEBUGFS_ADD(rc_rateidx_mask_5ghz);
177 286
178 DEBUGFS_ADD(num_sta_ps, ap); 287 DEBUGFS_ADD(num_sta_ps);
179 DEBUGFS_ADD(dtim_count, ap); 288 DEBUGFS_ADD(dtim_count);
180 DEBUGFS_ADD(num_buffered_multicast, ap); 289 DEBUGFS_ADD(num_buffered_multicast);
181} 290}
182 291
183static void add_wds_files(struct ieee80211_sub_if_data *sdata) 292static void add_wds_files(struct ieee80211_sub_if_data *sdata)
184{ 293{
185 DEBUGFS_ADD(drop_unencrypted, wds); 294 DEBUGFS_ADD(drop_unencrypted);
186 DEBUGFS_ADD(force_unicast_rateidx, wds); 295 DEBUGFS_ADD(rc_rateidx_mask_2ghz);
187 DEBUGFS_ADD(max_ratectrl_rateidx, wds); 296 DEBUGFS_ADD(rc_rateidx_mask_5ghz);
188 297
189 DEBUGFS_ADD(peer, wds); 298 DEBUGFS_ADD(peer);
190} 299}
191 300
192static void add_vlan_files(struct ieee80211_sub_if_data *sdata) 301static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
193{ 302{
194 DEBUGFS_ADD(drop_unencrypted, vlan); 303 DEBUGFS_ADD(drop_unencrypted);
195 DEBUGFS_ADD(force_unicast_rateidx, vlan); 304 DEBUGFS_ADD(rc_rateidx_mask_2ghz);
196 DEBUGFS_ADD(max_ratectrl_rateidx, vlan); 305 DEBUGFS_ADD(rc_rateidx_mask_5ghz);
197} 306}
198 307
199static void add_monitor_files(struct ieee80211_sub_if_data *sdata) 308static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
@@ -280,16 +389,11 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
280 } 389 }
281} 390}
282 391
283static int notif_registered;
284
285void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) 392void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
286{ 393{
287 char buf[10+IFNAMSIZ]; 394 char buf[10+IFNAMSIZ];
288 395
289 if (!notif_registered) 396 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, 397 sdata->debugfs.dir = debugfs_create_dir(buf,
294 sdata->local->hw.wiphy->debugfsdir); 398 sdata->local->hw.wiphy->debugfsdir);
295 add_files(sdata); 399 add_files(sdata);
@@ -304,58 +408,18 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
304 sdata->debugfs.dir = NULL; 408 sdata->debugfs.dir = NULL;
305} 409}
306 410
307static int netdev_notify(struct notifier_block *nb, 411void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
308 unsigned long state,
309 void *ndev)
310{ 412{
311 struct net_device *dev = ndev;
312 struct dentry *dir; 413 struct dentry *dir;
313 struct ieee80211_sub_if_data *sdata; 414 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 415
327 dir = sdata->debugfs.dir; 416 dir = sdata->debugfs.dir;
328 417
329 if (!dir) 418 if (!dir)
330 return 0; 419 return;
331 420
332 sprintf(buf, "netdev:%s", dev->name); 421 sprintf(buf, "netdev:%s", sdata->name);
333 if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) 422 if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf))
334 printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " 423 printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs "
335 "dir to %s\n", buf); 424 "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} 425}