debugfs_netdev.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2006   Jiri Benc <jbenc@suse.cz>
00003  * Copyright 2007       Johannes Berg <johannes@sipsolutions.net>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 2 as
00007  * published by the Free Software Foundation.
00008  */
00009 
00010 #include <linux/kernel.h>
00011 #include <linux/device.h>
00012 #include <linux/if.h>
00013 #include <linux/interrupt.h>
00014 #include <linux/netdevice.h>
00015 #include <linux/rtnetlink.h>
00016 #include <linux/slab.h>
00017 #include <linux/notifier.h>
00018 #include <net/mac80211.h>
00019 #include <net/cfg80211.h>
00020 #include "ieee80211_i.h"
00021 #include "rate.h"
00022 #include "debugfs.h"
00023 #include "debugfs_netdev.h"
00024 #include "driver-ops.h"
00025 
00026 static ssize_t ieee80211_if_read(
00027         struct ieee80211_sub_if_data *sdata,
00028         char __user *userbuf,
00029         size_t count, loff_t *ppos,
00030         ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int))
00031 {
00032         char buf[70];
00033         ssize_t ret = -EINVAL;
00034 
00035         read_lock(&dev_base_lock);
00036         if (sdata->dev->reg_state == NETREG_REGISTERED)
00037                 ret = (*format)(sdata, buf, sizeof(buf));
00038         read_unlock(&dev_base_lock);
00039 
00040         if (ret >= 0)
00041                 ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
00042 
00043         return ret;
00044 }
00045 
00046 static ssize_t ieee80211_if_write(
00047         struct ieee80211_sub_if_data *sdata,
00048         const char __user *userbuf,
00049         size_t count, loff_t *ppos,
00050         ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int))
00051 {
00052         char buf[64];
00053         ssize_t ret;
00054 
00055         if (count >= sizeof(buf))
00056                 return -E2BIG;
00057 
00058         if (copy_from_user(buf, userbuf, count))
00059                 return -EFAULT;
00060         buf[count] = '\0';
00061 
00062         ret = -ENODEV;
00063         rtnl_lock();
00064         if (sdata->dev->reg_state == NETREG_REGISTERED)
00065                 ret = (*write)(sdata, buf, count);
00066         rtnl_unlock();
00067 
00068         return ret;
00069 }
00070 
00071 #define IEEE80211_IF_FMT(name, field, format_string)                    \
00072 static ssize_t ieee80211_if_fmt_##name(                                 \
00073         const struct ieee80211_sub_if_data *sdata, char *buf,           \
00074         int buflen)                                                     \
00075 {                                                                       \
00076         return scnprintf(buf, buflen, format_string, sdata->field);     \
00077 }
00078 #define IEEE80211_IF_FMT_DEC(name, field)                               \
00079                 IEEE80211_IF_FMT(name, field, "%d\n")
00080 #define IEEE80211_IF_FMT_HEX(name, field)                               \
00081                 IEEE80211_IF_FMT(name, field, "%#x\n")
00082 #define IEEE80211_IF_FMT_LHEX(name, field)                              \
00083                 IEEE80211_IF_FMT(name, field, "%#lx\n")
00084 #define IEEE80211_IF_FMT_SIZE(name, field)                              \
00085                 IEEE80211_IF_FMT(name, field, "%zd\n")
00086 
00087 #define IEEE80211_IF_FMT_HEXARRAY(name, field)                          \
00088 static ssize_t ieee80211_if_fmt_##name(                                 \
00089         const struct ieee80211_sub_if_data *sdata,                      \
00090         char *buf, int buflen)                                          \
00091 {                                                                       \
00092         char *p = buf;                                                  \
00093         int i;                                                          \
00094         for (i = 0; i < sizeof(sdata->field); i++) {                    \
00095                 p += scnprintf(p, buflen + buf - p, "%.2x ",            \
00096                                  sdata->field[i]);                      \
00097         }                                                               \
00098         p += scnprintf(p, buflen + buf - p, "\n");                      \
00099         return p - buf;                                                 \
00100 }
00101 
00102 #define IEEE80211_IF_FMT_ATOMIC(name, field)                            \
00103 static ssize_t ieee80211_if_fmt_##name(                                 \
00104         const struct ieee80211_sub_if_data *sdata,                      \
00105         char *buf, int buflen)                                          \
00106 {                                                                       \
00107         return scnprintf(buf, buflen, "%d\n", atomic_read(&sdata->field));\
00108 }
00109 
00110 #define IEEE80211_IF_FMT_MAC(name, field)                               \
00111 static ssize_t ieee80211_if_fmt_##name(                                 \
00112         const struct ieee80211_sub_if_data *sdata, char *buf,           \
00113         int buflen)                                                     \
00114 {                                                                       \
00115         return scnprintf(buf, buflen, "%pM\n", sdata->field);           \
00116 }
00117 
00118 #define IEEE80211_IF_FMT_DEC_DIV_16(name, field)                        \
00119 static ssize_t ieee80211_if_fmt_##name(                                 \
00120         const struct ieee80211_sub_if_data *sdata,                      \
00121         char *buf, int buflen)                                          \
00122 {                                                                       \
00123         return scnprintf(buf, buflen, "%d\n", sdata->field / 16);       \
00124 }
00125 
00126 #define __IEEE80211_IF_FILE(name, _write)                               \
00127 static ssize_t ieee80211_if_read_##name(struct file *file,              \
00128                                         char __user *userbuf,           \
00129                                         size_t count, loff_t *ppos)     \
00130 {                                                                       \
00131         return ieee80211_if_read(file->private_data,                    \
00132                                  userbuf, count, ppos,                  \
00133                                  ieee80211_if_fmt_##name);              \
00134 }                                                                       \
00135 static const struct file_operations name##_ops = {                      \
00136         .read = ieee80211_if_read_##name,                               \
00137         .write = (_write),                                              \
00138         .open = simple_open,                                            \
00139         .llseek = generic_file_llseek,                                  \
00140 }
00141 
00142 #define __IEEE80211_IF_FILE_W(name)                                     \
00143 static ssize_t ieee80211_if_write_##name(struct file *file,             \
00144                                          const char __user *userbuf,    \
00145                                          size_t count, loff_t *ppos)    \
00146 {                                                                       \
00147         return ieee80211_if_write(file->private_data, userbuf, count,   \
00148                                   ppos, ieee80211_if_parse_##name);     \
00149 }                                                                       \
00150 __IEEE80211_IF_FILE(name, ieee80211_if_write_##name)
00151 
00152 
00153 #define IEEE80211_IF_FILE(name, field, format)                          \
00154                 IEEE80211_IF_FMT_##format(name, field)                  \
00155                 __IEEE80211_IF_FILE(name, NULL)
00156 
00157 /* common attributes */
00158 IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
00159 IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ],
00160                   HEX);
00161 IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ],
00162                   HEX);
00163 IEEE80211_IF_FILE(rc_rateidx_mcs_mask_2ghz,
00164                   rc_rateidx_mcs_mask[IEEE80211_BAND_2GHZ], HEXARRAY);
00165 IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz,
00166                   rc_rateidx_mcs_mask[IEEE80211_BAND_5GHZ], HEXARRAY);
00167 
00168 IEEE80211_IF_FILE(flags, flags, HEX);
00169 IEEE80211_IF_FILE(state, state, LHEX);
00170 IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC);
00171 
00172 /* STA attributes */
00173 IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
00174 IEEE80211_IF_FILE(aid, u.mgd.aid, DEC);
00175 IEEE80211_IF_FILE(last_beacon, u.mgd.last_beacon_signal, DEC);
00176 IEEE80211_IF_FILE(ave_beacon, u.mgd.ave_beacon_signal, DEC_DIV_16);
00177 
00178 static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
00179                               enum ieee80211_smps_mode smps_mode)
00180 {
00181         struct ieee80211_local *local = sdata->local;
00182         int err;
00183 
00184         if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) &&
00185             smps_mode == IEEE80211_SMPS_STATIC)
00186                 return -EINVAL;
00187 
00188         /* auto should be dynamic if in PS mode */
00189         if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) &&
00190             (smps_mode == IEEE80211_SMPS_DYNAMIC ||
00191              smps_mode == IEEE80211_SMPS_AUTOMATIC))
00192                 return -EINVAL;
00193 
00194         /* supported only on managed interfaces for now */
00195         if (sdata->vif.type != NL80211_IFTYPE_STATION)
00196                 return -EOPNOTSUPP;
00197 
00198         mutex_lock(&sdata->u.mgd.mtx);
00199         err = __ieee80211_request_smps(sdata, smps_mode);
00200         mutex_unlock(&sdata->u.mgd.mtx);
00201 
00202         return err;
00203 }
00204 
00205 static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = {
00206         [IEEE80211_SMPS_AUTOMATIC] = "auto",
00207         [IEEE80211_SMPS_OFF] = "off",
00208         [IEEE80211_SMPS_STATIC] = "static",
00209         [IEEE80211_SMPS_DYNAMIC] = "dynamic",
00210 };
00211 
00212 static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata,
00213                                      char *buf, int buflen)
00214 {
00215         if (sdata->vif.type != NL80211_IFTYPE_STATION)
00216                 return -EOPNOTSUPP;
00217 
00218         return snprintf(buf, buflen, "request: %s\nused: %s\n",
00219                         smps_modes[sdata->u.mgd.req_smps],
00220                         smps_modes[sdata->u.mgd.ap_smps]);
00221 }
00222 
00223 static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata,
00224                                        const char *buf, int buflen)
00225 {
00226         enum ieee80211_smps_mode mode;
00227 
00228         for (mode = 0; mode < IEEE80211_SMPS_NUM_MODES; mode++) {
00229                 if (strncmp(buf, smps_modes[mode], buflen) == 0) {
00230                         int err = ieee80211_set_smps(sdata, mode);
00231                         if (!err)
00232                                 return buflen;
00233                         return err;
00234                 }
00235         }
00236 
00237         return -EINVAL;
00238 }
00239 
00240 __IEEE80211_IF_FILE_W(smps);
00241 
00242 static ssize_t ieee80211_if_fmt_tkip_mic_test(
00243         const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
00244 {
00245         return -EOPNOTSUPP;
00246 }
00247 
00248 static int hwaddr_aton(const char *txt, u8 *addr)
00249 {
00250         int i;
00251 
00252         for (i = 0; i < ETH_ALEN; i++) {
00253                 int a, b;
00254 
00255                 a = hex_to_bin(*txt++);
00256                 if (a < 0)
00257                         return -1;
00258                 b = hex_to_bin(*txt++);
00259                 if (b < 0)
00260                         return -1;
00261                 *addr++ = (a << 4) | b;
00262                 if (i < 5 && *txt++ != ':')
00263                         return -1;
00264         }
00265 
00266         return 0;
00267 }
00268 
00269 static ssize_t ieee80211_if_parse_tkip_mic_test(
00270         struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
00271 {
00272         struct ieee80211_local *local = sdata->local;
00273         u8 addr[ETH_ALEN];
00274         struct sk_buff *skb;
00275         struct ieee80211_hdr *hdr;
00276         __le16 fc;
00277 
00278         /*
00279          * Assume colon-delimited MAC address with possible white space
00280          * following.
00281          */
00282         if (buflen < 3 * ETH_ALEN - 1)
00283                 return -EINVAL;
00284         if (hwaddr_aton(buf, addr) < 0)
00285                 return -EINVAL;
00286 
00287         if (!ieee80211_sdata_running(sdata))
00288                 return -ENOTCONN;
00289 
00290         skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24 + 100);
00291         if (!skb)
00292                 return -ENOMEM;
00293         skb_reserve(skb, local->hw.extra_tx_headroom);
00294 
00295         hdr = (struct ieee80211_hdr *) skb_put(skb, 24);
00296         memset(hdr, 0, 24);
00297         fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
00298 
00299         switch (sdata->vif.type) {
00300         case NL80211_IFTYPE_AP:
00301                 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
00302                 /* DA BSSID SA */
00303                 memcpy(hdr->addr1, addr, ETH_ALEN);
00304                 memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
00305                 memcpy(hdr->addr3, sdata->vif.addr, ETH_ALEN);
00306                 break;
00307         case NL80211_IFTYPE_STATION:
00308                 fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
00309                 /* BSSID SA DA */
00310                 if (sdata->vif.bss_conf.bssid == NULL) {
00311                         dev_kfree_skb(skb);
00312                         return -ENOTCONN;
00313                 }
00314                 memcpy(hdr->addr1, sdata->vif.bss_conf.bssid, ETH_ALEN);
00315                 memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
00316                 memcpy(hdr->addr3, addr, ETH_ALEN);
00317                 break;
00318         default:
00319                 dev_kfree_skb(skb);
00320                 return -EOPNOTSUPP;
00321         }
00322         hdr->frame_control = fc;
00323 
00324         /*
00325          * Add some length to the test frame to make it look bit more valid.
00326          * The exact contents does not matter since the recipient is required
00327          * to drop this because of the Michael MIC failure.
00328          */
00329         memset(skb_put(skb, 50), 0, 50);
00330 
00331         IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_TKIP_MIC_FAILURE;
00332 
00333         ieee80211_tx_skb(sdata, skb);
00334 
00335         return buflen;
00336 }
00337 
00338 __IEEE80211_IF_FILE_W(tkip_mic_test);
00339 
00340 static ssize_t ieee80211_if_fmt_uapsd_queues(
00341         const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
00342 {
00343         const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
00344 
00345         return snprintf(buf, buflen, "0x%x\n", ifmgd->uapsd_queues);
00346 }
00347 
00348 static ssize_t ieee80211_if_parse_uapsd_queues(
00349         struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
00350 {
00351         struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
00352         u8 val;
00353         int ret;
00354 
00355         ret = kstrtou8(buf, 0, &val);
00356         if (ret)
00357                 return ret;
00358 
00359         if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
00360                 return -ERANGE;
00361 
00362         ifmgd->uapsd_queues = val;
00363 
00364         return buflen;
00365 }
00366 __IEEE80211_IF_FILE_W(uapsd_queues);
00367 
00368 static ssize_t ieee80211_if_fmt_uapsd_max_sp_len(
00369         const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
00370 {
00371         const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
00372 
00373         return snprintf(buf, buflen, "0x%x\n", ifmgd->uapsd_max_sp_len);
00374 }
00375 
00376 static ssize_t ieee80211_if_parse_uapsd_max_sp_len(
00377         struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
00378 {
00379         struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
00380         unsigned long val;
00381         int ret;
00382 
00383         ret = kstrtoul(buf, 0, &val);
00384         if (ret)
00385                 return -EINVAL;
00386 
00387         if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
00388                 return -ERANGE;
00389 
00390         ifmgd->uapsd_max_sp_len = val;
00391 
00392         return buflen;
00393 }
00394 __IEEE80211_IF_FILE_W(uapsd_max_sp_len);
00395 
00396 /* AP attributes */
00397 IEEE80211_IF_FILE(num_mcast_sta, u.ap.num_mcast_sta, ATOMIC);
00398 IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
00399 IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
00400 
00401 static ssize_t ieee80211_if_fmt_num_buffered_multicast(
00402         const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
00403 {
00404         return scnprintf(buf, buflen, "%u\n",
00405                          skb_queue_len(&sdata->u.ap.ps_bc_buf));
00406 }
00407 __IEEE80211_IF_FILE(num_buffered_multicast, NULL);
00408 
00409 /* IBSS attributes */
00410 static ssize_t ieee80211_if_fmt_tsf(
00411         const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
00412 {
00413         struct ieee80211_local *local = sdata->local;
00414         u64 tsf;
00415 
00416         tsf = drv_get_tsf(local, (struct ieee80211_sub_if_data *)sdata);
00417 
00418         return scnprintf(buf, buflen, "0x%016llx\n", (unsigned long long) tsf);
00419 }
00420 
00421 static ssize_t ieee80211_if_parse_tsf(
00422         struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
00423 {
00424         struct ieee80211_local *local = sdata->local;
00425         unsigned long long tsf;
00426         int ret;
00427         int tsf_is_delta = 0;
00428 
00429         if (strncmp(buf, "reset", 5) == 0) {
00430                 if (local->ops->reset_tsf) {
00431                         drv_reset_tsf(local, sdata);
00432                         wiphy_info(local->hw.wiphy, "debugfs reset TSF\n");
00433                 }
00434         } else {
00435                 if (buflen > 10 && buf[1] == '=') {
00436                         if (buf[0] == '+')
00437                                 tsf_is_delta = 1;
00438                         else if (buf[0] == '-')
00439                                 tsf_is_delta = -1;
00440                         else
00441                                 return -EINVAL;
00442                         buf += 2;
00443                 }
00444                 ret = kstrtoull(buf, 10, &tsf);
00445                 if (ret < 0)
00446                         return -EINVAL;
00447                 if (tsf_is_delta)
00448                         tsf = drv_get_tsf(local, sdata) + tsf_is_delta * tsf;
00449                 if (local->ops->set_tsf) {
00450                         drv_set_tsf(local, sdata, tsf);
00451                         wiphy_info(local->hw.wiphy,
00452                                    "debugfs set TSF to %#018llx\n", tsf);
00453                 }
00454         }
00455 
00456         return buflen;
00457 }
00458 __IEEE80211_IF_FILE_W(tsf);
00459 
00460 
00461 /* WDS attributes */
00462 IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
00463 
00464 #ifdef CONFIG_MAC80211_MESH
00465 /* Mesh stats attributes */
00466 IEEE80211_IF_FILE(fwded_mcast, u.mesh.mshstats.fwded_mcast, DEC);
00467 IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC);
00468 IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC);
00469 IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC);
00470 IEEE80211_IF_FILE(dropped_frames_congestion,
00471                 u.mesh.mshstats.dropped_frames_congestion, DEC);
00472 IEEE80211_IF_FILE(dropped_frames_no_route,
00473                 u.mesh.mshstats.dropped_frames_no_route, DEC);
00474 IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC);
00475 
00476 /* Mesh parameters */
00477 IEEE80211_IF_FILE(dot11MeshMaxRetries,
00478                 u.mesh.mshcfg.dot11MeshMaxRetries, DEC);
00479 IEEE80211_IF_FILE(dot11MeshRetryTimeout,
00480                 u.mesh.mshcfg.dot11MeshRetryTimeout, DEC);
00481 IEEE80211_IF_FILE(dot11MeshConfirmTimeout,
00482                 u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC);
00483 IEEE80211_IF_FILE(dot11MeshHoldingTimeout,
00484                 u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC);
00485 IEEE80211_IF_FILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC);
00486 IEEE80211_IF_FILE(element_ttl, u.mesh.mshcfg.element_ttl, DEC);
00487 IEEE80211_IF_FILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC);
00488 IEEE80211_IF_FILE(dot11MeshMaxPeerLinks,
00489                 u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC);
00490 IEEE80211_IF_FILE(dot11MeshHWMPactivePathTimeout,
00491                 u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC);
00492 IEEE80211_IF_FILE(dot11MeshHWMPpreqMinInterval,
00493                 u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC);
00494 IEEE80211_IF_FILE(dot11MeshHWMPperrMinInterval,
00495                 u.mesh.mshcfg.dot11MeshHWMPperrMinInterval, DEC);
00496 IEEE80211_IF_FILE(dot11MeshHWMPnetDiameterTraversalTime,
00497                 u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC);
00498 IEEE80211_IF_FILE(dot11MeshHWMPmaxPREQretries,
00499                 u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC);
00500 IEEE80211_IF_FILE(path_refresh_time,
00501                 u.mesh.mshcfg.path_refresh_time, DEC);
00502 IEEE80211_IF_FILE(min_discovery_timeout,
00503                 u.mesh.mshcfg.min_discovery_timeout, DEC);
00504 IEEE80211_IF_FILE(dot11MeshHWMPRootMode,
00505                 u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC);
00506 IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol,
00507                 u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC);
00508 IEEE80211_IF_FILE(dot11MeshHWMPRannInterval,
00509                 u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
00510 IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC);
00511 IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC);
00512 IEEE80211_IF_FILE(ht_opmode, u.mesh.mshcfg.ht_opmode, DEC);
00513 #endif
00514 
00515 #define DEBUGFS_ADD_MODE(name, mode) \
00516         debugfs_create_file(#name, mode, sdata->debugfs.dir, \
00517                             sdata, &name##_ops);
00518 
00519 #define DEBUGFS_ADD(name) DEBUGFS_ADD_MODE(name, 0400)
00520 
00521 static void add_common_files(struct ieee80211_sub_if_data *sdata)
00522 {
00523         DEBUGFS_ADD(drop_unencrypted);
00524         DEBUGFS_ADD(rc_rateidx_mask_2ghz);
00525         DEBUGFS_ADD(rc_rateidx_mask_5ghz);
00526         DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz);
00527         DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz);
00528 }
00529 
00530 static void add_sta_files(struct ieee80211_sub_if_data *sdata)
00531 {
00532         DEBUGFS_ADD(bssid);
00533         DEBUGFS_ADD(aid);
00534         DEBUGFS_ADD(last_beacon);
00535         DEBUGFS_ADD(ave_beacon);
00536         DEBUGFS_ADD_MODE(smps, 0600);
00537         DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
00538         DEBUGFS_ADD_MODE(uapsd_queues, 0600);
00539         DEBUGFS_ADD_MODE(uapsd_max_sp_len, 0600);
00540 }
00541 
00542 static void add_ap_files(struct ieee80211_sub_if_data *sdata)
00543 {
00544         DEBUGFS_ADD(num_mcast_sta);
00545         DEBUGFS_ADD(num_sta_ps);
00546         DEBUGFS_ADD(dtim_count);
00547         DEBUGFS_ADD(num_buffered_multicast);
00548         DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
00549 }
00550 
00551 static void add_ibss_files(struct ieee80211_sub_if_data *sdata)
00552 {
00553         DEBUGFS_ADD_MODE(tsf, 0600);
00554 }
00555 
00556 static void add_wds_files(struct ieee80211_sub_if_data *sdata)
00557 {
00558         DEBUGFS_ADD(peer);
00559 }
00560 
00561 #ifdef CONFIG_MAC80211_MESH
00562 
00563 static void add_mesh_files(struct ieee80211_sub_if_data *sdata)
00564 {
00565         DEBUGFS_ADD_MODE(tsf, 0600);
00566 }
00567 
00568 static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
00569 {
00570         struct dentry *dir = debugfs_create_dir("mesh_stats",
00571                                                 sdata->debugfs.dir);
00572 #define MESHSTATS_ADD(name)\
00573         debugfs_create_file(#name, 0400, dir, sdata, &name##_ops);
00574 
00575         MESHSTATS_ADD(fwded_mcast);
00576         MESHSTATS_ADD(fwded_unicast);
00577         MESHSTATS_ADD(fwded_frames);
00578         MESHSTATS_ADD(dropped_frames_ttl);
00579         MESHSTATS_ADD(dropped_frames_no_route);
00580         MESHSTATS_ADD(dropped_frames_congestion);
00581         MESHSTATS_ADD(estab_plinks);
00582 #undef MESHSTATS_ADD
00583 }
00584 
00585 static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
00586 {
00587         struct dentry *dir = debugfs_create_dir("mesh_config",
00588                                                 sdata->debugfs.dir);
00589 
00590 #define MESHPARAMS_ADD(name) \
00591         debugfs_create_file(#name, 0600, dir, sdata, &name##_ops);
00592 
00593         MESHPARAMS_ADD(dot11MeshMaxRetries);
00594         MESHPARAMS_ADD(dot11MeshRetryTimeout);
00595         MESHPARAMS_ADD(dot11MeshConfirmTimeout);
00596         MESHPARAMS_ADD(dot11MeshHoldingTimeout);
00597         MESHPARAMS_ADD(dot11MeshTTL);
00598         MESHPARAMS_ADD(element_ttl);
00599         MESHPARAMS_ADD(auto_open_plinks);
00600         MESHPARAMS_ADD(dot11MeshMaxPeerLinks);
00601         MESHPARAMS_ADD(dot11MeshHWMPactivePathTimeout);
00602         MESHPARAMS_ADD(dot11MeshHWMPpreqMinInterval);
00603         MESHPARAMS_ADD(dot11MeshHWMPperrMinInterval);
00604         MESHPARAMS_ADD(dot11MeshHWMPnetDiameterTraversalTime);
00605         MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries);
00606         MESHPARAMS_ADD(path_refresh_time);
00607         MESHPARAMS_ADD(min_discovery_timeout);
00608         MESHPARAMS_ADD(dot11MeshHWMPRootMode);
00609         MESHPARAMS_ADD(dot11MeshHWMPRannInterval);
00610         MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol);
00611         MESHPARAMS_ADD(rssi_threshold);
00612         MESHPARAMS_ADD(ht_opmode);
00613 #undef MESHPARAMS_ADD
00614 }
00615 #endif
00616 
00617 static void add_files(struct ieee80211_sub_if_data *sdata)
00618 {
00619         if (!sdata->debugfs.dir)
00620                 return;
00621 
00622         DEBUGFS_ADD(flags);
00623         DEBUGFS_ADD(state);
00624         DEBUGFS_ADD(channel_type);
00625 
00626         if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
00627                 add_common_files(sdata);
00628 
00629         switch (sdata->vif.type) {
00630         case NL80211_IFTYPE_MESH_POINT:
00631 #ifdef CONFIG_MAC80211_MESH
00632                 add_mesh_files(sdata);
00633                 add_mesh_stats(sdata);
00634                 add_mesh_config(sdata);
00635 #endif
00636                 break;
00637         case NL80211_IFTYPE_STATION:
00638                 add_sta_files(sdata);
00639                 break;
00640         case NL80211_IFTYPE_ADHOC:
00641                 add_ibss_files(sdata);
00642                 break;
00643         case NL80211_IFTYPE_AP:
00644                 add_ap_files(sdata);
00645                 break;
00646         case NL80211_IFTYPE_WDS:
00647                 add_wds_files(sdata);
00648                 break;
00649         default:
00650                 break;
00651         }
00652 }
00653 
00654 void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
00655 {
00656         char buf[10+IFNAMSIZ];
00657 
00658         sprintf(buf, "netdev:%s", sdata->name);
00659         sdata->debugfs.dir = debugfs_create_dir(buf,
00660                 sdata->local->hw.wiphy->debugfsdir);
00661         if (sdata->debugfs.dir)
00662                 sdata->debugfs.subdir_stations = debugfs_create_dir("stations",
00663                         sdata->debugfs.dir);
00664         add_files(sdata);
00665 }
00666 
00667 void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
00668 {
00669         if (!sdata->debugfs.dir)
00670                 return;
00671 
00672         debugfs_remove_recursive(sdata->debugfs.dir);
00673         sdata->debugfs.dir = NULL;
00674 }
00675 
00676 void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
00677 {
00678         struct dentry *dir;
00679         char buf[10 + IFNAMSIZ];
00680 
00681         dir = sdata->debugfs.dir;
00682 
00683         if (!dir)
00684                 return;
00685 
00686         sprintf(buf, "netdev:%s", sdata->name);
00687         if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf))
00688                 printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs "
00689                        "dir to %s\n", buf);
00690 }


ros_rt_wmp
Author(s): Danilo Tardioli, dantard@unizar.es
autogenerated on Mon Oct 6 2014 08:27:09