1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * This file is part of wl1271 4 * 5 * Copyright (C) 2009 Nokia Corporation 6 * 7 * Contact: Luciano Coelho <luciano.coelho@nokia.com> 8 */ 9 10 #include "debugfs.h" 11 12 #include <linux/skbuff.h> 13 #include <linux/slab.h> 14 #include <linux/module.h> 15 #include <linux/pm_runtime.h> 16 17 #include "wlcore.h" 18 #include "debug.h" 19 #include "acx.h" 20 #include "ps.h" 21 #include "io.h" 22 #include "tx.h" 23 #include "hw_ops.h" 24 25 /* ms */ 26 #define WL1271_DEBUGFS_STATS_LIFETIME 1000 27 28 #define WLCORE_MAX_BLOCK_SIZE ((size_t)(4*PAGE_SIZE)) 29 30 /* debugfs macros idea from mac80211 */ 31 int wl1271_format_buffer(char __user *userbuf, size_t count, 32 loff_t *ppos, char *fmt, ...) 33 { 34 va_list args; 35 char buf[DEBUGFS_FORMAT_BUFFER_SIZE]; 36 int res; 37 38 va_start(args, fmt); 39 res = vscnprintf(buf, sizeof(buf), fmt, args); 40 va_end(args); 41 42 return simple_read_from_buffer(userbuf, count, ppos, buf, res); 43 } 44 EXPORT_SYMBOL_GPL(wl1271_format_buffer); 45 46 void wl1271_debugfs_update_stats(struct wl1271 *wl) 47 { 48 int ret; 49 50 mutex_lock(&wl->mutex); 51 52 if (unlikely(wl->state != WLCORE_STATE_ON)) 53 goto out; 54 55 ret = pm_runtime_get_sync(wl->dev); 56 if (ret < 0) { 57 pm_runtime_put_noidle(wl->dev); 58 goto out; 59 } 60 61 if (!wl->plt && 62 time_after(jiffies, wl->stats.fw_stats_update + 63 msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) { 64 wl1271_acx_statistics(wl, wl->stats.fw_stats); 65 wl->stats.fw_stats_update = jiffies; 66 } 67 68 pm_runtime_mark_last_busy(wl->dev); 69 pm_runtime_put_autosuspend(wl->dev); 70 71 out: 72 mutex_unlock(&wl->mutex); 73 } 74 EXPORT_SYMBOL_GPL(wl1271_debugfs_update_stats); 75 76 DEBUGFS_READONLY_FILE(retry_count, "%u", wl->stats.retry_count); 77 DEBUGFS_READONLY_FILE(excessive_retries, "%u", 78 wl->stats.excessive_retries); 79 80 static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf, 81 size_t count, loff_t *ppos) 82 { 83 struct wl1271 *wl = file->private_data; 84 u32 queue_len; 85 char buf[20]; 86 int res; 87 88 queue_len = wl1271_tx_total_queue_count(wl); 89 90 res = scnprintf(buf, sizeof(buf), "%u\n", queue_len); 91 return simple_read_from_buffer(userbuf, count, ppos, buf, res); 92 } 93 94 static const struct file_operations tx_queue_len_ops = { 95 .read = tx_queue_len_read, 96 .open = simple_open, 97 .llseek = default_llseek, 98 }; 99 100 static void chip_op_handler(struct wl1271 *wl, unsigned long value, 101 void *arg) 102 { 103 int ret; 104 int (*chip_op) (struct wl1271 *wl); 105 106 if (!arg) { 107 wl1271_warning("debugfs chip_op_handler with no callback"); 108 return; 109 } 110 111 ret = pm_runtime_get_sync(wl->dev); 112 if (ret < 0) { 113 pm_runtime_put_noidle(wl->dev); 114 115 return; 116 } 117 118 chip_op = arg; 119 chip_op(wl); 120 121 pm_runtime_mark_last_busy(wl->dev); 122 pm_runtime_put_autosuspend(wl->dev); 123 } 124 125 #define WL12XX_CONF_DEBUGFS(param, conf_sub_struct, \ 126 min_val, max_val, write_handler_locked, \ 127 write_handler_arg) \ 128 static ssize_t param##_read(struct file *file, \ 129 char __user *user_buf, \ 130 size_t count, loff_t *ppos) \ 131 { \ 132 struct wl1271 *wl = file->private_data; \ 133 return wl1271_format_buffer(user_buf, count, \ 134 ppos, "%d\n", \ 135 wl->conf.conf_sub_struct.param); \ 136 } \ 137 \ 138 static ssize_t param##_write(struct file *file, \ 139 const char __user *user_buf, \ 140 size_t count, loff_t *ppos) \ 141 { \ 142 struct wl1271 *wl = file->private_data; \ 143 unsigned long value; \ 144 int ret; \ 145 \ 146 ret = kstrtoul_from_user(user_buf, count, 10, &value); \ 147 if (ret < 0) { \ 148 wl1271_warning("illegal value for " #param); \ 149 return -EINVAL; \ 150 } \ 151 \ 152 if (value < min_val || value > max_val) { \ 153 wl1271_warning(#param " is not in valid range"); \ 154 return -ERANGE; \ 155 } \ 156 \ 157 mutex_lock(&wl->mutex); \ 158 wl->conf.conf_sub_struct.param = value; \ 159 \ 160 write_handler_locked(wl, value, write_handler_arg); \ 161 \ 162 mutex_unlock(&wl->mutex); \ 163 return count; \ 164 } \ 165 \ 166 static const struct file_operations param##_ops = { \ 167 .read = param##_read, \ 168 .write = param##_write, \ 169 .open = simple_open, \ 170 .llseek = default_llseek, \ 171 }; 172 173 WL12XX_CONF_DEBUGFS(irq_pkt_threshold, rx, 0, 65535, 174 chip_op_handler, wl1271_acx_init_rx_interrupt) 175 WL12XX_CONF_DEBUGFS(irq_blk_threshold, rx, 0, 65535, 176 chip_op_handler, wl1271_acx_init_rx_interrupt) 177 WL12XX_CONF_DEBUGFS(irq_timeout, rx, 0, 100, 178 chip_op_handler, wl1271_acx_init_rx_interrupt) 179 180 static ssize_t gpio_power_read(struct file *file, char __user *user_buf, 181 size_t count, loff_t *ppos) 182 { 183 struct wl1271 *wl = file->private_data; 184 bool state = test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); 185 186 int res; 187 char buf[10]; 188 189 res = scnprintf(buf, sizeof(buf), "%d\n", state); 190 191 return simple_read_from_buffer(user_buf, count, ppos, buf, res); 192 } 193 194 static ssize_t gpio_power_write(struct file *file, 195 const char __user *user_buf, 196 size_t count, loff_t *ppos) 197 { 198 struct wl1271 *wl = file->private_data; 199 unsigned long value; 200 int ret; 201 202 ret = kstrtoul_from_user(user_buf, count, 10, &value); 203 if (ret < 0) { 204 wl1271_warning("illegal value in gpio_power"); 205 return -EINVAL; 206 } 207 208 mutex_lock(&wl->mutex); 209 210 if (value) 211 wl1271_power_on(wl); 212 else 213 wl1271_power_off(wl); 214 215 mutex_unlock(&wl->mutex); 216 return count; 217 } 218 219 static const struct file_operations gpio_power_ops = { 220 .read = gpio_power_read, 221 .write = gpio_power_write, 222 .open = simple_open, 223 .llseek = default_llseek, 224 }; 225 226 static ssize_t start_recovery_write(struct file *file, 227 const char __user *user_buf, 228 size_t count, loff_t *ppos) 229 { 230 struct wl1271 *wl = file->private_data; 231 232 mutex_lock(&wl->mutex); 233 wl12xx_queue_recovery_work(wl); 234 mutex_unlock(&wl->mutex); 235 236 return count; 237 } 238 239 static const struct file_operations start_recovery_ops = { 240 .write = start_recovery_write, 241 .open = simple_open, 242 .llseek = default_llseek, 243 }; 244 245 static ssize_t dynamic_ps_timeout_read(struct file *file, char __user *user_buf, 246 size_t count, loff_t *ppos) 247 { 248 struct wl1271 *wl = file->private_data; 249 250 return wl1271_format_buffer(user_buf, count, 251 ppos, "%d\n", 252 wl->conf.conn.dynamic_ps_timeout); 253 } 254 255 static ssize_t dynamic_ps_timeout_write(struct file *file, 256 const char __user *user_buf, 257 size_t count, loff_t *ppos) 258 { 259 struct wl1271 *wl = file->private_data; 260 struct wl12xx_vif *wlvif; 261 unsigned long value; 262 int ret; 263 264 ret = kstrtoul_from_user(user_buf, count, 10, &value); 265 if (ret < 0) { 266 wl1271_warning("illegal value in dynamic_ps"); 267 return -EINVAL; 268 } 269 270 if (value < 1 || value > 65535) { 271 wl1271_warning("dynamic_ps_timeout is not in valid range"); 272 return -ERANGE; 273 } 274 275 mutex_lock(&wl->mutex); 276 277 wl->conf.conn.dynamic_ps_timeout = value; 278 279 if (unlikely(wl->state != WLCORE_STATE_ON)) 280 goto out; 281 282 ret = pm_runtime_get_sync(wl->dev); 283 if (ret < 0) { 284 pm_runtime_put_noidle(wl->dev); 285 goto out; 286 } 287 288 /* In case we're already in PSM, trigger it again to set new timeout 289 * immediately without waiting for re-association 290 */ 291 292 wl12xx_for_each_wlvif_sta(wl, wlvif) { 293 if (test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) 294 wl1271_ps_set_mode(wl, wlvif, STATION_AUTO_PS_MODE); 295 } 296 297 pm_runtime_mark_last_busy(wl->dev); 298 pm_runtime_put_autosuspend(wl->dev); 299 300 out: 301 mutex_unlock(&wl->mutex); 302 return count; 303 } 304 305 static const struct file_operations dynamic_ps_timeout_ops = { 306 .read = dynamic_ps_timeout_read, 307 .write = dynamic_ps_timeout_write, 308 .open = simple_open, 309 .llseek = default_llseek, 310 }; 311 312 static ssize_t forced_ps_read(struct file *file, char __user *user_buf, 313 size_t count, loff_t *ppos) 314 { 315 struct wl1271 *wl = file->private_data; 316 317 return wl1271_format_buffer(user_buf, count, 318 ppos, "%d\n", 319 wl->conf.conn.forced_ps); 320 } 321 322 static ssize_t forced_ps_write(struct file *file, 323 const char __user *user_buf, 324 size_t count, loff_t *ppos) 325 { 326 struct wl1271 *wl = file->private_data; 327 struct wl12xx_vif *wlvif; 328 unsigned long value; 329 int ret, ps_mode; 330 331 ret = kstrtoul_from_user(user_buf, count, 10, &value); 332 if (ret < 0) { 333 wl1271_warning("illegal value in forced_ps"); 334 return -EINVAL; 335 } 336 337 if (value != 1 && value != 0) { 338 wl1271_warning("forced_ps should be either 0 or 1"); 339 return -ERANGE; 340 } 341 342 mutex_lock(&wl->mutex); 343 344 if (wl->conf.conn.forced_ps == value) 345 goto out; 346 347 wl->conf.conn.forced_ps = value; 348 349 if (unlikely(wl->state != WLCORE_STATE_ON)) 350 goto out; 351 352 ret = pm_runtime_get_sync(wl->dev); 353 if (ret < 0) { 354 pm_runtime_put_noidle(wl->dev); 355 goto out; 356 } 357 358 /* In case we're already in PSM, trigger it again to switch mode 359 * immediately without waiting for re-association 360 */ 361 362 ps_mode = value ? STATION_POWER_SAVE_MODE : STATION_AUTO_PS_MODE; 363 364 wl12xx_for_each_wlvif_sta(wl, wlvif) { 365 if (test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) 366 wl1271_ps_set_mode(wl, wlvif, ps_mode); 367 } 368 369 pm_runtime_mark_last_busy(wl->dev); 370 pm_runtime_put_autosuspend(wl->dev); 371 372 out: 373 mutex_unlock(&wl->mutex); 374 return count; 375 } 376 377 static const struct file_operations forced_ps_ops = { 378 .read = forced_ps_read, 379 .write = forced_ps_write, 380 .open = simple_open, 381 .llseek = default_llseek, 382 }; 383 384 static ssize_t split_scan_timeout_read(struct file *file, char __user *user_buf, 385 size_t count, loff_t *ppos) 386 { 387 struct wl1271 *wl = file->private_data; 388 389 return wl1271_format_buffer(user_buf, count, 390 ppos, "%d\n", 391 wl->conf.scan.split_scan_timeout / 1000); 392 } 393 394 static ssize_t split_scan_timeout_write(struct file *file, 395 const char __user *user_buf, 396 size_t count, loff_t *ppos) 397 { 398 struct wl1271 *wl = file->private_data; 399 unsigned long value; 400 int ret; 401 402 ret = kstrtoul_from_user(user_buf, count, 10, &value); 403 if (ret < 0) { 404 wl1271_warning("illegal value in split_scan_timeout"); 405 return -EINVAL; 406 } 407 408 if (value == 0) 409 wl1271_info("split scan will be disabled"); 410 411 mutex_lock(&wl->mutex); 412 413 wl->conf.scan.split_scan_timeout = value * 1000; 414 415 mutex_unlock(&wl->mutex); 416 return count; 417 } 418 419 static const struct file_operations split_scan_timeout_ops = { 420 .read = split_scan_timeout_read, 421 .write = split_scan_timeout_write, 422 .open = simple_open, 423 .llseek = default_llseek, 424 }; 425 426 static ssize_t driver_state_read(struct file *file, char __user *user_buf, 427 size_t count, loff_t *ppos) 428 { 429 struct wl1271 *wl = file->private_data; 430 int res = 0; 431 ssize_t ret; 432 char *buf; 433 struct wl12xx_vif *wlvif; 434 435 #define DRIVER_STATE_BUF_LEN 1024 436 437 buf = kmalloc(DRIVER_STATE_BUF_LEN, GFP_KERNEL); 438 if (!buf) 439 return -ENOMEM; 440 441 mutex_lock(&wl->mutex); 442 443 #define DRIVER_STATE_PRINT(x, fmt) \ 444 (res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\ 445 #x " = " fmt "\n", wl->x)) 446 447 #define DRIVER_STATE_PRINT_GENERIC(x, fmt, args...) \ 448 (res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\ 449 #x " = " fmt "\n", args)) 450 451 #define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld") 452 #define DRIVER_STATE_PRINT_INT(x) DRIVER_STATE_PRINT(x, "%d") 453 #define DRIVER_STATE_PRINT_STR(x) DRIVER_STATE_PRINT(x, "%s") 454 #define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx") 455 #define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x") 456 457 wl12xx_for_each_wlvif_sta(wl, wlvif) { 458 if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) 459 continue; 460 461 DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel, 462 wlvif->p2p ? "P2P-CL" : "STA"); 463 } 464 465 wl12xx_for_each_wlvif_ap(wl, wlvif) 466 DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel, 467 wlvif->p2p ? "P2P-GO" : "AP"); 468 469 DRIVER_STATE_PRINT_INT(tx_blocks_available); 470 DRIVER_STATE_PRINT_INT(tx_allocated_blocks); 471 DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]); 472 DRIVER_STATE_PRINT_INT(tx_allocated_pkts[1]); 473 DRIVER_STATE_PRINT_INT(tx_allocated_pkts[2]); 474 DRIVER_STATE_PRINT_INT(tx_allocated_pkts[3]); 475 DRIVER_STATE_PRINT_INT(tx_frames_cnt); 476 DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]); 477 DRIVER_STATE_PRINT_INT(tx_queue_count[0]); 478 DRIVER_STATE_PRINT_INT(tx_queue_count[1]); 479 DRIVER_STATE_PRINT_INT(tx_queue_count[2]); 480 DRIVER_STATE_PRINT_INT(tx_queue_count[3]); 481 DRIVER_STATE_PRINT_INT(tx_packets_count); 482 DRIVER_STATE_PRINT_INT(tx_results_count); 483 DRIVER_STATE_PRINT_LHEX(flags); 484 DRIVER_STATE_PRINT_INT(tx_blocks_freed); 485 DRIVER_STATE_PRINT_INT(rx_counter); 486 DRIVER_STATE_PRINT_INT(state); 487 DRIVER_STATE_PRINT_INT(band); 488 DRIVER_STATE_PRINT_INT(power_level); 489 DRIVER_STATE_PRINT_INT(sg_enabled); 490 DRIVER_STATE_PRINT_INT(enable_11a); 491 DRIVER_STATE_PRINT_INT(noise); 492 DRIVER_STATE_PRINT_LHEX(ap_fw_ps_map); 493 DRIVER_STATE_PRINT_LHEX(ap_ps_map); 494 DRIVER_STATE_PRINT_HEX(quirks); 495 DRIVER_STATE_PRINT_HEX(irq); 496 /* TODO: ref_clock and tcxo_clock were moved to wl12xx priv */ 497 DRIVER_STATE_PRINT_HEX(hw_pg_ver); 498 DRIVER_STATE_PRINT_HEX(irq_flags); 499 DRIVER_STATE_PRINT_HEX(chip.id); 500 DRIVER_STATE_PRINT_STR(chip.fw_ver_str); 501 DRIVER_STATE_PRINT_STR(chip.phy_fw_ver_str); 502 DRIVER_STATE_PRINT_INT(recovery_count); 503 504 #undef DRIVER_STATE_PRINT_INT 505 #undef DRIVER_STATE_PRINT_LONG 506 #undef DRIVER_STATE_PRINT_HEX 507 #undef DRIVER_STATE_PRINT_LHEX 508 #undef DRIVER_STATE_PRINT_STR 509 #undef DRIVER_STATE_PRINT 510 #undef DRIVER_STATE_BUF_LEN 511 512 mutex_unlock(&wl->mutex); 513 514 ret = simple_read_from_buffer(user_buf, count, ppos, buf, res); 515 kfree(buf); 516 return ret; 517 } 518 519 static const struct file_operations driver_state_ops = { 520 .read = driver_state_read, 521 .open = simple_open, 522 .llseek = default_llseek, 523 }; 524 525 static ssize_t vifs_state_read(struct file *file, char __user *user_buf, 526 size_t count, loff_t *ppos) 527 { 528 struct wl1271 *wl = file->private_data; 529 struct wl12xx_vif *wlvif; 530 int ret, res = 0; 531 const int buf_size = 4096; 532 char *buf; 533 char tmp_buf[64]; 534 535 buf = kzalloc(buf_size, GFP_KERNEL); 536 if (!buf) 537 return -ENOMEM; 538 539 mutex_lock(&wl->mutex); 540 541 #define VIF_STATE_PRINT(x, fmt) \ 542 (res += scnprintf(buf + res, buf_size - res, \ 543 #x " = " fmt "\n", wlvif->x)) 544 545 #define VIF_STATE_PRINT_LONG(x) VIF_STATE_PRINT(x, "%ld") 546 #define VIF_STATE_PRINT_INT(x) VIF_STATE_PRINT(x, "%d") 547 #define VIF_STATE_PRINT_STR(x) VIF_STATE_PRINT(x, "%s") 548 #define VIF_STATE_PRINT_LHEX(x) VIF_STATE_PRINT(x, "0x%lx") 549 #define VIF_STATE_PRINT_LLHEX(x) VIF_STATE_PRINT(x, "0x%llx") 550 #define VIF_STATE_PRINT_HEX(x) VIF_STATE_PRINT(x, "0x%x") 551 552 #define VIF_STATE_PRINT_NSTR(x, len) \ 553 do { \ 554 memset(tmp_buf, 0, sizeof(tmp_buf)); \ 555 memcpy(tmp_buf, wlvif->x, \ 556 min_t(u8, len, sizeof(tmp_buf) - 1)); \ 557 res += scnprintf(buf + res, buf_size - res, \ 558 #x " = %s\n", tmp_buf); \ 559 } while (0) 560 561 wl12xx_for_each_wlvif(wl, wlvif) { 562 VIF_STATE_PRINT_INT(role_id); 563 VIF_STATE_PRINT_INT(bss_type); 564 VIF_STATE_PRINT_LHEX(flags); 565 VIF_STATE_PRINT_INT(p2p); 566 VIF_STATE_PRINT_INT(dev_role_id); 567 VIF_STATE_PRINT_INT(dev_hlid); 568 569 if (wlvif->bss_type == BSS_TYPE_STA_BSS || 570 wlvif->bss_type == BSS_TYPE_IBSS) { 571 VIF_STATE_PRINT_INT(sta.hlid); 572 VIF_STATE_PRINT_INT(sta.basic_rate_idx); 573 VIF_STATE_PRINT_INT(sta.ap_rate_idx); 574 VIF_STATE_PRINT_INT(sta.p2p_rate_idx); 575 VIF_STATE_PRINT_INT(sta.qos); 576 } else { 577 VIF_STATE_PRINT_INT(ap.global_hlid); 578 VIF_STATE_PRINT_INT(ap.bcast_hlid); 579 VIF_STATE_PRINT_LHEX(ap.sta_hlid_map[0]); 580 VIF_STATE_PRINT_INT(ap.mgmt_rate_idx); 581 VIF_STATE_PRINT_INT(ap.bcast_rate_idx); 582 VIF_STATE_PRINT_INT(ap.ucast_rate_idx[0]); 583 VIF_STATE_PRINT_INT(ap.ucast_rate_idx[1]); 584 VIF_STATE_PRINT_INT(ap.ucast_rate_idx[2]); 585 VIF_STATE_PRINT_INT(ap.ucast_rate_idx[3]); 586 } 587 VIF_STATE_PRINT_INT(last_tx_hlid); 588 VIF_STATE_PRINT_INT(tx_queue_count[0]); 589 VIF_STATE_PRINT_INT(tx_queue_count[1]); 590 VIF_STATE_PRINT_INT(tx_queue_count[2]); 591 VIF_STATE_PRINT_INT(tx_queue_count[3]); 592 VIF_STATE_PRINT_LHEX(links_map[0]); 593 VIF_STATE_PRINT_NSTR(ssid, wlvif->ssid_len); 594 VIF_STATE_PRINT_INT(band); 595 VIF_STATE_PRINT_INT(channel); 596 VIF_STATE_PRINT_HEX(bitrate_masks[0]); 597 VIF_STATE_PRINT_HEX(bitrate_masks[1]); 598 VIF_STATE_PRINT_HEX(basic_rate_set); 599 VIF_STATE_PRINT_HEX(basic_rate); 600 VIF_STATE_PRINT_HEX(rate_set); 601 VIF_STATE_PRINT_INT(beacon_int); 602 VIF_STATE_PRINT_INT(default_key); 603 VIF_STATE_PRINT_INT(aid); 604 VIF_STATE_PRINT_INT(psm_entry_retry); 605 VIF_STATE_PRINT_INT(power_level); 606 VIF_STATE_PRINT_INT(rssi_thold); 607 VIF_STATE_PRINT_INT(last_rssi_event); 608 VIF_STATE_PRINT_INT(ba_support); 609 VIF_STATE_PRINT_INT(ba_allowed); 610 VIF_STATE_PRINT_LLHEX(total_freed_pkts); 611 } 612 613 #undef VIF_STATE_PRINT_INT 614 #undef VIF_STATE_PRINT_LONG 615 #undef VIF_STATE_PRINT_HEX 616 #undef VIF_STATE_PRINT_LHEX 617 #undef VIF_STATE_PRINT_LLHEX 618 #undef VIF_STATE_PRINT_STR 619 #undef VIF_STATE_PRINT_NSTR 620 #undef VIF_STATE_PRINT 621 622 mutex_unlock(&wl->mutex); 623 624 ret = simple_read_from_buffer(user_buf, count, ppos, buf, res); 625 kfree(buf); 626 return ret; 627 } 628 629 static const struct file_operations vifs_state_ops = { 630 .read = vifs_state_read, 631 .open = simple_open, 632 .llseek = default_llseek, 633 }; 634 635 static ssize_t dtim_interval_read(struct file *file, char __user *user_buf, 636 size_t count, loff_t *ppos) 637 { 638 struct wl1271 *wl = file->private_data; 639 u8 value; 640 641 if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_DTIM || 642 wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM) 643 value = wl->conf.conn.listen_interval; 644 else 645 value = 0; 646 647 return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value); 648 } 649 650 static ssize_t dtim_interval_write(struct file *file, 651 const char __user *user_buf, 652 size_t count, loff_t *ppos) 653 { 654 struct wl1271 *wl = file->private_data; 655 unsigned long value; 656 int ret; 657 658 ret = kstrtoul_from_user(user_buf, count, 10, &value); 659 if (ret < 0) { 660 wl1271_warning("illegal value for dtim_interval"); 661 return -EINVAL; 662 } 663 664 if (value < 1 || value > 10) { 665 wl1271_warning("dtim value is not in valid range"); 666 return -ERANGE; 667 } 668 669 mutex_lock(&wl->mutex); 670 671 wl->conf.conn.listen_interval = value; 672 /* for some reason there are different event types for 1 and >1 */ 673 if (value == 1) 674 wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_DTIM; 675 else 676 wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM; 677 678 /* 679 * we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only 680 * take effect on the next time we enter psm. 681 */ 682 mutex_unlock(&wl->mutex); 683 return count; 684 } 685 686 static const struct file_operations dtim_interval_ops = { 687 .read = dtim_interval_read, 688 .write = dtim_interval_write, 689 .open = simple_open, 690 .llseek = default_llseek, 691 }; 692 693 694 695 static ssize_t suspend_dtim_interval_read(struct file *file, 696 char __user *user_buf, 697 size_t count, loff_t *ppos) 698 { 699 struct wl1271 *wl = file->private_data; 700 u8 value; 701 702 if (wl->conf.conn.suspend_wake_up_event == CONF_WAKE_UP_EVENT_DTIM || 703 wl->conf.conn.suspend_wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM) 704 value = wl->conf.conn.suspend_listen_interval; 705 else 706 value = 0; 707 708 return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value); 709 } 710 711 static ssize_t suspend_dtim_interval_write(struct file *file, 712 const char __user *user_buf, 713 size_t count, loff_t *ppos) 714 { 715 struct wl1271 *wl = file->private_data; 716 unsigned long value; 717 int ret; 718 719 ret = kstrtoul_from_user(user_buf, count, 10, &value); 720 if (ret < 0) { 721 wl1271_warning("illegal value for suspend_dtim_interval"); 722 return -EINVAL; 723 } 724 725 if (value < 1 || value > 10) { 726 wl1271_warning("suspend_dtim value is not in valid range"); 727 return -ERANGE; 728 } 729 730 mutex_lock(&wl->mutex); 731 732 wl->conf.conn.suspend_listen_interval = value; 733 /* for some reason there are different event types for 1 and >1 */ 734 if (value == 1) 735 wl->conf.conn.suspend_wake_up_event = CONF_WAKE_UP_EVENT_DTIM; 736 else 737 wl->conf.conn.suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM; 738 739 mutex_unlock(&wl->mutex); 740 return count; 741 } 742 743 744 static const struct file_operations suspend_dtim_interval_ops = { 745 .read = suspend_dtim_interval_read, 746 .write = suspend_dtim_interval_write, 747 .open = simple_open, 748 .llseek = default_llseek, 749 }; 750 751 static ssize_t beacon_interval_read(struct file *file, char __user *user_buf, 752 size_t count, loff_t *ppos) 753 { 754 struct wl1271 *wl = file->private_data; 755 u8 value; 756 757 if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_BEACON || 758 wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_BEACONS) 759 value = wl->conf.conn.listen_interval; 760 else 761 value = 0; 762 763 return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value); 764 } 765 766 static ssize_t beacon_interval_write(struct file *file, 767 const char __user *user_buf, 768 size_t count, loff_t *ppos) 769 { 770 struct wl1271 *wl = file->private_data; 771 unsigned long value; 772 int ret; 773 774 ret = kstrtoul_from_user(user_buf, count, 10, &value); 775 if (ret < 0) { 776 wl1271_warning("illegal value for beacon_interval"); 777 return -EINVAL; 778 } 779 780 if (value < 1 || value > 255) { 781 wl1271_warning("beacon interval value is not in valid range"); 782 return -ERANGE; 783 } 784 785 mutex_lock(&wl->mutex); 786 787 wl->conf.conn.listen_interval = value; 788 /* for some reason there are different event types for 1 and >1 */ 789 if (value == 1) 790 wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_BEACON; 791 else 792 wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_BEACONS; 793 794 /* 795 * we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only 796 * take effect on the next time we enter psm. 797 */ 798 mutex_unlock(&wl->mutex); 799 return count; 800 } 801 802 static const struct file_operations beacon_interval_ops = { 803 .read = beacon_interval_read, 804 .write = beacon_interval_write, 805 .open = simple_open, 806 .llseek = default_llseek, 807 }; 808 809 static ssize_t rx_streaming_interval_write(struct file *file, 810 const char __user *user_buf, 811 size_t count, loff_t *ppos) 812 { 813 struct wl1271 *wl = file->private_data; 814 struct wl12xx_vif *wlvif; 815 unsigned long value; 816 int ret; 817 818 ret = kstrtoul_from_user(user_buf, count, 10, &value); 819 if (ret < 0) { 820 wl1271_warning("illegal value in rx_streaming_interval!"); 821 return -EINVAL; 822 } 823 824 /* valid values: 0, 10-100 */ 825 if (value && (value < 10 || value > 100)) { 826 wl1271_warning("value is not in range!"); 827 return -ERANGE; 828 } 829 830 mutex_lock(&wl->mutex); 831 832 wl->conf.rx_streaming.interval = value; 833 834 ret = pm_runtime_get_sync(wl->dev); 835 if (ret < 0) { 836 pm_runtime_put_noidle(wl->dev); 837 goto out; 838 } 839 840 wl12xx_for_each_wlvif_sta(wl, wlvif) { 841 wl1271_recalc_rx_streaming(wl, wlvif); 842 } 843 844 pm_runtime_mark_last_busy(wl->dev); 845 pm_runtime_put_autosuspend(wl->dev); 846 out: 847 mutex_unlock(&wl->mutex); 848 return count; 849 } 850 851 static ssize_t rx_streaming_interval_read(struct file *file, 852 char __user *userbuf, 853 size_t count, loff_t *ppos) 854 { 855 struct wl1271 *wl = file->private_data; 856 return wl1271_format_buffer(userbuf, count, ppos, 857 "%d\n", wl->conf.rx_streaming.interval); 858 } 859 860 static const struct file_operations rx_streaming_interval_ops = { 861 .read = rx_streaming_interval_read, 862 .write = rx_streaming_interval_write, 863 .open = simple_open, 864 .llseek = default_llseek, 865 }; 866 867 static ssize_t rx_streaming_always_write(struct file *file, 868 const char __user *user_buf, 869 size_t count, loff_t *ppos) 870 { 871 struct wl1271 *wl = file->private_data; 872 struct wl12xx_vif *wlvif; 873 unsigned long value; 874 int ret; 875 876 ret = kstrtoul_from_user(user_buf, count, 10, &value); 877 if (ret < 0) { 878 wl1271_warning("illegal value in rx_streaming_write!"); 879 return -EINVAL; 880 } 881 882 /* valid values: 0, 10-100 */ 883 if (!(value == 0 || value == 1)) { 884 wl1271_warning("value is not in valid!"); 885 return -EINVAL; 886 } 887 888 mutex_lock(&wl->mutex); 889 890 wl->conf.rx_streaming.always = value; 891 892 ret = pm_runtime_get_sync(wl->dev); 893 if (ret < 0) { 894 pm_runtime_put_noidle(wl->dev); 895 goto out; 896 } 897 898 wl12xx_for_each_wlvif_sta(wl, wlvif) { 899 wl1271_recalc_rx_streaming(wl, wlvif); 900 } 901 902 pm_runtime_mark_last_busy(wl->dev); 903 pm_runtime_put_autosuspend(wl->dev); 904 out: 905 mutex_unlock(&wl->mutex); 906 return count; 907 } 908 909 static ssize_t rx_streaming_always_read(struct file *file, 910 char __user *userbuf, 911 size_t count, loff_t *ppos) 912 { 913 struct wl1271 *wl = file->private_data; 914 return wl1271_format_buffer(userbuf, count, ppos, 915 "%d\n", wl->conf.rx_streaming.always); 916 } 917 918 static const struct file_operations rx_streaming_always_ops = { 919 .read = rx_streaming_always_read, 920 .write = rx_streaming_always_write, 921 .open = simple_open, 922 .llseek = default_llseek, 923 }; 924 925 static ssize_t beacon_filtering_write(struct file *file, 926 const char __user *user_buf, 927 size_t count, loff_t *ppos) 928 { 929 struct wl1271 *wl = file->private_data; 930 struct wl12xx_vif *wlvif; 931 unsigned long value; 932 int ret; 933 934 ret = kstrtoul_from_user(user_buf, count, 0, &value); 935 if (ret < 0) { 936 wl1271_warning("illegal value for beacon_filtering!"); 937 return -EINVAL; 938 } 939 940 mutex_lock(&wl->mutex); 941 942 ret = pm_runtime_get_sync(wl->dev); 943 if (ret < 0) { 944 pm_runtime_put_noidle(wl->dev); 945 goto out; 946 } 947 948 wl12xx_for_each_wlvif(wl, wlvif) { 949 ret = wl1271_acx_beacon_filter_opt(wl, wlvif, !!value); 950 } 951 952 pm_runtime_mark_last_busy(wl->dev); 953 pm_runtime_put_autosuspend(wl->dev); 954 out: 955 mutex_unlock(&wl->mutex); 956 return count; 957 } 958 959 static const struct file_operations beacon_filtering_ops = { 960 .write = beacon_filtering_write, 961 .open = simple_open, 962 .llseek = default_llseek, 963 }; 964 965 static ssize_t fw_stats_raw_read(struct file *file, 966 char __user *userbuf, 967 size_t count, loff_t *ppos) 968 { 969 struct wl1271 *wl = file->private_data; 970 971 wl1271_debugfs_update_stats(wl); 972 973 return simple_read_from_buffer(userbuf, count, ppos, 974 wl->stats.fw_stats, 975 wl->stats.fw_stats_len); 976 } 977 978 static const struct file_operations fw_stats_raw_ops = { 979 .read = fw_stats_raw_read, 980 .open = simple_open, 981 .llseek = default_llseek, 982 }; 983 984 static ssize_t sleep_auth_read(struct file *file, char __user *user_buf, 985 size_t count, loff_t *ppos) 986 { 987 struct wl1271 *wl = file->private_data; 988 989 return wl1271_format_buffer(user_buf, count, 990 ppos, "%d\n", 991 wl->sleep_auth); 992 } 993 994 static ssize_t sleep_auth_write(struct file *file, 995 const char __user *user_buf, 996 size_t count, loff_t *ppos) 997 { 998 struct wl1271 *wl = file->private_data; 999 unsigned long value; 1000 int ret; 1001 1002 ret = kstrtoul_from_user(user_buf, count, 0, &value); 1003 if (ret < 0) { 1004 wl1271_warning("illegal value in sleep_auth"); 1005 return -EINVAL; 1006 } 1007 1008 if (value > WL1271_PSM_MAX) { 1009 wl1271_warning("sleep_auth must be between 0 and %d", 1010 WL1271_PSM_MAX); 1011 return -ERANGE; 1012 } 1013 1014 mutex_lock(&wl->mutex); 1015 1016 wl->conf.conn.sta_sleep_auth = value; 1017 1018 if (unlikely(wl->state != WLCORE_STATE_ON)) { 1019 /* this will show up on "read" in case we are off */ 1020 wl->sleep_auth = value; 1021 goto out; 1022 } 1023 1024 ret = pm_runtime_get_sync(wl->dev); 1025 if (ret < 0) { 1026 pm_runtime_put_noidle(wl->dev); 1027 goto out; 1028 } 1029 1030 ret = wl1271_acx_sleep_auth(wl, value); 1031 if (ret < 0) 1032 goto out_sleep; 1033 1034 out_sleep: 1035 pm_runtime_mark_last_busy(wl->dev); 1036 pm_runtime_put_autosuspend(wl->dev); 1037 out: 1038 mutex_unlock(&wl->mutex); 1039 return count; 1040 } 1041 1042 static const struct file_operations sleep_auth_ops = { 1043 .read = sleep_auth_read, 1044 .write = sleep_auth_write, 1045 .open = simple_open, 1046 .llseek = default_llseek, 1047 }; 1048 1049 static ssize_t dev_mem_read(struct file *file, 1050 char __user *user_buf, size_t count, 1051 loff_t *ppos) 1052 { 1053 struct wl1271 *wl = file->private_data; 1054 struct wlcore_partition_set part, old_part; 1055 size_t bytes = count; 1056 int ret; 1057 char *buf; 1058 1059 /* only requests of dword-aligned size and offset are supported */ 1060 if (bytes % 4) 1061 return -EINVAL; 1062 1063 if (*ppos % 4) 1064 return -EINVAL; 1065 1066 /* function should return in reasonable time */ 1067 bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE); 1068 1069 if (bytes == 0) 1070 return -EINVAL; 1071 1072 memset(&part, 0, sizeof(part)); 1073 part.mem.start = *ppos; 1074 part.mem.size = bytes; 1075 1076 buf = kmalloc(bytes, GFP_KERNEL); 1077 if (!buf) 1078 return -ENOMEM; 1079 1080 mutex_lock(&wl->mutex); 1081 1082 if (unlikely(wl->state == WLCORE_STATE_OFF)) { 1083 ret = -EFAULT; 1084 goto skip_read; 1085 } 1086 1087 /* 1088 * Don't fail if elp_wakeup returns an error, so the device's memory 1089 * could be read even if the FW crashed 1090 */ 1091 pm_runtime_get_sync(wl->dev); 1092 1093 /* store current partition and switch partition */ 1094 memcpy(&old_part, &wl->curr_part, sizeof(old_part)); 1095 ret = wlcore_set_partition(wl, &part); 1096 if (ret < 0) 1097 goto part_err; 1098 1099 ret = wlcore_raw_read(wl, 0, buf, bytes, false); 1100 if (ret < 0) 1101 goto read_err; 1102 1103 read_err: 1104 /* recover partition */ 1105 ret = wlcore_set_partition(wl, &old_part); 1106 if (ret < 0) 1107 goto part_err; 1108 1109 part_err: 1110 pm_runtime_mark_last_busy(wl->dev); 1111 pm_runtime_put_autosuspend(wl->dev); 1112 1113 skip_read: 1114 mutex_unlock(&wl->mutex); 1115 1116 if (ret == 0) { 1117 ret = copy_to_user(user_buf, buf, bytes); 1118 if (ret < bytes) { 1119 bytes -= ret; 1120 *ppos += bytes; 1121 ret = 0; 1122 } else { 1123 ret = -EFAULT; 1124 } 1125 } 1126 1127 kfree(buf); 1128 1129 return ((ret == 0) ? bytes : ret); 1130 } 1131 1132 static ssize_t dev_mem_write(struct file *file, const char __user *user_buf, 1133 size_t count, loff_t *ppos) 1134 { 1135 struct wl1271 *wl = file->private_data; 1136 struct wlcore_partition_set part, old_part; 1137 size_t bytes = count; 1138 int ret; 1139 char *buf; 1140 1141 /* only requests of dword-aligned size and offset are supported */ 1142 if (bytes % 4) 1143 return -EINVAL; 1144 1145 if (*ppos % 4) 1146 return -EINVAL; 1147 1148 /* function should return in reasonable time */ 1149 bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE); 1150 1151 if (bytes == 0) 1152 return -EINVAL; 1153 1154 memset(&part, 0, sizeof(part)); 1155 part.mem.start = *ppos; 1156 part.mem.size = bytes; 1157 1158 buf = memdup_user(user_buf, bytes); 1159 if (IS_ERR(buf)) 1160 return PTR_ERR(buf); 1161 1162 mutex_lock(&wl->mutex); 1163 1164 if (unlikely(wl->state == WLCORE_STATE_OFF)) { 1165 ret = -EFAULT; 1166 goto skip_write; 1167 } 1168 1169 /* 1170 * Don't fail if elp_wakeup returns an error, so the device's memory 1171 * could be read even if the FW crashed 1172 */ 1173 pm_runtime_get_sync(wl->dev); 1174 1175 /* store current partition and switch partition */ 1176 memcpy(&old_part, &wl->curr_part, sizeof(old_part)); 1177 ret = wlcore_set_partition(wl, &part); 1178 if (ret < 0) 1179 goto part_err; 1180 1181 ret = wlcore_raw_write(wl, 0, buf, bytes, false); 1182 if (ret < 0) 1183 goto write_err; 1184 1185 write_err: 1186 /* recover partition */ 1187 ret = wlcore_set_partition(wl, &old_part); 1188 if (ret < 0) 1189 goto part_err; 1190 1191 part_err: 1192 pm_runtime_mark_last_busy(wl->dev); 1193 pm_runtime_put_autosuspend(wl->dev); 1194 1195 skip_write: 1196 mutex_unlock(&wl->mutex); 1197 1198 if (ret == 0) 1199 *ppos += bytes; 1200 1201 kfree(buf); 1202 1203 return ((ret == 0) ? bytes : ret); 1204 } 1205 1206 static loff_t dev_mem_seek(struct file *file, loff_t offset, int orig) 1207 { 1208 /* only requests of dword-aligned size and offset are supported */ 1209 if (offset % 4) 1210 return -EINVAL; 1211 1212 return no_seek_end_llseek(file, offset, orig); 1213 } 1214 1215 static const struct file_operations dev_mem_ops = { 1216 .open = simple_open, 1217 .read = dev_mem_read, 1218 .write = dev_mem_write, 1219 .llseek = dev_mem_seek, 1220 }; 1221 1222 static ssize_t fw_logger_read(struct file *file, char __user *user_buf, 1223 size_t count, loff_t *ppos) 1224 { 1225 struct wl1271 *wl = file->private_data; 1226 1227 return wl1271_format_buffer(user_buf, count, 1228 ppos, "%d\n", 1229 wl->conf.fwlog.output); 1230 } 1231 1232 static ssize_t fw_logger_write(struct file *file, 1233 const char __user *user_buf, 1234 size_t count, loff_t *ppos) 1235 { 1236 struct wl1271 *wl = file->private_data; 1237 unsigned long value; 1238 int ret; 1239 1240 ret = kstrtoul_from_user(user_buf, count, 0, &value); 1241 if (ret < 0) { 1242 wl1271_warning("illegal value in fw_logger"); 1243 return -EINVAL; 1244 } 1245 1246 if ((value > 2) || (value == 0)) { 1247 wl1271_warning("fw_logger value must be 1-UART 2-SDIO"); 1248 return -ERANGE; 1249 } 1250 1251 if (wl->conf.fwlog.output == 0) { 1252 wl1271_warning("invalid operation - fw logger disabled by default, please change mode via wlconf"); 1253 return -EINVAL; 1254 } 1255 1256 mutex_lock(&wl->mutex); 1257 ret = pm_runtime_get_sync(wl->dev); 1258 if (ret < 0) { 1259 pm_runtime_put_noidle(wl->dev); 1260 count = ret; 1261 goto out; 1262 } 1263 1264 wl->conf.fwlog.output = value; 1265 1266 ret = wl12xx_cmd_config_fwlog(wl); 1267 1268 pm_runtime_mark_last_busy(wl->dev); 1269 pm_runtime_put_autosuspend(wl->dev); 1270 1271 out: 1272 mutex_unlock(&wl->mutex); 1273 return count; 1274 } 1275 1276 static const struct file_operations fw_logger_ops = { 1277 .open = simple_open, 1278 .read = fw_logger_read, 1279 .write = fw_logger_write, 1280 .llseek = default_llseek, 1281 }; 1282 1283 static void wl1271_debugfs_add_files(struct wl1271 *wl, 1284 struct dentry *rootdir) 1285 { 1286 struct dentry *streaming; 1287 1288 DEBUGFS_ADD(tx_queue_len, rootdir); 1289 DEBUGFS_ADD(retry_count, rootdir); 1290 DEBUGFS_ADD(excessive_retries, rootdir); 1291 1292 DEBUGFS_ADD(gpio_power, rootdir); 1293 DEBUGFS_ADD(start_recovery, rootdir); 1294 DEBUGFS_ADD(driver_state, rootdir); 1295 DEBUGFS_ADD(vifs_state, rootdir); 1296 DEBUGFS_ADD(dtim_interval, rootdir); 1297 DEBUGFS_ADD(suspend_dtim_interval, rootdir); 1298 DEBUGFS_ADD(beacon_interval, rootdir); 1299 DEBUGFS_ADD(beacon_filtering, rootdir); 1300 DEBUGFS_ADD(dynamic_ps_timeout, rootdir); 1301 DEBUGFS_ADD(forced_ps, rootdir); 1302 DEBUGFS_ADD(split_scan_timeout, rootdir); 1303 DEBUGFS_ADD(irq_pkt_threshold, rootdir); 1304 DEBUGFS_ADD(irq_blk_threshold, rootdir); 1305 DEBUGFS_ADD(irq_timeout, rootdir); 1306 DEBUGFS_ADD(fw_stats_raw, rootdir); 1307 DEBUGFS_ADD(sleep_auth, rootdir); 1308 DEBUGFS_ADD(fw_logger, rootdir); 1309 1310 streaming = debugfs_create_dir("rx_streaming", rootdir); 1311 1312 DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming); 1313 DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming); 1314 1315 DEBUGFS_ADD_PREFIX(dev, mem, rootdir); 1316 } 1317 1318 void wl1271_debugfs_reset(struct wl1271 *wl) 1319 { 1320 if (!wl->stats.fw_stats) 1321 return; 1322 1323 memset(wl->stats.fw_stats, 0, wl->stats.fw_stats_len); 1324 wl->stats.retry_count = 0; 1325 wl->stats.excessive_retries = 0; 1326 } 1327 1328 int wl1271_debugfs_init(struct wl1271 *wl) 1329 { 1330 int ret; 1331 struct dentry *rootdir; 1332 1333 rootdir = debugfs_create_dir(KBUILD_MODNAME, 1334 wl->hw->wiphy->debugfsdir); 1335 1336 wl->stats.fw_stats = kzalloc(wl->stats.fw_stats_len, GFP_KERNEL); 1337 if (!wl->stats.fw_stats) { 1338 ret = -ENOMEM; 1339 goto out_remove; 1340 } 1341 1342 wl->stats.fw_stats_update = jiffies; 1343 1344 wl1271_debugfs_add_files(wl, rootdir); 1345 1346 ret = wlcore_debugfs_init(wl, rootdir); 1347 if (ret < 0) 1348 goto out_exit; 1349 1350 goto out; 1351 1352 out_exit: 1353 wl1271_debugfs_exit(wl); 1354 1355 out_remove: 1356 debugfs_remove_recursive(rootdir); 1357 1358 out: 1359 return ret; 1360 } 1361 1362 void wl1271_debugfs_exit(struct wl1271 *wl) 1363 { 1364 kfree(wl->stats.fw_stats); 1365 wl->stats.fw_stats = NULL; 1366 } 1367