1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright (C) 2020-2023 Intel Corporation 6 */ 7 8 #include <linux/kernel.h> 9 #include <linux/device.h> 10 #include <linux/if.h> 11 #include <linux/if_ether.h> 12 #include <linux/interrupt.h> 13 #include <linux/netdevice.h> 14 #include <linux/rtnetlink.h> 15 #include <linux/slab.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 #include "driver-ops.h" 24 25 static ssize_t ieee80211_if_read_sdata( 26 struct ieee80211_sub_if_data *sdata, 27 char __user *userbuf, 28 size_t count, loff_t *ppos, 29 ssize_t (*format)(const struct ieee80211_sub_if_data *sdata, char *, int)) 30 { 31 char buf[200]; 32 ssize_t ret = -EINVAL; 33 34 wiphy_lock(sdata->local->hw.wiphy); 35 ret = (*format)(sdata, buf, sizeof(buf)); 36 wiphy_unlock(sdata->local->hw.wiphy); 37 38 if (ret >= 0) 39 ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret); 40 41 return ret; 42 } 43 44 static ssize_t ieee80211_if_write_sdata( 45 struct ieee80211_sub_if_data *sdata, 46 const char __user *userbuf, 47 size_t count, loff_t *ppos, 48 ssize_t (*write)(struct ieee80211_sub_if_data *sdata, const char *, int)) 49 { 50 char buf[64]; 51 ssize_t ret; 52 53 if (count >= sizeof(buf)) 54 return -E2BIG; 55 56 if (copy_from_user(buf, userbuf, count)) 57 return -EFAULT; 58 buf[count] = '\0'; 59 60 wiphy_lock(sdata->local->hw.wiphy); 61 ret = (*write)(sdata, buf, count); 62 wiphy_unlock(sdata->local->hw.wiphy); 63 64 return ret; 65 } 66 67 static ssize_t ieee80211_if_read_link( 68 struct ieee80211_link_data *link, 69 char __user *userbuf, 70 size_t count, loff_t *ppos, 71 ssize_t (*format)(const struct ieee80211_link_data *link, char *, int)) 72 { 73 char buf[200]; 74 ssize_t ret = -EINVAL; 75 76 wiphy_lock(link->sdata->local->hw.wiphy); 77 ret = (*format)(link, buf, sizeof(buf)); 78 wiphy_unlock(link->sdata->local->hw.wiphy); 79 80 if (ret >= 0) 81 ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret); 82 83 return ret; 84 } 85 86 static ssize_t ieee80211_if_write_link( 87 struct ieee80211_link_data *link, 88 const char __user *userbuf, 89 size_t count, loff_t *ppos, 90 ssize_t (*write)(struct ieee80211_link_data *link, const char *, int)) 91 { 92 char buf[64]; 93 ssize_t ret; 94 95 if (count >= sizeof(buf)) 96 return -E2BIG; 97 98 if (copy_from_user(buf, userbuf, count)) 99 return -EFAULT; 100 buf[count] = '\0'; 101 102 wiphy_lock(link->sdata->local->hw.wiphy); 103 ret = (*write)(link, buf, count); 104 wiphy_unlock(link->sdata->local->hw.wiphy); 105 106 return ret; 107 } 108 109 #define IEEE80211_IF_FMT(name, type, field, format_string) \ 110 static ssize_t ieee80211_if_fmt_##name( \ 111 const type *data, char *buf, \ 112 int buflen) \ 113 { \ 114 return scnprintf(buf, buflen, format_string, data->field); \ 115 } 116 #define IEEE80211_IF_FMT_DEC(name, type, field) \ 117 IEEE80211_IF_FMT(name, type, field, "%d\n") 118 #define IEEE80211_IF_FMT_HEX(name, type, field) \ 119 IEEE80211_IF_FMT(name, type, field, "%#x\n") 120 #define IEEE80211_IF_FMT_LHEX(name, type, field) \ 121 IEEE80211_IF_FMT(name, type, field, "%#lx\n") 122 123 #define IEEE80211_IF_FMT_HEXARRAY(name, type, field) \ 124 static ssize_t ieee80211_if_fmt_##name( \ 125 const type *data, \ 126 char *buf, int buflen) \ 127 { \ 128 char *p = buf; \ 129 int i; \ 130 for (i = 0; i < sizeof(data->field); i++) { \ 131 p += scnprintf(p, buflen + buf - p, "%.2x ", \ 132 data->field[i]); \ 133 } \ 134 p += scnprintf(p, buflen + buf - p, "\n"); \ 135 return p - buf; \ 136 } 137 138 #define IEEE80211_IF_FMT_ATOMIC(name, type, field) \ 139 static ssize_t ieee80211_if_fmt_##name( \ 140 const type *data, \ 141 char *buf, int buflen) \ 142 { \ 143 return scnprintf(buf, buflen, "%d\n", atomic_read(&data->field));\ 144 } 145 146 #define IEEE80211_IF_FMT_MAC(name, type, field) \ 147 static ssize_t ieee80211_if_fmt_##name( \ 148 const type *data, char *buf, \ 149 int buflen) \ 150 { \ 151 return scnprintf(buf, buflen, "%pM\n", data->field); \ 152 } 153 154 #define IEEE80211_IF_FMT_JIFFIES_TO_MS(name, type, field) \ 155 static ssize_t ieee80211_if_fmt_##name( \ 156 const type *data, \ 157 char *buf, int buflen) \ 158 { \ 159 return scnprintf(buf, buflen, "%d\n", \ 160 jiffies_to_msecs(data->field)); \ 161 } 162 163 #define _IEEE80211_IF_FILE_OPS(name, _read, _write) \ 164 static const struct file_operations name##_ops = { \ 165 .read = (_read), \ 166 .write = (_write), \ 167 .open = simple_open, \ 168 .llseek = generic_file_llseek, \ 169 } 170 171 #define _IEEE80211_IF_FILE_R_FN(name) \ 172 static ssize_t ieee80211_if_read_##name(struct file *file, \ 173 char __user *userbuf, \ 174 size_t count, loff_t *ppos) \ 175 { \ 176 return ieee80211_if_read_sdata(file->private_data, \ 177 userbuf, count, ppos, \ 178 ieee80211_if_fmt_##name); \ 179 } 180 181 #define _IEEE80211_IF_FILE_W_FN(name) \ 182 static ssize_t ieee80211_if_write_##name(struct file *file, \ 183 const char __user *userbuf, \ 184 size_t count, loff_t *ppos) \ 185 { \ 186 return ieee80211_if_write_sdata(file->private_data, userbuf, \ 187 count, ppos, \ 188 ieee80211_if_parse_##name); \ 189 } 190 191 #define IEEE80211_IF_FILE_R(name) \ 192 _IEEE80211_IF_FILE_R_FN(name) \ 193 _IEEE80211_IF_FILE_OPS(name, ieee80211_if_read_##name, NULL) 194 195 #define IEEE80211_IF_FILE_W(name) \ 196 _IEEE80211_IF_FILE_W_FN(name) \ 197 _IEEE80211_IF_FILE_OPS(name, NULL, ieee80211_if_write_##name) 198 199 #define IEEE80211_IF_FILE_RW(name) \ 200 _IEEE80211_IF_FILE_R_FN(name) \ 201 _IEEE80211_IF_FILE_W_FN(name) \ 202 _IEEE80211_IF_FILE_OPS(name, ieee80211_if_read_##name, \ 203 ieee80211_if_write_##name) 204 205 #define IEEE80211_IF_FILE(name, field, format) \ 206 IEEE80211_IF_FMT_##format(name, struct ieee80211_sub_if_data, field) \ 207 IEEE80211_IF_FILE_R(name) 208 209 #define _IEEE80211_IF_LINK_R_FN(name) \ 210 static ssize_t ieee80211_if_read_##name(struct file *file, \ 211 char __user *userbuf, \ 212 size_t count, loff_t *ppos) \ 213 { \ 214 return ieee80211_if_read_link(file->private_data, \ 215 userbuf, count, ppos, \ 216 ieee80211_if_fmt_##name); \ 217 } 218 219 #define _IEEE80211_IF_LINK_W_FN(name) \ 220 static ssize_t ieee80211_if_write_##name(struct file *file, \ 221 const char __user *userbuf, \ 222 size_t count, loff_t *ppos) \ 223 { \ 224 return ieee80211_if_write_link(file->private_data, userbuf, \ 225 count, ppos, \ 226 ieee80211_if_parse_##name); \ 227 } 228 229 #define IEEE80211_IF_LINK_FILE_R(name) \ 230 _IEEE80211_IF_LINK_R_FN(name) \ 231 _IEEE80211_IF_FILE_OPS(link_##name, ieee80211_if_read_##name, NULL) 232 233 #define IEEE80211_IF_LINK_FILE_W(name) \ 234 _IEEE80211_IF_LINK_W_FN(name) \ 235 _IEEE80211_IF_FILE_OPS(link_##name, NULL, ieee80211_if_write_##name) 236 237 #define IEEE80211_IF_LINK_FILE_RW(name) \ 238 _IEEE80211_IF_LINK_R_FN(name) \ 239 _IEEE80211_IF_LINK_W_FN(name) \ 240 _IEEE80211_IF_FILE_OPS(link_##name, ieee80211_if_read_##name, \ 241 ieee80211_if_write_##name) 242 243 #define IEEE80211_IF_LINK_FILE(name, field, format) \ 244 IEEE80211_IF_FMT_##format(name, struct ieee80211_link_data, field) \ 245 IEEE80211_IF_LINK_FILE_R(name) 246 247 /* common attributes */ 248 IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[NL80211_BAND_2GHZ], 249 HEX); 250 IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[NL80211_BAND_5GHZ], 251 HEX); 252 IEEE80211_IF_FILE(rc_rateidx_mcs_mask_2ghz, 253 rc_rateidx_mcs_mask[NL80211_BAND_2GHZ], HEXARRAY); 254 IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz, 255 rc_rateidx_mcs_mask[NL80211_BAND_5GHZ], HEXARRAY); 256 257 static ssize_t ieee80211_if_fmt_rc_rateidx_vht_mcs_mask_2ghz( 258 const struct ieee80211_sub_if_data *sdata, 259 char *buf, int buflen) 260 { 261 int i, len = 0; 262 const u16 *mask = sdata->rc_rateidx_vht_mcs_mask[NL80211_BAND_2GHZ]; 263 264 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) 265 len += scnprintf(buf + len, buflen - len, "%04x ", mask[i]); 266 len += scnprintf(buf + len, buflen - len, "\n"); 267 268 return len; 269 } 270 271 IEEE80211_IF_FILE_R(rc_rateidx_vht_mcs_mask_2ghz); 272 273 static ssize_t ieee80211_if_fmt_rc_rateidx_vht_mcs_mask_5ghz( 274 const struct ieee80211_sub_if_data *sdata, 275 char *buf, int buflen) 276 { 277 int i, len = 0; 278 const u16 *mask = sdata->rc_rateidx_vht_mcs_mask[NL80211_BAND_5GHZ]; 279 280 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) 281 len += scnprintf(buf + len, buflen - len, "%04x ", mask[i]); 282 len += scnprintf(buf + len, buflen - len, "\n"); 283 284 return len; 285 } 286 287 IEEE80211_IF_FILE_R(rc_rateidx_vht_mcs_mask_5ghz); 288 289 IEEE80211_IF_FILE(flags, flags, HEX); 290 IEEE80211_IF_FILE(state, state, LHEX); 291 IEEE80211_IF_LINK_FILE(txpower, conf->txpower, DEC); 292 IEEE80211_IF_LINK_FILE(ap_power_level, ap_power_level, DEC); 293 IEEE80211_IF_LINK_FILE(user_power_level, user_power_level, DEC); 294 295 static ssize_t 296 ieee80211_if_fmt_hw_queues(const struct ieee80211_sub_if_data *sdata, 297 char *buf, int buflen) 298 { 299 int len; 300 301 len = scnprintf(buf, buflen, "AC queues: VO:%d VI:%d BE:%d BK:%d\n", 302 sdata->vif.hw_queue[IEEE80211_AC_VO], 303 sdata->vif.hw_queue[IEEE80211_AC_VI], 304 sdata->vif.hw_queue[IEEE80211_AC_BE], 305 sdata->vif.hw_queue[IEEE80211_AC_BK]); 306 307 if (sdata->vif.type == NL80211_IFTYPE_AP) 308 len += scnprintf(buf + len, buflen - len, "cab queue: %d\n", 309 sdata->vif.cab_queue); 310 311 return len; 312 } 313 IEEE80211_IF_FILE_R(hw_queues); 314 315 /* STA attributes */ 316 IEEE80211_IF_FILE(bssid, deflink.u.mgd.bssid, MAC); 317 IEEE80211_IF_FILE(aid, vif.cfg.aid, DEC); 318 IEEE80211_IF_FILE(beacon_timeout, u.mgd.beacon_timeout, JIFFIES_TO_MS); 319 320 static int ieee80211_set_smps(struct ieee80211_link_data *link, 321 enum ieee80211_smps_mode smps_mode) 322 { 323 struct ieee80211_sub_if_data *sdata = link->sdata; 324 struct ieee80211_local *local = sdata->local; 325 326 if (sdata->vif.driver_flags & IEEE80211_VIF_DISABLE_SMPS_OVERRIDE) 327 return -EOPNOTSUPP; 328 329 if (!(local->hw.wiphy->features & NL80211_FEATURE_STATIC_SMPS) && 330 smps_mode == IEEE80211_SMPS_STATIC) 331 return -EINVAL; 332 333 /* auto should be dynamic if in PS mode */ 334 if (!(local->hw.wiphy->features & NL80211_FEATURE_DYNAMIC_SMPS) && 335 (smps_mode == IEEE80211_SMPS_DYNAMIC || 336 smps_mode == IEEE80211_SMPS_AUTOMATIC)) 337 return -EINVAL; 338 339 if (sdata->vif.type != NL80211_IFTYPE_STATION) 340 return -EOPNOTSUPP; 341 342 return __ieee80211_request_smps_mgd(link->sdata, link, smps_mode); 343 } 344 345 static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = { 346 [IEEE80211_SMPS_AUTOMATIC] = "auto", 347 [IEEE80211_SMPS_OFF] = "off", 348 [IEEE80211_SMPS_STATIC] = "static", 349 [IEEE80211_SMPS_DYNAMIC] = "dynamic", 350 }; 351 352 static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_link_data *link, 353 char *buf, int buflen) 354 { 355 if (link->sdata->vif.type == NL80211_IFTYPE_STATION) 356 return snprintf(buf, buflen, "request: %s\nused: %s\n", 357 smps_modes[link->u.mgd.req_smps], 358 smps_modes[link->smps_mode]); 359 return -EINVAL; 360 } 361 362 static ssize_t ieee80211_if_parse_smps(struct ieee80211_link_data *link, 363 const char *buf, int buflen) 364 { 365 enum ieee80211_smps_mode mode; 366 367 for (mode = 0; mode < IEEE80211_SMPS_NUM_MODES; mode++) { 368 if (strncmp(buf, smps_modes[mode], buflen) == 0) { 369 int err = ieee80211_set_smps(link, mode); 370 if (!err) 371 return buflen; 372 return err; 373 } 374 } 375 376 return -EINVAL; 377 } 378 IEEE80211_IF_LINK_FILE_RW(smps); 379 380 static ssize_t ieee80211_if_parse_tkip_mic_test( 381 struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) 382 { 383 struct ieee80211_local *local = sdata->local; 384 u8 addr[ETH_ALEN]; 385 struct sk_buff *skb; 386 struct ieee80211_hdr *hdr; 387 __le16 fc; 388 389 if (!mac_pton(buf, addr)) 390 return -EINVAL; 391 392 if (!ieee80211_sdata_running(sdata)) 393 return -ENOTCONN; 394 395 skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24 + 100); 396 if (!skb) 397 return -ENOMEM; 398 skb_reserve(skb, local->hw.extra_tx_headroom); 399 400 hdr = skb_put_zero(skb, 24); 401 fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); 402 403 switch (sdata->vif.type) { 404 case NL80211_IFTYPE_AP: 405 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); 406 /* DA BSSID SA */ 407 memcpy(hdr->addr1, addr, ETH_ALEN); 408 memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); 409 memcpy(hdr->addr3, sdata->vif.addr, ETH_ALEN); 410 break; 411 case NL80211_IFTYPE_STATION: 412 fc |= cpu_to_le16(IEEE80211_FCTL_TODS); 413 /* BSSID SA DA */ 414 if (!sdata->u.mgd.associated) { 415 dev_kfree_skb(skb); 416 return -ENOTCONN; 417 } 418 memcpy(hdr->addr1, sdata->deflink.u.mgd.bssid, ETH_ALEN); 419 memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); 420 memcpy(hdr->addr3, addr, ETH_ALEN); 421 break; 422 default: 423 dev_kfree_skb(skb); 424 return -EOPNOTSUPP; 425 } 426 hdr->frame_control = fc; 427 428 /* 429 * Add some length to the test frame to make it look bit more valid. 430 * The exact contents does not matter since the recipient is required 431 * to drop this because of the Michael MIC failure. 432 */ 433 skb_put_zero(skb, 50); 434 435 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_TKIP_MIC_FAILURE; 436 437 ieee80211_tx_skb(sdata, skb); 438 439 return buflen; 440 } 441 IEEE80211_IF_FILE_W(tkip_mic_test); 442 443 static ssize_t ieee80211_if_parse_beacon_loss( 444 struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) 445 { 446 if (!ieee80211_sdata_running(sdata) || !sdata->vif.cfg.assoc) 447 return -ENOTCONN; 448 449 ieee80211_beacon_loss(&sdata->vif); 450 451 return buflen; 452 } 453 IEEE80211_IF_FILE_W(beacon_loss); 454 455 static ssize_t ieee80211_if_fmt_uapsd_queues( 456 const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) 457 { 458 const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 459 460 return snprintf(buf, buflen, "0x%x\n", ifmgd->uapsd_queues); 461 } 462 463 static ssize_t ieee80211_if_parse_uapsd_queues( 464 struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) 465 { 466 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 467 u8 val; 468 int ret; 469 470 ret = kstrtou8(buf, 0, &val); 471 if (ret) 472 return ret; 473 474 if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) 475 return -ERANGE; 476 477 ifmgd->uapsd_queues = val; 478 479 return buflen; 480 } 481 IEEE80211_IF_FILE_RW(uapsd_queues); 482 483 static ssize_t ieee80211_if_fmt_uapsd_max_sp_len( 484 const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) 485 { 486 const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 487 488 return snprintf(buf, buflen, "0x%x\n", ifmgd->uapsd_max_sp_len); 489 } 490 491 static ssize_t ieee80211_if_parse_uapsd_max_sp_len( 492 struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) 493 { 494 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 495 unsigned long val; 496 int ret; 497 498 ret = kstrtoul(buf, 0, &val); 499 if (ret) 500 return -EINVAL; 501 502 if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) 503 return -ERANGE; 504 505 ifmgd->uapsd_max_sp_len = val; 506 507 return buflen; 508 } 509 IEEE80211_IF_FILE_RW(uapsd_max_sp_len); 510 511 static ssize_t ieee80211_if_fmt_tdls_wider_bw( 512 const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) 513 { 514 const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 515 bool tdls_wider_bw; 516 517 tdls_wider_bw = ieee80211_hw_check(&sdata->local->hw, TDLS_WIDER_BW) && 518 !ifmgd->tdls_wider_bw_prohibited; 519 520 return snprintf(buf, buflen, "%d\n", tdls_wider_bw); 521 } 522 523 static ssize_t ieee80211_if_parse_tdls_wider_bw( 524 struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) 525 { 526 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 527 u8 val; 528 int ret; 529 530 ret = kstrtou8(buf, 0, &val); 531 if (ret) 532 return ret; 533 534 ifmgd->tdls_wider_bw_prohibited = !val; 535 return buflen; 536 } 537 IEEE80211_IF_FILE_RW(tdls_wider_bw); 538 539 /* AP attributes */ 540 IEEE80211_IF_FILE(num_mcast_sta, u.ap.num_mcast_sta, ATOMIC); 541 IEEE80211_IF_FILE(num_sta_ps, u.ap.ps.num_sta_ps, ATOMIC); 542 IEEE80211_IF_FILE(dtim_count, u.ap.ps.dtim_count, DEC); 543 IEEE80211_IF_FILE(num_mcast_sta_vlan, u.vlan.num_mcast_sta, ATOMIC); 544 545 static ssize_t ieee80211_if_fmt_num_buffered_multicast( 546 const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) 547 { 548 return scnprintf(buf, buflen, "%u\n", 549 skb_queue_len(&sdata->u.ap.ps.bc_buf)); 550 } 551 IEEE80211_IF_FILE_R(num_buffered_multicast); 552 553 static ssize_t ieee80211_if_fmt_aqm( 554 const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) 555 { 556 struct ieee80211_local *local = sdata->local; 557 struct txq_info *txqi; 558 int len; 559 560 if (!sdata->vif.txq) 561 return 0; 562 563 txqi = to_txq_info(sdata->vif.txq); 564 565 spin_lock_bh(&local->fq.lock); 566 rcu_read_lock(); 567 568 len = scnprintf(buf, 569 buflen, 570 "ac backlog-bytes backlog-packets new-flows drops marks overlimit collisions tx-bytes tx-packets\n" 571 "%u %u %u %u %u %u %u %u %u %u\n", 572 txqi->txq.ac, 573 txqi->tin.backlog_bytes, 574 txqi->tin.backlog_packets, 575 txqi->tin.flows, 576 txqi->cstats.drop_count, 577 txqi->cstats.ecn_mark, 578 txqi->tin.overlimit, 579 txqi->tin.collisions, 580 txqi->tin.tx_bytes, 581 txqi->tin.tx_packets); 582 583 rcu_read_unlock(); 584 spin_unlock_bh(&local->fq.lock); 585 586 return len; 587 } 588 IEEE80211_IF_FILE_R(aqm); 589 590 IEEE80211_IF_FILE(multicast_to_unicast, u.ap.multicast_to_unicast, HEX); 591 592 /* IBSS attributes */ 593 static ssize_t ieee80211_if_fmt_tsf( 594 const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) 595 { 596 struct ieee80211_local *local = sdata->local; 597 u64 tsf; 598 599 tsf = drv_get_tsf(local, (struct ieee80211_sub_if_data *)sdata); 600 601 return scnprintf(buf, buflen, "0x%016llx\n", (unsigned long long) tsf); 602 } 603 604 static ssize_t ieee80211_if_parse_tsf( 605 struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) 606 { 607 struct ieee80211_local *local = sdata->local; 608 unsigned long long tsf; 609 int ret; 610 int tsf_is_delta = 0; 611 612 if (strncmp(buf, "reset", 5) == 0) { 613 if (local->ops->reset_tsf) { 614 drv_reset_tsf(local, sdata); 615 wiphy_info(local->hw.wiphy, "debugfs reset TSF\n"); 616 } 617 } else { 618 if (buflen > 10 && buf[1] == '=') { 619 if (buf[0] == '+') 620 tsf_is_delta = 1; 621 else if (buf[0] == '-') 622 tsf_is_delta = -1; 623 else 624 return -EINVAL; 625 buf += 2; 626 } 627 ret = kstrtoull(buf, 10, &tsf); 628 if (ret < 0) 629 return ret; 630 if (tsf_is_delta && local->ops->offset_tsf) { 631 drv_offset_tsf(local, sdata, tsf_is_delta * tsf); 632 wiphy_info(local->hw.wiphy, 633 "debugfs offset TSF by %018lld\n", 634 tsf_is_delta * tsf); 635 } else if (local->ops->set_tsf) { 636 if (tsf_is_delta) 637 tsf = drv_get_tsf(local, sdata) + 638 tsf_is_delta * tsf; 639 drv_set_tsf(local, sdata, tsf); 640 wiphy_info(local->hw.wiphy, 641 "debugfs set TSF to %#018llx\n", tsf); 642 } 643 } 644 645 ieee80211_recalc_dtim(local, sdata); 646 return buflen; 647 } 648 IEEE80211_IF_FILE_RW(tsf); 649 650 static ssize_t ieee80211_if_fmt_valid_links(const struct ieee80211_sub_if_data *sdata, 651 char *buf, int buflen) 652 { 653 return snprintf(buf, buflen, "0x%x\n", sdata->vif.valid_links); 654 } 655 IEEE80211_IF_FILE_R(valid_links); 656 657 static ssize_t ieee80211_if_fmt_active_links(const struct ieee80211_sub_if_data *sdata, 658 char *buf, int buflen) 659 { 660 return snprintf(buf, buflen, "0x%x\n", sdata->vif.active_links); 661 } 662 663 static ssize_t ieee80211_if_parse_active_links(struct ieee80211_sub_if_data *sdata, 664 const char *buf, int buflen) 665 { 666 u16 active_links; 667 668 if (kstrtou16(buf, 0, &active_links)) 669 return -EINVAL; 670 671 return ieee80211_set_active_links(&sdata->vif, active_links) ?: buflen; 672 } 673 IEEE80211_IF_FILE_RW(active_links); 674 675 IEEE80211_IF_LINK_FILE(addr, conf->addr, MAC); 676 677 #ifdef CONFIG_MAC80211_MESH 678 IEEE80211_IF_FILE(estab_plinks, u.mesh.estab_plinks, ATOMIC); 679 680 /* Mesh stats attributes */ 681 IEEE80211_IF_FILE(fwded_mcast, u.mesh.mshstats.fwded_mcast, DEC); 682 IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC); 683 IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC); 684 IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC); 685 IEEE80211_IF_FILE(dropped_frames_no_route, 686 u.mesh.mshstats.dropped_frames_no_route, DEC); 687 688 /* Mesh parameters */ 689 IEEE80211_IF_FILE(dot11MeshMaxRetries, 690 u.mesh.mshcfg.dot11MeshMaxRetries, DEC); 691 IEEE80211_IF_FILE(dot11MeshRetryTimeout, 692 u.mesh.mshcfg.dot11MeshRetryTimeout, DEC); 693 IEEE80211_IF_FILE(dot11MeshConfirmTimeout, 694 u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC); 695 IEEE80211_IF_FILE(dot11MeshHoldingTimeout, 696 u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC); 697 IEEE80211_IF_FILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC); 698 IEEE80211_IF_FILE(element_ttl, u.mesh.mshcfg.element_ttl, DEC); 699 IEEE80211_IF_FILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC); 700 IEEE80211_IF_FILE(dot11MeshMaxPeerLinks, 701 u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC); 702 IEEE80211_IF_FILE(dot11MeshHWMPactivePathTimeout, 703 u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC); 704 IEEE80211_IF_FILE(dot11MeshHWMPpreqMinInterval, 705 u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC); 706 IEEE80211_IF_FILE(dot11MeshHWMPperrMinInterval, 707 u.mesh.mshcfg.dot11MeshHWMPperrMinInterval, DEC); 708 IEEE80211_IF_FILE(dot11MeshHWMPnetDiameterTraversalTime, 709 u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC); 710 IEEE80211_IF_FILE(dot11MeshHWMPmaxPREQretries, 711 u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC); 712 IEEE80211_IF_FILE(path_refresh_time, 713 u.mesh.mshcfg.path_refresh_time, DEC); 714 IEEE80211_IF_FILE(min_discovery_timeout, 715 u.mesh.mshcfg.min_discovery_timeout, DEC); 716 IEEE80211_IF_FILE(dot11MeshHWMPRootMode, 717 u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC); 718 IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol, 719 u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC); 720 IEEE80211_IF_FILE(dot11MeshHWMPRannInterval, 721 u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC); 722 IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC); 723 IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC); 724 IEEE80211_IF_FILE(ht_opmode, u.mesh.mshcfg.ht_opmode, DEC); 725 IEEE80211_IF_FILE(dot11MeshHWMPactivePathToRootTimeout, 726 u.mesh.mshcfg.dot11MeshHWMPactivePathToRootTimeout, DEC); 727 IEEE80211_IF_FILE(dot11MeshHWMProotInterval, 728 u.mesh.mshcfg.dot11MeshHWMProotInterval, DEC); 729 IEEE80211_IF_FILE(dot11MeshHWMPconfirmationInterval, 730 u.mesh.mshcfg.dot11MeshHWMPconfirmationInterval, DEC); 731 IEEE80211_IF_FILE(power_mode, u.mesh.mshcfg.power_mode, DEC); 732 IEEE80211_IF_FILE(dot11MeshAwakeWindowDuration, 733 u.mesh.mshcfg.dot11MeshAwakeWindowDuration, DEC); 734 IEEE80211_IF_FILE(dot11MeshConnectedToMeshGate, 735 u.mesh.mshcfg.dot11MeshConnectedToMeshGate, DEC); 736 IEEE80211_IF_FILE(dot11MeshNolearn, u.mesh.mshcfg.dot11MeshNolearn, DEC); 737 IEEE80211_IF_FILE(dot11MeshConnectedToAuthServer, 738 u.mesh.mshcfg.dot11MeshConnectedToAuthServer, DEC); 739 #endif 740 741 #define DEBUGFS_ADD_MODE(name, mode) \ 742 debugfs_create_file(#name, mode, sdata->vif.debugfs_dir, \ 743 sdata, &name##_ops) 744 745 #define DEBUGFS_ADD_X(_bits, _name, _mode) \ 746 debugfs_create_x##_bits(#_name, _mode, sdata->vif.debugfs_dir, \ 747 &sdata->vif._name) 748 749 #define DEBUGFS_ADD_X8(_name, _mode) \ 750 DEBUGFS_ADD_X(8, _name, _mode) 751 752 #define DEBUGFS_ADD_X16(_name, _mode) \ 753 DEBUGFS_ADD_X(16, _name, _mode) 754 755 #define DEBUGFS_ADD_X32(_name, _mode) \ 756 DEBUGFS_ADD_X(32, _name, _mode) 757 758 #define DEBUGFS_ADD(name) DEBUGFS_ADD_MODE(name, 0400) 759 760 static void add_common_files(struct ieee80211_sub_if_data *sdata) 761 { 762 DEBUGFS_ADD(rc_rateidx_mask_2ghz); 763 DEBUGFS_ADD(rc_rateidx_mask_5ghz); 764 DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); 765 DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); 766 DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_2ghz); 767 DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_5ghz); 768 DEBUGFS_ADD(hw_queues); 769 770 if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE && 771 sdata->vif.type != NL80211_IFTYPE_NAN) 772 DEBUGFS_ADD(aqm); 773 } 774 775 static void add_sta_files(struct ieee80211_sub_if_data *sdata) 776 { 777 DEBUGFS_ADD(bssid); 778 DEBUGFS_ADD(aid); 779 DEBUGFS_ADD(beacon_timeout); 780 DEBUGFS_ADD_MODE(tkip_mic_test, 0200); 781 DEBUGFS_ADD_MODE(beacon_loss, 0200); 782 DEBUGFS_ADD_MODE(uapsd_queues, 0600); 783 DEBUGFS_ADD_MODE(uapsd_max_sp_len, 0600); 784 DEBUGFS_ADD_MODE(tdls_wider_bw, 0600); 785 DEBUGFS_ADD_MODE(valid_links, 0400); 786 DEBUGFS_ADD_MODE(active_links, 0600); 787 DEBUGFS_ADD_X16(dormant_links, 0400); 788 } 789 790 static void add_ap_files(struct ieee80211_sub_if_data *sdata) 791 { 792 DEBUGFS_ADD(num_mcast_sta); 793 DEBUGFS_ADD(num_sta_ps); 794 DEBUGFS_ADD(dtim_count); 795 DEBUGFS_ADD(num_buffered_multicast); 796 DEBUGFS_ADD_MODE(tkip_mic_test, 0200); 797 DEBUGFS_ADD_MODE(multicast_to_unicast, 0600); 798 } 799 800 static void add_vlan_files(struct ieee80211_sub_if_data *sdata) 801 { 802 /* add num_mcast_sta_vlan using name num_mcast_sta */ 803 debugfs_create_file("num_mcast_sta", 0400, sdata->vif.debugfs_dir, 804 sdata, &num_mcast_sta_vlan_ops); 805 } 806 807 static void add_ibss_files(struct ieee80211_sub_if_data *sdata) 808 { 809 DEBUGFS_ADD_MODE(tsf, 0600); 810 } 811 812 #ifdef CONFIG_MAC80211_MESH 813 814 static void add_mesh_files(struct ieee80211_sub_if_data *sdata) 815 { 816 DEBUGFS_ADD_MODE(tsf, 0600); 817 DEBUGFS_ADD_MODE(estab_plinks, 0400); 818 } 819 820 static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) 821 { 822 struct dentry *dir = debugfs_create_dir("mesh_stats", 823 sdata->vif.debugfs_dir); 824 #define MESHSTATS_ADD(name)\ 825 debugfs_create_file(#name, 0400, dir, sdata, &name##_ops) 826 827 MESHSTATS_ADD(fwded_mcast); 828 MESHSTATS_ADD(fwded_unicast); 829 MESHSTATS_ADD(fwded_frames); 830 MESHSTATS_ADD(dropped_frames_ttl); 831 MESHSTATS_ADD(dropped_frames_no_route); 832 #undef MESHSTATS_ADD 833 } 834 835 static void add_mesh_config(struct ieee80211_sub_if_data *sdata) 836 { 837 struct dentry *dir = debugfs_create_dir("mesh_config", 838 sdata->vif.debugfs_dir); 839 840 #define MESHPARAMS_ADD(name) \ 841 debugfs_create_file(#name, 0600, dir, sdata, &name##_ops) 842 843 MESHPARAMS_ADD(dot11MeshMaxRetries); 844 MESHPARAMS_ADD(dot11MeshRetryTimeout); 845 MESHPARAMS_ADD(dot11MeshConfirmTimeout); 846 MESHPARAMS_ADD(dot11MeshHoldingTimeout); 847 MESHPARAMS_ADD(dot11MeshTTL); 848 MESHPARAMS_ADD(element_ttl); 849 MESHPARAMS_ADD(auto_open_plinks); 850 MESHPARAMS_ADD(dot11MeshMaxPeerLinks); 851 MESHPARAMS_ADD(dot11MeshHWMPactivePathTimeout); 852 MESHPARAMS_ADD(dot11MeshHWMPpreqMinInterval); 853 MESHPARAMS_ADD(dot11MeshHWMPperrMinInterval); 854 MESHPARAMS_ADD(dot11MeshHWMPnetDiameterTraversalTime); 855 MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries); 856 MESHPARAMS_ADD(path_refresh_time); 857 MESHPARAMS_ADD(min_discovery_timeout); 858 MESHPARAMS_ADD(dot11MeshHWMPRootMode); 859 MESHPARAMS_ADD(dot11MeshHWMPRannInterval); 860 MESHPARAMS_ADD(dot11MeshForwarding); 861 MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol); 862 MESHPARAMS_ADD(rssi_threshold); 863 MESHPARAMS_ADD(ht_opmode); 864 MESHPARAMS_ADD(dot11MeshHWMPactivePathToRootTimeout); 865 MESHPARAMS_ADD(dot11MeshHWMProotInterval); 866 MESHPARAMS_ADD(dot11MeshHWMPconfirmationInterval); 867 MESHPARAMS_ADD(power_mode); 868 MESHPARAMS_ADD(dot11MeshAwakeWindowDuration); 869 MESHPARAMS_ADD(dot11MeshConnectedToMeshGate); 870 MESHPARAMS_ADD(dot11MeshNolearn); 871 MESHPARAMS_ADD(dot11MeshConnectedToAuthServer); 872 #undef MESHPARAMS_ADD 873 } 874 #endif 875 876 static void add_files(struct ieee80211_sub_if_data *sdata) 877 { 878 if (!sdata->vif.debugfs_dir) 879 return; 880 881 DEBUGFS_ADD(flags); 882 DEBUGFS_ADD(state); 883 884 if (sdata->vif.type != NL80211_IFTYPE_MONITOR) 885 add_common_files(sdata); 886 887 switch (sdata->vif.type) { 888 case NL80211_IFTYPE_MESH_POINT: 889 #ifdef CONFIG_MAC80211_MESH 890 add_mesh_files(sdata); 891 add_mesh_stats(sdata); 892 add_mesh_config(sdata); 893 #endif 894 break; 895 case NL80211_IFTYPE_STATION: 896 add_sta_files(sdata); 897 break; 898 case NL80211_IFTYPE_ADHOC: 899 add_ibss_files(sdata); 900 break; 901 case NL80211_IFTYPE_AP: 902 add_ap_files(sdata); 903 break; 904 case NL80211_IFTYPE_AP_VLAN: 905 add_vlan_files(sdata); 906 break; 907 default: 908 break; 909 } 910 } 911 912 #undef DEBUGFS_ADD_MODE 913 #undef DEBUGFS_ADD 914 915 #define DEBUGFS_ADD_MODE(dentry, name, mode) \ 916 debugfs_create_file(#name, mode, dentry, \ 917 link, &link_##name##_ops) 918 919 #define DEBUGFS_ADD(dentry, name) DEBUGFS_ADD_MODE(dentry, name, 0400) 920 921 static void add_link_files(struct ieee80211_link_data *link, 922 struct dentry *dentry) 923 { 924 DEBUGFS_ADD(dentry, txpower); 925 DEBUGFS_ADD(dentry, user_power_level); 926 DEBUGFS_ADD(dentry, ap_power_level); 927 928 switch (link->sdata->vif.type) { 929 case NL80211_IFTYPE_STATION: 930 DEBUGFS_ADD_MODE(dentry, smps, 0600); 931 break; 932 default: 933 break; 934 } 935 } 936 937 void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) 938 { 939 char buf[10+IFNAMSIZ]; 940 941 sprintf(buf, "netdev:%s", sdata->name); 942 sdata->vif.debugfs_dir = debugfs_create_dir(buf, 943 sdata->local->hw.wiphy->debugfsdir); 944 sdata->debugfs.subdir_stations = debugfs_create_dir("stations", 945 sdata->vif.debugfs_dir); 946 add_files(sdata); 947 948 if (!(sdata->local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO)) 949 add_link_files(&sdata->deflink, sdata->vif.debugfs_dir); 950 } 951 952 void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) 953 { 954 if (!sdata->vif.debugfs_dir) 955 return; 956 957 debugfs_remove_recursive(sdata->vif.debugfs_dir); 958 sdata->vif.debugfs_dir = NULL; 959 sdata->debugfs.subdir_stations = NULL; 960 } 961 962 void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) 963 { 964 struct dentry *dir; 965 char buf[10 + IFNAMSIZ]; 966 967 dir = sdata->vif.debugfs_dir; 968 969 if (IS_ERR_OR_NULL(dir)) 970 return; 971 972 sprintf(buf, "netdev:%s", sdata->name); 973 debugfs_rename(dir->d_parent, dir, dir->d_parent, buf); 974 } 975 976 void ieee80211_link_debugfs_add(struct ieee80211_link_data *link) 977 { 978 char link_dir_name[10]; 979 980 if (WARN_ON(!link->sdata->vif.debugfs_dir)) 981 return; 982 983 /* For now, this should not be called for non-MLO capable drivers */ 984 if (WARN_ON(!(link->sdata->local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO))) 985 return; 986 987 snprintf(link_dir_name, sizeof(link_dir_name), 988 "link-%d", link->link_id); 989 990 link->debugfs_dir = 991 debugfs_create_dir(link_dir_name, 992 link->sdata->vif.debugfs_dir); 993 994 DEBUGFS_ADD(link->debugfs_dir, addr); 995 add_link_files(link, link->debugfs_dir); 996 } 997 998 void ieee80211_link_debugfs_remove(struct ieee80211_link_data *link) 999 { 1000 if (!link->sdata->vif.debugfs_dir || !link->debugfs_dir) { 1001 link->debugfs_dir = NULL; 1002 return; 1003 } 1004 1005 if (link->debugfs_dir == link->sdata->vif.debugfs_dir) { 1006 WARN_ON(link != &link->sdata->deflink); 1007 link->debugfs_dir = NULL; 1008 return; 1009 } 1010 1011 debugfs_remove_recursive(link->debugfs_dir); 1012 link->debugfs_dir = NULL; 1013 } 1014 1015 void ieee80211_link_debugfs_drv_add(struct ieee80211_link_data *link) 1016 { 1017 if (WARN_ON(!link->debugfs_dir)) 1018 return; 1019 1020 drv_link_add_debugfs(link->sdata->local, link->sdata, 1021 link->conf, link->debugfs_dir); 1022 } 1023 1024 void ieee80211_link_debugfs_drv_remove(struct ieee80211_link_data *link) 1025 { 1026 if (!link || !link->debugfs_dir) 1027 return; 1028 1029 if (WARN_ON(link->debugfs_dir == link->sdata->vif.debugfs_dir)) 1030 return; 1031 1032 /* Recreate the directory excluding the driver data */ 1033 debugfs_remove_recursive(link->debugfs_dir); 1034 link->debugfs_dir = NULL; 1035 1036 ieee80211_link_debugfs_add(link); 1037 } 1038