1 | // SPDX-License-Identifier: ISC |
2 | /* |
3 | * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> |
4 | */ |
5 | #include "mt76.h" |
6 | |
7 | static int |
8 | mt76_reg_set(void *data, u64 val) |
9 | { |
10 | struct mt76_dev *dev = data; |
11 | |
12 | __mt76_wr(dev, dev->debugfs_reg, val); |
13 | return 0; |
14 | } |
15 | |
16 | static int |
17 | mt76_reg_get(void *data, u64 *val) |
18 | { |
19 | struct mt76_dev *dev = data; |
20 | |
21 | *val = __mt76_rr(dev, dev->debugfs_reg); |
22 | return 0; |
23 | } |
24 | |
25 | DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt76_reg_get, mt76_reg_set, |
26 | "0x%08llx\n" ); |
27 | |
28 | static int |
29 | mt76_napi_threaded_set(void *data, u64 val) |
30 | { |
31 | struct mt76_dev *dev = data; |
32 | |
33 | if (!mt76_is_mmio(dev)) |
34 | return -EOPNOTSUPP; |
35 | |
36 | if (dev->napi_dev.threaded != val) |
37 | return dev_set_threaded(dev: &dev->napi_dev, threaded: val); |
38 | |
39 | return 0; |
40 | } |
41 | |
42 | static int |
43 | mt76_napi_threaded_get(void *data, u64 *val) |
44 | { |
45 | struct mt76_dev *dev = data; |
46 | |
47 | *val = dev->napi_dev.threaded; |
48 | return 0; |
49 | } |
50 | |
51 | DEFINE_DEBUGFS_ATTRIBUTE(fops_napi_threaded, mt76_napi_threaded_get, |
52 | mt76_napi_threaded_set, "%llu\n" ); |
53 | |
54 | int mt76_queues_read(struct seq_file *s, void *data) |
55 | { |
56 | struct mt76_dev *dev = dev_get_drvdata(dev: s->private); |
57 | int i; |
58 | |
59 | seq_puts(m: s, s: " queue | hw-queued | head | tail |\n" ); |
60 | for (i = 0; i < ARRAY_SIZE(dev->phy.q_tx); i++) { |
61 | struct mt76_queue *q = dev->phy.q_tx[i]; |
62 | |
63 | if (!q) |
64 | continue; |
65 | |
66 | seq_printf(m: s, fmt: " %9d | %9d | %9d | %9d |\n" , |
67 | i, q->queued, q->head, q->tail); |
68 | } |
69 | |
70 | return 0; |
71 | } |
72 | EXPORT_SYMBOL_GPL(mt76_queues_read); |
73 | |
74 | static int mt76_rx_queues_read(struct seq_file *s, void *data) |
75 | { |
76 | struct mt76_dev *dev = dev_get_drvdata(dev: s->private); |
77 | int i, queued; |
78 | |
79 | seq_puts(m: s, s: " queue | hw-queued | head | tail |\n" ); |
80 | mt76_for_each_q_rx(dev, i) { |
81 | struct mt76_queue *q = &dev->q_rx[i]; |
82 | |
83 | queued = mt76_is_usb(dev) ? q->ndesc - q->queued : q->queued; |
84 | seq_printf(m: s, fmt: " %9d | %9d | %9d | %9d |\n" , |
85 | i, queued, q->head, q->tail); |
86 | } |
87 | |
88 | return 0; |
89 | } |
90 | |
91 | void mt76_seq_puts_array(struct seq_file *file, const char *str, |
92 | s8 *val, int len) |
93 | { |
94 | int i; |
95 | |
96 | seq_printf(m: file, fmt: "%10s:" , str); |
97 | for (i = 0; i < len; i++) |
98 | seq_printf(m: file, fmt: " %2d" , val[i]); |
99 | seq_puts(m: file, s: "\n" ); |
100 | } |
101 | EXPORT_SYMBOL_GPL(mt76_seq_puts_array); |
102 | |
103 | struct dentry * |
104 | mt76_register_debugfs_fops(struct mt76_phy *phy, |
105 | const struct file_operations *ops) |
106 | { |
107 | const struct file_operations *fops = ops ? ops : &fops_regval; |
108 | struct mt76_dev *dev = phy->dev; |
109 | struct dentry *dir; |
110 | |
111 | dir = debugfs_create_dir(name: "mt76" , parent: phy->hw->wiphy->debugfsdir); |
112 | |
113 | debugfs_create_u8(name: "led_pin" , mode: 0600, parent: dir, value: &phy->leds.pin); |
114 | debugfs_create_u32(name: "regidx" , mode: 0600, parent: dir, value: &dev->debugfs_reg); |
115 | debugfs_create_file_unsafe(name: "regval" , mode: 0600, parent: dir, data: dev, fops); |
116 | debugfs_create_file_unsafe(name: "napi_threaded" , mode: 0600, parent: dir, data: dev, |
117 | fops: &fops_napi_threaded); |
118 | debugfs_create_blob(name: "eeprom" , mode: 0400, parent: dir, blob: &dev->eeprom); |
119 | if (dev->otp.data) |
120 | debugfs_create_blob(name: "otp" , mode: 0400, parent: dir, blob: &dev->otp); |
121 | debugfs_create_devm_seqfile(dev: dev->dev, name: "rx-queues" , parent: dir, |
122 | read_fn: mt76_rx_queues_read); |
123 | |
124 | return dir; |
125 | } |
126 | EXPORT_SYMBOL_GPL(mt76_register_debugfs_fops); |
127 | |