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 
164 	spin_lock_bh(&ar->data_lock);
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 
262 	spin_unlock_bh(&ar->data_lock);
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;
272 	char *buf = NULL;
273 	unsigned int len = 0, buf_len = 2500;
274 	ssize_t ret_cnt = 0;
275 	long left;
276 	int i;
277 	int ret;
278 
279 	fw_stats = &ar->debug.target_stats;
280 
281 	mutex_lock(&ar->conf_mutex);
282 
283 	if (ar->state != ATH10K_STATE_ON)
284 		goto exit;
285 
286 	buf = kzalloc(buf_len, GFP_KERNEL);
287 	if (!buf)
288 		goto exit;
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);
293 		goto exit;
294 	}
295 
296 	left = wait_for_completion_timeout(&ar->debug.event_stats_compl, 1*HZ);
297 	if (left <= 0)
298 		goto exit;
299 
300 	spin_lock_bh(&ar->data_lock);
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 	}
428 	spin_unlock_bh(&ar->data_lock);
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 
435 exit:
436 	mutex_unlock(&ar->conf_mutex);
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 static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
449 					     char __user *user_buf,
450 					     size_t count, loff_t *ppos)
451 {
452 	const char buf[] = "To simulate firmware crash write the keyword"
453 			   " `crash` to this file.\nThis will force firmware"
454 			   " to report a crash to the host system.\n";
455 	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
456 }
457 
458 static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
459 					      const char __user *user_buf,
460 					      size_t count, loff_t *ppos)
461 {
462 	struct ath10k *ar = file->private_data;
463 	char buf[32] = {};
464 	int ret;
465 
466 	mutex_lock(&ar->conf_mutex);
467 
468 	simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
469 	if (strcmp(buf, "crash") && strcmp(buf, "crash\n")) {
470 		ret = -EINVAL;
471 		goto exit;
472 	}
473 
474 	if (ar->state != ATH10K_STATE_ON &&
475 	    ar->state != ATH10K_STATE_RESTARTED) {
476 		ret = -ENETDOWN;
477 		goto exit;
478 	}
479 
480 	ath10k_info("simulating firmware crash\n");
481 
482 	ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
483 	if (ret)
484 		ath10k_warn("failed to force fw hang (%d)\n", ret);
485 
486 	if (ret == 0)
487 		ret = count;
488 
489 exit:
490 	mutex_unlock(&ar->conf_mutex);
491 	return ret;
492 }
493 
494 static const struct file_operations fops_simulate_fw_crash = {
495 	.read = ath10k_read_simulate_fw_crash,
496 	.write = ath10k_write_simulate_fw_crash,
497 	.open = simple_open,
498 	.owner = THIS_MODULE,
499 	.llseek = default_llseek,
500 };
501 
502 int ath10k_debug_create(struct ath10k *ar)
503 {
504 	ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
505 						   ar->hw->wiphy->debugfsdir);
506 
507 	if (!ar->debug.debugfs_phy)
508 		return -ENOMEM;
509 
510 	init_completion(&ar->debug.event_stats_compl);
511 
512 	debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar,
513 			    &fops_fw_stats);
514 
515 	debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
516 			    &fops_wmi_services);
517 
518 	debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy,
519 			    ar, &fops_simulate_fw_crash);
520 
521 	return 0;
522 }
523 #endif /* CONFIG_ATH10K_DEBUGFS */
524 
525 #ifdef CONFIG_ATH10K_DEBUG
526 void ath10k_dbg(enum ath10k_debug_mask mask, const char *fmt, ...)
527 {
528 	struct va_format vaf;
529 	va_list args;
530 
531 	va_start(args, fmt);
532 
533 	vaf.fmt = fmt;
534 	vaf.va = &args;
535 
536 	if (ath10k_debug_mask & mask)
537 		ath10k_printk(KERN_DEBUG, "%pV", &vaf);
538 
539 	trace_ath10k_log_dbg(mask, &vaf);
540 
541 	va_end(args);
542 }
543 EXPORT_SYMBOL(ath10k_dbg);
544 
545 void ath10k_dbg_dump(enum ath10k_debug_mask mask,
546 		     const char *msg, const char *prefix,
547 		     const void *buf, size_t len)
548 {
549 	if (ath10k_debug_mask & mask) {
550 		if (msg)
551 			ath10k_dbg(mask, "%s\n", msg);
552 
553 		print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len);
554 	}
555 
556 	/* tracing code doesn't like null strings :/ */
557 	trace_ath10k_log_dbg_dump(msg ? msg : "", prefix ? prefix : "",
558 				  buf, len);
559 }
560 EXPORT_SYMBOL(ath10k_dbg_dump);
561 
562 #endif /* CONFIG_ATH10K_DEBUG */
563