diff options
Diffstat (limited to 'net/mac80211/debugfs_netdev.c')
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 212 |
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 | ||
44 | static 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) \ |
45 | static ssize_t ieee80211_if_fmt_##name( \ | 69 | static 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) \ |
75 | static ssize_t ieee80211_if_read_##name(struct file *file, \ | 99 | static 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 | } \ |
83 | static const struct file_operations name##_ops = { \ | 107 | static 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) \ | ||
114 | static 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 */ |
93 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); | 129 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); |
94 | IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC); | 130 | IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ], |
95 | IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC); | 131 | HEX); |
132 | IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], | ||
133 | HEX); | ||
96 | 134 | ||
97 | /* STA attributes */ | 135 | /* STA attributes */ |
98 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); | 136 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); |
99 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); | 137 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); |
100 | IEEE80211_IF_FILE(capab, u.mgd.capab, HEX); | 138 | |
139 | static 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 | |||
166 | static 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 | |||
173 | static 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 | |||
184 | static 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 */ |
103 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); | 204 | IEEE80211_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 */ |
115 | IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); | 216 | IEEE80211_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 | |||
161 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) | 266 | static 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 | ||
172 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 277 | static 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 | ||
183 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) | 288 | static 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 | ||
192 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | 297 | static 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 | ||
199 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | 304 | static 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 | ||
283 | static int notif_registered; | ||
284 | |||
285 | void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) | 388 | void 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 | ||
307 | static int netdev_notify(struct notifier_block *nb, | 407 | void 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 | |||
340 | static struct notifier_block mac80211_debugfs_netdev_notifier = { | ||
341 | .notifier_call = netdev_notify, | ||
342 | }; | ||
343 | |||
344 | void 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 | |||
357 | void ieee80211_debugfs_netdev_exit(void) | ||
358 | { | ||
359 | unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier); | ||
360 | notif_registered = 0; | ||
361 | } | 421 | } |