linux/net/mac80211/debugfs_netdev.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2006   Jiri Benc <jbenc@suse.cz>
   3 * Copyright 2007       Johannes Berg <johannes@sipsolutions.net>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/device.h>
  12#include <linux/if.h>
  13#include <linux/interrupt.h>
  14#include <linux/netdevice.h>
  15#include <linux/rtnetlink.h>
  16#include <linux/notifier.h>
  17#include <net/mac80211.h>
  18#include <net/cfg80211.h>
  19#include "ieee80211_i.h"
  20#include "rate.h"
  21#include "debugfs.h"
  22#include "debugfs_netdev.h"
  23
  24static ssize_t ieee80211_if_read(
  25        struct ieee80211_sub_if_data *sdata,
  26        char __user *userbuf,
  27        size_t count, loff_t *ppos,
  28        ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int))
  29{
  30        char buf[70];
  31        ssize_t ret = -EINVAL;
  32
  33        read_lock(&dev_base_lock);
  34        if (sdata->dev->reg_state == NETREG_REGISTERED)
  35                ret = (*format)(sdata, buf, sizeof(buf));
  36        read_unlock(&dev_base_lock);
  37
  38        if (ret != -EINVAL)
  39                ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
  40
  41        return ret;
  42}
  43
  44#ifdef CONFIG_MAC80211_MESH
  45static ssize_t ieee80211_if_write(
  46        struct ieee80211_sub_if_data *sdata,
  47        char const __user *userbuf,
  48        size_t count, loff_t *ppos,
  49        int (*format)(struct ieee80211_sub_if_data *, char *))
  50{
  51        char buf[10];
  52        int buf_size;
  53
  54        memset(buf, 0x00, sizeof(buf));
  55        buf_size = min(count, (sizeof(buf)-1));
  56        if (copy_from_user(buf, userbuf, buf_size))
  57                return count;
  58        read_lock(&dev_base_lock);
  59        if (sdata->dev->reg_state == NETREG_REGISTERED)
  60                (*format)(sdata, buf);
  61        read_unlock(&dev_base_lock);
  62
  63        return count;
  64}
  65#endif
  66
  67#define IEEE80211_IF_FMT(name, field, format_string)                    \
  68static ssize_t ieee80211_if_fmt_##name(                                 \
  69        const struct ieee80211_sub_if_data *sdata, char *buf,           \
  70        int buflen)                                                     \
  71{                                                                       \
  72        return scnprintf(buf, buflen, format_string, sdata->field);     \
  73}
  74#define IEEE80211_IF_WFMT(name, field, type)                            \
  75static int ieee80211_if_wfmt_##name(                                    \
  76        struct ieee80211_sub_if_data *sdata, char *buf)                 \
  77{                                                                       \
  78        unsigned long tmp;                                              \
  79        char *endp;                                                     \
  80                                                                        \
  81        tmp = simple_strtoul(buf, &endp, 0);                            \
  82        if ((endp == buf) || ((type)tmp != tmp))                        \
  83                return -EINVAL;                                         \
  84        sdata->field = tmp;                                             \
  85        return 0;                                                       \
  86}
  87#define IEEE80211_IF_FMT_DEC(name, field)                               \
  88                IEEE80211_IF_FMT(name, field, "%d\n")
  89#define IEEE80211_IF_FMT_HEX(name, field)                               \
  90                IEEE80211_IF_FMT(name, field, "%#x\n")
  91#define IEEE80211_IF_FMT_SIZE(name, field)                              \
  92                IEEE80211_IF_FMT(name, field, "%zd\n")
  93
  94#define IEEE80211_IF_FMT_ATOMIC(name, field)                            \
  95static ssize_t ieee80211_if_fmt_##name(                                 \
  96        const struct ieee80211_sub_if_data *sdata,                      \
  97        char *buf, int buflen)                                          \
  98{                                                                       \
  99        return scnprintf(buf, buflen, "%d\n", atomic_read(&sdata->field));\
 100}
 101
 102#define IEEE80211_IF_FMT_MAC(name, field)                               \
 103static ssize_t ieee80211_if_fmt_##name(                                 \
 104        const struct ieee80211_sub_if_data *sdata, char *buf,           \
 105        int buflen)                                                     \
 106{                                                                       \
 107        DECLARE_MAC_BUF(mac);                                           \
 108        return scnprintf(buf, buflen, "%s\n", print_mac(mac, sdata->field));\
 109}
 110
 111#define __IEEE80211_IF_FILE(name)                                       \
 112static ssize_t ieee80211_if_read_##name(struct file *file,              \
 113                                        char __user *userbuf,           \
 114                                        size_t count, loff_t *ppos)     \
 115{                                                                       \
 116        return ieee80211_if_read(file->private_data,                    \
 117                                 userbuf, count, ppos,                  \
 118                                 ieee80211_if_fmt_##name);              \
 119}                                                                       \
 120static const struct file_operations name##_ops = {                      \
 121        .read = ieee80211_if_read_##name,                               \
 122        .open = mac80211_open_file_generic,                             \
 123}
 124
 125#define IEEE80211_IF_FILE(name, field, format)                          \
 126                IEEE80211_IF_FMT_##format(name, field)                  \
 127                __IEEE80211_IF_FILE(name)
 128
 129#define __IEEE80211_IF_WFILE(name)                                      \
 130static ssize_t ieee80211_if_read_##name(struct file *file,              \
 131                                        char __user *userbuf,           \
 132                                        size_t count, loff_t *ppos)     \
 133{                                                                       \
 134        return ieee80211_if_read(file->private_data,                    \
 135                                 userbuf, count, ppos,                  \
 136                                 ieee80211_if_fmt_##name);              \
 137}                                                                       \
 138static ssize_t ieee80211_if_write_##name(struct file *file,             \
 139                                        const char __user *userbuf,     \
 140                                        size_t count, loff_t *ppos)     \
 141{                                                                       \
 142        return ieee80211_if_write(file->private_data,                   \
 143                                 userbuf, count, ppos,                  \
 144                                 ieee80211_if_wfmt_##name);             \
 145}                                                                       \
 146static const struct file_operations name##_ops = {                      \
 147        .read = ieee80211_if_read_##name,                               \
 148        .write = ieee80211_if_write_##name,                             \
 149        .open = mac80211_open_file_generic,                             \
 150}
 151
 152#define IEEE80211_IF_WFILE(name, field, format, type)                   \
 153                IEEE80211_IF_FMT_##format(name, field)                  \
 154                IEEE80211_IF_WFMT(name, field, type)                    \
 155                __IEEE80211_IF_WFILE(name)
 156
 157/* common attributes */
 158IEEE80211_IF_FILE(channel_use, channel_use, DEC);
 159IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
 160
 161/* STA/IBSS attributes */
 162IEEE80211_IF_FILE(state, u.sta.state, DEC);
 163IEEE80211_IF_FILE(bssid, u.sta.bssid, MAC);
 164IEEE80211_IF_FILE(prev_bssid, u.sta.prev_bssid, MAC);
 165IEEE80211_IF_FILE(ssid_len, u.sta.ssid_len, SIZE);
 166IEEE80211_IF_FILE(aid, u.sta.aid, DEC);
 167IEEE80211_IF_FILE(ap_capab, u.sta.ap_capab, HEX);
 168IEEE80211_IF_FILE(capab, u.sta.capab, HEX);
 169IEEE80211_IF_FILE(extra_ie_len, u.sta.extra_ie_len, SIZE);
 170IEEE80211_IF_FILE(auth_tries, u.sta.auth_tries, DEC);
 171IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC);
 172IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX);
 173IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC);
 174IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC);
 175IEEE80211_IF_FILE(num_beacons_sta, u.sta.num_beacons, DEC);
 176
 177static ssize_t ieee80211_if_fmt_flags(
 178        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
 179{
 180        return scnprintf(buf, buflen, "%s%s%s%s%s%s%s\n",
 181                 sdata->u.sta.flags & IEEE80211_STA_SSID_SET ? "SSID\n" : "",
 182                 sdata->u.sta.flags & IEEE80211_STA_BSSID_SET ? "BSSID\n" : "",
 183                 sdata->u.sta.flags & IEEE80211_STA_PREV_BSSID_SET ? "prev BSSID\n" : "",
 184                 sdata->u.sta.flags & IEEE80211_STA_AUTHENTICATED ? "AUTH\n" : "",
 185                 sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED ? "ASSOC\n" : "",
 186                 sdata->u.sta.flags & IEEE80211_STA_PROBEREQ_POLL ? "PROBEREQ POLL\n" : "",
 187                 sdata->bss_conf.use_cts_prot ? "CTS prot\n" : "");
 188}
 189__IEEE80211_IF_FILE(flags);
 190
 191/* AP attributes */
 192IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
 193IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
 194IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC);
 195IEEE80211_IF_FILE(force_unicast_rateidx, u.ap.force_unicast_rateidx, DEC);
 196IEEE80211_IF_FILE(max_ratectrl_rateidx, u.ap.max_ratectrl_rateidx, DEC);
 197
 198static ssize_t ieee80211_if_fmt_num_buffered_multicast(
 199        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
 200{
 201        return scnprintf(buf, buflen, "%u\n",
 202                         skb_queue_len(&sdata->u.ap.ps_bc_buf));
 203}
 204__IEEE80211_IF_FILE(num_buffered_multicast);
 205
 206/* WDS attributes */
 207IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
 208
 209#ifdef CONFIG_MAC80211_MESH
 210/* Mesh stats attributes */
 211IEEE80211_IF_FILE(fwded_frames, u.sta.mshstats.fwded_frames, DEC);
 212IEEE80211_IF_FILE(dropped_frames_ttl, u.sta.mshstats.dropped_frames_ttl, DEC);
 213IEEE80211_IF_FILE(dropped_frames_no_route,
 214                u.sta.mshstats.dropped_frames_no_route, DEC);
 215IEEE80211_IF_FILE(estab_plinks, u.sta.mshstats.estab_plinks, ATOMIC);
 216
 217/* Mesh parameters */
 218IEEE80211_IF_WFILE(dot11MeshMaxRetries,
 219                u.sta.mshcfg.dot11MeshMaxRetries, DEC, u8);
 220IEEE80211_IF_WFILE(dot11MeshRetryTimeout,
 221                u.sta.mshcfg.dot11MeshRetryTimeout, DEC, u16);
 222IEEE80211_IF_WFILE(dot11MeshConfirmTimeout,
 223                u.sta.mshcfg.dot11MeshConfirmTimeout, DEC, u16);
 224IEEE80211_IF_WFILE(dot11MeshHoldingTimeout,
 225                u.sta.mshcfg.dot11MeshHoldingTimeout, DEC, u16);
 226IEEE80211_IF_WFILE(dot11MeshTTL, u.sta.mshcfg.dot11MeshTTL, DEC, u8);
 227IEEE80211_IF_WFILE(auto_open_plinks, u.sta.mshcfg.auto_open_plinks, DEC, u8);
 228IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks,
 229                u.sta.mshcfg.dot11MeshMaxPeerLinks, DEC, u16);
 230IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout,
 231                u.sta.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32);
 232IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval,
 233                u.sta.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16);
 234IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime,
 235                u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16);
 236IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries,
 237                u.sta.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8);
 238IEEE80211_IF_WFILE(path_refresh_time,
 239                u.sta.mshcfg.path_refresh_time, DEC, u32);
 240IEEE80211_IF_WFILE(min_discovery_timeout,
 241                u.sta.mshcfg.min_discovery_timeout, DEC, u16);
 242#endif
 243
 244
 245#define DEBUGFS_ADD(name, type)\
 246        sdata->debugfs.type.name = debugfs_create_file(#name, 0400,\
 247                sdata->debugfsdir, sdata, &name##_ops);
 248
 249static void add_sta_files(struct ieee80211_sub_if_data *sdata)
 250{
 251        DEBUGFS_ADD(channel_use, sta);
 252        DEBUGFS_ADD(drop_unencrypted, sta);
 253        DEBUGFS_ADD(state, sta);
 254        DEBUGFS_ADD(bssid, sta);
 255        DEBUGFS_ADD(prev_bssid, sta);
 256        DEBUGFS_ADD(ssid_len, sta);
 257        DEBUGFS_ADD(aid, sta);
 258        DEBUGFS_ADD(ap_capab, sta);
 259        DEBUGFS_ADD(capab, sta);
 260        DEBUGFS_ADD(extra_ie_len, sta);
 261        DEBUGFS_ADD(auth_tries, sta);
 262        DEBUGFS_ADD(assoc_tries, sta);
 263        DEBUGFS_ADD(auth_algs, sta);
 264        DEBUGFS_ADD(auth_alg, sta);
 265        DEBUGFS_ADD(auth_transaction, sta);
 266        DEBUGFS_ADD(flags, sta);
 267        DEBUGFS_ADD(num_beacons_sta, sta);
 268}
 269
 270static void add_ap_files(struct ieee80211_sub_if_data *sdata)
 271{
 272        DEBUGFS_ADD(channel_use, ap);
 273        DEBUGFS_ADD(drop_unencrypted, ap);
 274        DEBUGFS_ADD(num_sta_ps, ap);
 275        DEBUGFS_ADD(dtim_count, ap);
 276        DEBUGFS_ADD(num_beacons, ap);
 277        DEBUGFS_ADD(force_unicast_rateidx, ap);
 278        DEBUGFS_ADD(max_ratectrl_rateidx, ap);
 279        DEBUGFS_ADD(num_buffered_multicast, ap);
 280}
 281
 282static void add_wds_files(struct ieee80211_sub_if_data *sdata)
 283{
 284        DEBUGFS_ADD(channel_use, wds);
 285        DEBUGFS_ADD(drop_unencrypted, wds);
 286        DEBUGFS_ADD(peer, wds);
 287}
 288
 289static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
 290{
 291        DEBUGFS_ADD(channel_use, vlan);
 292        DEBUGFS_ADD(drop_unencrypted, vlan);
 293}
 294
 295static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
 296{
 297}
 298
 299#ifdef CONFIG_MAC80211_MESH
 300#define MESHSTATS_ADD(name)\
 301        sdata->mesh_stats.name = debugfs_create_file(#name, 0400,\
 302                sdata->mesh_stats_dir, sdata, &name##_ops);
 303
 304static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
 305{
 306        sdata->mesh_stats_dir = debugfs_create_dir("mesh_stats",
 307                                sdata->debugfsdir);
 308        MESHSTATS_ADD(fwded_frames);
 309        MESHSTATS_ADD(dropped_frames_ttl);
 310        MESHSTATS_ADD(dropped_frames_no_route);
 311        MESHSTATS_ADD(estab_plinks);
 312}
 313
 314#define MESHPARAMS_ADD(name)\
 315        sdata->mesh_config.name = debugfs_create_file(#name, 0600,\
 316                sdata->mesh_config_dir, sdata, &name##_ops);
 317
 318static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
 319{
 320        sdata->mesh_config_dir = debugfs_create_dir("mesh_config",
 321                                sdata->debugfsdir);
 322        MESHPARAMS_ADD(dot11MeshMaxRetries);
 323        MESHPARAMS_ADD(dot11MeshRetryTimeout);
 324        MESHPARAMS_ADD(dot11MeshConfirmTimeout);
 325        MESHPARAMS_ADD(dot11MeshHoldingTimeout);
 326        MESHPARAMS_ADD(dot11MeshTTL);
 327        MESHPARAMS_ADD(auto_open_plinks);
 328        MESHPARAMS_ADD(dot11MeshMaxPeerLinks);
 329        MESHPARAMS_ADD(dot11MeshHWMPactivePathTimeout);
 330        MESHPARAMS_ADD(dot11MeshHWMPpreqMinInterval);
 331        MESHPARAMS_ADD(dot11MeshHWMPnetDiameterTraversalTime);
 332        MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries);
 333        MESHPARAMS_ADD(path_refresh_time);
 334        MESHPARAMS_ADD(min_discovery_timeout);
 335}
 336#endif
 337
 338static void add_files(struct ieee80211_sub_if_data *sdata)
 339{
 340        if (!sdata->debugfsdir)
 341                return;
 342
 343        switch (sdata->vif.type) {
 344        case IEEE80211_IF_TYPE_MESH_POINT:
 345#ifdef CONFIG_MAC80211_MESH
 346                add_mesh_stats(sdata);
 347                add_mesh_config(sdata);
 348#endif
 349                /* fall through */
 350        case IEEE80211_IF_TYPE_STA:
 351        case IEEE80211_IF_TYPE_IBSS:
 352                add_sta_files(sdata);
 353                break;
 354        case IEEE80211_IF_TYPE_AP:
 355                add_ap_files(sdata);
 356                break;
 357        case IEEE80211_IF_TYPE_WDS:
 358                add_wds_files(sdata);
 359                break;
 360        case IEEE80211_IF_TYPE_MNTR:
 361                add_monitor_files(sdata);
 362                break;
 363        case IEEE80211_IF_TYPE_VLAN:
 364                add_vlan_files(sdata);
 365                break;
 366        default:
 367                break;
 368        }
 369}
 370
 371#define DEBUGFS_DEL(name, type)                                 \
 372        do {                                                    \
 373                debugfs_remove(sdata->debugfs.type.name);       \
 374                sdata->debugfs.type.name = NULL;                \
 375        } while (0)
 376
 377static void del_sta_files(struct ieee80211_sub_if_data *sdata)
 378{
 379        DEBUGFS_DEL(channel_use, sta);
 380        DEBUGFS_DEL(drop_unencrypted, sta);
 381        DEBUGFS_DEL(state, sta);
 382        DEBUGFS_DEL(bssid, sta);
 383        DEBUGFS_DEL(prev_bssid, sta);
 384        DEBUGFS_DEL(ssid_len, sta);
 385        DEBUGFS_DEL(aid, sta);
 386        DEBUGFS_DEL(ap_capab, sta);
 387        DEBUGFS_DEL(capab, sta);
 388        DEBUGFS_DEL(extra_ie_len, sta);
 389        DEBUGFS_DEL(auth_tries, sta);
 390        DEBUGFS_DEL(assoc_tries, sta);
 391        DEBUGFS_DEL(auth_algs, sta);
 392        DEBUGFS_DEL(auth_alg, sta);
 393        DEBUGFS_DEL(auth_transaction, sta);
 394        DEBUGFS_DEL(flags, sta);
 395        DEBUGFS_DEL(num_beacons_sta, sta);
 396}
 397
 398static void del_ap_files(struct ieee80211_sub_if_data *sdata)
 399{
 400        DEBUGFS_DEL(channel_use, ap);
 401        DEBUGFS_DEL(drop_unencrypted, ap);
 402        DEBUGFS_DEL(num_sta_ps, ap);
 403        DEBUGFS_DEL(dtim_count, ap);
 404        DEBUGFS_DEL(num_beacons, ap);
 405        DEBUGFS_DEL(force_unicast_rateidx, ap);
 406        DEBUGFS_DEL(max_ratectrl_rateidx, ap);
 407        DEBUGFS_DEL(num_buffered_multicast, ap);
 408}
 409
 410static void del_wds_files(struct ieee80211_sub_if_data *sdata)
 411{
 412        DEBUGFS_DEL(channel_use, wds);
 413        DEBUGFS_DEL(drop_unencrypted, wds);
 414        DEBUGFS_DEL(peer, wds);
 415}
 416
 417static void del_vlan_files(struct ieee80211_sub_if_data *sdata)
 418{
 419        DEBUGFS_DEL(channel_use, vlan);
 420        DEBUGFS_DEL(drop_unencrypted, vlan);
 421}
 422
 423static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
 424{
 425}
 426
 427#ifdef CONFIG_MAC80211_MESH
 428#define MESHSTATS_DEL(name)                     \
 429        do {                                            \
 430                debugfs_remove(sdata->mesh_stats.name); \
 431                sdata->mesh_stats.name = NULL;          \
 432        } while (0)
 433
 434static void del_mesh_stats(struct ieee80211_sub_if_data *sdata)
 435{
 436        MESHSTATS_DEL(fwded_frames);
 437        MESHSTATS_DEL(dropped_frames_ttl);
 438        MESHSTATS_DEL(dropped_frames_no_route);
 439        MESHSTATS_DEL(estab_plinks);
 440        debugfs_remove(sdata->mesh_stats_dir);
 441        sdata->mesh_stats_dir = NULL;
 442}
 443
 444#define MESHPARAMS_DEL(name)                    \
 445        do {                                            \
 446                debugfs_remove(sdata->mesh_config.name);        \
 447                sdata->mesh_config.name = NULL;         \
 448        } while (0)
 449
 450static void del_mesh_config(struct ieee80211_sub_if_data *sdata)
 451{
 452        MESHPARAMS_DEL(dot11MeshMaxRetries);
 453        MESHPARAMS_DEL(dot11MeshRetryTimeout);
 454        MESHPARAMS_DEL(dot11MeshConfirmTimeout);
 455        MESHPARAMS_DEL(dot11MeshHoldingTimeout);
 456        MESHPARAMS_DEL(dot11MeshTTL);
 457        MESHPARAMS_DEL(auto_open_plinks);
 458        MESHPARAMS_DEL(dot11MeshMaxPeerLinks);
 459        MESHPARAMS_DEL(dot11MeshHWMPactivePathTimeout);
 460        MESHPARAMS_DEL(dot11MeshHWMPpreqMinInterval);
 461        MESHPARAMS_DEL(dot11MeshHWMPnetDiameterTraversalTime);
 462        MESHPARAMS_DEL(dot11MeshHWMPmaxPREQretries);
 463        MESHPARAMS_DEL(path_refresh_time);
 464        MESHPARAMS_DEL(min_discovery_timeout);
 465        debugfs_remove(sdata->mesh_config_dir);
 466        sdata->mesh_config_dir = NULL;
 467}
 468#endif
 469
 470static void del_files(struct ieee80211_sub_if_data *sdata, int type)
 471{
 472        if (!sdata->debugfsdir)
 473                return;
 474
 475        switch (type) {
 476        case IEEE80211_IF_TYPE_MESH_POINT:
 477#ifdef CONFIG_MAC80211_MESH
 478                del_mesh_stats(sdata);
 479                del_mesh_config(sdata);
 480#endif
 481                /* fall through */
 482        case IEEE80211_IF_TYPE_STA:
 483        case IEEE80211_IF_TYPE_IBSS:
 484                del_sta_files(sdata);
 485                break;
 486        case IEEE80211_IF_TYPE_AP:
 487                del_ap_files(sdata);
 488                break;
 489        case IEEE80211_IF_TYPE_WDS:
 490                del_wds_files(sdata);
 491                break;
 492        case IEEE80211_IF_TYPE_MNTR:
 493                del_monitor_files(sdata);
 494                break;
 495        case IEEE80211_IF_TYPE_VLAN:
 496                del_vlan_files(sdata);
 497                break;
 498        default:
 499                break;
 500        }
 501}
 502
 503static int notif_registered;
 504
 505void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
 506{
 507        char buf[10+IFNAMSIZ];
 508
 509        if (!notif_registered)
 510                return;
 511
 512        sprintf(buf, "netdev:%s", sdata->dev->name);
 513        sdata->debugfsdir = debugfs_create_dir(buf,
 514                sdata->local->hw.wiphy->debugfsdir);
 515}
 516
 517void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
 518{
 519        del_files(sdata, sdata->vif.type);
 520        debugfs_remove(sdata->debugfsdir);
 521        sdata->debugfsdir = NULL;
 522}
 523
 524void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
 525                                      int oldtype)
 526{
 527        del_files(sdata, oldtype);
 528        add_files(sdata);
 529}
 530
 531static int netdev_notify(struct notifier_block * nb,
 532                         unsigned long state,
 533                         void *ndev)
 534{
 535        struct net_device *dev = ndev;
 536        struct dentry *dir;
 537        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 538        char buf[10+IFNAMSIZ];
 539
 540        if (state != NETDEV_CHANGENAME)
 541                return 0;
 542
 543        if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
 544                return 0;
 545
 546        if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
 547                return 0;
 548
 549        sprintf(buf, "netdev:%s", dev->name);
 550        dir = sdata->debugfsdir;
 551        if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf))
 552                printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs "
 553                       "dir to %s\n", buf);
 554
 555        return 0;
 556}
 557
 558static struct notifier_block mac80211_debugfs_netdev_notifier = {
 559        .notifier_call = netdev_notify,
 560};
 561
 562void ieee80211_debugfs_netdev_init(void)
 563{
 564        int err;
 565
 566        err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
 567        if (err) {
 568                printk(KERN_ERR
 569                       "mac80211: failed to install netdev notifier,"
 570                       " disabling per-netdev debugfs!\n");
 571        } else
 572                notif_registered = 1;
 573}
 574
 575void ieee80211_debugfs_netdev_exit(void)
 576{
 577        unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
 578        notif_registered = 0;
 579}
 580
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.