1 2 /* 3 * mac80211 debugfs for wireless PHYs 4 * 5 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 6 * 7 * GPLv2 8 * 9 */ 10 11 #include <linux/debugfs.h> 12 #include <linux/rtnetlink.h> 13 #include "ieee80211_i.h" 14 #include "driver-ops.h" 15 #include "rate.h" 16 #include "debugfs.h" 17 18 int mac80211_open_file_generic(struct inode *inode, struct file *file) 19 { 20 file->private_data = inode->i_private; 21 return 0; 22 } 23 24 #define DEBUGFS_FORMAT_BUFFER_SIZE 100 25 26 int mac80211_format_buffer(char __user *userbuf, size_t count, 27 loff_t *ppos, char *fmt, ...) 28 { 29 va_list args; 30 char buf[DEBUGFS_FORMAT_BUFFER_SIZE]; 31 int res; 32 33 va_start(args, fmt); 34 res = vscnprintf(buf, sizeof(buf), fmt, args); 35 va_end(args); 36 37 return simple_read_from_buffer(userbuf, count, ppos, buf, res); 38 } 39 40 #define DEBUGFS_READONLY_FILE_FN(name, fmt, value...) \ 41 static ssize_t name## _read(struct file *file, char __user *userbuf, \ 42 size_t count, loff_t *ppos) \ 43 { \ 44 struct ieee80211_local *local = file->private_data; \ 45 \ 46 return mac80211_format_buffer(userbuf, count, ppos, \ 47 fmt "\n", ##value); \ 48 } 49 50 #define DEBUGFS_READONLY_FILE_OPS(name) \ 51 static const struct file_operations name## _ops = { \ 52 .read = name## _read, \ 53 .open = mac80211_open_file_generic, \ 54 .llseek = generic_file_llseek, \ 55 }; 56 57 #define DEBUGFS_READONLY_FILE(name, fmt, value...) \ 58 DEBUGFS_READONLY_FILE_FN(name, fmt, value) \ 59 DEBUGFS_READONLY_FILE_OPS(name) 60 61 #define DEBUGFS_ADD(name) \ 62 debugfs_create_file(#name, 0400, phyd, local, &name## _ops); 63 64 #define DEBUGFS_ADD_MODE(name, mode) \ 65 debugfs_create_file(#name, mode, phyd, local, &name## _ops); 66 67 68 DEBUGFS_READONLY_FILE(user_power, "%d", 69 local->user_power_level); 70 DEBUGFS_READONLY_FILE(power, "%d", 71 local->hw.conf.power_level); 72 DEBUGFS_READONLY_FILE(frequency, "%d", 73 local->hw.conf.channel->center_freq); 74 DEBUGFS_READONLY_FILE(total_ps_buffered, "%d", 75 local->total_ps_buffered); 76 DEBUGFS_READONLY_FILE(wep_iv, "%#08x", 77 local->wep_iv & 0xffffff); 78 DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s", 79 local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver"); 80 81 static ssize_t tsf_read(struct file *file, char __user *user_buf, 82 size_t count, loff_t *ppos) 83 { 84 struct ieee80211_local *local = file->private_data; 85 u64 tsf; 86 87 tsf = drv_get_tsf(local); 88 89 return mac80211_format_buffer(user_buf, count, ppos, "0x%016llx\n", 90 (unsigned long long) tsf); 91 } 92 93 static ssize_t tsf_write(struct file *file, 94 const char __user *user_buf, 95 size_t count, loff_t *ppos) 96 { 97 struct ieee80211_local *local = file->private_data; 98 unsigned long long tsf; 99 char buf[100]; 100 size_t len; 101 102 len = min(count, sizeof(buf) - 1); 103 if (copy_from_user(buf, user_buf, len)) 104 return -EFAULT; 105 buf[len] = '\0'; 106 107 if (strncmp(buf, "reset", 5) == 0) { 108 if (local->ops->reset_tsf) { 109 drv_reset_tsf(local); 110 wiphy_info(local->hw.wiphy, "debugfs reset TSF\n"); 111 } 112 } else { 113 tsf = simple_strtoul(buf, NULL, 0); 114 if (local->ops->set_tsf) { 115 drv_set_tsf(local, tsf); 116 wiphy_info(local->hw.wiphy, 117 "debugfs set TSF to %#018llx\n", tsf); 118 119 } 120 } 121 122 return count; 123 } 124 125 static const struct file_operations tsf_ops = { 126 .read = tsf_read, 127 .write = tsf_write, 128 .open = mac80211_open_file_generic, 129 .llseek = default_llseek, 130 }; 131 132 static ssize_t reset_write(struct file *file, const char __user *user_buf, 133 size_t count, loff_t *ppos) 134 { 135 struct ieee80211_local *local = file->private_data; 136 137 rtnl_lock(); 138 __ieee80211_suspend(&local->hw, NULL); 139 __ieee80211_resume(&local->hw); 140 rtnl_unlock(); 141 142 return count; 143 } 144 145 static const struct file_operations reset_ops = { 146 .write = reset_write, 147 .open = mac80211_open_file_generic, 148 .llseek = noop_llseek, 149 }; 150 151 static ssize_t noack_read(struct file *file, char __user *user_buf, 152 size_t count, loff_t *ppos) 153 { 154 struct ieee80211_local *local = file->private_data; 155 156 return mac80211_format_buffer(user_buf, count, ppos, "%d\n", 157 local->wifi_wme_noack_test); 158 } 159 160 static ssize_t noack_write(struct file *file, 161 const char __user *user_buf, 162 size_t count, loff_t *ppos) 163 { 164 struct ieee80211_local *local = file->private_data; 165 char buf[10]; 166 size_t len; 167 168 len = min(count, sizeof(buf) - 1); 169 if (copy_from_user(buf, user_buf, len)) 170 return -EFAULT; 171 buf[len] = '\0'; 172 173 local->wifi_wme_noack_test = !!simple_strtoul(buf, NULL, 0); 174 175 return count; 176 } 177 178 static const struct file_operations noack_ops = { 179 .read = noack_read, 180 .write = noack_write, 181 .open = mac80211_open_file_generic, 182 .llseek = default_llseek, 183 }; 184 185 static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf, 186 size_t count, loff_t *ppos) 187 { 188 struct ieee80211_local *local = file->private_data; 189 return mac80211_format_buffer(user_buf, count, ppos, "0x%x\n", 190 local->uapsd_queues); 191 } 192 193 static ssize_t uapsd_queues_write(struct file *file, 194 const char __user *user_buf, 195 size_t count, loff_t *ppos) 196 { 197 struct ieee80211_local *local = file->private_data; 198 unsigned long val; 199 char buf[10]; 200 size_t len; 201 int ret; 202 203 len = min(count, sizeof(buf) - 1); 204 if (copy_from_user(buf, user_buf, len)) 205 return -EFAULT; 206 buf[len] = '\0'; 207 208 ret = strict_strtoul(buf, 0, &val); 209 210 if (ret) 211 return -EINVAL; 212 213 if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) 214 return -ERANGE; 215 216 local->uapsd_queues = val; 217 218 return count; 219 } 220 221 static const struct file_operations uapsd_queues_ops = { 222 .read = uapsd_queues_read, 223 .write = uapsd_queues_write, 224 .open = mac80211_open_file_generic, 225 .llseek = default_llseek, 226 }; 227 228 static ssize_t uapsd_max_sp_len_read(struct file *file, char __user *user_buf, 229 size_t count, loff_t *ppos) 230 { 231 struct ieee80211_local *local = file->private_data; 232 233 return mac80211_format_buffer(user_buf, count, ppos, "0x%x\n", 234 local->uapsd_max_sp_len); 235 } 236 237 static ssize_t uapsd_max_sp_len_write(struct file *file, 238 const char __user *user_buf, 239 size_t count, loff_t *ppos) 240 { 241 struct ieee80211_local *local = file->private_data; 242 unsigned long val; 243 char buf[10]; 244 size_t len; 245 int ret; 246 247 len = min(count, sizeof(buf) - 1); 248 if (copy_from_user(buf, user_buf, len)) 249 return -EFAULT; 250 buf[len] = '\0'; 251 252 ret = strict_strtoul(buf, 0, &val); 253 254 if (ret) 255 return -EINVAL; 256 257 if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) 258 return -ERANGE; 259 260 local->uapsd_max_sp_len = val; 261 262 return count; 263 } 264 265 static const struct file_operations uapsd_max_sp_len_ops = { 266 .read = uapsd_max_sp_len_read, 267 .write = uapsd_max_sp_len_write, 268 .open = mac80211_open_file_generic, 269 .llseek = default_llseek, 270 }; 271 272 static ssize_t channel_type_read(struct file *file, char __user *user_buf, 273 size_t count, loff_t *ppos) 274 { 275 struct ieee80211_local *local = file->private_data; 276 const char *buf; 277 278 switch (local->hw.conf.channel_type) { 279 case NL80211_CHAN_NO_HT: 280 buf = "no ht\n"; 281 break; 282 case NL80211_CHAN_HT20: 283 buf = "ht20\n"; 284 break; 285 case NL80211_CHAN_HT40MINUS: 286 buf = "ht40-\n"; 287 break; 288 case NL80211_CHAN_HT40PLUS: 289 buf = "ht40+\n"; 290 break; 291 default: 292 buf = "???"; 293 break; 294 } 295 296 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); 297 } 298 299 static ssize_t hwflags_read(struct file *file, char __user *user_buf, 300 size_t count, loff_t *ppos) 301 { 302 struct ieee80211_local *local = file->private_data; 303 int mxln = 500; 304 ssize_t rv; 305 char *buf = kzalloc(mxln, GFP_KERNEL); 306 int sf = 0; /* how many written so far */ 307 308 sf += snprintf(buf, mxln - sf, "0x%x\n", local->hw.flags); 309 if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) 310 sf += snprintf(buf + sf, mxln - sf, "HAS_RATE_CONTROL\n"); 311 if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) 312 sf += snprintf(buf + sf, mxln - sf, "RX_INCLUDES_FCS\n"); 313 if (local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) 314 sf += snprintf(buf + sf, mxln - sf, 315 "HOST_BCAST_PS_BUFFERING\n"); 316 if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE) 317 sf += snprintf(buf + sf, mxln - sf, 318 "2GHZ_SHORT_SLOT_INCAPABLE\n"); 319 if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE) 320 sf += snprintf(buf + sf, mxln - sf, 321 "2GHZ_SHORT_PREAMBLE_INCAPABLE\n"); 322 if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) 323 sf += snprintf(buf + sf, mxln - sf, "SIGNAL_UNSPEC\n"); 324 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) 325 sf += snprintf(buf + sf, mxln - sf, "SIGNAL_DBM\n"); 326 if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) 327 sf += snprintf(buf + sf, mxln - sf, "NEED_DTIM_PERIOD\n"); 328 if (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT) 329 sf += snprintf(buf + sf, mxln - sf, "SPECTRUM_MGMT\n"); 330 if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) 331 sf += snprintf(buf + sf, mxln - sf, "AMPDU_AGGREGATION\n"); 332 if (local->hw.flags & IEEE80211_HW_SUPPORTS_PS) 333 sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PS\n"); 334 if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) 335 sf += snprintf(buf + sf, mxln - sf, "PS_NULLFUNC_STACK\n"); 336 if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) 337 sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n"); 338 if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE) 339 sf += snprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n"); 340 if (local->hw.flags & IEEE80211_HW_BEACON_FILTER) 341 sf += snprintf(buf + sf, mxln - sf, "BEACON_FILTER\n"); 342 if (local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) 343 sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n"); 344 if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) 345 sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_SMPS\n"); 346 if (local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) 347 sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_UAPSD\n"); 348 if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) 349 sf += snprintf(buf + sf, mxln - sf, "REPORTS_TX_ACK_STATUS\n"); 350 if (local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) 351 sf += snprintf(buf + sf, mxln - sf, "CONNECTION_MONITOR\n"); 352 if (local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) 353 sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_CQM_RSSI\n"); 354 if (local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK) 355 sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n"); 356 if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) 357 sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); 358 359 rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); 360 kfree(buf); 361 return rv; 362 } 363 364 static ssize_t queues_read(struct file *file, char __user *user_buf, 365 size_t count, loff_t *ppos) 366 { 367 struct ieee80211_local *local = file->private_data; 368 unsigned long flags; 369 char buf[IEEE80211_MAX_QUEUES * 20]; 370 int q, res = 0; 371 372 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 373 for (q = 0; q < local->hw.queues; q++) 374 res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q, 375 local->queue_stop_reasons[q], 376 skb_queue_len(&local->pending[q])); 377 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 378 379 return simple_read_from_buffer(user_buf, count, ppos, buf, res); 380 } 381 382 DEBUGFS_READONLY_FILE_OPS(hwflags); 383 DEBUGFS_READONLY_FILE_OPS(channel_type); 384 DEBUGFS_READONLY_FILE_OPS(queues); 385 386 /* statistics stuff */ 387 388 static ssize_t format_devstat_counter(struct ieee80211_local *local, 389 char __user *userbuf, 390 size_t count, loff_t *ppos, 391 int (*printvalue)(struct ieee80211_low_level_stats *stats, char *buf, 392 int buflen)) 393 { 394 struct ieee80211_low_level_stats stats; 395 char buf[20]; 396 int res; 397 398 rtnl_lock(); 399 res = drv_get_stats(local, &stats); 400 rtnl_unlock(); 401 if (res) 402 return res; 403 res = printvalue(&stats, buf, sizeof(buf)); 404 return simple_read_from_buffer(userbuf, count, ppos, buf, res); 405 } 406 407 #define DEBUGFS_DEVSTATS_FILE(name) \ 408 static int print_devstats_##name(struct ieee80211_low_level_stats *stats,\ 409 char *buf, int buflen) \ 410 { \ 411 return scnprintf(buf, buflen, "%u\n", stats->name); \ 412 } \ 413 static ssize_t stats_ ##name## _read(struct file *file, \ 414 char __user *userbuf, \ 415 size_t count, loff_t *ppos) \ 416 { \ 417 return format_devstat_counter(file->private_data, \ 418 userbuf, \ 419 count, \ 420 ppos, \ 421 print_devstats_##name); \ 422 } \ 423 \ 424 static const struct file_operations stats_ ##name## _ops = { \ 425 .read = stats_ ##name## _read, \ 426 .open = mac80211_open_file_generic, \ 427 .llseek = generic_file_llseek, \ 428 }; 429 430 #define DEBUGFS_STATS_ADD(name, field) \ 431 debugfs_create_u32(#name, 0400, statsd, (u32 *) &field); 432 #define DEBUGFS_DEVSTATS_ADD(name) \ 433 debugfs_create_file(#name, 0400, statsd, local, &stats_ ##name## _ops); 434 435 DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount); 436 DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount); 437 DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount); 438 DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount); 439 440 void debugfs_hw_add(struct ieee80211_local *local) 441 { 442 struct dentry *phyd = local->hw.wiphy->debugfsdir; 443 struct dentry *statsd; 444 445 if (!phyd) 446 return; 447 448 local->debugfs.keys = debugfs_create_dir("keys", phyd); 449 450 DEBUGFS_ADD(frequency); 451 DEBUGFS_ADD(total_ps_buffered); 452 DEBUGFS_ADD(wep_iv); 453 DEBUGFS_ADD(tsf); 454 DEBUGFS_ADD(queues); 455 DEBUGFS_ADD_MODE(reset, 0200); 456 DEBUGFS_ADD(noack); 457 DEBUGFS_ADD(uapsd_queues); 458 DEBUGFS_ADD(uapsd_max_sp_len); 459 DEBUGFS_ADD(channel_type); 460 DEBUGFS_ADD(hwflags); 461 DEBUGFS_ADD(user_power); 462 DEBUGFS_ADD(power); 463 464 statsd = debugfs_create_dir("statistics", phyd); 465 466 /* if the dir failed, don't put all the other things into the root! */ 467 if (!statsd) 468 return; 469 470 DEBUGFS_STATS_ADD(transmitted_fragment_count, 471 local->dot11TransmittedFragmentCount); 472 DEBUGFS_STATS_ADD(multicast_transmitted_frame_count, 473 local->dot11MulticastTransmittedFrameCount); 474 DEBUGFS_STATS_ADD(failed_count, local->dot11FailedCount); 475 DEBUGFS_STATS_ADD(retry_count, local->dot11RetryCount); 476 DEBUGFS_STATS_ADD(multiple_retry_count, 477 local->dot11MultipleRetryCount); 478 DEBUGFS_STATS_ADD(frame_duplicate_count, 479 local->dot11FrameDuplicateCount); 480 DEBUGFS_STATS_ADD(received_fragment_count, 481 local->dot11ReceivedFragmentCount); 482 DEBUGFS_STATS_ADD(multicast_received_frame_count, 483 local->dot11MulticastReceivedFrameCount); 484 DEBUGFS_STATS_ADD(transmitted_frame_count, 485 local->dot11TransmittedFrameCount); 486 #ifdef CONFIG_MAC80211_DEBUG_COUNTERS 487 DEBUGFS_STATS_ADD(tx_handlers_drop, local->tx_handlers_drop); 488 DEBUGFS_STATS_ADD(tx_handlers_queued, local->tx_handlers_queued); 489 DEBUGFS_STATS_ADD(tx_handlers_drop_unencrypted, 490 local->tx_handlers_drop_unencrypted); 491 DEBUGFS_STATS_ADD(tx_handlers_drop_fragment, 492 local->tx_handlers_drop_fragment); 493 DEBUGFS_STATS_ADD(tx_handlers_drop_wep, 494 local->tx_handlers_drop_wep); 495 DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc, 496 local->tx_handlers_drop_not_assoc); 497 DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port, 498 local->tx_handlers_drop_unauth_port); 499 DEBUGFS_STATS_ADD(rx_handlers_drop, local->rx_handlers_drop); 500 DEBUGFS_STATS_ADD(rx_handlers_queued, local->rx_handlers_queued); 501 DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc, 502 local->rx_handlers_drop_nullfunc); 503 DEBUGFS_STATS_ADD(rx_handlers_drop_defrag, 504 local->rx_handlers_drop_defrag); 505 DEBUGFS_STATS_ADD(rx_handlers_drop_short, 506 local->rx_handlers_drop_short); 507 DEBUGFS_STATS_ADD(rx_handlers_drop_passive_scan, 508 local->rx_handlers_drop_passive_scan); 509 DEBUGFS_STATS_ADD(tx_expand_skb_head, 510 local->tx_expand_skb_head); 511 DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned, 512 local->tx_expand_skb_head_cloned); 513 DEBUGFS_STATS_ADD(rx_expand_skb_head, 514 local->rx_expand_skb_head); 515 DEBUGFS_STATS_ADD(rx_expand_skb_head2, 516 local->rx_expand_skb_head2); 517 DEBUGFS_STATS_ADD(rx_handlers_fragments, 518 local->rx_handlers_fragments); 519 DEBUGFS_STATS_ADD(tx_status_drop, 520 local->tx_status_drop); 521 #endif 522 DEBUGFS_DEVSTATS_ADD(dot11ACKFailureCount); 523 DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount); 524 DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount); 525 DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount); 526 } 527