1 /* 2 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. 3 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <linux/module.h> 19 #include <linux/debugfs.h> 20 #include <linux/seq_file.h> 21 #include <linux/pci.h> 22 #include <linux/rtnetlink.h> 23 #include <linux/power_supply.h> 24 #include "wil6210.h" 25 #include "wmi.h" 26 #include "txrx.h" 27 #include "pmc.h" 28 29 /* Nasty hack. Better have per device instances */ 30 static u32 mem_addr; 31 static u32 dbg_txdesc_index; 32 static u32 dbg_ring_index; /* 24+ for Rx, 0..23 for Tx */ 33 static u32 dbg_status_msg_index; 34 /* 0..wil->num_rx_status_rings-1 for Rx, wil->tx_sring_idx for Tx */ 35 static u32 dbg_sring_index; 36 37 enum dbg_off_type { 38 doff_u32 = 0, 39 doff_x32 = 1, 40 doff_ulong = 2, 41 doff_io32 = 3, 42 doff_u8 = 4 43 }; 44 45 /* offset to "wil" */ 46 struct dbg_off { 47 const char *name; 48 umode_t mode; 49 ulong off; 50 enum dbg_off_type type; 51 }; 52 53 static void wil_print_desc_edma(struct seq_file *s, struct wil6210_priv *wil, 54 struct wil_ring *ring, 55 char _s, char _h, int idx) 56 { 57 u8 num_of_descs; 58 bool has_skb = false; 59 60 if (ring->is_rx) { 61 struct wil_rx_enhanced_desc *rx_d = 62 (struct wil_rx_enhanced_desc *) 63 &ring->va[idx].rx.enhanced; 64 u16 buff_id = le16_to_cpu(rx_d->mac.buff_id); 65 66 if (wil->rx_buff_mgmt.buff_arr && 67 wil_val_in_range(buff_id, 0, wil->rx_buff_mgmt.size)) 68 has_skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb; 69 seq_printf(s, "%c", (has_skb) ? _h : _s); 70 } else { 71 struct wil_tx_enhanced_desc *d = 72 (struct wil_tx_enhanced_desc *) 73 &ring->va[idx].tx.enhanced; 74 75 num_of_descs = (u8)d->mac.d[2]; 76 has_skb = ring->ctx && ring->ctx[idx].skb; 77 if (num_of_descs >= 1) 78 seq_printf(s, "%c", has_skb ? _h : _s); 79 else 80 /* num_of_descs == 0, it's a frag in a list of descs */ 81 seq_printf(s, "%c", has_skb ? 'h' : _s); 82 } 83 } 84 85 static void wil_print_ring(struct seq_file *s, struct wil6210_priv *wil, 86 const char *name, struct wil_ring *ring, 87 char _s, char _h) 88 { 89 void __iomem *x; 90 u32 v; 91 92 seq_printf(s, "RING %s = {\n", name); 93 seq_printf(s, " pa = %pad\n", &ring->pa); 94 seq_printf(s, " va = 0x%p\n", ring->va); 95 seq_printf(s, " size = %d\n", ring->size); 96 if (wil->use_enhanced_dma_hw && ring->is_rx) 97 seq_printf(s, " swtail = %u\n", *ring->edma_rx_swtail.va); 98 else 99 seq_printf(s, " swtail = %d\n", ring->swtail); 100 seq_printf(s, " swhead = %d\n", ring->swhead); 101 if (wil->use_enhanced_dma_hw) { 102 int ring_id = ring->is_rx ? 103 WIL_RX_DESC_RING_ID : ring - wil->ring_tx; 104 /* SUBQ_CONS is a table of 32 entries, one for each Q pair. 105 * lower 16bits are for even ring_id and upper 16bits are for 106 * odd ring_id 107 */ 108 x = wmi_addr(wil, RGF_DMA_SCM_SUBQ_CONS + 4 * (ring_id / 2)); 109 v = readl_relaxed(x); 110 111 v = (ring_id % 2 ? (v >> 16) : (v & 0xffff)); 112 seq_printf(s, " hwhead = %u\n", v); 113 } 114 seq_printf(s, " hwtail = [0x%08x] -> ", ring->hwtail); 115 x = wmi_addr(wil, ring->hwtail); 116 if (x) { 117 v = readl(x); 118 seq_printf(s, "0x%08x = %d\n", v, v); 119 } else { 120 seq_puts(s, "???\n"); 121 } 122 123 if (ring->va && (ring->size <= (1 << WIL_RING_SIZE_ORDER_MAX))) { 124 uint i; 125 126 for (i = 0; i < ring->size; i++) { 127 if ((i % 128) == 0 && i != 0) 128 seq_puts(s, "\n"); 129 if (wil->use_enhanced_dma_hw) { 130 wil_print_desc_edma(s, wil, ring, _s, _h, i); 131 } else { 132 volatile struct vring_tx_desc *d = 133 &ring->va[i].tx.legacy; 134 seq_printf(s, "%c", (d->dma.status & BIT(0)) ? 135 _s : (ring->ctx[i].skb ? _h : 'h')); 136 } 137 } 138 seq_puts(s, "\n"); 139 } 140 seq_puts(s, "}\n"); 141 } 142 143 static int ring_show(struct seq_file *s, void *data) 144 { 145 uint i; 146 struct wil6210_priv *wil = s->private; 147 148 wil_print_ring(s, wil, "rx", &wil->ring_rx, 'S', '_'); 149 150 for (i = 0; i < ARRAY_SIZE(wil->ring_tx); i++) { 151 struct wil_ring *ring = &wil->ring_tx[i]; 152 struct wil_ring_tx_data *txdata = &wil->ring_tx_data[i]; 153 154 if (ring->va) { 155 int cid = wil->ring2cid_tid[i][0]; 156 int tid = wil->ring2cid_tid[i][1]; 157 u32 swhead = ring->swhead; 158 u32 swtail = ring->swtail; 159 int used = (ring->size + swhead - swtail) 160 % ring->size; 161 int avail = ring->size - used - 1; 162 char name[10]; 163 char sidle[10]; 164 /* performance monitoring */ 165 cycles_t now = get_cycles(); 166 uint64_t idle = txdata->idle * 100; 167 uint64_t total = now - txdata->begin; 168 169 if (total != 0) { 170 do_div(idle, total); 171 snprintf(sidle, sizeof(sidle), "%3d%%", 172 (int)idle); 173 } else { 174 snprintf(sidle, sizeof(sidle), "N/A"); 175 } 176 txdata->begin = now; 177 txdata->idle = 0ULL; 178 179 snprintf(name, sizeof(name), "tx_%2d", i); 180 181 if (cid < wil->max_assoc_sta) 182 seq_printf(s, 183 "\n%pM CID %d TID %d 1x%s BACK([%u] %u TU A%s) [%3d|%3d] idle %s\n", 184 wil->sta[cid].addr, cid, tid, 185 txdata->dot1x_open ? "+" : "-", 186 txdata->agg_wsize, 187 txdata->agg_timeout, 188 txdata->agg_amsdu ? "+" : "-", 189 used, avail, sidle); 190 else 191 seq_printf(s, 192 "\nBroadcast 1x%s [%3d|%3d] idle %s\n", 193 txdata->dot1x_open ? "+" : "-", 194 used, avail, sidle); 195 196 wil_print_ring(s, wil, name, ring, '_', 'H'); 197 } 198 } 199 200 return 0; 201 } 202 DEFINE_SHOW_ATTRIBUTE(ring); 203 204 static void wil_print_sring(struct seq_file *s, struct wil6210_priv *wil, 205 struct wil_status_ring *sring) 206 { 207 void __iomem *x; 208 int sring_idx = sring - wil->srings; 209 u32 v; 210 211 seq_printf(s, "Status Ring %s [ %d ] = {\n", 212 sring->is_rx ? "RX" : "TX", sring_idx); 213 seq_printf(s, " pa = %pad\n", &sring->pa); 214 seq_printf(s, " va = 0x%pK\n", sring->va); 215 seq_printf(s, " size = %d\n", sring->size); 216 seq_printf(s, " elem_size = %zu\n", sring->elem_size); 217 seq_printf(s, " swhead = %d\n", sring->swhead); 218 if (wil->use_enhanced_dma_hw) { 219 /* COMPQ_PROD is a table of 32 entries, one for each Q pair. 220 * lower 16bits are for even ring_id and upper 16bits are for 221 * odd ring_id 222 */ 223 x = wmi_addr(wil, RGF_DMA_SCM_COMPQ_PROD + 4 * (sring_idx / 2)); 224 v = readl_relaxed(x); 225 226 v = (sring_idx % 2 ? (v >> 16) : (v & 0xffff)); 227 seq_printf(s, " hwhead = %u\n", v); 228 } 229 seq_printf(s, " hwtail = [0x%08x] -> ", sring->hwtail); 230 x = wmi_addr(wil, sring->hwtail); 231 if (x) { 232 v = readl_relaxed(x); 233 seq_printf(s, "0x%08x = %d\n", v, v); 234 } else { 235 seq_puts(s, "???\n"); 236 } 237 seq_printf(s, " desc_rdy_pol = %d\n", sring->desc_rdy_pol); 238 seq_printf(s, " invalid_buff_id_cnt = %d\n", 239 sring->invalid_buff_id_cnt); 240 241 if (sring->va && (sring->size <= (1 << WIL_RING_SIZE_ORDER_MAX))) { 242 uint i; 243 244 for (i = 0; i < sring->size; i++) { 245 u32 *sdword_0 = 246 (u32 *)(sring->va + (sring->elem_size * i)); 247 248 if ((i % 128) == 0 && i != 0) 249 seq_puts(s, "\n"); 250 if (i == sring->swhead) 251 seq_printf(s, "%c", (*sdword_0 & BIT(31)) ? 252 'X' : 'x'); 253 else 254 seq_printf(s, "%c", (*sdword_0 & BIT(31)) ? 255 '1' : '0'); 256 } 257 seq_puts(s, "\n"); 258 } 259 seq_puts(s, "}\n"); 260 } 261 262 static int srings_show(struct seq_file *s, void *data) 263 { 264 struct wil6210_priv *wil = s->private; 265 int i = 0; 266 267 for (i = 0; i < WIL6210_MAX_STATUS_RINGS; i++) 268 if (wil->srings[i].va) 269 wil_print_sring(s, wil, &wil->srings[i]); 270 271 return 0; 272 } 273 DEFINE_SHOW_ATTRIBUTE(srings); 274 275 static void wil_seq_hexdump(struct seq_file *s, void *p, int len, 276 const char *prefix) 277 { 278 seq_hex_dump(s, prefix, DUMP_PREFIX_NONE, 16, 1, p, len, false); 279 } 280 281 static void wil_print_mbox_ring(struct seq_file *s, const char *prefix, 282 void __iomem *off) 283 { 284 struct wil6210_priv *wil = s->private; 285 struct wil6210_mbox_ring r; 286 int rsize; 287 uint i; 288 289 wil_halp_vote(wil); 290 291 if (wil_mem_access_lock(wil)) { 292 wil_halp_unvote(wil); 293 return; 294 } 295 296 wil_memcpy_fromio_32(&r, off, sizeof(r)); 297 wil_mbox_ring_le2cpus(&r); 298 /* 299 * we just read memory block from NIC. This memory may be 300 * garbage. Check validity before using it. 301 */ 302 rsize = r.size / sizeof(struct wil6210_mbox_ring_desc); 303 304 seq_printf(s, "ring %s = {\n", prefix); 305 seq_printf(s, " base = 0x%08x\n", r.base); 306 seq_printf(s, " size = 0x%04x bytes -> %d entries\n", r.size, rsize); 307 seq_printf(s, " tail = 0x%08x\n", r.tail); 308 seq_printf(s, " head = 0x%08x\n", r.head); 309 seq_printf(s, " entry size = %d\n", r.entry_size); 310 311 if (r.size % sizeof(struct wil6210_mbox_ring_desc)) { 312 seq_printf(s, " ??? size is not multiple of %zd, garbage?\n", 313 sizeof(struct wil6210_mbox_ring_desc)); 314 goto out; 315 } 316 317 if (!wmi_addr(wil, r.base) || 318 !wmi_addr(wil, r.tail) || 319 !wmi_addr(wil, r.head)) { 320 seq_puts(s, " ??? pointers are garbage?\n"); 321 goto out; 322 } 323 324 for (i = 0; i < rsize; i++) { 325 struct wil6210_mbox_ring_desc d; 326 struct wil6210_mbox_hdr hdr; 327 size_t delta = i * sizeof(d); 328 void __iomem *x = wil->csr + HOSTADDR(r.base) + delta; 329 330 wil_memcpy_fromio_32(&d, x, sizeof(d)); 331 332 seq_printf(s, " [%2x] %s %s%s 0x%08x", i, 333 d.sync ? "F" : "E", 334 (r.tail - r.base == delta) ? "t" : " ", 335 (r.head - r.base == delta) ? "h" : " ", 336 le32_to_cpu(d.addr)); 337 if (0 == wmi_read_hdr(wil, d.addr, &hdr)) { 338 u16 len = le16_to_cpu(hdr.len); 339 340 seq_printf(s, " -> %04x %04x %04x %02x\n", 341 le16_to_cpu(hdr.seq), len, 342 le16_to_cpu(hdr.type), hdr.flags); 343 if (len <= MAX_MBOXITEM_SIZE) { 344 unsigned char databuf[MAX_MBOXITEM_SIZE]; 345 void __iomem *src = wmi_buffer(wil, d.addr) + 346 sizeof(struct wil6210_mbox_hdr); 347 /* 348 * No need to check @src for validity - 349 * we already validated @d.addr while 350 * reading header 351 */ 352 wil_memcpy_fromio_32(databuf, src, len); 353 wil_seq_hexdump(s, databuf, len, " : "); 354 } 355 } else { 356 seq_puts(s, "\n"); 357 } 358 } 359 out: 360 seq_puts(s, "}\n"); 361 wil_mem_access_unlock(wil); 362 wil_halp_unvote(wil); 363 } 364 365 static int mbox_show(struct seq_file *s, void *data) 366 { 367 struct wil6210_priv *wil = s->private; 368 int ret; 369 370 ret = wil_pm_runtime_get(wil); 371 if (ret < 0) 372 return ret; 373 374 wil_print_mbox_ring(s, "tx", wil->csr + HOST_MBOX + 375 offsetof(struct wil6210_mbox_ctl, tx)); 376 wil_print_mbox_ring(s, "rx", wil->csr + HOST_MBOX + 377 offsetof(struct wil6210_mbox_ctl, rx)); 378 379 wil_pm_runtime_put(wil); 380 381 return 0; 382 } 383 DEFINE_SHOW_ATTRIBUTE(mbox); 384 385 static int wil_debugfs_iomem_x32_set(void *data, u64 val) 386 { 387 struct wil_debugfs_iomem_data *d = (struct 388 wil_debugfs_iomem_data *)data; 389 struct wil6210_priv *wil = d->wil; 390 int ret; 391 392 ret = wil_pm_runtime_get(wil); 393 if (ret < 0) 394 return ret; 395 396 writel(val, (void __iomem *)d->offset); 397 wmb(); /* make sure write propagated to HW */ 398 399 wil_pm_runtime_put(wil); 400 401 return 0; 402 } 403 404 static int wil_debugfs_iomem_x32_get(void *data, u64 *val) 405 { 406 struct wil_debugfs_iomem_data *d = (struct 407 wil_debugfs_iomem_data *)data; 408 struct wil6210_priv *wil = d->wil; 409 int ret; 410 411 ret = wil_pm_runtime_get(wil); 412 if (ret < 0) 413 return ret; 414 415 *val = readl((void __iomem *)d->offset); 416 417 wil_pm_runtime_put(wil); 418 419 return 0; 420 } 421 422 DEFINE_DEBUGFS_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get, 423 wil_debugfs_iomem_x32_set, "0x%08llx\n"); 424 425 static void wil_debugfs_create_iomem_x32(const char *name, umode_t mode, 426 struct dentry *parent, void *value, 427 struct wil6210_priv *wil) 428 { 429 struct wil_debugfs_iomem_data *data = &wil->dbg_data.data_arr[ 430 wil->dbg_data.iomem_data_count]; 431 432 data->wil = wil; 433 data->offset = value; 434 435 debugfs_create_file_unsafe(name, mode, parent, data, &fops_iomem_x32); 436 wil->dbg_data.iomem_data_count++; 437 } 438 439 static int wil_debugfs_ulong_set(void *data, u64 val) 440 { 441 *(ulong *)data = val; 442 return 0; 443 } 444 445 static int wil_debugfs_ulong_get(void *data, u64 *val) 446 { 447 *val = *(ulong *)data; 448 return 0; 449 } 450 451 DEFINE_DEBUGFS_ATTRIBUTE(wil_fops_ulong, wil_debugfs_ulong_get, 452 wil_debugfs_ulong_set, "0x%llx\n"); 453 454 /** 455 * wil6210_debugfs_init_offset - create set of debugfs files 456 * @wil - driver's context, used for printing 457 * @dbg - directory on the debugfs, where files will be created 458 * @base - base address used in address calculation 459 * @tbl - table with file descriptions. Should be terminated with empty element. 460 * 461 * Creates files accordingly to the @tbl. 462 */ 463 static void wil6210_debugfs_init_offset(struct wil6210_priv *wil, 464 struct dentry *dbg, void *base, 465 const struct dbg_off * const tbl) 466 { 467 int i; 468 469 for (i = 0; tbl[i].name; i++) { 470 switch (tbl[i].type) { 471 case doff_u32: 472 debugfs_create_u32(tbl[i].name, tbl[i].mode, dbg, 473 base + tbl[i].off); 474 break; 475 case doff_x32: 476 debugfs_create_x32(tbl[i].name, tbl[i].mode, dbg, 477 base + tbl[i].off); 478 break; 479 case doff_ulong: 480 debugfs_create_file_unsafe(tbl[i].name, tbl[i].mode, 481 dbg, base + tbl[i].off, 482 &wil_fops_ulong); 483 break; 484 case doff_io32: 485 wil_debugfs_create_iomem_x32(tbl[i].name, tbl[i].mode, 486 dbg, base + tbl[i].off, 487 wil); 488 break; 489 case doff_u8: 490 debugfs_create_u8(tbl[i].name, tbl[i].mode, dbg, 491 base + tbl[i].off); 492 break; 493 } 494 } 495 } 496 497 static const struct dbg_off isr_off[] = { 498 {"ICC", 0644, offsetof(struct RGF_ICR, ICC), doff_io32}, 499 {"ICR", 0644, offsetof(struct RGF_ICR, ICR), doff_io32}, 500 {"ICM", 0644, offsetof(struct RGF_ICR, ICM), doff_io32}, 501 {"ICS", 0244, offsetof(struct RGF_ICR, ICS), doff_io32}, 502 {"IMV", 0644, offsetof(struct RGF_ICR, IMV), doff_io32}, 503 {"IMS", 0244, offsetof(struct RGF_ICR, IMS), doff_io32}, 504 {"IMC", 0244, offsetof(struct RGF_ICR, IMC), doff_io32}, 505 {}, 506 }; 507 508 static void wil6210_debugfs_create_ISR(struct wil6210_priv *wil, 509 const char *name, struct dentry *parent, 510 u32 off) 511 { 512 struct dentry *d = debugfs_create_dir(name, parent); 513 514 wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr + off, 515 isr_off); 516 } 517 518 static const struct dbg_off pseudo_isr_off[] = { 519 {"CAUSE", 0444, HOSTADDR(RGF_DMA_PSEUDO_CAUSE), doff_io32}, 520 {"MASK_SW", 0444, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW), doff_io32}, 521 {"MASK_FW", 0444, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW), doff_io32}, 522 {}, 523 }; 524 525 static void wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil, 526 struct dentry *parent) 527 { 528 struct dentry *d = debugfs_create_dir("PSEUDO_ISR", parent); 529 530 wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr, 531 pseudo_isr_off); 532 } 533 534 static const struct dbg_off lgc_itr_cnt_off[] = { 535 {"TRSH", 0644, HOSTADDR(RGF_DMA_ITR_CNT_TRSH), doff_io32}, 536 {"DATA", 0644, HOSTADDR(RGF_DMA_ITR_CNT_DATA), doff_io32}, 537 {"CTL", 0644, HOSTADDR(RGF_DMA_ITR_CNT_CRL), doff_io32}, 538 {}, 539 }; 540 541 static const struct dbg_off tx_itr_cnt_off[] = { 542 {"TRSH", 0644, HOSTADDR(RGF_DMA_ITR_TX_CNT_TRSH), 543 doff_io32}, 544 {"DATA", 0644, HOSTADDR(RGF_DMA_ITR_TX_CNT_DATA), 545 doff_io32}, 546 {"CTL", 0644, HOSTADDR(RGF_DMA_ITR_TX_CNT_CTL), 547 doff_io32}, 548 {"IDL_TRSH", 0644, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_TRSH), 549 doff_io32}, 550 {"IDL_DATA", 0644, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_DATA), 551 doff_io32}, 552 {"IDL_CTL", 0644, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_CTL), 553 doff_io32}, 554 {}, 555 }; 556 557 static const struct dbg_off rx_itr_cnt_off[] = { 558 {"TRSH", 0644, HOSTADDR(RGF_DMA_ITR_RX_CNT_TRSH), 559 doff_io32}, 560 {"DATA", 0644, HOSTADDR(RGF_DMA_ITR_RX_CNT_DATA), 561 doff_io32}, 562 {"CTL", 0644, HOSTADDR(RGF_DMA_ITR_RX_CNT_CTL), 563 doff_io32}, 564 {"IDL_TRSH", 0644, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_TRSH), 565 doff_io32}, 566 {"IDL_DATA", 0644, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_DATA), 567 doff_io32}, 568 {"IDL_CTL", 0644, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_CTL), 569 doff_io32}, 570 {}, 571 }; 572 573 static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil, 574 struct dentry *parent) 575 { 576 struct dentry *d, *dtx, *drx; 577 578 d = debugfs_create_dir("ITR_CNT", parent); 579 580 dtx = debugfs_create_dir("TX", d); 581 drx = debugfs_create_dir("RX", d); 582 583 wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr, 584 lgc_itr_cnt_off); 585 586 wil6210_debugfs_init_offset(wil, dtx, (void * __force)wil->csr, 587 tx_itr_cnt_off); 588 589 wil6210_debugfs_init_offset(wil, drx, (void * __force)wil->csr, 590 rx_itr_cnt_off); 591 return 0; 592 } 593 594 static int memread_show(struct seq_file *s, void *data) 595 { 596 struct wil6210_priv *wil = s->private; 597 void __iomem *a; 598 int ret; 599 600 ret = wil_pm_runtime_get(wil); 601 if (ret < 0) 602 return ret; 603 604 ret = wil_mem_access_lock(wil); 605 if (ret) { 606 wil_pm_runtime_put(wil); 607 return ret; 608 } 609 610 a = wmi_buffer(wil, cpu_to_le32(mem_addr)); 611 612 if (a) 613 seq_printf(s, "[0x%08x] = 0x%08x\n", mem_addr, readl(a)); 614 else 615 seq_printf(s, "[0x%08x] = INVALID\n", mem_addr); 616 617 wil_mem_access_unlock(wil); 618 wil_pm_runtime_put(wil); 619 620 return 0; 621 } 622 DEFINE_SHOW_ATTRIBUTE(memread); 623 624 static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, 625 size_t count, loff_t *ppos) 626 { 627 enum { max_count = 4096 }; 628 struct wil_blob_wrapper *wil_blob = file->private_data; 629 struct wil6210_priv *wil = wil_blob->wil; 630 loff_t aligned_pos, pos = *ppos; 631 size_t available = wil_blob->blob.size; 632 void *buf; 633 size_t unaligned_bytes, aligned_count, ret; 634 int rc; 635 636 if (pos < 0) 637 return -EINVAL; 638 639 if (pos >= available || !count) 640 return 0; 641 642 if (count > available - pos) 643 count = available - pos; 644 if (count > max_count) 645 count = max_count; 646 647 /* set pos to 4 bytes aligned */ 648 unaligned_bytes = pos % 4; 649 aligned_pos = pos - unaligned_bytes; 650 aligned_count = count + unaligned_bytes; 651 652 buf = kmalloc(aligned_count, GFP_KERNEL); 653 if (!buf) 654 return -ENOMEM; 655 656 rc = wil_pm_runtime_get(wil); 657 if (rc < 0) { 658 kfree(buf); 659 return rc; 660 } 661 662 rc = wil_mem_access_lock(wil); 663 if (rc) { 664 kfree(buf); 665 wil_pm_runtime_put(wil); 666 return rc; 667 } 668 669 wil_memcpy_fromio_32(buf, (const void __iomem *) 670 wil_blob->blob.data + aligned_pos, aligned_count); 671 672 ret = copy_to_user(user_buf, buf + unaligned_bytes, count); 673 674 wil_mem_access_unlock(wil); 675 wil_pm_runtime_put(wil); 676 677 kfree(buf); 678 if (ret == count) 679 return -EFAULT; 680 681 count -= ret; 682 *ppos = pos + count; 683 684 return count; 685 } 686 687 static const struct file_operations fops_ioblob = { 688 .read = wil_read_file_ioblob, 689 .open = simple_open, 690 .llseek = default_llseek, 691 }; 692 693 static 694 struct dentry *wil_debugfs_create_ioblob(const char *name, 695 umode_t mode, 696 struct dentry *parent, 697 struct wil_blob_wrapper *wil_blob) 698 { 699 return debugfs_create_file(name, mode, parent, wil_blob, &fops_ioblob); 700 } 701 702 /*---write channel 1..4 to rxon for it, 0 to rxoff---*/ 703 static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf, 704 size_t len, loff_t *ppos) 705 { 706 struct wil6210_priv *wil = file->private_data; 707 int rc; 708 long channel; 709 bool on; 710 711 char *kbuf = memdup_user_nul(buf, len); 712 713 if (IS_ERR(kbuf)) 714 return PTR_ERR(kbuf); 715 rc = kstrtol(kbuf, 0, &channel); 716 kfree(kbuf); 717 if (rc) 718 return rc; 719 720 if ((channel < 0) || (channel > 4)) { 721 wil_err(wil, "Invalid channel %ld\n", channel); 722 return -EINVAL; 723 } 724 on = !!channel; 725 726 if (on) { 727 rc = wmi_set_channel(wil, (int)channel); 728 if (rc) 729 return rc; 730 } 731 732 rc = wmi_rxon(wil, on); 733 if (rc) 734 return rc; 735 736 return len; 737 } 738 739 static const struct file_operations fops_rxon = { 740 .write = wil_write_file_rxon, 741 .open = simple_open, 742 }; 743 744 static ssize_t wil_write_file_rbufcap(struct file *file, 745 const char __user *buf, 746 size_t count, loff_t *ppos) 747 { 748 struct wil6210_priv *wil = file->private_data; 749 int val; 750 int rc; 751 752 rc = kstrtoint_from_user(buf, count, 0, &val); 753 if (rc) { 754 wil_err(wil, "Invalid argument\n"); 755 return rc; 756 } 757 /* input value: negative to disable, 0 to use system default, 758 * 1..ring size to set descriptor threshold 759 */ 760 wil_info(wil, "%s RBUFCAP, descriptors threshold - %d\n", 761 val < 0 ? "Disabling" : "Enabling", val); 762 763 if (!wil->ring_rx.va || val > wil->ring_rx.size) { 764 wil_err(wil, "Invalid descriptors threshold, %d\n", val); 765 return -EINVAL; 766 } 767 768 rc = wmi_rbufcap_cfg(wil, val < 0 ? 0 : 1, val < 0 ? 0 : val); 769 if (rc) { 770 wil_err(wil, "RBUFCAP config failed: %d\n", rc); 771 return rc; 772 } 773 774 return count; 775 } 776 777 static const struct file_operations fops_rbufcap = { 778 .write = wil_write_file_rbufcap, 779 .open = simple_open, 780 }; 781 782 /* block ack control, write: 783 * - "add <ringid> <agg_size> <timeout>" to trigger ADDBA 784 * - "del_tx <ringid> <reason>" to trigger DELBA for Tx side 785 * - "del_rx <CID> <TID> <reason>" to trigger DELBA for Rx side 786 */ 787 static ssize_t wil_write_back(struct file *file, const char __user *buf, 788 size_t len, loff_t *ppos) 789 { 790 struct wil6210_priv *wil = file->private_data; 791 int rc; 792 char *kbuf = kmalloc(len + 1, GFP_KERNEL); 793 char cmd[9]; 794 int p1, p2, p3; 795 796 if (!kbuf) 797 return -ENOMEM; 798 799 rc = simple_write_to_buffer(kbuf, len, ppos, buf, len); 800 if (rc != len) { 801 kfree(kbuf); 802 return rc >= 0 ? -EIO : rc; 803 } 804 805 kbuf[len] = '\0'; 806 rc = sscanf(kbuf, "%8s %d %d %d", cmd, &p1, &p2, &p3); 807 kfree(kbuf); 808 809 if (rc < 0) 810 return rc; 811 if (rc < 2) 812 return -EINVAL; 813 814 if ((strcmp(cmd, "add") == 0) || 815 (strcmp(cmd, "del_tx") == 0)) { 816 struct wil_ring_tx_data *txdata; 817 818 if (p1 < 0 || p1 >= WIL6210_MAX_TX_RINGS) { 819 wil_err(wil, "BACK: invalid ring id %d\n", p1); 820 return -EINVAL; 821 } 822 txdata = &wil->ring_tx_data[p1]; 823 if (strcmp(cmd, "add") == 0) { 824 if (rc < 3) { 825 wil_err(wil, "BACK: add require at least 2 params\n"); 826 return -EINVAL; 827 } 828 if (rc < 4) 829 p3 = 0; 830 wmi_addba(wil, txdata->mid, p1, p2, p3); 831 } else { 832 if (rc < 3) 833 p2 = WLAN_REASON_QSTA_LEAVE_QBSS; 834 wmi_delba_tx(wil, txdata->mid, p1, p2); 835 } 836 } else if (strcmp(cmd, "del_rx") == 0) { 837 struct wil_sta_info *sta; 838 839 if (rc < 3) { 840 wil_err(wil, 841 "BACK: del_rx require at least 2 params\n"); 842 return -EINVAL; 843 } 844 if (p1 < 0 || p1 >= wil->max_assoc_sta) { 845 wil_err(wil, "BACK: invalid CID %d\n", p1); 846 return -EINVAL; 847 } 848 if (rc < 4) 849 p3 = WLAN_REASON_QSTA_LEAVE_QBSS; 850 sta = &wil->sta[p1]; 851 wmi_delba_rx(wil, sta->mid, p1, p2, p3); 852 } else { 853 wil_err(wil, "BACK: Unrecognized command \"%s\"\n", cmd); 854 return -EINVAL; 855 } 856 857 return len; 858 } 859 860 static ssize_t wil_read_back(struct file *file, char __user *user_buf, 861 size_t count, loff_t *ppos) 862 { 863 static const char text[] = "block ack control, write:\n" 864 " - \"add <ringid> <agg_size> <timeout>\" to trigger ADDBA\n" 865 "If missing, <timeout> defaults to 0\n" 866 " - \"del_tx <ringid> <reason>\" to trigger DELBA for Tx side\n" 867 " - \"del_rx <CID> <TID> <reason>\" to trigger DELBA for Rx side\n" 868 "If missing, <reason> set to \"STA_LEAVING\" (36)\n"; 869 870 return simple_read_from_buffer(user_buf, count, ppos, text, 871 sizeof(text)); 872 } 873 874 static const struct file_operations fops_back = { 875 .read = wil_read_back, 876 .write = wil_write_back, 877 .open = simple_open, 878 }; 879 880 /* pmc control, write: 881 * - "alloc <num descriptors> <descriptor_size>" to allocate PMC 882 * - "free" to release memory allocated for PMC 883 */ 884 static ssize_t wil_write_pmccfg(struct file *file, const char __user *buf, 885 size_t len, loff_t *ppos) 886 { 887 struct wil6210_priv *wil = file->private_data; 888 int rc; 889 char *kbuf = kmalloc(len + 1, GFP_KERNEL); 890 char cmd[9]; 891 int num_descs, desc_size; 892 893 if (!kbuf) 894 return -ENOMEM; 895 896 rc = simple_write_to_buffer(kbuf, len, ppos, buf, len); 897 if (rc != len) { 898 kfree(kbuf); 899 return rc >= 0 ? -EIO : rc; 900 } 901 902 kbuf[len] = '\0'; 903 rc = sscanf(kbuf, "%8s %d %d", cmd, &num_descs, &desc_size); 904 kfree(kbuf); 905 906 if (rc < 0) 907 return rc; 908 909 if (rc < 1) { 910 wil_err(wil, "pmccfg: no params given\n"); 911 return -EINVAL; 912 } 913 914 if (0 == strcmp(cmd, "alloc")) { 915 if (rc != 3) { 916 wil_err(wil, "pmccfg: alloc requires 2 params\n"); 917 return -EINVAL; 918 } 919 wil_pmc_alloc(wil, num_descs, desc_size); 920 } else if (0 == strcmp(cmd, "free")) { 921 if (rc != 1) { 922 wil_err(wil, "pmccfg: free does not have any params\n"); 923 return -EINVAL; 924 } 925 wil_pmc_free(wil, true); 926 } else { 927 wil_err(wil, "pmccfg: Unrecognized command \"%s\"\n", cmd); 928 return -EINVAL; 929 } 930 931 return len; 932 } 933 934 static ssize_t wil_read_pmccfg(struct file *file, char __user *user_buf, 935 size_t count, loff_t *ppos) 936 { 937 struct wil6210_priv *wil = file->private_data; 938 char text[256]; 939 char help[] = "pmc control, write:\n" 940 " - \"alloc <num descriptors> <descriptor_size>\" to allocate pmc\n" 941 " - \"free\" to free memory allocated for pmc\n"; 942 943 snprintf(text, sizeof(text), "Last command status: %d\n\n%s", 944 wil_pmc_last_cmd_status(wil), help); 945 946 return simple_read_from_buffer(user_buf, count, ppos, text, 947 strlen(text) + 1); 948 } 949 950 static const struct file_operations fops_pmccfg = { 951 .read = wil_read_pmccfg, 952 .write = wil_write_pmccfg, 953 .open = simple_open, 954 }; 955 956 static const struct file_operations fops_pmcdata = { 957 .open = simple_open, 958 .read = wil_pmc_read, 959 .llseek = wil_pmc_llseek, 960 }; 961 962 /*---tx_mgmt---*/ 963 /* Write mgmt frame to this file to send it */ 964 static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf, 965 size_t len, loff_t *ppos) 966 { 967 struct wil6210_priv *wil = file->private_data; 968 struct wiphy *wiphy = wil_to_wiphy(wil); 969 struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr; 970 struct cfg80211_mgmt_tx_params params; 971 int rc; 972 void *frame; 973 974 memset(¶ms, 0, sizeof(params)); 975 976 if (!len) 977 return -EINVAL; 978 979 frame = memdup_user(buf, len); 980 if (IS_ERR(frame)) 981 return PTR_ERR(frame); 982 983 params.buf = frame; 984 params.len = len; 985 986 rc = wil_cfg80211_mgmt_tx(wiphy, wdev, ¶ms, NULL); 987 988 kfree(frame); 989 wil_info(wil, "-> %d\n", rc); 990 991 return len; 992 } 993 994 static const struct file_operations fops_txmgmt = { 995 .write = wil_write_file_txmgmt, 996 .open = simple_open, 997 }; 998 999 /* Write WMI command (w/o mbox header) to this file to send it 1000 * WMI starts from wil6210_mbox_hdr_wmi header 1001 */ 1002 static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, 1003 size_t len, loff_t *ppos) 1004 { 1005 struct wil6210_priv *wil = file->private_data; 1006 struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); 1007 struct wmi_cmd_hdr *wmi; 1008 void *cmd; 1009 int cmdlen = len - sizeof(struct wmi_cmd_hdr); 1010 u16 cmdid; 1011 int rc, rc1; 1012 1013 if (cmdlen < 0) 1014 return -EINVAL; 1015 1016 wmi = kmalloc(len, GFP_KERNEL); 1017 if (!wmi) 1018 return -ENOMEM; 1019 1020 rc = simple_write_to_buffer(wmi, len, ppos, buf, len); 1021 if (rc < 0) { 1022 kfree(wmi); 1023 return rc; 1024 } 1025 1026 cmd = (cmdlen > 0) ? &wmi[1] : NULL; 1027 cmdid = le16_to_cpu(wmi->command_id); 1028 1029 rc1 = wmi_send(wil, cmdid, vif->mid, cmd, cmdlen); 1030 kfree(wmi); 1031 1032 wil_info(wil, "0x%04x[%d] -> %d\n", cmdid, cmdlen, rc1); 1033 1034 return rc; 1035 } 1036 1037 static const struct file_operations fops_wmi = { 1038 .write = wil_write_file_wmi, 1039 .open = simple_open, 1040 }; 1041 1042 static void wil_seq_print_skb(struct seq_file *s, struct sk_buff *skb) 1043 { 1044 int i = 0; 1045 int len = skb_headlen(skb); 1046 void *p = skb->data; 1047 int nr_frags = skb_shinfo(skb)->nr_frags; 1048 1049 seq_printf(s, " len = %d\n", len); 1050 wil_seq_hexdump(s, p, len, " : "); 1051 1052 if (nr_frags) { 1053 seq_printf(s, " nr_frags = %d\n", nr_frags); 1054 for (i = 0; i < nr_frags; i++) { 1055 const struct skb_frag_struct *frag = 1056 &skb_shinfo(skb)->frags[i]; 1057 1058 len = skb_frag_size(frag); 1059 p = skb_frag_address_safe(frag); 1060 seq_printf(s, " [%2d] : len = %d\n", i, len); 1061 wil_seq_hexdump(s, p, len, " : "); 1062 } 1063 } 1064 } 1065 1066 /*---------Tx/Rx descriptor------------*/ 1067 static int txdesc_show(struct seq_file *s, void *data) 1068 { 1069 struct wil6210_priv *wil = s->private; 1070 struct wil_ring *ring; 1071 bool tx; 1072 int ring_idx = dbg_ring_index; 1073 int txdesc_idx = dbg_txdesc_index; 1074 volatile struct vring_tx_desc *d; 1075 volatile u32 *u; 1076 struct sk_buff *skb; 1077 1078 if (wil->use_enhanced_dma_hw) { 1079 /* RX ring index == 0 */ 1080 if (ring_idx >= WIL6210_MAX_TX_RINGS) { 1081 seq_printf(s, "invalid ring index %d\n", ring_idx); 1082 return 0; 1083 } 1084 tx = ring_idx > 0; /* desc ring 0 is reserved for RX */ 1085 } else { 1086 /* RX ring index == WIL6210_MAX_TX_RINGS */ 1087 if (ring_idx > WIL6210_MAX_TX_RINGS) { 1088 seq_printf(s, "invalid ring index %d\n", ring_idx); 1089 return 0; 1090 } 1091 tx = (ring_idx < WIL6210_MAX_TX_RINGS); 1092 } 1093 1094 ring = tx ? &wil->ring_tx[ring_idx] : &wil->ring_rx; 1095 1096 if (!ring->va) { 1097 if (tx) 1098 seq_printf(s, "No Tx[%2d] RING\n", ring_idx); 1099 else 1100 seq_puts(s, "No Rx RING\n"); 1101 return 0; 1102 } 1103 1104 if (txdesc_idx >= ring->size) { 1105 if (tx) 1106 seq_printf(s, "[%2d] TxDesc index (%d) >= size (%d)\n", 1107 ring_idx, txdesc_idx, ring->size); 1108 else 1109 seq_printf(s, "RxDesc index (%d) >= size (%d)\n", 1110 txdesc_idx, ring->size); 1111 return 0; 1112 } 1113 1114 /* use struct vring_tx_desc for Rx as well, 1115 * only field used, .dma.length, is the same 1116 */ 1117 d = &ring->va[txdesc_idx].tx.legacy; 1118 u = (volatile u32 *)d; 1119 skb = NULL; 1120 1121 if (wil->use_enhanced_dma_hw) { 1122 if (tx) { 1123 skb = ring->ctx ? ring->ctx[txdesc_idx].skb : NULL; 1124 } else if (wil->rx_buff_mgmt.buff_arr) { 1125 struct wil_rx_enhanced_desc *rx_d = 1126 (struct wil_rx_enhanced_desc *) 1127 &ring->va[txdesc_idx].rx.enhanced; 1128 u16 buff_id = le16_to_cpu(rx_d->mac.buff_id); 1129 1130 if (!wil_val_in_range(buff_id, 0, 1131 wil->rx_buff_mgmt.size)) 1132 seq_printf(s, "invalid buff_id %d\n", buff_id); 1133 else 1134 skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb; 1135 } 1136 } else { 1137 skb = ring->ctx[txdesc_idx].skb; 1138 } 1139 if (tx) 1140 seq_printf(s, "Tx[%2d][%3d] = {\n", ring_idx, 1141 txdesc_idx); 1142 else 1143 seq_printf(s, "Rx[%3d] = {\n", txdesc_idx); 1144 seq_printf(s, " MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n", 1145 u[0], u[1], u[2], u[3]); 1146 seq_printf(s, " DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n", 1147 u[4], u[5], u[6], u[7]); 1148 seq_printf(s, " SKB = 0x%p\n", skb); 1149 1150 if (skb) { 1151 skb_get(skb); 1152 wil_seq_print_skb(s, skb); 1153 kfree_skb(skb); 1154 } 1155 seq_puts(s, "}\n"); 1156 1157 return 0; 1158 } 1159 DEFINE_SHOW_ATTRIBUTE(txdesc); 1160 1161 /*---------Tx/Rx status message------------*/ 1162 static int status_msg_show(struct seq_file *s, void *data) 1163 { 1164 struct wil6210_priv *wil = s->private; 1165 int sring_idx = dbg_sring_index; 1166 struct wil_status_ring *sring; 1167 bool tx; 1168 u32 status_msg_idx = dbg_status_msg_index; 1169 u32 *u; 1170 1171 if (sring_idx >= WIL6210_MAX_STATUS_RINGS) { 1172 seq_printf(s, "invalid status ring index %d\n", sring_idx); 1173 return 0; 1174 } 1175 1176 sring = &wil->srings[sring_idx]; 1177 tx = !sring->is_rx; 1178 1179 if (!sring->va) { 1180 seq_printf(s, "No %cX status ring\n", tx ? 'T' : 'R'); 1181 return 0; 1182 } 1183 1184 if (status_msg_idx >= sring->size) { 1185 seq_printf(s, "%cxDesc index (%d) >= size (%d)\n", 1186 tx ? 'T' : 'R', status_msg_idx, sring->size); 1187 return 0; 1188 } 1189 1190 u = sring->va + (sring->elem_size * status_msg_idx); 1191 1192 seq_printf(s, "%cx[%d][%3d] = {\n", 1193 tx ? 'T' : 'R', sring_idx, status_msg_idx); 1194 1195 seq_printf(s, " 0x%08x 0x%08x 0x%08x 0x%08x\n", 1196 u[0], u[1], u[2], u[3]); 1197 if (!tx && !wil->use_compressed_rx_status) 1198 seq_printf(s, " 0x%08x 0x%08x 0x%08x 0x%08x\n", 1199 u[4], u[5], u[6], u[7]); 1200 1201 seq_puts(s, "}\n"); 1202 1203 return 0; 1204 } 1205 DEFINE_SHOW_ATTRIBUTE(status_msg); 1206 1207 static int wil_print_rx_buff(struct seq_file *s, struct list_head *lh) 1208 { 1209 struct wil_rx_buff *it; 1210 int i = 0; 1211 1212 list_for_each_entry(it, lh, list) { 1213 if ((i % 16) == 0 && i != 0) 1214 seq_puts(s, "\n "); 1215 seq_printf(s, "[%4d] ", it->id); 1216 i++; 1217 } 1218 seq_printf(s, "\nNumber of buffers: %u\n", i); 1219 1220 return i; 1221 } 1222 1223 static int rx_buff_mgmt_show(struct seq_file *s, void *data) 1224 { 1225 struct wil6210_priv *wil = s->private; 1226 struct wil_rx_buff_mgmt *rbm = &wil->rx_buff_mgmt; 1227 int num_active; 1228 int num_free; 1229 1230 if (!rbm->buff_arr) 1231 return -EINVAL; 1232 1233 seq_printf(s, " size = %zu\n", rbm->size); 1234 seq_printf(s, " free_list_empty_cnt = %lu\n", 1235 rbm->free_list_empty_cnt); 1236 1237 /* Print active list */ 1238 seq_puts(s, " Active list:\n"); 1239 num_active = wil_print_rx_buff(s, &rbm->active); 1240 seq_puts(s, "\n Free list:\n"); 1241 num_free = wil_print_rx_buff(s, &rbm->free); 1242 1243 seq_printf(s, " Total number of buffers: %u\n", 1244 num_active + num_free); 1245 1246 return 0; 1247 } 1248 DEFINE_SHOW_ATTRIBUTE(rx_buff_mgmt); 1249 1250 /*---------beamforming------------*/ 1251 static char *wil_bfstatus_str(u32 status) 1252 { 1253 switch (status) { 1254 case 0: 1255 return "Failed"; 1256 case 1: 1257 return "OK"; 1258 case 2: 1259 return "Retrying"; 1260 default: 1261 return "??"; 1262 } 1263 } 1264 1265 static bool is_all_zeros(void * const x_, size_t sz) 1266 { 1267 /* if reply is all-0, ignore this CID */ 1268 u32 *x = x_; 1269 int n; 1270 1271 for (n = 0; n < sz / sizeof(*x); n++) 1272 if (x[n]) 1273 return false; 1274 1275 return true; 1276 } 1277 1278 static int bf_show(struct seq_file *s, void *data) 1279 { 1280 int rc; 1281 int i; 1282 struct wil6210_priv *wil = s->private; 1283 struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); 1284 struct wmi_notify_req_cmd cmd = { 1285 .interval_usec = 0, 1286 }; 1287 struct { 1288 struct wmi_cmd_hdr wmi; 1289 struct wmi_notify_req_done_event evt; 1290 } __packed reply; 1291 1292 memset(&reply, 0, sizeof(reply)); 1293 1294 for (i = 0; i < wil->max_assoc_sta; i++) { 1295 u32 status; 1296 1297 cmd.cid = i; 1298 rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid, 1299 &cmd, sizeof(cmd), 1300 WMI_NOTIFY_REQ_DONE_EVENTID, &reply, 1301 sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS); 1302 /* if reply is all-0, ignore this CID */ 1303 if (rc || is_all_zeros(&reply.evt, sizeof(reply.evt))) 1304 continue; 1305 1306 status = le32_to_cpu(reply.evt.status); 1307 seq_printf(s, "CID %d {\n" 1308 " TSF = 0x%016llx\n" 1309 " TxMCS = %2d TxTpt = %4d\n" 1310 " SQI = %4d\n" 1311 " RSSI = %4d\n" 1312 " Status = 0x%08x %s\n" 1313 " Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n" 1314 " Goodput(rx:tx) %4d:%4d\n" 1315 "}\n", 1316 i, 1317 le64_to_cpu(reply.evt.tsf), 1318 le16_to_cpu(reply.evt.bf_mcs), 1319 le32_to_cpu(reply.evt.tx_tpt), 1320 reply.evt.sqi, 1321 reply.evt.rssi, 1322 status, wil_bfstatus_str(status), 1323 le16_to_cpu(reply.evt.my_rx_sector), 1324 le16_to_cpu(reply.evt.my_tx_sector), 1325 le16_to_cpu(reply.evt.other_rx_sector), 1326 le16_to_cpu(reply.evt.other_tx_sector), 1327 le32_to_cpu(reply.evt.rx_goodput), 1328 le32_to_cpu(reply.evt.tx_goodput)); 1329 } 1330 return 0; 1331 } 1332 DEFINE_SHOW_ATTRIBUTE(bf); 1333 1334 /*---------temp------------*/ 1335 static void print_temp(struct seq_file *s, const char *prefix, s32 t) 1336 { 1337 switch (t) { 1338 case 0: 1339 case WMI_INVALID_TEMPERATURE: 1340 seq_printf(s, "%s N/A\n", prefix); 1341 break; 1342 default: 1343 seq_printf(s, "%s %s%d.%03d\n", prefix, (t < 0 ? "-" : ""), 1344 abs(t / 1000), abs(t % 1000)); 1345 break; 1346 } 1347 } 1348 1349 static int temp_show(struct seq_file *s, void *data) 1350 { 1351 struct wil6210_priv *wil = s->private; 1352 int rc, i; 1353 1354 if (test_bit(WMI_FW_CAPABILITY_TEMPERATURE_ALL_RF, 1355 wil->fw_capabilities)) { 1356 struct wmi_temp_sense_all_done_event sense_all_evt; 1357 1358 wil_dbg_misc(wil, 1359 "WMI_FW_CAPABILITY_TEMPERATURE_ALL_RF is supported"); 1360 rc = wmi_get_all_temperatures(wil, &sense_all_evt); 1361 if (rc) { 1362 seq_puts(s, "Failed\n"); 1363 return 0; 1364 } 1365 print_temp(s, "T_mac =", 1366 le32_to_cpu(sense_all_evt.baseband_t1000)); 1367 seq_printf(s, "Connected RFs [0x%08x]\n", 1368 sense_all_evt.rf_bitmap); 1369 for (i = 0; i < WMI_MAX_XIF_PORTS_NUM; i++) { 1370 seq_printf(s, "RF[%d] = ", i); 1371 print_temp(s, "", 1372 le32_to_cpu(sense_all_evt.rf_t1000[i])); 1373 } 1374 } else { 1375 s32 t_m, t_r; 1376 1377 wil_dbg_misc(wil, 1378 "WMI_FW_CAPABILITY_TEMPERATURE_ALL_RF is not supported"); 1379 rc = wmi_get_temperature(wil, &t_m, &t_r); 1380 if (rc) { 1381 seq_puts(s, "Failed\n"); 1382 return 0; 1383 } 1384 print_temp(s, "T_mac =", t_m); 1385 print_temp(s, "T_radio =", t_r); 1386 } 1387 return 0; 1388 } 1389 DEFINE_SHOW_ATTRIBUTE(temp); 1390 1391 /*---------freq------------*/ 1392 static int freq_show(struct seq_file *s, void *data) 1393 { 1394 struct wil6210_priv *wil = s->private; 1395 struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr; 1396 u32 freq = wdev->chandef.chan ? wdev->chandef.chan->center_freq : 0; 1397 1398 seq_printf(s, "Freq = %d\n", freq); 1399 1400 return 0; 1401 } 1402 DEFINE_SHOW_ATTRIBUTE(freq); 1403 1404 /*---------link------------*/ 1405 static int link_show(struct seq_file *s, void *data) 1406 { 1407 struct wil6210_priv *wil = s->private; 1408 struct station_info *sinfo; 1409 int i, rc = 0; 1410 1411 sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL); 1412 if (!sinfo) 1413 return -ENOMEM; 1414 1415 for (i = 0; i < wil->max_assoc_sta; i++) { 1416 struct wil_sta_info *p = &wil->sta[i]; 1417 char *status = "unknown"; 1418 struct wil6210_vif *vif; 1419 u8 mid; 1420 1421 switch (p->status) { 1422 case wil_sta_unused: 1423 status = "unused "; 1424 break; 1425 case wil_sta_conn_pending: 1426 status = "pending "; 1427 break; 1428 case wil_sta_connected: 1429 status = "connected"; 1430 break; 1431 } 1432 mid = (p->status != wil_sta_unused) ? p->mid : U8_MAX; 1433 seq_printf(s, "[%d][MID %d] %pM %s\n", 1434 i, mid, p->addr, status); 1435 1436 if (p->status != wil_sta_connected) 1437 continue; 1438 1439 vif = (mid < GET_MAX_VIFS(wil)) ? wil->vifs[mid] : NULL; 1440 if (vif) { 1441 rc = wil_cid_fill_sinfo(vif, i, sinfo); 1442 if (rc) 1443 goto out; 1444 1445 seq_printf(s, " Tx_mcs = %d\n", sinfo->txrate.mcs); 1446 seq_printf(s, " Rx_mcs = %d\n", sinfo->rxrate.mcs); 1447 seq_printf(s, " SQ = %d\n", sinfo->signal); 1448 } else { 1449 seq_puts(s, " INVALID MID\n"); 1450 } 1451 } 1452 1453 out: 1454 kfree(sinfo); 1455 return rc; 1456 } 1457 DEFINE_SHOW_ATTRIBUTE(link); 1458 1459 /*---------info------------*/ 1460 static int info_show(struct seq_file *s, void *data) 1461 { 1462 struct wil6210_priv *wil = s->private; 1463 struct net_device *ndev = wil->main_ndev; 1464 int is_ac = power_supply_is_system_supplied(); 1465 int rx = atomic_xchg(&wil->isr_count_rx, 0); 1466 int tx = atomic_xchg(&wil->isr_count_tx, 0); 1467 static ulong rxf_old, txf_old; 1468 ulong rxf = ndev->stats.rx_packets; 1469 ulong txf = ndev->stats.tx_packets; 1470 unsigned int i; 1471 1472 /* >0 : AC; 0 : battery; <0 : error */ 1473 seq_printf(s, "AC powered : %d\n", is_ac); 1474 seq_printf(s, "Rx irqs:packets : %8d : %8ld\n", rx, rxf - rxf_old); 1475 seq_printf(s, "Tx irqs:packets : %8d : %8ld\n", tx, txf - txf_old); 1476 rxf_old = rxf; 1477 txf_old = txf; 1478 1479 #define CHECK_QSTATE(x) (state & BIT(__QUEUE_STATE_ ## x)) ? \ 1480 " " __stringify(x) : "" 1481 1482 for (i = 0; i < ndev->num_tx_queues; i++) { 1483 struct netdev_queue *txq = netdev_get_tx_queue(ndev, i); 1484 unsigned long state = txq->state; 1485 1486 seq_printf(s, "Tx queue[%i] state : 0x%lx%s%s%s\n", i, state, 1487 CHECK_QSTATE(DRV_XOFF), 1488 CHECK_QSTATE(STACK_XOFF), 1489 CHECK_QSTATE(FROZEN) 1490 ); 1491 } 1492 #undef CHECK_QSTATE 1493 return 0; 1494 } 1495 DEFINE_SHOW_ATTRIBUTE(info); 1496 1497 /*---------recovery------------*/ 1498 /* mode = [manual|auto] 1499 * state = [idle|pending|running] 1500 */ 1501 static ssize_t wil_read_file_recovery(struct file *file, char __user *user_buf, 1502 size_t count, loff_t *ppos) 1503 { 1504 struct wil6210_priv *wil = file->private_data; 1505 char buf[80]; 1506 int n; 1507 static const char * const sstate[] = {"idle", "pending", "running"}; 1508 1509 n = snprintf(buf, sizeof(buf), "mode = %s\nstate = %s\n", 1510 no_fw_recovery ? "manual" : "auto", 1511 sstate[wil->recovery_state]); 1512 1513 n = min_t(int, n, sizeof(buf)); 1514 1515 return simple_read_from_buffer(user_buf, count, ppos, 1516 buf, n); 1517 } 1518 1519 static ssize_t wil_write_file_recovery(struct file *file, 1520 const char __user *buf_, 1521 size_t count, loff_t *ppos) 1522 { 1523 struct wil6210_priv *wil = file->private_data; 1524 static const char run_command[] = "run"; 1525 char buf[sizeof(run_command) + 1]; /* to detect "runx" */ 1526 ssize_t rc; 1527 1528 if (wil->recovery_state != fw_recovery_pending) { 1529 wil_err(wil, "No recovery pending\n"); 1530 return -EINVAL; 1531 } 1532 1533 if (*ppos != 0) { 1534 wil_err(wil, "Offset [%d]\n", (int)*ppos); 1535 return -EINVAL; 1536 } 1537 1538 if (count > sizeof(buf)) { 1539 wil_err(wil, "Input too long, len = %d\n", (int)count); 1540 return -EINVAL; 1541 } 1542 1543 rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, buf_, count); 1544 if (rc < 0) 1545 return rc; 1546 1547 buf[rc] = '\0'; 1548 if (0 == strcmp(buf, run_command)) 1549 wil_set_recovery_state(wil, fw_recovery_running); 1550 else 1551 wil_err(wil, "Bad recovery command \"%s\"\n", buf); 1552 1553 return rc; 1554 } 1555 1556 static const struct file_operations fops_recovery = { 1557 .read = wil_read_file_recovery, 1558 .write = wil_write_file_recovery, 1559 .open = simple_open, 1560 }; 1561 1562 /*---------Station matrix------------*/ 1563 static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r) 1564 { 1565 int i; 1566 u16 index = ((r->head_seq_num - r->ssn) & 0xfff) % r->buf_size; 1567 unsigned long long drop_dup = r->drop_dup, drop_old = r->drop_old; 1568 unsigned long long drop_dup_mcast = r->drop_dup_mcast; 1569 1570 seq_printf(s, "([%2d]) 0x%03x [", r->buf_size, r->head_seq_num); 1571 for (i = 0; i < r->buf_size; i++) { 1572 if (i == index) 1573 seq_printf(s, "%c", r->reorder_buf[i] ? 'O' : '|'); 1574 else 1575 seq_printf(s, "%c", r->reorder_buf[i] ? '*' : '_'); 1576 } 1577 seq_printf(s, 1578 "] total %llu drop %llu (dup %llu + old %llu + dup mcast %llu) last 0x%03x\n", 1579 r->total, drop_dup + drop_old + drop_dup_mcast, drop_dup, 1580 drop_old, drop_dup_mcast, r->ssn_last_drop); 1581 } 1582 1583 static void wil_print_rxtid_crypto(struct seq_file *s, int tid, 1584 struct wil_tid_crypto_rx *c) 1585 { 1586 int i; 1587 1588 for (i = 0; i < 4; i++) { 1589 struct wil_tid_crypto_rx_single *cc = &c->key_id[i]; 1590 1591 if (cc->key_set) 1592 goto has_keys; 1593 } 1594 return; 1595 1596 has_keys: 1597 if (tid < WIL_STA_TID_NUM) 1598 seq_printf(s, " [%2d] PN", tid); 1599 else 1600 seq_puts(s, " [GR] PN"); 1601 1602 for (i = 0; i < 4; i++) { 1603 struct wil_tid_crypto_rx_single *cc = &c->key_id[i]; 1604 1605 seq_printf(s, " [%i%s]%6phN", i, cc->key_set ? "+" : "-", 1606 cc->pn); 1607 } 1608 seq_puts(s, "\n"); 1609 } 1610 1611 static int sta_show(struct seq_file *s, void *data) 1612 __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) 1613 { 1614 struct wil6210_priv *wil = s->private; 1615 int i, tid, mcs; 1616 1617 for (i = 0; i < wil->max_assoc_sta; i++) { 1618 struct wil_sta_info *p = &wil->sta[i]; 1619 char *status = "unknown"; 1620 u8 aid = 0; 1621 u8 mid; 1622 bool sta_connected = false; 1623 1624 switch (p->status) { 1625 case wil_sta_unused: 1626 status = "unused "; 1627 break; 1628 case wil_sta_conn_pending: 1629 status = "pending "; 1630 break; 1631 case wil_sta_connected: 1632 status = "connected"; 1633 aid = p->aid; 1634 break; 1635 } 1636 mid = (p->status != wil_sta_unused) ? p->mid : U8_MAX; 1637 if (mid < GET_MAX_VIFS(wil)) { 1638 struct wil6210_vif *vif = wil->vifs[mid]; 1639 1640 if (vif->wdev.iftype == NL80211_IFTYPE_STATION && 1641 p->status == wil_sta_connected) 1642 sta_connected = true; 1643 } 1644 /* print roam counter only for connected stations */ 1645 if (sta_connected) 1646 seq_printf(s, "[%d] %pM connected (roam counter %d) MID %d AID %d\n", 1647 i, p->addr, p->stats.ft_roams, mid, aid); 1648 else 1649 seq_printf(s, "[%d] %pM %s MID %d AID %d\n", i, 1650 p->addr, status, mid, aid); 1651 1652 if (p->status == wil_sta_connected) { 1653 spin_lock_bh(&p->tid_rx_lock); 1654 for (tid = 0; tid < WIL_STA_TID_NUM; tid++) { 1655 struct wil_tid_ampdu_rx *r = p->tid_rx[tid]; 1656 struct wil_tid_crypto_rx *c = 1657 &p->tid_crypto_rx[tid]; 1658 1659 if (r) { 1660 seq_printf(s, " [%2d] ", tid); 1661 wil_print_rxtid(s, r); 1662 } 1663 1664 wil_print_rxtid_crypto(s, tid, c); 1665 } 1666 wil_print_rxtid_crypto(s, WIL_STA_TID_NUM, 1667 &p->group_crypto_rx); 1668 spin_unlock_bh(&p->tid_rx_lock); 1669 seq_printf(s, 1670 "Rx invalid frame: non-data %lu, short %lu, large %lu, replay %lu\n", 1671 p->stats.rx_non_data_frame, 1672 p->stats.rx_short_frame, 1673 p->stats.rx_large_frame, 1674 p->stats.rx_replay); 1675 seq_printf(s, 1676 "mic error %lu, key error %lu, amsdu error %lu, csum error %lu\n", 1677 p->stats.rx_mic_error, 1678 p->stats.rx_key_error, 1679 p->stats.rx_amsdu_error, 1680 p->stats.rx_csum_err); 1681 1682 seq_puts(s, "Rx/MCS:"); 1683 for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs); 1684 mcs++) 1685 seq_printf(s, " %lld", 1686 p->stats.rx_per_mcs[mcs]); 1687 seq_puts(s, "\n"); 1688 } 1689 } 1690 1691 return 0; 1692 } 1693 DEFINE_SHOW_ATTRIBUTE(sta); 1694 1695 static int mids_show(struct seq_file *s, void *data) 1696 { 1697 struct wil6210_priv *wil = s->private; 1698 struct wil6210_vif *vif; 1699 struct net_device *ndev; 1700 int i; 1701 1702 mutex_lock(&wil->vif_mutex); 1703 for (i = 0; i < GET_MAX_VIFS(wil); i++) { 1704 vif = wil->vifs[i]; 1705 1706 if (vif) { 1707 ndev = vif_to_ndev(vif); 1708 seq_printf(s, "[%d] %pM %s\n", i, ndev->dev_addr, 1709 ndev->name); 1710 } else { 1711 seq_printf(s, "[%d] unused\n", i); 1712 } 1713 } 1714 mutex_unlock(&wil->vif_mutex); 1715 1716 return 0; 1717 } 1718 DEFINE_SHOW_ATTRIBUTE(mids); 1719 1720 static int wil_tx_latency_debugfs_show(struct seq_file *s, void *data) 1721 __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) 1722 { 1723 struct wil6210_priv *wil = s->private; 1724 int i, bin; 1725 1726 for (i = 0; i < wil->max_assoc_sta; i++) { 1727 struct wil_sta_info *p = &wil->sta[i]; 1728 char *status = "unknown"; 1729 u8 aid = 0; 1730 u8 mid; 1731 1732 if (!p->tx_latency_bins) 1733 continue; 1734 1735 switch (p->status) { 1736 case wil_sta_unused: 1737 status = "unused "; 1738 break; 1739 case wil_sta_conn_pending: 1740 status = "pending "; 1741 break; 1742 case wil_sta_connected: 1743 status = "connected"; 1744 aid = p->aid; 1745 break; 1746 } 1747 mid = (p->status != wil_sta_unused) ? p->mid : U8_MAX; 1748 seq_printf(s, "[%d] %pM %s MID %d AID %d\n", i, p->addr, status, 1749 mid, aid); 1750 1751 if (p->status == wil_sta_connected) { 1752 u64 num_packets = 0; 1753 u64 tx_latency_avg = p->stats.tx_latency_total_us; 1754 1755 seq_puts(s, "Tx/Latency bin:"); 1756 for (bin = 0; bin < WIL_NUM_LATENCY_BINS; bin++) { 1757 seq_printf(s, " %lld", 1758 p->tx_latency_bins[bin]); 1759 num_packets += p->tx_latency_bins[bin]; 1760 } 1761 seq_puts(s, "\n"); 1762 if (!num_packets) 1763 continue; 1764 do_div(tx_latency_avg, num_packets); 1765 seq_printf(s, "Tx/Latency min/avg/max (us): %d/%lld/%d", 1766 p->stats.tx_latency_min_us, 1767 tx_latency_avg, 1768 p->stats.tx_latency_max_us); 1769 1770 seq_puts(s, "\n"); 1771 } 1772 } 1773 1774 return 0; 1775 } 1776 1777 static int wil_tx_latency_seq_open(struct inode *inode, struct file *file) 1778 { 1779 return single_open(file, wil_tx_latency_debugfs_show, 1780 inode->i_private); 1781 } 1782 1783 static ssize_t wil_tx_latency_write(struct file *file, const char __user *buf, 1784 size_t len, loff_t *ppos) 1785 { 1786 struct seq_file *s = file->private_data; 1787 struct wil6210_priv *wil = s->private; 1788 int val, rc, i; 1789 bool enable; 1790 1791 rc = kstrtoint_from_user(buf, len, 0, &val); 1792 if (rc) { 1793 wil_err(wil, "Invalid argument\n"); 1794 return rc; 1795 } 1796 if (val == 1) 1797 /* default resolution */ 1798 val = 500; 1799 if (val && (val < 50 || val > 1000)) { 1800 wil_err(wil, "Invalid resolution %d\n", val); 1801 return -EINVAL; 1802 } 1803 1804 enable = !!val; 1805 if (wil->tx_latency == enable) 1806 return len; 1807 1808 wil_info(wil, "%s TX latency measurements (resolution %dusec)\n", 1809 enable ? "Enabling" : "Disabling", val); 1810 1811 if (enable) { 1812 size_t sz = sizeof(u64) * WIL_NUM_LATENCY_BINS; 1813 1814 wil->tx_latency_res = val; 1815 for (i = 0; i < wil->max_assoc_sta; i++) { 1816 struct wil_sta_info *sta = &wil->sta[i]; 1817 1818 kfree(sta->tx_latency_bins); 1819 sta->tx_latency_bins = kzalloc(sz, GFP_KERNEL); 1820 if (!sta->tx_latency_bins) 1821 return -ENOMEM; 1822 sta->stats.tx_latency_min_us = U32_MAX; 1823 sta->stats.tx_latency_max_us = 0; 1824 sta->stats.tx_latency_total_us = 0; 1825 } 1826 } 1827 wil->tx_latency = enable; 1828 1829 return len; 1830 } 1831 1832 static const struct file_operations fops_tx_latency = { 1833 .open = wil_tx_latency_seq_open, 1834 .release = single_release, 1835 .read = seq_read, 1836 .write = wil_tx_latency_write, 1837 .llseek = seq_lseek, 1838 }; 1839 1840 static void wil_link_stats_print_basic(struct wil6210_vif *vif, 1841 struct seq_file *s, 1842 struct wmi_link_stats_basic *basic) 1843 { 1844 char per[5] = "?"; 1845 1846 if (basic->per_average != 0xff) 1847 snprintf(per, sizeof(per), "%d%%", basic->per_average); 1848 1849 seq_printf(s, "CID %d {\n" 1850 "\tTxMCS %d TxTpt %d\n" 1851 "\tGoodput(rx:tx) %d:%d\n" 1852 "\tRxBcastFrames %d\n" 1853 "\tRSSI %d SQI %d SNR %d PER %s\n" 1854 "\tRx RFC %d Ant num %d\n" 1855 "\tSectors(rx:tx) my %d:%d peer %d:%d\n" 1856 "}\n", 1857 basic->cid, 1858 basic->bf_mcs, le32_to_cpu(basic->tx_tpt), 1859 le32_to_cpu(basic->rx_goodput), 1860 le32_to_cpu(basic->tx_goodput), 1861 le32_to_cpu(basic->rx_bcast_frames), 1862 basic->rssi, basic->sqi, basic->snr, per, 1863 basic->selected_rfc, basic->rx_effective_ant_num, 1864 basic->my_rx_sector, basic->my_tx_sector, 1865 basic->other_rx_sector, basic->other_tx_sector); 1866 } 1867 1868 static void wil_link_stats_print_global(struct wil6210_priv *wil, 1869 struct seq_file *s, 1870 struct wmi_link_stats_global *global) 1871 { 1872 seq_printf(s, "Frames(rx:tx) %d:%d\n" 1873 "BA Frames(rx:tx) %d:%d\n" 1874 "Beacons %d\n" 1875 "Rx Errors (MIC:CRC) %d:%d\n" 1876 "Tx Errors (no ack) %d\n", 1877 le32_to_cpu(global->rx_frames), 1878 le32_to_cpu(global->tx_frames), 1879 le32_to_cpu(global->rx_ba_frames), 1880 le32_to_cpu(global->tx_ba_frames), 1881 le32_to_cpu(global->tx_beacons), 1882 le32_to_cpu(global->rx_mic_errors), 1883 le32_to_cpu(global->rx_crc_errors), 1884 le32_to_cpu(global->tx_fail_no_ack)); 1885 } 1886 1887 static void wil_link_stats_debugfs_show_vif(struct wil6210_vif *vif, 1888 struct seq_file *s) 1889 { 1890 struct wil6210_priv *wil = vif_to_wil(vif); 1891 struct wmi_link_stats_basic *stats; 1892 int i; 1893 1894 if (!vif->fw_stats_ready) { 1895 seq_puts(s, "no statistics\n"); 1896 return; 1897 } 1898 1899 seq_printf(s, "TSF %lld\n", vif->fw_stats_tsf); 1900 for (i = 0; i < wil->max_assoc_sta; i++) { 1901 if (wil->sta[i].status == wil_sta_unused) 1902 continue; 1903 if (wil->sta[i].mid != vif->mid) 1904 continue; 1905 1906 stats = &wil->sta[i].fw_stats_basic; 1907 wil_link_stats_print_basic(vif, s, stats); 1908 } 1909 } 1910 1911 static int wil_link_stats_debugfs_show(struct seq_file *s, void *data) 1912 { 1913 struct wil6210_priv *wil = s->private; 1914 struct wil6210_vif *vif; 1915 int i, rc; 1916 1917 rc = mutex_lock_interruptible(&wil->vif_mutex); 1918 if (rc) 1919 return rc; 1920 1921 /* iterate over all MIDs and show per-cid statistics. Then show the 1922 * global statistics 1923 */ 1924 for (i = 0; i < GET_MAX_VIFS(wil); i++) { 1925 vif = wil->vifs[i]; 1926 1927 seq_printf(s, "MID %d ", i); 1928 if (!vif) { 1929 seq_puts(s, "unused\n"); 1930 continue; 1931 } 1932 1933 wil_link_stats_debugfs_show_vif(vif, s); 1934 } 1935 1936 mutex_unlock(&wil->vif_mutex); 1937 1938 return 0; 1939 } 1940 1941 static int wil_link_stats_seq_open(struct inode *inode, struct file *file) 1942 { 1943 return single_open(file, wil_link_stats_debugfs_show, inode->i_private); 1944 } 1945 1946 static ssize_t wil_link_stats_write(struct file *file, const char __user *buf, 1947 size_t len, loff_t *ppos) 1948 { 1949 struct seq_file *s = file->private_data; 1950 struct wil6210_priv *wil = s->private; 1951 int cid, interval, rc, i; 1952 struct wil6210_vif *vif; 1953 char *kbuf = kmalloc(len + 1, GFP_KERNEL); 1954 1955 if (!kbuf) 1956 return -ENOMEM; 1957 1958 rc = simple_write_to_buffer(kbuf, len, ppos, buf, len); 1959 if (rc != len) { 1960 kfree(kbuf); 1961 return rc >= 0 ? -EIO : rc; 1962 } 1963 1964 kbuf[len] = '\0'; 1965 /* specify cid (use -1 for all cids) and snapshot interval in ms */ 1966 rc = sscanf(kbuf, "%d %d", &cid, &interval); 1967 kfree(kbuf); 1968 if (rc < 0) 1969 return rc; 1970 if (rc < 2 || interval < 0) 1971 return -EINVAL; 1972 1973 wil_info(wil, "request link statistics, cid %d interval %d\n", 1974 cid, interval); 1975 1976 rc = mutex_lock_interruptible(&wil->vif_mutex); 1977 if (rc) 1978 return rc; 1979 1980 for (i = 0; i < GET_MAX_VIFS(wil); i++) { 1981 vif = wil->vifs[i]; 1982 if (!vif) 1983 continue; 1984 1985 rc = wmi_link_stats_cfg(vif, WMI_LINK_STATS_TYPE_BASIC, 1986 (cid == -1 ? 0xff : cid), interval); 1987 if (rc) 1988 wil_err(wil, "link statistics failed for mid %d\n", i); 1989 } 1990 mutex_unlock(&wil->vif_mutex); 1991 1992 return len; 1993 } 1994 1995 static const struct file_operations fops_link_stats = { 1996 .open = wil_link_stats_seq_open, 1997 .release = single_release, 1998 .read = seq_read, 1999 .write = wil_link_stats_write, 2000 .llseek = seq_lseek, 2001 }; 2002 2003 static int 2004 wil_link_stats_global_debugfs_show(struct seq_file *s, void *data) 2005 { 2006 struct wil6210_priv *wil = s->private; 2007 2008 if (!wil->fw_stats_global.ready) 2009 return 0; 2010 2011 seq_printf(s, "TSF %lld\n", wil->fw_stats_global.tsf); 2012 wil_link_stats_print_global(wil, s, &wil->fw_stats_global.stats); 2013 2014 return 0; 2015 } 2016 2017 static int 2018 wil_link_stats_global_seq_open(struct inode *inode, struct file *file) 2019 { 2020 return single_open(file, wil_link_stats_global_debugfs_show, 2021 inode->i_private); 2022 } 2023 2024 static ssize_t 2025 wil_link_stats_global_write(struct file *file, const char __user *buf, 2026 size_t len, loff_t *ppos) 2027 { 2028 struct seq_file *s = file->private_data; 2029 struct wil6210_priv *wil = s->private; 2030 int interval, rc; 2031 struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev); 2032 2033 /* specify snapshot interval in ms */ 2034 rc = kstrtoint_from_user(buf, len, 0, &interval); 2035 if (rc || interval < 0) { 2036 wil_err(wil, "Invalid argument\n"); 2037 return -EINVAL; 2038 } 2039 2040 wil_info(wil, "request global link stats, interval %d\n", interval); 2041 2042 rc = wmi_link_stats_cfg(vif, WMI_LINK_STATS_TYPE_GLOBAL, 0, interval); 2043 if (rc) 2044 wil_err(wil, "global link stats failed %d\n", rc); 2045 2046 return rc ? rc : len; 2047 } 2048 2049 static const struct file_operations fops_link_stats_global = { 2050 .open = wil_link_stats_global_seq_open, 2051 .release = single_release, 2052 .read = seq_read, 2053 .write = wil_link_stats_global_write, 2054 .llseek = seq_lseek, 2055 }; 2056 2057 static ssize_t wil_read_file_led_cfg(struct file *file, char __user *user_buf, 2058 size_t count, loff_t *ppos) 2059 { 2060 char buf[80]; 2061 int n; 2062 2063 n = snprintf(buf, sizeof(buf), 2064 "led_id is set to %d, echo 1 to enable, 0 to disable\n", 2065 led_id); 2066 2067 n = min_t(int, n, sizeof(buf)); 2068 2069 return simple_read_from_buffer(user_buf, count, ppos, 2070 buf, n); 2071 } 2072 2073 static ssize_t wil_write_file_led_cfg(struct file *file, 2074 const char __user *buf_, 2075 size_t count, loff_t *ppos) 2076 { 2077 struct wil6210_priv *wil = file->private_data; 2078 int val; 2079 int rc; 2080 2081 rc = kstrtoint_from_user(buf_, count, 0, &val); 2082 if (rc) { 2083 wil_err(wil, "Invalid argument\n"); 2084 return rc; 2085 } 2086 2087 wil_info(wil, "%s led %d\n", val ? "Enabling" : "Disabling", led_id); 2088 rc = wmi_led_cfg(wil, val); 2089 if (rc) { 2090 wil_info(wil, "%s led %d failed\n", 2091 val ? "Enabling" : "Disabling", led_id); 2092 return rc; 2093 } 2094 2095 return count; 2096 } 2097 2098 static const struct file_operations fops_led_cfg = { 2099 .read = wil_read_file_led_cfg, 2100 .write = wil_write_file_led_cfg, 2101 .open = simple_open, 2102 }; 2103 2104 /* led_blink_time, write: 2105 * "<blink_on_slow> <blink_off_slow> <blink_on_med> <blink_off_med> <blink_on_fast> <blink_off_fast> 2106 */ 2107 static ssize_t wil_write_led_blink_time(struct file *file, 2108 const char __user *buf, 2109 size_t len, loff_t *ppos) 2110 { 2111 int rc; 2112 char *kbuf = kmalloc(len + 1, GFP_KERNEL); 2113 2114 if (!kbuf) 2115 return -ENOMEM; 2116 2117 rc = simple_write_to_buffer(kbuf, len, ppos, buf, len); 2118 if (rc != len) { 2119 kfree(kbuf); 2120 return rc >= 0 ? -EIO : rc; 2121 } 2122 2123 kbuf[len] = '\0'; 2124 rc = sscanf(kbuf, "%d %d %d %d %d %d", 2125 &led_blink_time[WIL_LED_TIME_SLOW].on_ms, 2126 &led_blink_time[WIL_LED_TIME_SLOW].off_ms, 2127 &led_blink_time[WIL_LED_TIME_MED].on_ms, 2128 &led_blink_time[WIL_LED_TIME_MED].off_ms, 2129 &led_blink_time[WIL_LED_TIME_FAST].on_ms, 2130 &led_blink_time[WIL_LED_TIME_FAST].off_ms); 2131 kfree(kbuf); 2132 2133 if (rc < 0) 2134 return rc; 2135 if (rc < 6) 2136 return -EINVAL; 2137 2138 return len; 2139 } 2140 2141 static ssize_t wil_read_led_blink_time(struct file *file, char __user *user_buf, 2142 size_t count, loff_t *ppos) 2143 { 2144 static char text[400]; 2145 2146 snprintf(text, sizeof(text), 2147 "To set led blink on/off time variables write:\n" 2148 "<blink_on_slow> <blink_off_slow> <blink_on_med> " 2149 "<blink_off_med> <blink_on_fast> <blink_off_fast>\n" 2150 "The current values are:\n" 2151 "%d %d %d %d %d %d\n", 2152 led_blink_time[WIL_LED_TIME_SLOW].on_ms, 2153 led_blink_time[WIL_LED_TIME_SLOW].off_ms, 2154 led_blink_time[WIL_LED_TIME_MED].on_ms, 2155 led_blink_time[WIL_LED_TIME_MED].off_ms, 2156 led_blink_time[WIL_LED_TIME_FAST].on_ms, 2157 led_blink_time[WIL_LED_TIME_FAST].off_ms); 2158 2159 return simple_read_from_buffer(user_buf, count, ppos, text, 2160 sizeof(text)); 2161 } 2162 2163 static const struct file_operations fops_led_blink_time = { 2164 .read = wil_read_led_blink_time, 2165 .write = wil_write_led_blink_time, 2166 .open = simple_open, 2167 }; 2168 2169 /*---------FW capabilities------------*/ 2170 static int wil_fw_capabilities_debugfs_show(struct seq_file *s, void *data) 2171 { 2172 struct wil6210_priv *wil = s->private; 2173 2174 seq_printf(s, "fw_capabilities : %*pb\n", WMI_FW_CAPABILITY_MAX, 2175 wil->fw_capabilities); 2176 2177 return 0; 2178 } 2179 2180 static int wil_fw_capabilities_seq_open(struct inode *inode, struct file *file) 2181 { 2182 return single_open(file, wil_fw_capabilities_debugfs_show, 2183 inode->i_private); 2184 } 2185 2186 static const struct file_operations fops_fw_capabilities = { 2187 .open = wil_fw_capabilities_seq_open, 2188 .release = single_release, 2189 .read = seq_read, 2190 .llseek = seq_lseek, 2191 }; 2192 2193 /*---------FW version------------*/ 2194 static int wil_fw_version_debugfs_show(struct seq_file *s, void *data) 2195 { 2196 struct wil6210_priv *wil = s->private; 2197 2198 if (wil->fw_version[0]) 2199 seq_printf(s, "%s\n", wil->fw_version); 2200 else 2201 seq_puts(s, "N/A\n"); 2202 2203 return 0; 2204 } 2205 2206 static int wil_fw_version_seq_open(struct inode *inode, struct file *file) 2207 { 2208 return single_open(file, wil_fw_version_debugfs_show, 2209 inode->i_private); 2210 } 2211 2212 static const struct file_operations fops_fw_version = { 2213 .open = wil_fw_version_seq_open, 2214 .release = single_release, 2215 .read = seq_read, 2216 .llseek = seq_lseek, 2217 }; 2218 2219 /*---------suspend_stats---------*/ 2220 static ssize_t wil_write_suspend_stats(struct file *file, 2221 const char __user *buf, 2222 size_t len, loff_t *ppos) 2223 { 2224 struct wil6210_priv *wil = file->private_data; 2225 2226 memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats)); 2227 2228 return len; 2229 } 2230 2231 static ssize_t wil_read_suspend_stats(struct file *file, 2232 char __user *user_buf, 2233 size_t count, loff_t *ppos) 2234 { 2235 struct wil6210_priv *wil = file->private_data; 2236 char *text; 2237 int n, ret, text_size = 500; 2238 2239 text = kmalloc(text_size, GFP_KERNEL); 2240 if (!text) 2241 return -ENOMEM; 2242 2243 n = snprintf(text, text_size, 2244 "Radio on suspend statistics:\n" 2245 "successful suspends:%ld failed suspends:%ld\n" 2246 "successful resumes:%ld failed resumes:%ld\n" 2247 "rejected by device:%ld\n" 2248 "Radio off suspend statistics:\n" 2249 "successful suspends:%ld failed suspends:%ld\n" 2250 "successful resumes:%ld failed resumes:%ld\n" 2251 "General statistics:\n" 2252 "rejected by host:%ld\n", 2253 wil->suspend_stats.r_on.successful_suspends, 2254 wil->suspend_stats.r_on.failed_suspends, 2255 wil->suspend_stats.r_on.successful_resumes, 2256 wil->suspend_stats.r_on.failed_resumes, 2257 wil->suspend_stats.rejected_by_device, 2258 wil->suspend_stats.r_off.successful_suspends, 2259 wil->suspend_stats.r_off.failed_suspends, 2260 wil->suspend_stats.r_off.successful_resumes, 2261 wil->suspend_stats.r_off.failed_resumes, 2262 wil->suspend_stats.rejected_by_host); 2263 2264 n = min_t(int, n, text_size); 2265 2266 ret = simple_read_from_buffer(user_buf, count, ppos, text, n); 2267 2268 kfree(text); 2269 2270 return ret; 2271 } 2272 2273 static const struct file_operations fops_suspend_stats = { 2274 .read = wil_read_suspend_stats, 2275 .write = wil_write_suspend_stats, 2276 .open = simple_open, 2277 }; 2278 2279 /*---------compressed_rx_status---------*/ 2280 static ssize_t wil_compressed_rx_status_write(struct file *file, 2281 const char __user *buf, 2282 size_t len, loff_t *ppos) 2283 { 2284 struct seq_file *s = file->private_data; 2285 struct wil6210_priv *wil = s->private; 2286 int compressed_rx_status; 2287 int rc; 2288 2289 rc = kstrtoint_from_user(buf, len, 0, &compressed_rx_status); 2290 if (rc) { 2291 wil_err(wil, "Invalid argument\n"); 2292 return rc; 2293 } 2294 2295 if (wil_has_active_ifaces(wil, true, false)) { 2296 wil_err(wil, "cannot change edma config after iface is up\n"); 2297 return -EPERM; 2298 } 2299 2300 wil_info(wil, "%sable compressed_rx_status\n", 2301 compressed_rx_status ? "En" : "Dis"); 2302 2303 wil->use_compressed_rx_status = compressed_rx_status; 2304 2305 return len; 2306 } 2307 2308 static int 2309 wil_compressed_rx_status_show(struct seq_file *s, void *data) 2310 { 2311 struct wil6210_priv *wil = s->private; 2312 2313 seq_printf(s, "%d\n", wil->use_compressed_rx_status); 2314 2315 return 0; 2316 } 2317 2318 static int 2319 wil_compressed_rx_status_seq_open(struct inode *inode, struct file *file) 2320 { 2321 return single_open(file, wil_compressed_rx_status_show, 2322 inode->i_private); 2323 } 2324 2325 static const struct file_operations fops_compressed_rx_status = { 2326 .open = wil_compressed_rx_status_seq_open, 2327 .release = single_release, 2328 .read = seq_read, 2329 .write = wil_compressed_rx_status_write, 2330 .llseek = seq_lseek, 2331 }; 2332 2333 /*----------------*/ 2334 static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil, 2335 struct dentry *dbg) 2336 { 2337 int i; 2338 char name[32]; 2339 2340 for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { 2341 struct wil_blob_wrapper *wil_blob = &wil->blobs[i]; 2342 struct debugfs_blob_wrapper *blob = &wil_blob->blob; 2343 const struct fw_map *map = &fw_mapping[i]; 2344 2345 if (!map->name) 2346 continue; 2347 2348 wil_blob->wil = wil; 2349 blob->data = (void * __force)wil->csr + HOSTADDR(map->host); 2350 blob->size = map->to - map->from; 2351 snprintf(name, sizeof(name), "blob_%s", map->name); 2352 wil_debugfs_create_ioblob(name, 0444, dbg, wil_blob); 2353 } 2354 } 2355 2356 /* misc files */ 2357 static const struct { 2358 const char *name; 2359 umode_t mode; 2360 const struct file_operations *fops; 2361 } dbg_files[] = { 2362 {"mbox", 0444, &mbox_fops}, 2363 {"rings", 0444, &ring_fops}, 2364 {"stations", 0444, &sta_fops}, 2365 {"mids", 0444, &mids_fops}, 2366 {"desc", 0444, &txdesc_fops}, 2367 {"bf", 0444, &bf_fops}, 2368 {"mem_val", 0644, &memread_fops}, 2369 {"rxon", 0244, &fops_rxon}, 2370 {"tx_mgmt", 0244, &fops_txmgmt}, 2371 {"wmi_send", 0244, &fops_wmi}, 2372 {"back", 0644, &fops_back}, 2373 {"pmccfg", 0644, &fops_pmccfg}, 2374 {"pmcdata", 0444, &fops_pmcdata}, 2375 {"temp", 0444, &temp_fops}, 2376 {"freq", 0444, &freq_fops}, 2377 {"link", 0444, &link_fops}, 2378 {"info", 0444, &info_fops}, 2379 {"recovery", 0644, &fops_recovery}, 2380 {"led_cfg", 0644, &fops_led_cfg}, 2381 {"led_blink_time", 0644, &fops_led_blink_time}, 2382 {"fw_capabilities", 0444, &fops_fw_capabilities}, 2383 {"fw_version", 0444, &fops_fw_version}, 2384 {"suspend_stats", 0644, &fops_suspend_stats}, 2385 {"compressed_rx_status", 0644, &fops_compressed_rx_status}, 2386 {"srings", 0444, &srings_fops}, 2387 {"status_msg", 0444, &status_msg_fops}, 2388 {"rx_buff_mgmt", 0444, &rx_buff_mgmt_fops}, 2389 {"tx_latency", 0644, &fops_tx_latency}, 2390 {"link_stats", 0644, &fops_link_stats}, 2391 {"link_stats_global", 0644, &fops_link_stats_global}, 2392 {"rbufcap", 0244, &fops_rbufcap}, 2393 }; 2394 2395 static void wil6210_debugfs_init_files(struct wil6210_priv *wil, 2396 struct dentry *dbg) 2397 { 2398 int i; 2399 2400 for (i = 0; i < ARRAY_SIZE(dbg_files); i++) 2401 debugfs_create_file(dbg_files[i].name, dbg_files[i].mode, dbg, 2402 wil, dbg_files[i].fops); 2403 } 2404 2405 /* interrupt control blocks */ 2406 static const struct { 2407 const char *name; 2408 u32 icr_off; 2409 } dbg_icr[] = { 2410 {"USER_ICR", HOSTADDR(RGF_USER_USER_ICR)}, 2411 {"DMA_EP_TX_ICR", HOSTADDR(RGF_DMA_EP_TX_ICR)}, 2412 {"DMA_EP_RX_ICR", HOSTADDR(RGF_DMA_EP_RX_ICR)}, 2413 {"DMA_EP_MISC_ICR", HOSTADDR(RGF_DMA_EP_MISC_ICR)}, 2414 }; 2415 2416 static void wil6210_debugfs_init_isr(struct wil6210_priv *wil, 2417 struct dentry *dbg) 2418 { 2419 int i; 2420 2421 for (i = 0; i < ARRAY_SIZE(dbg_icr); i++) 2422 wil6210_debugfs_create_ISR(wil, dbg_icr[i].name, dbg, 2423 dbg_icr[i].icr_off); 2424 } 2425 2426 #define WIL_FIELD(name, mode, type) { __stringify(name), mode, \ 2427 offsetof(struct wil6210_priv, name), type} 2428 2429 /* fields in struct wil6210_priv */ 2430 static const struct dbg_off dbg_wil_off[] = { 2431 WIL_FIELD(status[0], 0644, doff_ulong), 2432 WIL_FIELD(hw_version, 0444, doff_x32), 2433 WIL_FIELD(recovery_count, 0444, doff_u32), 2434 WIL_FIELD(discovery_mode, 0644, doff_u8), 2435 WIL_FIELD(chip_revision, 0444, doff_u8), 2436 WIL_FIELD(abft_len, 0644, doff_u8), 2437 WIL_FIELD(wakeup_trigger, 0644, doff_u8), 2438 WIL_FIELD(ring_idle_trsh, 0644, doff_u32), 2439 WIL_FIELD(num_rx_status_rings, 0644, doff_u8), 2440 WIL_FIELD(rx_status_ring_order, 0644, doff_u32), 2441 WIL_FIELD(tx_status_ring_order, 0644, doff_u32), 2442 WIL_FIELD(rx_buff_id_count, 0644, doff_u32), 2443 WIL_FIELD(amsdu_en, 0644, doff_u8), 2444 {}, 2445 }; 2446 2447 static const struct dbg_off dbg_wil_regs[] = { 2448 {"RGF_MAC_MTRL_COUNTER_0", 0444, HOSTADDR(RGF_MAC_MTRL_COUNTER_0), 2449 doff_io32}, 2450 {"RGF_USER_USAGE_1", 0444, HOSTADDR(RGF_USER_USAGE_1), doff_io32}, 2451 {"RGF_USER_USAGE_2", 0444, HOSTADDR(RGF_USER_USAGE_2), doff_io32}, 2452 {}, 2453 }; 2454 2455 /* static parameters */ 2456 static const struct dbg_off dbg_statics[] = { 2457 {"desc_index", 0644, (ulong)&dbg_txdesc_index, doff_u32}, 2458 {"ring_index", 0644, (ulong)&dbg_ring_index, doff_u32}, 2459 {"mem_addr", 0644, (ulong)&mem_addr, doff_u32}, 2460 {"led_polarity", 0644, (ulong)&led_polarity, doff_u8}, 2461 {"status_index", 0644, (ulong)&dbg_status_msg_index, doff_u32}, 2462 {"sring_index", 0644, (ulong)&dbg_sring_index, doff_u32}, 2463 {"drop_if_ring_full", 0644, (ulong)&drop_if_ring_full, doff_u8}, 2464 {}, 2465 }; 2466 2467 static const int dbg_off_count = 4 * (ARRAY_SIZE(isr_off) - 1) + 2468 ARRAY_SIZE(dbg_wil_regs) - 1 + 2469 ARRAY_SIZE(pseudo_isr_off) - 1 + 2470 ARRAY_SIZE(lgc_itr_cnt_off) - 1 + 2471 ARRAY_SIZE(tx_itr_cnt_off) - 1 + 2472 ARRAY_SIZE(rx_itr_cnt_off) - 1; 2473 2474 int wil6210_debugfs_init(struct wil6210_priv *wil) 2475 { 2476 struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME, 2477 wil_to_wiphy(wil)->debugfsdir); 2478 if (IS_ERR_OR_NULL(dbg)) 2479 return -ENODEV; 2480 2481 wil->dbg_data.data_arr = kcalloc(dbg_off_count, 2482 sizeof(struct wil_debugfs_iomem_data), 2483 GFP_KERNEL); 2484 if (!wil->dbg_data.data_arr) { 2485 debugfs_remove_recursive(dbg); 2486 wil->debug = NULL; 2487 return -ENOMEM; 2488 } 2489 2490 wil->dbg_data.iomem_data_count = 0; 2491 2492 wil_pmc_init(wil); 2493 2494 wil6210_debugfs_init_files(wil, dbg); 2495 wil6210_debugfs_init_isr(wil, dbg); 2496 wil6210_debugfs_init_blobs(wil, dbg); 2497 wil6210_debugfs_init_offset(wil, dbg, wil, dbg_wil_off); 2498 wil6210_debugfs_init_offset(wil, dbg, (void * __force)wil->csr, 2499 dbg_wil_regs); 2500 wil6210_debugfs_init_offset(wil, dbg, NULL, dbg_statics); 2501 2502 wil6210_debugfs_create_pseudo_ISR(wil, dbg); 2503 2504 wil6210_debugfs_create_ITR_CNT(wil, dbg); 2505 2506 return 0; 2507 } 2508 2509 void wil6210_debugfs_remove(struct wil6210_priv *wil) 2510 { 2511 int i; 2512 2513 debugfs_remove_recursive(wil->debug); 2514 wil->debug = NULL; 2515 2516 kfree(wil->dbg_data.data_arr); 2517 for (i = 0; i < wil->max_assoc_sta; i++) 2518 kfree(wil->sta[i].tx_latency_bins); 2519 2520 /* free pmc memory without sending command to fw, as it will 2521 * be reset on the way down anyway 2522 */ 2523 wil_pmc_free(wil, false); 2524 } 2525