1*4a5fb1bbSJérôme Pouiller // SPDX-License-Identifier: GPL-2.0-only
2*4a5fb1bbSJérôme Pouiller /*
3*4a5fb1bbSJérôme Pouiller * Debugfs interface.
4*4a5fb1bbSJérôme Pouiller *
5*4a5fb1bbSJérôme Pouiller * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
6*4a5fb1bbSJérôme Pouiller * Copyright (c) 2010, ST-Ericsson
7*4a5fb1bbSJérôme Pouiller */
8*4a5fb1bbSJérôme Pouiller #include <linux/debugfs.h>
9*4a5fb1bbSJérôme Pouiller #include <linux/seq_file.h>
10*4a5fb1bbSJérôme Pouiller #include <linux/crc32.h>
11*4a5fb1bbSJérôme Pouiller
12*4a5fb1bbSJérôme Pouiller #include "debug.h"
13*4a5fb1bbSJérôme Pouiller #include "wfx.h"
14*4a5fb1bbSJérôme Pouiller #include "sta.h"
15*4a5fb1bbSJérôme Pouiller #include "main.h"
16*4a5fb1bbSJérôme Pouiller #include "hif_tx.h"
17*4a5fb1bbSJérôme Pouiller #include "hif_tx_mib.h"
18*4a5fb1bbSJérôme Pouiller
19*4a5fb1bbSJérôme Pouiller #define CREATE_TRACE_POINTS
20*4a5fb1bbSJérôme Pouiller #include "traces.h"
21*4a5fb1bbSJérôme Pouiller
22*4a5fb1bbSJérôme Pouiller static const struct trace_print_flags hif_msg_print_map[] = {
23*4a5fb1bbSJérôme Pouiller hif_msg_list,
24*4a5fb1bbSJérôme Pouiller };
25*4a5fb1bbSJérôme Pouiller
26*4a5fb1bbSJérôme Pouiller static const struct trace_print_flags hif_mib_print_map[] = {
27*4a5fb1bbSJérôme Pouiller hif_mib_list,
28*4a5fb1bbSJérôme Pouiller };
29*4a5fb1bbSJérôme Pouiller
30*4a5fb1bbSJérôme Pouiller static const struct trace_print_flags wfx_reg_print_map[] = {
31*4a5fb1bbSJérôme Pouiller wfx_reg_list,
32*4a5fb1bbSJérôme Pouiller };
33*4a5fb1bbSJérôme Pouiller
get_symbol(unsigned long val,const struct trace_print_flags * symbol_array)34*4a5fb1bbSJérôme Pouiller static const char *get_symbol(unsigned long val, const struct trace_print_flags *symbol_array)
35*4a5fb1bbSJérôme Pouiller {
36*4a5fb1bbSJérôme Pouiller int i;
37*4a5fb1bbSJérôme Pouiller
38*4a5fb1bbSJérôme Pouiller for (i = 0; symbol_array[i].mask != -1; i++) {
39*4a5fb1bbSJérôme Pouiller if (val == symbol_array[i].mask)
40*4a5fb1bbSJérôme Pouiller return symbol_array[i].name;
41*4a5fb1bbSJérôme Pouiller }
42*4a5fb1bbSJérôme Pouiller
43*4a5fb1bbSJérôme Pouiller return "unknown";
44*4a5fb1bbSJérôme Pouiller }
45*4a5fb1bbSJérôme Pouiller
wfx_get_hif_name(unsigned long id)46*4a5fb1bbSJérôme Pouiller const char *wfx_get_hif_name(unsigned long id)
47*4a5fb1bbSJérôme Pouiller {
48*4a5fb1bbSJérôme Pouiller return get_symbol(id, hif_msg_print_map);
49*4a5fb1bbSJérôme Pouiller }
50*4a5fb1bbSJérôme Pouiller
wfx_get_mib_name(unsigned long id)51*4a5fb1bbSJérôme Pouiller const char *wfx_get_mib_name(unsigned long id)
52*4a5fb1bbSJérôme Pouiller {
53*4a5fb1bbSJérôme Pouiller return get_symbol(id, hif_mib_print_map);
54*4a5fb1bbSJérôme Pouiller }
55*4a5fb1bbSJérôme Pouiller
wfx_get_reg_name(unsigned long id)56*4a5fb1bbSJérôme Pouiller const char *wfx_get_reg_name(unsigned long id)
57*4a5fb1bbSJérôme Pouiller {
58*4a5fb1bbSJérôme Pouiller return get_symbol(id, wfx_reg_print_map);
59*4a5fb1bbSJérôme Pouiller }
60*4a5fb1bbSJérôme Pouiller
wfx_counters_show(struct seq_file * seq,void * v)61*4a5fb1bbSJérôme Pouiller static int wfx_counters_show(struct seq_file *seq, void *v)
62*4a5fb1bbSJérôme Pouiller {
63*4a5fb1bbSJérôme Pouiller int ret, i;
64*4a5fb1bbSJérôme Pouiller struct wfx_dev *wdev = seq->private;
65*4a5fb1bbSJérôme Pouiller struct wfx_hif_mib_extended_count_table counters[3];
66*4a5fb1bbSJérôme Pouiller
67*4a5fb1bbSJérôme Pouiller for (i = 0; i < ARRAY_SIZE(counters); i++) {
68*4a5fb1bbSJérôme Pouiller ret = wfx_hif_get_counters_table(wdev, i, counters + i);
69*4a5fb1bbSJérôme Pouiller if (ret < 0)
70*4a5fb1bbSJérôme Pouiller return ret;
71*4a5fb1bbSJérôme Pouiller if (ret > 0)
72*4a5fb1bbSJérôme Pouiller return -EIO;
73*4a5fb1bbSJérôme Pouiller }
74*4a5fb1bbSJérôme Pouiller
75*4a5fb1bbSJérôme Pouiller seq_printf(seq, "%-24s %12s %12s %12s\n", "", "global", "iface 0", "iface 1");
76*4a5fb1bbSJérôme Pouiller
77*4a5fb1bbSJérôme Pouiller #define PUT_COUNTER(name) \
78*4a5fb1bbSJérôme Pouiller seq_printf(seq, "%-24s %12d %12d %12d\n", #name, \
79*4a5fb1bbSJérôme Pouiller le32_to_cpu(counters[2].count_##name), \
80*4a5fb1bbSJérôme Pouiller le32_to_cpu(counters[0].count_##name), \
81*4a5fb1bbSJérôme Pouiller le32_to_cpu(counters[1].count_##name))
82*4a5fb1bbSJérôme Pouiller
83*4a5fb1bbSJérôme Pouiller PUT_COUNTER(tx_frames);
84*4a5fb1bbSJérôme Pouiller PUT_COUNTER(tx_frames_multicast);
85*4a5fb1bbSJérôme Pouiller PUT_COUNTER(tx_frames_success);
86*4a5fb1bbSJérôme Pouiller PUT_COUNTER(tx_frames_retried);
87*4a5fb1bbSJérôme Pouiller PUT_COUNTER(tx_frames_multi_retried);
88*4a5fb1bbSJérôme Pouiller PUT_COUNTER(tx_frames_failed);
89*4a5fb1bbSJérôme Pouiller
90*4a5fb1bbSJérôme Pouiller PUT_COUNTER(ack_failed);
91*4a5fb1bbSJérôme Pouiller PUT_COUNTER(rts_success);
92*4a5fb1bbSJérôme Pouiller PUT_COUNTER(rts_failed);
93*4a5fb1bbSJérôme Pouiller
94*4a5fb1bbSJérôme Pouiller PUT_COUNTER(rx_frames);
95*4a5fb1bbSJérôme Pouiller PUT_COUNTER(rx_frames_multicast);
96*4a5fb1bbSJérôme Pouiller PUT_COUNTER(rx_frames_success);
97*4a5fb1bbSJérôme Pouiller PUT_COUNTER(rx_frames_failed);
98*4a5fb1bbSJérôme Pouiller PUT_COUNTER(drop_plcp);
99*4a5fb1bbSJérôme Pouiller PUT_COUNTER(drop_fcs);
100*4a5fb1bbSJérôme Pouiller PUT_COUNTER(drop_no_key);
101*4a5fb1bbSJérôme Pouiller PUT_COUNTER(drop_decryption);
102*4a5fb1bbSJérôme Pouiller PUT_COUNTER(drop_tkip_mic);
103*4a5fb1bbSJérôme Pouiller PUT_COUNTER(drop_bip_mic);
104*4a5fb1bbSJérôme Pouiller PUT_COUNTER(drop_cmac_icv);
105*4a5fb1bbSJérôme Pouiller PUT_COUNTER(drop_cmac_replay);
106*4a5fb1bbSJérôme Pouiller PUT_COUNTER(drop_ccmp_replay);
107*4a5fb1bbSJérôme Pouiller PUT_COUNTER(drop_duplicate);
108*4a5fb1bbSJérôme Pouiller
109*4a5fb1bbSJérôme Pouiller PUT_COUNTER(rx_bcn_miss);
110*4a5fb1bbSJérôme Pouiller PUT_COUNTER(rx_bcn_success);
111*4a5fb1bbSJérôme Pouiller PUT_COUNTER(rx_bcn_dtim);
112*4a5fb1bbSJérôme Pouiller PUT_COUNTER(rx_bcn_dtim_aid0_clr);
113*4a5fb1bbSJérôme Pouiller PUT_COUNTER(rx_bcn_dtim_aid0_set);
114*4a5fb1bbSJérôme Pouiller
115*4a5fb1bbSJérôme Pouiller #undef PUT_COUNTER
116*4a5fb1bbSJérôme Pouiller
117*4a5fb1bbSJérôme Pouiller for (i = 0; i < ARRAY_SIZE(counters[0].reserved); i++)
118*4a5fb1bbSJérôme Pouiller seq_printf(seq, "reserved[%02d]%12s %12d %12d %12d\n", i, "",
119*4a5fb1bbSJérôme Pouiller le32_to_cpu(counters[2].reserved[i]),
120*4a5fb1bbSJérôme Pouiller le32_to_cpu(counters[0].reserved[i]),
121*4a5fb1bbSJérôme Pouiller le32_to_cpu(counters[1].reserved[i]));
122*4a5fb1bbSJérôme Pouiller
123*4a5fb1bbSJérôme Pouiller return 0;
124*4a5fb1bbSJérôme Pouiller }
125*4a5fb1bbSJérôme Pouiller DEFINE_SHOW_ATTRIBUTE(wfx_counters);
126*4a5fb1bbSJérôme Pouiller
127*4a5fb1bbSJérôme Pouiller static const char * const channel_names[] = {
128*4a5fb1bbSJérôme Pouiller [0] = "1M",
129*4a5fb1bbSJérôme Pouiller [1] = "2M",
130*4a5fb1bbSJérôme Pouiller [2] = "5.5M",
131*4a5fb1bbSJérôme Pouiller [3] = "11M",
132*4a5fb1bbSJérôme Pouiller /* Entries 4 and 5 does not exist */
133*4a5fb1bbSJérôme Pouiller [6] = "6M",
134*4a5fb1bbSJérôme Pouiller [7] = "9M",
135*4a5fb1bbSJérôme Pouiller [8] = "12M",
136*4a5fb1bbSJérôme Pouiller [9] = "18M",
137*4a5fb1bbSJérôme Pouiller [10] = "24M",
138*4a5fb1bbSJérôme Pouiller [11] = "36M",
139*4a5fb1bbSJérôme Pouiller [12] = "48M",
140*4a5fb1bbSJérôme Pouiller [13] = "54M",
141*4a5fb1bbSJérôme Pouiller [14] = "MCS0",
142*4a5fb1bbSJérôme Pouiller [15] = "MCS1",
143*4a5fb1bbSJérôme Pouiller [16] = "MCS2",
144*4a5fb1bbSJérôme Pouiller [17] = "MCS3",
145*4a5fb1bbSJérôme Pouiller [18] = "MCS4",
146*4a5fb1bbSJérôme Pouiller [19] = "MCS5",
147*4a5fb1bbSJérôme Pouiller [20] = "MCS6",
148*4a5fb1bbSJérôme Pouiller [21] = "MCS7",
149*4a5fb1bbSJérôme Pouiller };
150*4a5fb1bbSJérôme Pouiller
wfx_rx_stats_show(struct seq_file * seq,void * v)151*4a5fb1bbSJérôme Pouiller static int wfx_rx_stats_show(struct seq_file *seq, void *v)
152*4a5fb1bbSJérôme Pouiller {
153*4a5fb1bbSJérôme Pouiller struct wfx_dev *wdev = seq->private;
154*4a5fb1bbSJérôme Pouiller struct wfx_hif_rx_stats *st = &wdev->rx_stats;
155*4a5fb1bbSJérôme Pouiller int i;
156*4a5fb1bbSJérôme Pouiller
157*4a5fb1bbSJérôme Pouiller mutex_lock(&wdev->rx_stats_lock);
158*4a5fb1bbSJérôme Pouiller seq_printf(seq, "Timestamp: %dus\n", st->date);
159*4a5fb1bbSJérôme Pouiller seq_printf(seq, "Low power clock: frequency %uHz, external %s\n",
160*4a5fb1bbSJérôme Pouiller le32_to_cpu(st->pwr_clk_freq), st->is_ext_pwr_clk ? "yes" : "no");
161*4a5fb1bbSJérôme Pouiller seq_printf(seq, "Num. of frames: %d, PER (x10e4): %d, Throughput: %dKbps/s\n",
162*4a5fb1bbSJérôme Pouiller st->nb_rx_frame, st->per_total, st->throughput);
163*4a5fb1bbSJérôme Pouiller seq_puts(seq, " Num. of PER RSSI SNR CFO\n");
164*4a5fb1bbSJérôme Pouiller seq_puts(seq, " frames (x10e4) (dBm) (dB) (kHz)\n");
165*4a5fb1bbSJérôme Pouiller for (i = 0; i < ARRAY_SIZE(channel_names); i++) {
166*4a5fb1bbSJérôme Pouiller if (channel_names[i])
167*4a5fb1bbSJérôme Pouiller seq_printf(seq, "%5s %8d %8d %8d %8d %8d\n",
168*4a5fb1bbSJérôme Pouiller channel_names[i],
169*4a5fb1bbSJérôme Pouiller le32_to_cpu(st->nb_rx_by_rate[i]),
170*4a5fb1bbSJérôme Pouiller le16_to_cpu(st->per[i]),
171*4a5fb1bbSJérôme Pouiller (s16)le16_to_cpu(st->rssi[i]) / 100,
172*4a5fb1bbSJérôme Pouiller (s16)le16_to_cpu(st->snr[i]) / 100,
173*4a5fb1bbSJérôme Pouiller (s16)le16_to_cpu(st->cfo[i]));
174*4a5fb1bbSJérôme Pouiller }
175*4a5fb1bbSJérôme Pouiller mutex_unlock(&wdev->rx_stats_lock);
176*4a5fb1bbSJérôme Pouiller
177*4a5fb1bbSJérôme Pouiller return 0;
178*4a5fb1bbSJérôme Pouiller }
179*4a5fb1bbSJérôme Pouiller DEFINE_SHOW_ATTRIBUTE(wfx_rx_stats);
180*4a5fb1bbSJérôme Pouiller
wfx_tx_power_loop_show(struct seq_file * seq,void * v)181*4a5fb1bbSJérôme Pouiller static int wfx_tx_power_loop_show(struct seq_file *seq, void *v)
182*4a5fb1bbSJérôme Pouiller {
183*4a5fb1bbSJérôme Pouiller struct wfx_dev *wdev = seq->private;
184*4a5fb1bbSJérôme Pouiller struct wfx_hif_tx_power_loop_info *st = &wdev->tx_power_loop_info;
185*4a5fb1bbSJérôme Pouiller int tmp;
186*4a5fb1bbSJérôme Pouiller
187*4a5fb1bbSJérôme Pouiller mutex_lock(&wdev->tx_power_loop_info_lock);
188*4a5fb1bbSJérôme Pouiller tmp = le16_to_cpu(st->tx_gain_dig);
189*4a5fb1bbSJérôme Pouiller seq_printf(seq, "Tx gain digital: %d\n", tmp);
190*4a5fb1bbSJérôme Pouiller tmp = le16_to_cpu(st->tx_gain_pa);
191*4a5fb1bbSJérôme Pouiller seq_printf(seq, "Tx gain PA: %d\n", tmp);
192*4a5fb1bbSJérôme Pouiller tmp = (s16)le16_to_cpu(st->target_pout);
193*4a5fb1bbSJérôme Pouiller seq_printf(seq, "Target Pout: %d.%02d dBm\n", tmp / 4, (tmp % 4) * 25);
194*4a5fb1bbSJérôme Pouiller tmp = (s16)le16_to_cpu(st->p_estimation);
195*4a5fb1bbSJérôme Pouiller seq_printf(seq, "FEM Pout: %d.%02d dBm\n", tmp / 4, (tmp % 4) * 25);
196*4a5fb1bbSJérôme Pouiller tmp = le16_to_cpu(st->vpdet);
197*4a5fb1bbSJérôme Pouiller seq_printf(seq, "Vpdet: %d mV\n", tmp);
198*4a5fb1bbSJérôme Pouiller seq_printf(seq, "Measure index: %d\n", st->measurement_index);
199*4a5fb1bbSJérôme Pouiller mutex_unlock(&wdev->tx_power_loop_info_lock);
200*4a5fb1bbSJérôme Pouiller
201*4a5fb1bbSJérôme Pouiller return 0;
202*4a5fb1bbSJérôme Pouiller }
203*4a5fb1bbSJérôme Pouiller DEFINE_SHOW_ATTRIBUTE(wfx_tx_power_loop);
204*4a5fb1bbSJérôme Pouiller
wfx_send_pds_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)205*4a5fb1bbSJérôme Pouiller static ssize_t wfx_send_pds_write(struct file *file, const char __user *user_buf,
206*4a5fb1bbSJérôme Pouiller size_t count, loff_t *ppos)
207*4a5fb1bbSJérôme Pouiller {
208*4a5fb1bbSJérôme Pouiller struct wfx_dev *wdev = file->private_data;
209*4a5fb1bbSJérôme Pouiller char *buf;
210*4a5fb1bbSJérôme Pouiller int ret;
211*4a5fb1bbSJérôme Pouiller
212*4a5fb1bbSJérôme Pouiller if (*ppos != 0) {
213*4a5fb1bbSJérôme Pouiller dev_dbg(wdev->dev, "PDS data must be written in one transaction");
214*4a5fb1bbSJérôme Pouiller return -EBUSY;
215*4a5fb1bbSJérôme Pouiller }
216*4a5fb1bbSJérôme Pouiller buf = memdup_user(user_buf, count);
217*4a5fb1bbSJérôme Pouiller if (IS_ERR(buf))
218*4a5fb1bbSJérôme Pouiller return PTR_ERR(buf);
219*4a5fb1bbSJérôme Pouiller *ppos = *ppos + count;
220*4a5fb1bbSJérôme Pouiller ret = wfx_send_pds(wdev, buf, count);
221*4a5fb1bbSJérôme Pouiller kfree(buf);
222*4a5fb1bbSJérôme Pouiller if (ret < 0)
223*4a5fb1bbSJérôme Pouiller return ret;
224*4a5fb1bbSJérôme Pouiller return count;
225*4a5fb1bbSJérôme Pouiller }
226*4a5fb1bbSJérôme Pouiller
227*4a5fb1bbSJérôme Pouiller static const struct file_operations wfx_send_pds_fops = {
228*4a5fb1bbSJérôme Pouiller .open = simple_open,
229*4a5fb1bbSJérôme Pouiller .write = wfx_send_pds_write,
230*4a5fb1bbSJérôme Pouiller };
231*4a5fb1bbSJérôme Pouiller
232*4a5fb1bbSJérôme Pouiller struct dbgfs_hif_msg {
233*4a5fb1bbSJérôme Pouiller struct wfx_dev *wdev;
234*4a5fb1bbSJérôme Pouiller struct completion complete;
235*4a5fb1bbSJérôme Pouiller u8 reply[1024];
236*4a5fb1bbSJérôme Pouiller int ret;
237*4a5fb1bbSJérôme Pouiller };
238*4a5fb1bbSJérôme Pouiller
wfx_send_hif_msg_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)239*4a5fb1bbSJérôme Pouiller static ssize_t wfx_send_hif_msg_write(struct file *file, const char __user *user_buf,
240*4a5fb1bbSJérôme Pouiller size_t count, loff_t *ppos)
241*4a5fb1bbSJérôme Pouiller {
242*4a5fb1bbSJérôme Pouiller struct dbgfs_hif_msg *context = file->private_data;
243*4a5fb1bbSJérôme Pouiller struct wfx_dev *wdev = context->wdev;
244*4a5fb1bbSJérôme Pouiller struct wfx_hif_msg *request;
245*4a5fb1bbSJérôme Pouiller
246*4a5fb1bbSJérôme Pouiller if (completion_done(&context->complete)) {
247*4a5fb1bbSJérôme Pouiller dev_dbg(wdev->dev, "read previous result before start a new one\n");
248*4a5fb1bbSJérôme Pouiller return -EBUSY;
249*4a5fb1bbSJérôme Pouiller }
250*4a5fb1bbSJérôme Pouiller if (count < sizeof(struct wfx_hif_msg))
251*4a5fb1bbSJérôme Pouiller return -EINVAL;
252*4a5fb1bbSJérôme Pouiller
253*4a5fb1bbSJérôme Pouiller /* wfx_cmd_send() checks that reply buffer is wide enough, but does not return precise
254*4a5fb1bbSJérôme Pouiller * length read. User have to know how many bytes should be read. Filling reply buffer with a
255*4a5fb1bbSJérôme Pouiller * memory pattern may help user.
256*4a5fb1bbSJérôme Pouiller */
257*4a5fb1bbSJérôme Pouiller memset(context->reply, 0xFF, sizeof(context->reply));
258*4a5fb1bbSJérôme Pouiller request = memdup_user(user_buf, count);
259*4a5fb1bbSJérôme Pouiller if (IS_ERR(request))
260*4a5fb1bbSJérôme Pouiller return PTR_ERR(request);
261*4a5fb1bbSJérôme Pouiller if (le16_to_cpu(request->len) != count) {
262*4a5fb1bbSJérôme Pouiller kfree(request);
263*4a5fb1bbSJérôme Pouiller return -EINVAL;
264*4a5fb1bbSJérôme Pouiller }
265*4a5fb1bbSJérôme Pouiller context->ret = wfx_cmd_send(wdev, request, context->reply, sizeof(context->reply), false);
266*4a5fb1bbSJérôme Pouiller
267*4a5fb1bbSJérôme Pouiller kfree(request);
268*4a5fb1bbSJérôme Pouiller complete(&context->complete);
269*4a5fb1bbSJérôme Pouiller return count;
270*4a5fb1bbSJérôme Pouiller }
271*4a5fb1bbSJérôme Pouiller
wfx_send_hif_msg_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)272*4a5fb1bbSJérôme Pouiller static ssize_t wfx_send_hif_msg_read(struct file *file, char __user *user_buf,
273*4a5fb1bbSJérôme Pouiller size_t count, loff_t *ppos)
274*4a5fb1bbSJérôme Pouiller {
275*4a5fb1bbSJérôme Pouiller struct dbgfs_hif_msg *context = file->private_data;
276*4a5fb1bbSJérôme Pouiller int ret;
277*4a5fb1bbSJérôme Pouiller
278*4a5fb1bbSJérôme Pouiller if (count > sizeof(context->reply))
279*4a5fb1bbSJérôme Pouiller return -EINVAL;
280*4a5fb1bbSJérôme Pouiller ret = wait_for_completion_interruptible(&context->complete);
281*4a5fb1bbSJérôme Pouiller if (ret)
282*4a5fb1bbSJérôme Pouiller return ret;
283*4a5fb1bbSJérôme Pouiller if (context->ret < 0)
284*4a5fb1bbSJérôme Pouiller return context->ret;
285*4a5fb1bbSJérôme Pouiller /* Be careful, write() is waiting for a full message while read() only returns a payload */
286*4a5fb1bbSJérôme Pouiller if (copy_to_user(user_buf, context->reply, count))
287*4a5fb1bbSJérôme Pouiller return -EFAULT;
288*4a5fb1bbSJérôme Pouiller
289*4a5fb1bbSJérôme Pouiller return count;
290*4a5fb1bbSJérôme Pouiller }
291*4a5fb1bbSJérôme Pouiller
wfx_send_hif_msg_open(struct inode * inode,struct file * file)292*4a5fb1bbSJérôme Pouiller static int wfx_send_hif_msg_open(struct inode *inode, struct file *file)
293*4a5fb1bbSJérôme Pouiller {
294*4a5fb1bbSJérôme Pouiller struct dbgfs_hif_msg *context = kzalloc(sizeof(*context), GFP_KERNEL);
295*4a5fb1bbSJérôme Pouiller
296*4a5fb1bbSJérôme Pouiller if (!context)
297*4a5fb1bbSJérôme Pouiller return -ENOMEM;
298*4a5fb1bbSJérôme Pouiller context->wdev = inode->i_private;
299*4a5fb1bbSJérôme Pouiller init_completion(&context->complete);
300*4a5fb1bbSJérôme Pouiller file->private_data = context;
301*4a5fb1bbSJérôme Pouiller return 0;
302*4a5fb1bbSJérôme Pouiller }
303*4a5fb1bbSJérôme Pouiller
wfx_send_hif_msg_release(struct inode * inode,struct file * file)304*4a5fb1bbSJérôme Pouiller static int wfx_send_hif_msg_release(struct inode *inode, struct file *file)
305*4a5fb1bbSJérôme Pouiller {
306*4a5fb1bbSJérôme Pouiller struct dbgfs_hif_msg *context = file->private_data;
307*4a5fb1bbSJérôme Pouiller
308*4a5fb1bbSJérôme Pouiller kfree(context);
309*4a5fb1bbSJérôme Pouiller return 0;
310*4a5fb1bbSJérôme Pouiller }
311*4a5fb1bbSJérôme Pouiller
312*4a5fb1bbSJérôme Pouiller static const struct file_operations wfx_send_hif_msg_fops = {
313*4a5fb1bbSJérôme Pouiller .open = wfx_send_hif_msg_open,
314*4a5fb1bbSJérôme Pouiller .release = wfx_send_hif_msg_release,
315*4a5fb1bbSJérôme Pouiller .write = wfx_send_hif_msg_write,
316*4a5fb1bbSJérôme Pouiller .read = wfx_send_hif_msg_read,
317*4a5fb1bbSJérôme Pouiller };
318*4a5fb1bbSJérôme Pouiller
wfx_debug_init(struct wfx_dev * wdev)319*4a5fb1bbSJérôme Pouiller int wfx_debug_init(struct wfx_dev *wdev)
320*4a5fb1bbSJérôme Pouiller {
321*4a5fb1bbSJérôme Pouiller struct dentry *d;
322*4a5fb1bbSJérôme Pouiller
323*4a5fb1bbSJérôme Pouiller d = debugfs_create_dir("wfx", wdev->hw->wiphy->debugfsdir);
324*4a5fb1bbSJérôme Pouiller debugfs_create_file("counters", 0444, d, wdev, &wfx_counters_fops);
325*4a5fb1bbSJérôme Pouiller debugfs_create_file("rx_stats", 0444, d, wdev, &wfx_rx_stats_fops);
326*4a5fb1bbSJérôme Pouiller debugfs_create_file("tx_power_loop", 0444, d, wdev, &wfx_tx_power_loop_fops);
327*4a5fb1bbSJérôme Pouiller debugfs_create_file("send_pds", 0200, d, wdev, &wfx_send_pds_fops);
328*4a5fb1bbSJérôme Pouiller debugfs_create_file("send_hif_msg", 0600, d, wdev, &wfx_send_hif_msg_fops);
329*4a5fb1bbSJérôme Pouiller
330*4a5fb1bbSJérôme Pouiller return 0;
331*4a5fb1bbSJérôme Pouiller }
332