]>
Commit | Line | Data |
---|---|---|
5e3dd157 KV |
1 | /* |
2 | * Copyright (c) 2005-2011 Atheros Communications Inc. | |
3 | * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. | |
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 | ||
21 | #include "core.h" | |
22 | #include "debug.h" | |
23 | ||
24 | static int ath10k_printk(const char *level, const char *fmt, ...) | |
25 | { | |
26 | struct va_format vaf; | |
27 | va_list args; | |
28 | int rtn; | |
29 | ||
30 | va_start(args, fmt); | |
31 | ||
32 | vaf.fmt = fmt; | |
33 | vaf.va = &args; | |
34 | ||
35 | rtn = printk("%sath10k: %pV", level, &vaf); | |
36 | ||
37 | va_end(args); | |
38 | ||
39 | return rtn; | |
40 | } | |
41 | ||
42 | int ath10k_info(const char *fmt, ...) | |
43 | { | |
44 | struct va_format vaf = { | |
45 | .fmt = fmt, | |
46 | }; | |
47 | va_list args; | |
48 | int ret; | |
49 | ||
50 | va_start(args, fmt); | |
51 | vaf.va = &args; | |
52 | ret = ath10k_printk(KERN_INFO, "%pV", &vaf); | |
53 | trace_ath10k_log_info(&vaf); | |
54 | va_end(args); | |
55 | ||
56 | return ret; | |
57 | } | |
58 | EXPORT_SYMBOL(ath10k_info); | |
59 | ||
60 | int ath10k_err(const char *fmt, ...) | |
61 | { | |
62 | struct va_format vaf = { | |
63 | .fmt = fmt, | |
64 | }; | |
65 | va_list args; | |
66 | int ret; | |
67 | ||
68 | va_start(args, fmt); | |
69 | vaf.va = &args; | |
70 | ret = ath10k_printk(KERN_ERR, "%pV", &vaf); | |
71 | trace_ath10k_log_err(&vaf); | |
72 | va_end(args); | |
73 | ||
74 | return ret; | |
75 | } | |
76 | EXPORT_SYMBOL(ath10k_err); | |
77 | ||
78 | int ath10k_warn(const char *fmt, ...) | |
79 | { | |
80 | struct va_format vaf = { | |
81 | .fmt = fmt, | |
82 | }; | |
83 | va_list args; | |
84 | int ret = 0; | |
85 | ||
86 | va_start(args, fmt); | |
87 | vaf.va = &args; | |
88 | ||
89 | if (net_ratelimit()) | |
90 | ret = ath10k_printk(KERN_WARNING, "%pV", &vaf); | |
91 | ||
92 | trace_ath10k_log_warn(&vaf); | |
93 | ||
94 | va_end(args); | |
95 | ||
96 | return ret; | |
97 | } | |
98 | EXPORT_SYMBOL(ath10k_warn); | |
99 | ||
100 | #ifdef CONFIG_ATH10K_DEBUGFS | |
101 | ||
102 | void ath10k_debug_read_service_map(struct ath10k *ar, | |
103 | void *service_map, | |
104 | size_t map_size) | |
105 | { | |
106 | memcpy(ar->debug.wmi_service_bitmap, service_map, map_size); | |
107 | } | |
108 | ||
109 | static ssize_t ath10k_read_wmi_services(struct file *file, | |
110 | char __user *user_buf, | |
111 | size_t count, loff_t *ppos) | |
112 | { | |
113 | struct ath10k *ar = file->private_data; | |
114 | char *buf; | |
115 | unsigned int len = 0, buf_len = 1500; | |
116 | const char *status; | |
117 | ssize_t ret_cnt; | |
118 | int i; | |
119 | ||
120 | buf = kzalloc(buf_len, GFP_KERNEL); | |
121 | if (!buf) | |
122 | return -ENOMEM; | |
123 | ||
124 | mutex_lock(&ar->conf_mutex); | |
125 | ||
126 | if (len > buf_len) | |
127 | len = buf_len; | |
128 | ||
129 | for (i = 0; i < WMI_SERVICE_LAST; i++) { | |
130 | if (WMI_SERVICE_IS_ENABLED(ar->debug.wmi_service_bitmap, i)) | |
131 | status = "enabled"; | |
132 | else | |
133 | status = "disabled"; | |
134 | ||
135 | len += scnprintf(buf + len, buf_len - len, | |
136 | "0x%02x - %20s - %s\n", | |
137 | i, wmi_service_name(i), status); | |
138 | } | |
139 | ||
140 | ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); | |
141 | ||
142 | mutex_unlock(&ar->conf_mutex); | |
143 | ||
144 | kfree(buf); | |
145 | return ret_cnt; | |
146 | } | |
147 | ||
148 | static const struct file_operations fops_wmi_services = { | |
149 | .read = ath10k_read_wmi_services, | |
150 | .open = simple_open, | |
151 | .owner = THIS_MODULE, | |
152 | .llseek = default_llseek, | |
153 | }; | |
154 | ||
155 | void ath10k_debug_read_target_stats(struct ath10k *ar, | |
156 | struct wmi_stats_event *ev) | |
157 | { | |
158 | u8 *tmp = ev->data; | |
159 | struct ath10k_target_stats *stats; | |
160 | int num_pdev_stats, num_vdev_stats, num_peer_stats; | |
161 | struct wmi_pdev_stats *ps; | |
162 | int i; | |
163 | ||
87571bf0 | 164 | spin_lock_bh(&ar->data_lock); |
5e3dd157 KV |
165 | |
166 | stats = &ar->debug.target_stats; | |
167 | ||
168 | num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); /* 0 or 1 */ | |
169 | num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); /* 0 or max vdevs */ | |
170 | num_peer_stats = __le32_to_cpu(ev->num_peer_stats); /* 0 or max peers */ | |
171 | ||
172 | if (num_pdev_stats) { | |
173 | ps = (struct wmi_pdev_stats *)tmp; | |
174 | ||
175 | stats->ch_noise_floor = __le32_to_cpu(ps->chan_nf); | |
176 | stats->tx_frame_count = __le32_to_cpu(ps->tx_frame_count); | |
177 | stats->rx_frame_count = __le32_to_cpu(ps->rx_frame_count); | |
178 | stats->rx_clear_count = __le32_to_cpu(ps->rx_clear_count); | |
179 | stats->cycle_count = __le32_to_cpu(ps->cycle_count); | |
180 | stats->phy_err_count = __le32_to_cpu(ps->phy_err_count); | |
181 | stats->chan_tx_power = __le32_to_cpu(ps->chan_tx_pwr); | |
182 | ||
183 | stats->comp_queued = __le32_to_cpu(ps->wal.tx.comp_queued); | |
184 | stats->comp_delivered = | |
185 | __le32_to_cpu(ps->wal.tx.comp_delivered); | |
186 | stats->msdu_enqued = __le32_to_cpu(ps->wal.tx.msdu_enqued); | |
187 | stats->mpdu_enqued = __le32_to_cpu(ps->wal.tx.mpdu_enqued); | |
188 | stats->wmm_drop = __le32_to_cpu(ps->wal.tx.wmm_drop); | |
189 | stats->local_enqued = __le32_to_cpu(ps->wal.tx.local_enqued); | |
190 | stats->local_freed = __le32_to_cpu(ps->wal.tx.local_freed); | |
191 | stats->hw_queued = __le32_to_cpu(ps->wal.tx.hw_queued); | |
192 | stats->hw_reaped = __le32_to_cpu(ps->wal.tx.hw_reaped); | |
193 | stats->underrun = __le32_to_cpu(ps->wal.tx.underrun); | |
194 | stats->tx_abort = __le32_to_cpu(ps->wal.tx.tx_abort); | |
195 | stats->mpdus_requed = __le32_to_cpu(ps->wal.tx.mpdus_requed); | |
196 | stats->tx_ko = __le32_to_cpu(ps->wal.tx.tx_ko); | |
197 | stats->data_rc = __le32_to_cpu(ps->wal.tx.data_rc); | |
198 | stats->self_triggers = __le32_to_cpu(ps->wal.tx.self_triggers); | |
199 | stats->sw_retry_failure = | |
200 | __le32_to_cpu(ps->wal.tx.sw_retry_failure); | |
201 | stats->illgl_rate_phy_err = | |
202 | __le32_to_cpu(ps->wal.tx.illgl_rate_phy_err); | |
203 | stats->pdev_cont_xretry = | |
204 | __le32_to_cpu(ps->wal.tx.pdev_cont_xretry); | |
205 | stats->pdev_tx_timeout = | |
206 | __le32_to_cpu(ps->wal.tx.pdev_tx_timeout); | |
207 | stats->pdev_resets = __le32_to_cpu(ps->wal.tx.pdev_resets); | |
208 | stats->phy_underrun = __le32_to_cpu(ps->wal.tx.phy_underrun); | |
209 | stats->txop_ovf = __le32_to_cpu(ps->wal.tx.txop_ovf); | |
210 | ||
211 | stats->mid_ppdu_route_change = | |
212 | __le32_to_cpu(ps->wal.rx.mid_ppdu_route_change); | |
213 | stats->status_rcvd = __le32_to_cpu(ps->wal.rx.status_rcvd); | |
214 | stats->r0_frags = __le32_to_cpu(ps->wal.rx.r0_frags); | |
215 | stats->r1_frags = __le32_to_cpu(ps->wal.rx.r1_frags); | |
216 | stats->r2_frags = __le32_to_cpu(ps->wal.rx.r2_frags); | |
217 | stats->r3_frags = __le32_to_cpu(ps->wal.rx.r3_frags); | |
218 | stats->htt_msdus = __le32_to_cpu(ps->wal.rx.htt_msdus); | |
219 | stats->htt_mpdus = __le32_to_cpu(ps->wal.rx.htt_mpdus); | |
220 | stats->loc_msdus = __le32_to_cpu(ps->wal.rx.loc_msdus); | |
221 | stats->loc_mpdus = __le32_to_cpu(ps->wal.rx.loc_mpdus); | |
222 | stats->oversize_amsdu = | |
223 | __le32_to_cpu(ps->wal.rx.oversize_amsdu); | |
224 | stats->phy_errs = __le32_to_cpu(ps->wal.rx.phy_errs); | |
225 | stats->phy_err_drop = __le32_to_cpu(ps->wal.rx.phy_err_drop); | |
226 | stats->mpdu_errs = __le32_to_cpu(ps->wal.rx.mpdu_errs); | |
227 | ||
228 | tmp += sizeof(struct wmi_pdev_stats); | |
229 | } | |
230 | ||
231 | /* 0 or max vdevs */ | |
232 | /* Currently firmware does not support VDEV stats */ | |
233 | if (num_vdev_stats) { | |
234 | struct wmi_vdev_stats *vdev_stats; | |
235 | ||
236 | for (i = 0; i < num_vdev_stats; i++) { | |
237 | vdev_stats = (struct wmi_vdev_stats *)tmp; | |
238 | tmp += sizeof(struct wmi_vdev_stats); | |
239 | } | |
240 | } | |
241 | ||
242 | if (num_peer_stats) { | |
243 | struct wmi_peer_stats *peer_stats; | |
244 | struct ath10k_peer_stat *s; | |
245 | ||
246 | stats->peers = num_peer_stats; | |
247 | ||
248 | for (i = 0; i < num_peer_stats; i++) { | |
249 | peer_stats = (struct wmi_peer_stats *)tmp; | |
250 | s = &stats->peer_stat[i]; | |
251 | ||
252 | WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_stats->peer_macaddr, | |
253 | s->peer_macaddr); | |
254 | s->peer_rssi = __le32_to_cpu(peer_stats->peer_rssi); | |
255 | s->peer_tx_rate = | |
256 | __le32_to_cpu(peer_stats->peer_tx_rate); | |
257 | ||
258 | tmp += sizeof(struct wmi_peer_stats); | |
259 | } | |
260 | } | |
261 | ||
87571bf0 | 262 | spin_unlock_bh(&ar->data_lock); |
5e3dd157 KV |
263 | mutex_unlock(&ar->conf_mutex); |
264 | complete(&ar->debug.event_stats_compl); | |
265 | } | |
266 | ||
267 | static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf, | |
268 | size_t count, loff_t *ppos) | |
269 | { | |
270 | struct ath10k *ar = file->private_data; | |
271 | struct ath10k_target_stats *fw_stats; | |
87571bf0 | 272 | char *buf = NULL; |
5e3dd157 | 273 | unsigned int len = 0, buf_len = 2500; |
87571bf0 | 274 | ssize_t ret_cnt = 0; |
5e3dd157 KV |
275 | long left; |
276 | int i; | |
277 | int ret; | |
278 | ||
279 | fw_stats = &ar->debug.target_stats; | |
280 | ||
87571bf0 MK |
281 | mutex_lock(&ar->conf_mutex); |
282 | ||
283 | if (ar->state != ATH10K_STATE_ON) | |
284 | goto exit; | |
285 | ||
5e3dd157 KV |
286 | buf = kzalloc(buf_len, GFP_KERNEL); |
287 | if (!buf) | |
87571bf0 | 288 | goto exit; |
5e3dd157 KV |
289 | |
290 | ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT); | |
291 | if (ret) { | |
292 | ath10k_warn("could not request stats (%d)\n", ret); | |
87571bf0 | 293 | goto exit; |
5e3dd157 KV |
294 | } |
295 | ||
296 | left = wait_for_completion_timeout(&ar->debug.event_stats_compl, 1*HZ); | |
87571bf0 MK |
297 | if (left <= 0) |
298 | goto exit; | |
5e3dd157 | 299 | |
87571bf0 | 300 | spin_lock_bh(&ar->data_lock); |
5e3dd157 KV |
301 | len += scnprintf(buf + len, buf_len - len, "\n"); |
302 | len += scnprintf(buf + len, buf_len - len, "%30s\n", | |
303 | "ath10k PDEV stats"); | |
304 | len += scnprintf(buf + len, buf_len - len, "%30s\n\n", | |
305 | "================="); | |
306 | ||
307 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
308 | "Channel noise floor", fw_stats->ch_noise_floor); | |
309 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | |
310 | "Channel TX power", fw_stats->chan_tx_power); | |
311 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | |
312 | "TX frame count", fw_stats->tx_frame_count); | |
313 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | |
314 | "RX frame count", fw_stats->rx_frame_count); | |
315 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | |
316 | "RX clear count", fw_stats->rx_clear_count); | |
317 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | |
318 | "Cycle count", fw_stats->cycle_count); | |
319 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | |
320 | "PHY error count", fw_stats->phy_err_count); | |
321 | ||
322 | len += scnprintf(buf + len, buf_len - len, "\n"); | |
323 | len += scnprintf(buf + len, buf_len - len, "%30s\n", | |
324 | "ath10k PDEV TX stats"); | |
325 | len += scnprintf(buf + len, buf_len - len, "%30s\n\n", | |
326 | "================="); | |
327 | ||
328 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
329 | "HTT cookies queued", fw_stats->comp_queued); | |
330 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
331 | "HTT cookies disp.", fw_stats->comp_delivered); | |
332 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
333 | "MSDU queued", fw_stats->msdu_enqued); | |
334 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
335 | "MPDU queued", fw_stats->mpdu_enqued); | |
336 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
337 | "MSDUs dropped", fw_stats->wmm_drop); | |
338 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
339 | "Local enqued", fw_stats->local_enqued); | |
340 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
341 | "Local freed", fw_stats->local_freed); | |
342 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
343 | "HW queued", fw_stats->hw_queued); | |
344 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
345 | "PPDUs reaped", fw_stats->hw_reaped); | |
346 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
347 | "Num underruns", fw_stats->underrun); | |
348 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
349 | "PPDUs cleaned", fw_stats->tx_abort); | |
350 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
351 | "MPDUs requed", fw_stats->mpdus_requed); | |
352 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
353 | "Excessive retries", fw_stats->tx_ko); | |
354 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
355 | "HW rate", fw_stats->data_rc); | |
356 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
357 | "Sched self tiggers", fw_stats->self_triggers); | |
358 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
359 | "Dropped due to SW retries", | |
360 | fw_stats->sw_retry_failure); | |
361 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
362 | "Illegal rate phy errors", | |
363 | fw_stats->illgl_rate_phy_err); | |
364 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
365 | "Pdev continous xretry", fw_stats->pdev_cont_xretry); | |
366 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
367 | "TX timeout", fw_stats->pdev_tx_timeout); | |
368 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
369 | "PDEV resets", fw_stats->pdev_resets); | |
370 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
371 | "PHY underrun", fw_stats->phy_underrun); | |
372 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
373 | "MPDU is more than txop limit", fw_stats->txop_ovf); | |
374 | ||
375 | len += scnprintf(buf + len, buf_len - len, "\n"); | |
376 | len += scnprintf(buf + len, buf_len - len, "%30s\n", | |
377 | "ath10k PDEV RX stats"); | |
378 | len += scnprintf(buf + len, buf_len - len, "%30s\n\n", | |
379 | "================="); | |
380 | ||
381 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
382 | "Mid PPDU route change", | |
383 | fw_stats->mid_ppdu_route_change); | |
384 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
385 | "Tot. number of statuses", fw_stats->status_rcvd); | |
386 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
387 | "Extra frags on rings 0", fw_stats->r0_frags); | |
388 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
389 | "Extra frags on rings 1", fw_stats->r1_frags); | |
390 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
391 | "Extra frags on rings 2", fw_stats->r2_frags); | |
392 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
393 | "Extra frags on rings 3", fw_stats->r3_frags); | |
394 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
395 | "MSDUs delivered to HTT", fw_stats->htt_msdus); | |
396 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
397 | "MPDUs delivered to HTT", fw_stats->htt_mpdus); | |
398 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
399 | "MSDUs delivered to stack", fw_stats->loc_msdus); | |
400 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
401 | "MPDUs delivered to stack", fw_stats->loc_mpdus); | |
402 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
403 | "Oversized AMSUs", fw_stats->oversize_amsdu); | |
404 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
405 | "PHY errors", fw_stats->phy_errs); | |
406 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
407 | "PHY errors drops", fw_stats->phy_err_drop); | |
408 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | |
409 | "MPDU errors (FCS, MIC, ENC)", fw_stats->mpdu_errs); | |
410 | ||
411 | len += scnprintf(buf + len, buf_len - len, "\n"); | |
412 | len += scnprintf(buf + len, buf_len - len, "%30s\n", | |
413 | "ath10k PEER stats"); | |
414 | len += scnprintf(buf + len, buf_len - len, "%30s\n\n", | |
415 | "================="); | |
416 | ||
417 | for (i = 0; i < fw_stats->peers; i++) { | |
418 | len += scnprintf(buf + len, buf_len - len, "%30s %pM\n", | |
419 | "Peer MAC address", | |
420 | fw_stats->peer_stat[i].peer_macaddr); | |
421 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | |
422 | "Peer RSSI", fw_stats->peer_stat[i].peer_rssi); | |
423 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | |
424 | "Peer TX rate", | |
425 | fw_stats->peer_stat[i].peer_tx_rate); | |
426 | len += scnprintf(buf + len, buf_len - len, "\n"); | |
427 | } | |
87571bf0 | 428 | spin_unlock_bh(&ar->data_lock); |
5e3dd157 KV |
429 | |
430 | if (len > buf_len) | |
431 | len = buf_len; | |
432 | ||
433 | ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); | |
434 | ||
87571bf0 | 435 | exit: |
5e3dd157 | 436 | mutex_unlock(&ar->conf_mutex); |
5e3dd157 KV |
437 | kfree(buf); |
438 | return ret_cnt; | |
439 | } | |
440 | ||
441 | static const struct file_operations fops_fw_stats = { | |
442 | .read = ath10k_read_fw_stats, | |
443 | .open = simple_open, | |
444 | .owner = THIS_MODULE, | |
445 | .llseek = default_llseek, | |
446 | }; | |
447 | ||
448 | int ath10k_debug_create(struct ath10k *ar) | |
449 | { | |
450 | ar->debug.debugfs_phy = debugfs_create_dir("ath10k", | |
451 | ar->hw->wiphy->debugfsdir); | |
452 | ||
453 | if (!ar->debug.debugfs_phy) | |
454 | return -ENOMEM; | |
455 | ||
456 | init_completion(&ar->debug.event_stats_compl); | |
457 | ||
458 | debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar, | |
459 | &fops_fw_stats); | |
460 | ||
461 | debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar, | |
462 | &fops_wmi_services); | |
463 | ||
464 | return 0; | |
465 | } | |
466 | #endif /* CONFIG_ATH10K_DEBUGFS */ | |
467 | ||
468 | #ifdef CONFIG_ATH10K_DEBUG | |
469 | void ath10k_dbg(enum ath10k_debug_mask mask, const char *fmt, ...) | |
470 | { | |
471 | struct va_format vaf; | |
472 | va_list args; | |
473 | ||
474 | va_start(args, fmt); | |
475 | ||
476 | vaf.fmt = fmt; | |
477 | vaf.va = &args; | |
478 | ||
479 | if (ath10k_debug_mask & mask) | |
480 | ath10k_printk(KERN_DEBUG, "%pV", &vaf); | |
481 | ||
482 | trace_ath10k_log_dbg(mask, &vaf); | |
483 | ||
484 | va_end(args); | |
485 | } | |
486 | EXPORT_SYMBOL(ath10k_dbg); | |
487 | ||
488 | void ath10k_dbg_dump(enum ath10k_debug_mask mask, | |
489 | const char *msg, const char *prefix, | |
490 | const void *buf, size_t len) | |
491 | { | |
492 | if (ath10k_debug_mask & mask) { | |
493 | if (msg) | |
494 | ath10k_dbg(mask, "%s\n", msg); | |
495 | ||
496 | print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); | |
497 | } | |
498 | ||
499 | /* tracing code doesn't like null strings :/ */ | |
500 | trace_ath10k_log_dbg_dump(msg ? msg : "", prefix ? prefix : "", | |
501 | buf, len); | |
502 | } | |
503 | EXPORT_SYMBOL(ath10k_dbg_dump); | |
504 | ||
505 | #endif /* CONFIG_ATH10K_DEBUG */ |