diff options
| author | Michal Marek <mmarek@suse.cz> | 2010-10-27 18:15:57 -0400 |
|---|---|---|
| committer | Michal Marek <mmarek@suse.cz> | 2010-10-27 18:15:57 -0400 |
| commit | b74b953b998bcc2db91b694446f3a2619ec32de6 (patch) | |
| tree | 6ce24caabd730f6ae9287ed0676ec32e6ff31e9d /net/mac80211/debugfs_netdev.c | |
| parent | abb438526201c6a79949ad45375c051b6681c253 (diff) | |
| parent | f6f94e2ab1b33f0082ac22d71f66385a60d8157f (diff) | |
Merge commit 'v2.6.36' into kbuild/misc
Update to be able to fix a recent change to scripts/basic/docproc.c
(commit eda603f).
Diffstat (limited to 'net/mac80211/debugfs_netdev.c')
| -rw-r--r-- | net/mac80211/debugfs_netdev.c | 231 |
1 files changed, 154 insertions, 77 deletions
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 472b2039906c..20b2998fa0ed 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
| 14 | #include <linux/netdevice.h> | 14 | #include <linux/netdevice.h> |
| 15 | #include <linux/rtnetlink.h> | 15 | #include <linux/rtnetlink.h> |
| 16 | #include <linux/slab.h> | ||
| 16 | #include <linux/notifier.h> | 17 | #include <linux/notifier.h> |
| 17 | #include <net/mac80211.h> | 18 | #include <net/mac80211.h> |
| 18 | #include <net/cfg80211.h> | 19 | #include <net/cfg80211.h> |
| @@ -41,6 +42,34 @@ static ssize_t ieee80211_if_read( | |||
| 41 | return ret; | 42 | return ret; |
| 42 | } | 43 | } |
| 43 | 44 | ||
| 45 | static ssize_t ieee80211_if_write( | ||
| 46 | struct ieee80211_sub_if_data *sdata, | ||
| 47 | const char __user *userbuf, | ||
| 48 | size_t count, loff_t *ppos, | ||
| 49 | ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int)) | ||
| 50 | { | ||
| 51 | u8 *buf; | ||
| 52 | ssize_t ret; | ||
| 53 | |||
| 54 | buf = kmalloc(count, GFP_KERNEL); | ||
| 55 | if (!buf) | ||
| 56 | return -ENOMEM; | ||
| 57 | |||
| 58 | ret = -EFAULT; | ||
| 59 | if (copy_from_user(buf, userbuf, count)) | ||
| 60 | goto freebuf; | ||
| 61 | |||
| 62 | ret = -ENODEV; | ||
| 63 | rtnl_lock(); | ||
| 64 | if (sdata->dev->reg_state == NETREG_REGISTERED) | ||
| 65 | ret = (*write)(sdata, buf, count); | ||
| 66 | rtnl_unlock(); | ||
| 67 | |||
| 68 | freebuf: | ||
| 69 | kfree(buf); | ||
| 70 | return ret; | ||
| 71 | } | ||
| 72 | |||
| 44 | #define IEEE80211_IF_FMT(name, field, format_string) \ | 73 | #define IEEE80211_IF_FMT(name, field, format_string) \ |
| 45 | static ssize_t ieee80211_if_fmt_##name( \ | 74 | static ssize_t ieee80211_if_fmt_##name( \ |
| 46 | const struct ieee80211_sub_if_data *sdata, char *buf, \ | 75 | const struct ieee80211_sub_if_data *sdata, char *buf, \ |
| @@ -71,7 +100,15 @@ static ssize_t ieee80211_if_fmt_##name( \ | |||
| 71 | return scnprintf(buf, buflen, "%pM\n", sdata->field); \ | 100 | return scnprintf(buf, buflen, "%pM\n", sdata->field); \ |
| 72 | } | 101 | } |
| 73 | 102 | ||
| 74 | #define __IEEE80211_IF_FILE(name) \ | 103 | #define IEEE80211_IF_FMT_DEC_DIV_16(name, field) \ |
| 104 | static ssize_t ieee80211_if_fmt_##name( \ | ||
| 105 | const struct ieee80211_sub_if_data *sdata, \ | ||
| 106 | char *buf, int buflen) \ | ||
| 107 | { \ | ||
| 108 | return scnprintf(buf, buflen, "%d\n", sdata->field / 16); \ | ||
| 109 | } | ||
| 110 | |||
| 111 | #define __IEEE80211_IF_FILE(name, _write) \ | ||
| 75 | static ssize_t ieee80211_if_read_##name(struct file *file, \ | 112 | static ssize_t ieee80211_if_read_##name(struct file *file, \ |
| 76 | char __user *userbuf, \ | 113 | char __user *userbuf, \ |
| 77 | size_t count, loff_t *ppos) \ | 114 | size_t count, loff_t *ppos) \ |
| @@ -82,22 +119,101 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \ | |||
| 82 | } \ | 119 | } \ |
| 83 | static const struct file_operations name##_ops = { \ | 120 | static const struct file_operations name##_ops = { \ |
| 84 | .read = ieee80211_if_read_##name, \ | 121 | .read = ieee80211_if_read_##name, \ |
| 122 | .write = (_write), \ | ||
| 85 | .open = mac80211_open_file_generic, \ | 123 | .open = mac80211_open_file_generic, \ |
| 86 | } | 124 | } |
| 87 | 125 | ||
| 126 | #define __IEEE80211_IF_FILE_W(name) \ | ||
| 127 | static ssize_t ieee80211_if_write_##name(struct file *file, \ | ||
| 128 | const char __user *userbuf, \ | ||
| 129 | size_t count, loff_t *ppos) \ | ||
| 130 | { \ | ||
| 131 | return ieee80211_if_write(file->private_data, userbuf, count, \ | ||
| 132 | ppos, ieee80211_if_parse_##name); \ | ||
| 133 | } \ | ||
| 134 | __IEEE80211_IF_FILE(name, ieee80211_if_write_##name) | ||
| 135 | |||
| 136 | |||
| 88 | #define IEEE80211_IF_FILE(name, field, format) \ | 137 | #define IEEE80211_IF_FILE(name, field, format) \ |
| 89 | IEEE80211_IF_FMT_##format(name, field) \ | 138 | IEEE80211_IF_FMT_##format(name, field) \ |
| 90 | __IEEE80211_IF_FILE(name) | 139 | __IEEE80211_IF_FILE(name, NULL) |
| 91 | 140 | ||
| 92 | /* common attributes */ | 141 | /* common attributes */ |
| 93 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); | 142 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); |
| 94 | IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC); | 143 | IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ], |
| 95 | IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC); | 144 | HEX); |
| 145 | IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], | ||
| 146 | HEX); | ||
| 96 | 147 | ||
| 97 | /* STA attributes */ | 148 | /* STA attributes */ |
| 98 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); | 149 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); |
| 99 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); | 150 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); |
| 100 | IEEE80211_IF_FILE(capab, u.mgd.capab, HEX); | 151 | IEEE80211_IF_FILE(last_beacon, u.mgd.last_beacon_signal, DEC); |
| 152 | IEEE80211_IF_FILE(ave_beacon, u.mgd.ave_beacon_signal, DEC_DIV_16); | ||
| 153 | |||
| 154 | static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, | ||
| 155 | enum ieee80211_smps_mode smps_mode) | ||
| 156 | { | ||
| 157 | struct ieee80211_local *local = sdata->local; | ||
| 158 | int err; | ||
| 159 | |||
| 160 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) && | ||
| 161 | smps_mode == IEEE80211_SMPS_STATIC) | ||
| 162 | return -EINVAL; | ||
| 163 | |||
| 164 | /* auto should be dynamic if in PS mode */ | ||
| 165 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) && | ||
| 166 | (smps_mode == IEEE80211_SMPS_DYNAMIC || | ||
| 167 | smps_mode == IEEE80211_SMPS_AUTOMATIC)) | ||
| 168 | return -EINVAL; | ||
| 169 | |||
| 170 | /* supported only on managed interfaces for now */ | ||
| 171 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
| 172 | return -EOPNOTSUPP; | ||
| 173 | |||
| 174 | mutex_lock(&local->iflist_mtx); | ||
| 175 | err = __ieee80211_request_smps(sdata, smps_mode); | ||
| 176 | mutex_unlock(&local->iflist_mtx); | ||
| 177 | |||
| 178 | return err; | ||
| 179 | } | ||
| 180 | |||
| 181 | static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = { | ||
| 182 | [IEEE80211_SMPS_AUTOMATIC] = "auto", | ||
| 183 | [IEEE80211_SMPS_OFF] = "off", | ||
| 184 | [IEEE80211_SMPS_STATIC] = "static", | ||
| 185 | [IEEE80211_SMPS_DYNAMIC] = "dynamic", | ||
| 186 | }; | ||
| 187 | |||
| 188 | static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata, | ||
| 189 | char *buf, int buflen) | ||
| 190 | { | ||
| 191 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
| 192 | return -EOPNOTSUPP; | ||
| 193 | |||
| 194 | return snprintf(buf, buflen, "request: %s\nused: %s\n", | ||
| 195 | smps_modes[sdata->u.mgd.req_smps], | ||
| 196 | smps_modes[sdata->u.mgd.ap_smps]); | ||
| 197 | } | ||
| 198 | |||
| 199 | static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata, | ||
| 200 | const char *buf, int buflen) | ||
| 201 | { | ||
| 202 | enum ieee80211_smps_mode mode; | ||
| 203 | |||
| 204 | for (mode = 0; mode < IEEE80211_SMPS_NUM_MODES; mode++) { | ||
| 205 | if (strncmp(buf, smps_modes[mode], buflen) == 0) { | ||
| 206 | int err = ieee80211_set_smps(sdata, mode); | ||
| 207 | if (!err) | ||
| 208 | return buflen; | ||
| 209 | return err; | ||
| 210 | } | ||
| 211 | } | ||
| 212 | |||
| 213 | return -EINVAL; | ||
| 214 | } | ||
| 215 | |||
| 216 | __IEEE80211_IF_FILE_W(smps); | ||
| 101 | 217 | ||
| 102 | /* AP attributes */ | 218 | /* AP attributes */ |
| 103 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); | 219 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); |
| @@ -109,7 +225,7 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast( | |||
| 109 | return scnprintf(buf, buflen, "%u\n", | 225 | return scnprintf(buf, buflen, "%u\n", |
| 110 | skb_queue_len(&sdata->u.ap.ps_bc_buf)); | 226 | skb_queue_len(&sdata->u.ap.ps_bc_buf)); |
| 111 | } | 227 | } |
| 112 | __IEEE80211_IF_FILE(num_buffered_multicast); | 228 | __IEEE80211_IF_FILE(num_buffered_multicast, NULL); |
| 113 | 229 | ||
| 114 | /* WDS attributes */ | 230 | /* WDS attributes */ |
| 115 | IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); | 231 | IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); |
| @@ -154,46 +270,52 @@ IEEE80211_IF_FILE(dot11MeshHWMPRootMode, | |||
| 154 | #endif | 270 | #endif |
| 155 | 271 | ||
| 156 | 272 | ||
| 157 | #define DEBUGFS_ADD(name, type) \ | 273 | #define DEBUGFS_ADD(name) \ |
| 158 | debugfs_create_file(#name, 0400, sdata->debugfs.dir, \ | 274 | debugfs_create_file(#name, 0400, sdata->debugfs.dir, \ |
| 159 | sdata, &name##_ops); | 275 | sdata, &name##_ops); |
| 160 | 276 | ||
| 277 | #define DEBUGFS_ADD_MODE(name, mode) \ | ||
| 278 | debugfs_create_file(#name, mode, sdata->debugfs.dir, \ | ||
| 279 | sdata, &name##_ops); | ||
| 280 | |||
| 161 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) | 281 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) |
| 162 | { | 282 | { |
| 163 | DEBUGFS_ADD(drop_unencrypted, sta); | 283 | DEBUGFS_ADD(drop_unencrypted); |
| 164 | DEBUGFS_ADD(force_unicast_rateidx, sta); | 284 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
| 165 | DEBUGFS_ADD(max_ratectrl_rateidx, sta); | 285 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
| 166 | 286 | ||
| 167 | DEBUGFS_ADD(bssid, sta); | 287 | DEBUGFS_ADD(bssid); |
| 168 | DEBUGFS_ADD(aid, sta); | 288 | DEBUGFS_ADD(aid); |
| 169 | DEBUGFS_ADD(capab, sta); | 289 | DEBUGFS_ADD(last_beacon); |
| 290 | DEBUGFS_ADD(ave_beacon); | ||
| 291 | DEBUGFS_ADD_MODE(smps, 0600); | ||
| 170 | } | 292 | } |
| 171 | 293 | ||
| 172 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 294 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
| 173 | { | 295 | { |
| 174 | DEBUGFS_ADD(drop_unencrypted, ap); | 296 | DEBUGFS_ADD(drop_unencrypted); |
| 175 | DEBUGFS_ADD(force_unicast_rateidx, ap); | 297 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
| 176 | DEBUGFS_ADD(max_ratectrl_rateidx, ap); | 298 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
| 177 | 299 | ||
| 178 | DEBUGFS_ADD(num_sta_ps, ap); | 300 | DEBUGFS_ADD(num_sta_ps); |
| 179 | DEBUGFS_ADD(dtim_count, ap); | 301 | DEBUGFS_ADD(dtim_count); |
| 180 | DEBUGFS_ADD(num_buffered_multicast, ap); | 302 | DEBUGFS_ADD(num_buffered_multicast); |
| 181 | } | 303 | } |
| 182 | 304 | ||
| 183 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) | 305 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) |
| 184 | { | 306 | { |
| 185 | DEBUGFS_ADD(drop_unencrypted, wds); | 307 | DEBUGFS_ADD(drop_unencrypted); |
| 186 | DEBUGFS_ADD(force_unicast_rateidx, wds); | 308 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
| 187 | DEBUGFS_ADD(max_ratectrl_rateidx, wds); | 309 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
| 188 | 310 | ||
| 189 | DEBUGFS_ADD(peer, wds); | 311 | DEBUGFS_ADD(peer); |
| 190 | } | 312 | } |
| 191 | 313 | ||
| 192 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | 314 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) |
| 193 | { | 315 | { |
| 194 | DEBUGFS_ADD(drop_unencrypted, vlan); | 316 | DEBUGFS_ADD(drop_unencrypted); |
| 195 | DEBUGFS_ADD(force_unicast_rateidx, vlan); | 317 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
| 196 | DEBUGFS_ADD(max_ratectrl_rateidx, vlan); | 318 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
| 197 | } | 319 | } |
| 198 | 320 | ||
| 199 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | 321 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) |
| @@ -280,16 +402,11 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
| 280 | } | 402 | } |
| 281 | } | 403 | } |
| 282 | 404 | ||
| 283 | static int notif_registered; | ||
| 284 | |||
| 285 | void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) | 405 | void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) |
| 286 | { | 406 | { |
| 287 | char buf[10+IFNAMSIZ]; | 407 | char buf[10+IFNAMSIZ]; |
| 288 | 408 | ||
| 289 | if (!notif_registered) | 409 | 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, | 410 | sdata->debugfs.dir = debugfs_create_dir(buf, |
| 294 | sdata->local->hw.wiphy->debugfsdir); | 411 | sdata->local->hw.wiphy->debugfsdir); |
| 295 | add_files(sdata); | 412 | add_files(sdata); |
| @@ -304,58 +421,18 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) | |||
| 304 | sdata->debugfs.dir = NULL; | 421 | sdata->debugfs.dir = NULL; |
| 305 | } | 422 | } |
| 306 | 423 | ||
| 307 | static int netdev_notify(struct notifier_block *nb, | 424 | void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) |
| 308 | unsigned long state, | ||
| 309 | void *ndev) | ||
| 310 | { | 425 | { |
| 311 | struct net_device *dev = ndev; | ||
| 312 | struct dentry *dir; | 426 | struct dentry *dir; |
| 313 | struct ieee80211_sub_if_data *sdata; | 427 | 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 | 428 | ||
| 327 | dir = sdata->debugfs.dir; | 429 | dir = sdata->debugfs.dir; |
| 328 | 430 | ||
| 329 | if (!dir) | 431 | if (!dir) |
| 330 | return 0; | 432 | return; |
| 331 | 433 | ||
| 332 | sprintf(buf, "netdev:%s", dev->name); | 434 | sprintf(buf, "netdev:%s", sdata->name); |
| 333 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) | 435 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) |
| 334 | printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " | 436 | printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " |
| 335 | "dir to %s\n", buf); | 437 | "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 | } | 438 | } |
