1 /* 2 * mac80211 debugfs for wireless PHYs 3 * 4 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 5 * 6 * GPLv2 7 * 8 */ 9 10 #include <linux/debugfs.h> 11 #include <linux/rtnetlink.h> 12 #include "ieee80211_i.h" 13 #include "rate.h" 14 #include "debugfs.h" 15 16 int mac80211_open_file_generic(struct inode *inode, struct file *file) 17 { 18 file->private_data = inode->i_private; 19 return 0; 20 } 21 22 #define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \ 23 static ssize_t name## _read(struct file *file, char __user *userbuf, \ 24 size_t count, loff_t *ppos) \ 25 { \ 26 struct ieee80211_local *local = file->private_data; \ 27 char buf[buflen]; \ 28 int res; \ 29 \ 30 res = scnprintf(buf, buflen, fmt "\n", ##value); \ 31 return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ 32 } \ 33 \ 34 static const struct file_operations name## _ops = { \ 35 .read = name## _read, \ 36 .open = mac80211_open_file_generic, \ 37 }; 38 39 #define DEBUGFS_ADD(name) \ 40 local->debugfs.name = debugfs_create_file(#name, 0400, phyd, \ 41 local, &name## _ops); 42 43 #define DEBUGFS_ADD_MODE(name, mode) \ 44 local->debugfs.name = debugfs_create_file(#name, mode, phyd, \ 45 local, &name## _ops); 46 47 #define DEBUGFS_DEL(name) \ 48 debugfs_remove(local->debugfs.name); \ 49 local->debugfs.name = NULL; 50 51 52 DEBUGFS_READONLY_FILE(frequency, 20, "%d", 53 local->hw.conf.channel->center_freq); 54 DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", 55 local->rts_threshold); 56 DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", 57 local->fragmentation_threshold); 58 DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d", 59 local->hw.conf.short_frame_max_tx_count); 60 DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d", 61 local->hw.conf.long_frame_max_tx_count); 62 DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d", 63 local->total_ps_buffered); 64 DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x", 65 local->wep_iv & 0xffffff); 66 DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s", 67 local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>"); 68 69 static ssize_t tsf_read(struct file *file, char __user *user_buf, 70 size_t count, loff_t *ppos) 71 { 72 struct ieee80211_local *local = file->private_data; 73 u64 tsf = 0; 74 char buf[100]; 75 76 if (local->ops->get_tsf) 77 tsf = local->ops->get_tsf(local_to_hw(local)); 78 79 snprintf(buf, sizeof(buf), "0x%016llx\n", (unsigned long long) tsf); 80 81 return simple_read_from_buffer(user_buf, count, ppos, buf, 19); 82 } 83 84 static ssize_t tsf_write(struct file *file, 85 const char __user *user_buf, 86 size_t count, loff_t *ppos) 87 { 88 struct ieee80211_local *local = file->private_data; 89 unsigned long long tsf; 90 char buf[100]; 91 size_t len; 92 93 len = min(count, sizeof(buf) - 1); 94 if (copy_from_user(buf, user_buf, len)) 95 return -EFAULT; 96 buf[len] = '\0'; 97 98 if (strncmp(buf, "reset", 5) == 0) { 99 if (local->ops->reset_tsf) { 100 local->ops->reset_tsf(local_to_hw(local)); 101 printk(KERN_INFO "%s: debugfs reset TSF\n", wiphy_name(local->hw.wiphy)); 102 } 103 } else { 104 tsf = simple_strtoul(buf, NULL, 0); 105 if (local->ops->set_tsf) { 106 local->ops->set_tsf(local_to_hw(local), tsf); 107 printk(KERN_INFO "%s: debugfs set TSF to %#018llx\n", wiphy_name(local->hw.wiphy), tsf); 108 } 109 } 110 111 return count; 112 } 113 114 static const struct file_operations tsf_ops = { 115 .read = tsf_read, 116 .write = tsf_write, 117 .open = mac80211_open_file_generic 118 }; 119 120 static ssize_t reset_write(struct file *file, const char __user *user_buf, 121 size_t count, loff_t *ppos) 122 { 123 struct ieee80211_local *local = file->private_data; 124 125 rtnl_lock(); 126 __ieee80211_suspend(&local->hw); 127 __ieee80211_resume(&local->hw); 128 rtnl_unlock(); 129 130 return count; 131 } 132 133 static const struct file_operations reset_ops = { 134 .write = reset_write, 135 .open = mac80211_open_file_generic, 136 }; 137 138 /* statistics stuff */ 139 140 #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \ 141 DEBUGFS_READONLY_FILE(stats_ ##name, buflen, fmt, ##value) 142 143 static ssize_t format_devstat_counter(struct ieee80211_local *local, 144 char __user *userbuf, 145 size_t count, loff_t *ppos, 146 int (*printvalue)(struct ieee80211_low_level_stats *stats, char *buf, 147 int buflen)) 148 { 149 struct ieee80211_low_level_stats stats; 150 char buf[20]; 151 int res; 152 153 if (!local->ops->get_stats) 154 return -EOPNOTSUPP; 155 156 rtnl_lock(); 157 res = local->ops->get_stats(local_to_hw(local), &stats); 158 rtnl_unlock(); 159 if (!res) 160 res = printvalue(&stats, buf, sizeof(buf)); 161 return simple_read_from_buffer(userbuf, count, ppos, buf, res); 162 } 163 164 #define DEBUGFS_DEVSTATS_FILE(name) \ 165 static int print_devstats_##name(struct ieee80211_low_level_stats *stats,\ 166 char *buf, int buflen) \ 167 { \ 168 return scnprintf(buf, buflen, "%u\n", stats->name); \ 169 } \ 170 static ssize_t stats_ ##name## _read(struct file *file, \ 171 char __user *userbuf, \ 172 size_t count, loff_t *ppos) \ 173 { \ 174 return format_devstat_counter(file->private_data, \ 175 userbuf, \ 176 count, \ 177 ppos, \ 178 print_devstats_##name); \ 179 } \ 180 \ 181 static const struct file_operations stats_ ##name## _ops = { \ 182 .read = stats_ ##name## _read, \ 183 .open = mac80211_open_file_generic, \ 184 }; 185 186 #define DEBUGFS_STATS_ADD(name) \ 187 local->debugfs.stats.name = debugfs_create_file(#name, 0400, statsd,\ 188 local, &stats_ ##name## _ops); 189 190 #define DEBUGFS_STATS_DEL(name) \ 191 debugfs_remove(local->debugfs.stats.name); \ 192 local->debugfs.stats.name = NULL; 193 194 DEBUGFS_STATS_FILE(transmitted_fragment_count, 20, "%u", 195 local->dot11TransmittedFragmentCount); 196 DEBUGFS_STATS_FILE(multicast_transmitted_frame_count, 20, "%u", 197 local->dot11MulticastTransmittedFrameCount); 198 DEBUGFS_STATS_FILE(failed_count, 20, "%u", 199 local->dot11FailedCount); 200 DEBUGFS_STATS_FILE(retry_count, 20, "%u", 201 local->dot11RetryCount); 202 DEBUGFS_STATS_FILE(multiple_retry_count, 20, "%u", 203 local->dot11MultipleRetryCount); 204 DEBUGFS_STATS_FILE(frame_duplicate_count, 20, "%u", 205 local->dot11FrameDuplicateCount); 206 DEBUGFS_STATS_FILE(received_fragment_count, 20, "%u", 207 local->dot11ReceivedFragmentCount); 208 DEBUGFS_STATS_FILE(multicast_received_frame_count, 20, "%u", 209 local->dot11MulticastReceivedFrameCount); 210 DEBUGFS_STATS_FILE(transmitted_frame_count, 20, "%u", 211 local->dot11TransmittedFrameCount); 212 #ifdef CONFIG_MAC80211_DEBUG_COUNTERS 213 DEBUGFS_STATS_FILE(tx_handlers_drop, 20, "%u", 214 local->tx_handlers_drop); 215 DEBUGFS_STATS_FILE(tx_handlers_queued, 20, "%u", 216 local->tx_handlers_queued); 217 DEBUGFS_STATS_FILE(tx_handlers_drop_unencrypted, 20, "%u", 218 local->tx_handlers_drop_unencrypted); 219 DEBUGFS_STATS_FILE(tx_handlers_drop_fragment, 20, "%u", 220 local->tx_handlers_drop_fragment); 221 DEBUGFS_STATS_FILE(tx_handlers_drop_wep, 20, "%u", 222 local->tx_handlers_drop_wep); 223 DEBUGFS_STATS_FILE(tx_handlers_drop_not_assoc, 20, "%u", 224 local->tx_handlers_drop_not_assoc); 225 DEBUGFS_STATS_FILE(tx_handlers_drop_unauth_port, 20, "%u", 226 local->tx_handlers_drop_unauth_port); 227 DEBUGFS_STATS_FILE(rx_handlers_drop, 20, "%u", 228 local->rx_handlers_drop); 229 DEBUGFS_STATS_FILE(rx_handlers_queued, 20, "%u", 230 local->rx_handlers_queued); 231 DEBUGFS_STATS_FILE(rx_handlers_drop_nullfunc, 20, "%u", 232 local->rx_handlers_drop_nullfunc); 233 DEBUGFS_STATS_FILE(rx_handlers_drop_defrag, 20, "%u", 234 local->rx_handlers_drop_defrag); 235 DEBUGFS_STATS_FILE(rx_handlers_drop_short, 20, "%u", 236 local->rx_handlers_drop_short); 237 DEBUGFS_STATS_FILE(rx_handlers_drop_passive_scan, 20, "%u", 238 local->rx_handlers_drop_passive_scan); 239 DEBUGFS_STATS_FILE(tx_expand_skb_head, 20, "%u", 240 local->tx_expand_skb_head); 241 DEBUGFS_STATS_FILE(tx_expand_skb_head_cloned, 20, "%u", 242 local->tx_expand_skb_head_cloned); 243 DEBUGFS_STATS_FILE(rx_expand_skb_head, 20, "%u", 244 local->rx_expand_skb_head); 245 DEBUGFS_STATS_FILE(rx_expand_skb_head2, 20, "%u", 246 local->rx_expand_skb_head2); 247 DEBUGFS_STATS_FILE(rx_handlers_fragments, 20, "%u", 248 local->rx_handlers_fragments); 249 DEBUGFS_STATS_FILE(tx_status_drop, 20, "%u", 250 local->tx_status_drop); 251 252 #endif 253 254 DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount); 255 DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount); 256 DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount); 257 DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount); 258 259 260 void debugfs_hw_add(struct ieee80211_local *local) 261 { 262 struct dentry *phyd = local->hw.wiphy->debugfsdir; 263 struct dentry *statsd; 264 265 if (!phyd) 266 return; 267 268 local->debugfs.stations = debugfs_create_dir("stations", phyd); 269 local->debugfs.keys = debugfs_create_dir("keys", phyd); 270 271 DEBUGFS_ADD(frequency); 272 DEBUGFS_ADD(rts_threshold); 273 DEBUGFS_ADD(fragmentation_threshold); 274 DEBUGFS_ADD(short_retry_limit); 275 DEBUGFS_ADD(long_retry_limit); 276 DEBUGFS_ADD(total_ps_buffered); 277 DEBUGFS_ADD(wep_iv); 278 DEBUGFS_ADD(tsf); 279 DEBUGFS_ADD_MODE(reset, 0200); 280 281 statsd = debugfs_create_dir("statistics", phyd); 282 local->debugfs.statistics = statsd; 283 284 /* if the dir failed, don't put all the other things into the root! */ 285 if (!statsd) 286 return; 287 288 DEBUGFS_STATS_ADD(transmitted_fragment_count); 289 DEBUGFS_STATS_ADD(multicast_transmitted_frame_count); 290 DEBUGFS_STATS_ADD(failed_count); 291 DEBUGFS_STATS_ADD(retry_count); 292 DEBUGFS_STATS_ADD(multiple_retry_count); 293 DEBUGFS_STATS_ADD(frame_duplicate_count); 294 DEBUGFS_STATS_ADD(received_fragment_count); 295 DEBUGFS_STATS_ADD(multicast_received_frame_count); 296 DEBUGFS_STATS_ADD(transmitted_frame_count); 297 #ifdef CONFIG_MAC80211_DEBUG_COUNTERS 298 DEBUGFS_STATS_ADD(tx_handlers_drop); 299 DEBUGFS_STATS_ADD(tx_handlers_queued); 300 DEBUGFS_STATS_ADD(tx_handlers_drop_unencrypted); 301 DEBUGFS_STATS_ADD(tx_handlers_drop_fragment); 302 DEBUGFS_STATS_ADD(tx_handlers_drop_wep); 303 DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc); 304 DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port); 305 DEBUGFS_STATS_ADD(rx_handlers_drop); 306 DEBUGFS_STATS_ADD(rx_handlers_queued); 307 DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc); 308 DEBUGFS_STATS_ADD(rx_handlers_drop_defrag); 309 DEBUGFS_STATS_ADD(rx_handlers_drop_short); 310 DEBUGFS_STATS_ADD(rx_handlers_drop_passive_scan); 311 DEBUGFS_STATS_ADD(tx_expand_skb_head); 312 DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned); 313 DEBUGFS_STATS_ADD(rx_expand_skb_head); 314 DEBUGFS_STATS_ADD(rx_expand_skb_head2); 315 DEBUGFS_STATS_ADD(rx_handlers_fragments); 316 DEBUGFS_STATS_ADD(tx_status_drop); 317 #endif 318 DEBUGFS_STATS_ADD(dot11ACKFailureCount); 319 DEBUGFS_STATS_ADD(dot11RTSFailureCount); 320 DEBUGFS_STATS_ADD(dot11FCSErrorCount); 321 DEBUGFS_STATS_ADD(dot11RTSSuccessCount); 322 } 323 324 void debugfs_hw_del(struct ieee80211_local *local) 325 { 326 DEBUGFS_DEL(frequency); 327 DEBUGFS_DEL(rts_threshold); 328 DEBUGFS_DEL(fragmentation_threshold); 329 DEBUGFS_DEL(short_retry_limit); 330 DEBUGFS_DEL(long_retry_limit); 331 DEBUGFS_DEL(total_ps_buffered); 332 DEBUGFS_DEL(wep_iv); 333 DEBUGFS_DEL(tsf); 334 DEBUGFS_DEL(reset); 335 336 DEBUGFS_STATS_DEL(transmitted_fragment_count); 337 DEBUGFS_STATS_DEL(multicast_transmitted_frame_count); 338 DEBUGFS_STATS_DEL(failed_count); 339 DEBUGFS_STATS_DEL(retry_count); 340 DEBUGFS_STATS_DEL(multiple_retry_count); 341 DEBUGFS_STATS_DEL(frame_duplicate_count); 342 DEBUGFS_STATS_DEL(received_fragment_count); 343 DEBUGFS_STATS_DEL(multicast_received_frame_count); 344 DEBUGFS_STATS_DEL(transmitted_frame_count); 345 DEBUGFS_STATS_DEL(num_scans); 346 #ifdef CONFIG_MAC80211_DEBUG_COUNTERS 347 DEBUGFS_STATS_DEL(tx_handlers_drop); 348 DEBUGFS_STATS_DEL(tx_handlers_queued); 349 DEBUGFS_STATS_DEL(tx_handlers_drop_unencrypted); 350 DEBUGFS_STATS_DEL(tx_handlers_drop_fragment); 351 DEBUGFS_STATS_DEL(tx_handlers_drop_wep); 352 DEBUGFS_STATS_DEL(tx_handlers_drop_not_assoc); 353 DEBUGFS_STATS_DEL(tx_handlers_drop_unauth_port); 354 DEBUGFS_STATS_DEL(rx_handlers_drop); 355 DEBUGFS_STATS_DEL(rx_handlers_queued); 356 DEBUGFS_STATS_DEL(rx_handlers_drop_nullfunc); 357 DEBUGFS_STATS_DEL(rx_handlers_drop_defrag); 358 DEBUGFS_STATS_DEL(rx_handlers_drop_short); 359 DEBUGFS_STATS_DEL(rx_handlers_drop_passive_scan); 360 DEBUGFS_STATS_DEL(tx_expand_skb_head); 361 DEBUGFS_STATS_DEL(tx_expand_skb_head_cloned); 362 DEBUGFS_STATS_DEL(rx_expand_skb_head); 363 DEBUGFS_STATS_DEL(rx_expand_skb_head2); 364 DEBUGFS_STATS_DEL(rx_handlers_fragments); 365 DEBUGFS_STATS_DEL(tx_status_drop); 366 #endif 367 DEBUGFS_STATS_DEL(dot11ACKFailureCount); 368 DEBUGFS_STATS_DEL(dot11RTSFailureCount); 369 DEBUGFS_STATS_DEL(dot11FCSErrorCount); 370 DEBUGFS_STATS_DEL(dot11RTSSuccessCount); 371 372 debugfs_remove(local->debugfs.statistics); 373 local->debugfs.statistics = NULL; 374 debugfs_remove(local->debugfs.stations); 375 local->debugfs.stations = NULL; 376 debugfs_remove(local->debugfs.keys); 377 local->debugfs.keys = NULL; 378 } 379