1 /*
2  * Copyright (c) 2004-2011 Atheros Communications Inc.
3  * Copyright (c) 2011-2012 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 "core.h"
19 
20 #include <linux/skbuff.h>
21 #include <linux/fs.h>
22 #include <linux/vmalloc.h>
23 #include <linux/export.h>
24 
25 #include "debug.h"
26 #include "target.h"
27 
28 struct ath6kl_fwlog_slot {
29 	__le32 timestamp;
30 	__le32 length;
31 
32 	/* max ATH6KL_FWLOG_PAYLOAD_SIZE bytes */
33 	u8 payload[0];
34 };
35 
36 #define ATH6KL_FWLOG_MAX_ENTRIES 20
37 
38 #define ATH6KL_FWLOG_VALID_MASK 0x1ffff
39 
40 int ath6kl_printk(const char *level, const char *fmt, ...)
41 {
42 	struct va_format vaf;
43 	va_list args;
44 	int rtn;
45 
46 	va_start(args, fmt);
47 
48 	vaf.fmt = fmt;
49 	vaf.va = &args;
50 
51 	rtn = printk("%sath6kl: %pV", level, &vaf);
52 
53 	va_end(args);
54 
55 	return rtn;
56 }
57 EXPORT_SYMBOL(ath6kl_printk);
58 
59 int ath6kl_info(const char *fmt, ...)
60 {
61 	struct va_format vaf = {
62 		.fmt = fmt,
63 	};
64 	va_list args;
65 	int ret;
66 
67 	va_start(args, fmt);
68 	vaf.va = &args;
69 	ret = ath6kl_printk(KERN_INFO, "%pV", &vaf);
70 	trace_ath6kl_log_info(&vaf);
71 	va_end(args);
72 
73 	return ret;
74 }
75 EXPORT_SYMBOL(ath6kl_info);
76 
77 int ath6kl_err(const char *fmt, ...)
78 {
79 	struct va_format vaf = {
80 		.fmt = fmt,
81 	};
82 	va_list args;
83 	int ret;
84 
85 	va_start(args, fmt);
86 	vaf.va = &args;
87 	ret = ath6kl_printk(KERN_ERR, "%pV", &vaf);
88 	trace_ath6kl_log_err(&vaf);
89 	va_end(args);
90 
91 	return ret;
92 }
93 EXPORT_SYMBOL(ath6kl_err);
94 
95 int ath6kl_warn(const char *fmt, ...)
96 {
97 	struct va_format vaf = {
98 		.fmt = fmt,
99 	};
100 	va_list args;
101 	int ret;
102 
103 	va_start(args, fmt);
104 	vaf.va = &args;
105 	ret = ath6kl_printk(KERN_WARNING, "%pV", &vaf);
106 	trace_ath6kl_log_warn(&vaf);
107 	va_end(args);
108 
109 	return ret;
110 }
111 EXPORT_SYMBOL(ath6kl_warn);
112 
113 #ifdef CONFIG_ATH6KL_DEBUG
114 
115 void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...)
116 {
117 	struct va_format vaf;
118 	va_list args;
119 
120 	va_start(args, fmt);
121 
122 	vaf.fmt = fmt;
123 	vaf.va = &args;
124 
125 	if (debug_mask & mask)
126 		ath6kl_printk(KERN_DEBUG, "%pV", &vaf);
127 
128 	trace_ath6kl_log_dbg(mask, &vaf);
129 
130 	va_end(args);
131 }
132 EXPORT_SYMBOL(ath6kl_dbg);
133 
134 void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask,
135 		     const char *msg, const char *prefix,
136 		     const void *buf, size_t len)
137 {
138 	if (debug_mask & mask) {
139 		if (msg)
140 			ath6kl_dbg(mask, "%s\n", msg);
141 
142 		print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len);
143 	}
144 
145 	/* tracing code doesn't like null strings :/ */
146 	trace_ath6kl_log_dbg_dump(msg ? msg : "", prefix ? prefix : "",
147 				  buf, len);
148 }
149 EXPORT_SYMBOL(ath6kl_dbg_dump);
150 
151 #define REG_OUTPUT_LEN_PER_LINE	25
152 #define REGTYPE_STR_LEN		100
153 
154 struct ath6kl_diag_reg_info {
155 	u32 reg_start;
156 	u32 reg_end;
157 	const char *reg_info;
158 };
159 
160 static const struct ath6kl_diag_reg_info diag_reg[] = {
161 	{ 0x20000, 0x200fc, "General DMA and Rx registers" },
162 	{ 0x28000, 0x28900, "MAC PCU register & keycache" },
163 	{ 0x20800, 0x20a40, "QCU" },
164 	{ 0x21000, 0x212f0, "DCU" },
165 	{ 0x4000,  0x42e4, "RTC" },
166 	{ 0x540000, 0x540000 + (256 * 1024), "RAM" },
167 	{ 0x29800, 0x2B210, "Base Band" },
168 	{ 0x1C000, 0x1C748, "Analog" },
169 };
170 
171 void ath6kl_dump_registers(struct ath6kl_device *dev,
172 			   struct ath6kl_irq_proc_registers *irq_proc_reg,
173 			   struct ath6kl_irq_enable_reg *irq_enable_reg)
174 {
175 
176 	ath6kl_dbg(ATH6KL_DBG_IRQ, ("<------- Register Table -------->\n"));
177 
178 	if (irq_proc_reg != NULL) {
179 		ath6kl_dbg(ATH6KL_DBG_IRQ,
180 			   "Host Int status:           0x%x\n",
181 			   irq_proc_reg->host_int_status);
182 		ath6kl_dbg(ATH6KL_DBG_IRQ,
183 			   "CPU Int status:            0x%x\n",
184 			   irq_proc_reg->cpu_int_status);
185 		ath6kl_dbg(ATH6KL_DBG_IRQ,
186 			   "Error Int status:          0x%x\n",
187 			   irq_proc_reg->error_int_status);
188 		ath6kl_dbg(ATH6KL_DBG_IRQ,
189 			   "Counter Int status:        0x%x\n",
190 			   irq_proc_reg->counter_int_status);
191 		ath6kl_dbg(ATH6KL_DBG_IRQ,
192 			   "Mbox Frame:                0x%x\n",
193 			   irq_proc_reg->mbox_frame);
194 		ath6kl_dbg(ATH6KL_DBG_IRQ,
195 			   "Rx Lookahead Valid:        0x%x\n",
196 			   irq_proc_reg->rx_lkahd_valid);
197 		ath6kl_dbg(ATH6KL_DBG_IRQ,
198 			   "Rx Lookahead 0:            0x%x\n",
199 			   irq_proc_reg->rx_lkahd[0]);
200 		ath6kl_dbg(ATH6KL_DBG_IRQ,
201 			   "Rx Lookahead 1:            0x%x\n",
202 			   irq_proc_reg->rx_lkahd[1]);
203 
204 		if (dev->ar->mbox_info.gmbox_addr != 0) {
205 			/*
206 			 * If the target supports GMBOX hardware, dump some
207 			 * additional state.
208 			 */
209 			ath6kl_dbg(ATH6KL_DBG_IRQ,
210 				   "GMBOX Host Int status 2:   0x%x\n",
211 				   irq_proc_reg->host_int_status2);
212 			ath6kl_dbg(ATH6KL_DBG_IRQ,
213 				   "GMBOX RX Avail:            0x%x\n",
214 				   irq_proc_reg->gmbox_rx_avail);
215 			ath6kl_dbg(ATH6KL_DBG_IRQ,
216 				   "GMBOX lookahead alias 0:   0x%x\n",
217 				   irq_proc_reg->rx_gmbox_lkahd_alias[0]);
218 			ath6kl_dbg(ATH6KL_DBG_IRQ,
219 				   "GMBOX lookahead alias 1:   0x%x\n",
220 				   irq_proc_reg->rx_gmbox_lkahd_alias[1]);
221 		}
222 
223 	}
224 
225 	if (irq_enable_reg != NULL) {
226 		ath6kl_dbg(ATH6KL_DBG_IRQ,
227 			   "Int status Enable:         0x%x\n",
228 			   irq_enable_reg->int_status_en);
229 		ath6kl_dbg(ATH6KL_DBG_IRQ, "Counter Int status Enable: 0x%x\n",
230 			   irq_enable_reg->cntr_int_status_en);
231 	}
232 	ath6kl_dbg(ATH6KL_DBG_IRQ, "<------------------------------->\n");
233 }
234 
235 static void dump_cred_dist(struct htc_endpoint_credit_dist *ep_dist)
236 {
237 	ath6kl_dbg(ATH6KL_DBG_CREDIT,
238 		   "--- endpoint: %d  svc_id: 0x%X ---\n",
239 		   ep_dist->endpoint, ep_dist->svc_id);
240 	ath6kl_dbg(ATH6KL_DBG_CREDIT, " dist_flags     : 0x%X\n",
241 		   ep_dist->dist_flags);
242 	ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_norm      : %d\n",
243 		   ep_dist->cred_norm);
244 	ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_min       : %d\n",
245 		   ep_dist->cred_min);
246 	ath6kl_dbg(ATH6KL_DBG_CREDIT, " credits        : %d\n",
247 		   ep_dist->credits);
248 	ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_assngd    : %d\n",
249 		   ep_dist->cred_assngd);
250 	ath6kl_dbg(ATH6KL_DBG_CREDIT, " seek_cred      : %d\n",
251 		   ep_dist->seek_cred);
252 	ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_sz        : %d\n",
253 		   ep_dist->cred_sz);
254 	ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_per_msg   : %d\n",
255 		   ep_dist->cred_per_msg);
256 	ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_to_dist   : %d\n",
257 		   ep_dist->cred_to_dist);
258 	ath6kl_dbg(ATH6KL_DBG_CREDIT, " txq_depth      : %d\n",
259 		   get_queue_depth(&ep_dist->htc_ep->txq));
260 	ath6kl_dbg(ATH6KL_DBG_CREDIT,
261 		   "----------------------------------\n");
262 }
263 
264 /* FIXME: move to htc.c */
265 void dump_cred_dist_stats(struct htc_target *target)
266 {
267 	struct htc_endpoint_credit_dist *ep_list;
268 
269 	list_for_each_entry(ep_list, &target->cred_dist_list, list)
270 		dump_cred_dist(ep_list);
271 
272 	ath6kl_dbg(ATH6KL_DBG_CREDIT,
273 		   "credit distribution total %d free %d\n",
274 		   target->credit_info->total_avail_credits,
275 		   target->credit_info->cur_free_credits);
276 }
277 
278 void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war)
279 {
280 	switch (war) {
281 	case ATH6KL_WAR_INVALID_RATE:
282 		ar->debug.war_stats.invalid_rate++;
283 		break;
284 	}
285 }
286 
287 static ssize_t read_file_war_stats(struct file *file, char __user *user_buf,
288 				   size_t count, loff_t *ppos)
289 {
290 	struct ath6kl *ar = file->private_data;
291 	char *buf;
292 	unsigned int len = 0, buf_len = 1500;
293 	ssize_t ret_cnt;
294 
295 	buf = kzalloc(buf_len, GFP_KERNEL);
296 	if (!buf)
297 		return -ENOMEM;
298 
299 	len += scnprintf(buf + len, buf_len - len, "\n");
300 	len += scnprintf(buf + len, buf_len - len, "%25s\n",
301 			 "Workaround stats");
302 	len += scnprintf(buf + len, buf_len - len, "%25s\n\n",
303 			 "=================");
304 	len += scnprintf(buf + len, buf_len - len, "%20s %10u\n",
305 			 "Invalid rates", ar->debug.war_stats.invalid_rate);
306 
307 	if (WARN_ON(len > buf_len))
308 		len = buf_len;
309 
310 	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
311 
312 	kfree(buf);
313 	return ret_cnt;
314 }
315 
316 static const struct file_operations fops_war_stats = {
317 	.read = read_file_war_stats,
318 	.open = simple_open,
319 	.owner = THIS_MODULE,
320 	.llseek = default_llseek,
321 };
322 
323 void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len)
324 {
325 	struct ath6kl_fwlog_slot *slot;
326 	struct sk_buff *skb;
327 	size_t slot_len;
328 
329 	if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE))
330 		return;
331 
332 	slot_len = sizeof(*slot) + ATH6KL_FWLOG_PAYLOAD_SIZE;
333 
334 	skb = alloc_skb(slot_len, GFP_KERNEL);
335 	if (!skb)
336 		return;
337 
338 	slot = (struct ath6kl_fwlog_slot *) skb_put(skb, slot_len);
339 	slot->timestamp = cpu_to_le32(jiffies);
340 	slot->length = cpu_to_le32(len);
341 	memcpy(slot->payload, buf, len);
342 
343 	/* Need to pad each record to fixed length ATH6KL_FWLOG_PAYLOAD_SIZE */
344 	memset(slot->payload + len, 0, ATH6KL_FWLOG_PAYLOAD_SIZE - len);
345 
346 	spin_lock(&ar->debug.fwlog_queue.lock);
347 
348 	__skb_queue_tail(&ar->debug.fwlog_queue, skb);
349 	complete(&ar->debug.fwlog_completion);
350 
351 	/* drop oldest entries */
352 	while (skb_queue_len(&ar->debug.fwlog_queue) >
353 	       ATH6KL_FWLOG_MAX_ENTRIES) {
354 		skb = __skb_dequeue(&ar->debug.fwlog_queue);
355 		kfree_skb(skb);
356 	}
357 
358 	spin_unlock(&ar->debug.fwlog_queue.lock);
359 
360 	return;
361 }
362 
363 static int ath6kl_fwlog_open(struct inode *inode, struct file *file)
364 {
365 	struct ath6kl *ar = inode->i_private;
366 
367 	if (ar->debug.fwlog_open)
368 		return -EBUSY;
369 
370 	ar->debug.fwlog_open = true;
371 
372 	file->private_data = inode->i_private;
373 	return 0;
374 }
375 
376 static int ath6kl_fwlog_release(struct inode *inode, struct file *file)
377 {
378 	struct ath6kl *ar = inode->i_private;
379 
380 	ar->debug.fwlog_open = false;
381 
382 	return 0;
383 }
384 
385 static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf,
386 				 size_t count, loff_t *ppos)
387 {
388 	struct ath6kl *ar = file->private_data;
389 	struct sk_buff *skb;
390 	ssize_t ret_cnt;
391 	size_t len = 0;
392 	char *buf;
393 
394 	buf = vmalloc(count);
395 	if (!buf)
396 		return -ENOMEM;
397 
398 	/* read undelivered logs from firmware */
399 	ath6kl_read_fwlogs(ar);
400 
401 	spin_lock(&ar->debug.fwlog_queue.lock);
402 
403 	while ((skb = __skb_dequeue(&ar->debug.fwlog_queue))) {
404 		if (skb->len > count - len) {
405 			/* not enough space, put skb back and leave */
406 			__skb_queue_head(&ar->debug.fwlog_queue, skb);
407 			break;
408 		}
409 
410 
411 		memcpy(buf + len, skb->data, skb->len);
412 		len += skb->len;
413 
414 		kfree_skb(skb);
415 	}
416 
417 	spin_unlock(&ar->debug.fwlog_queue.lock);
418 
419 	/* FIXME: what to do if len == 0? */
420 
421 	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
422 
423 	vfree(buf);
424 
425 	return ret_cnt;
426 }
427 
428 static const struct file_operations fops_fwlog = {
429 	.open = ath6kl_fwlog_open,
430 	.release = ath6kl_fwlog_release,
431 	.read = ath6kl_fwlog_read,
432 	.owner = THIS_MODULE,
433 	.llseek = default_llseek,
434 };
435 
436 static ssize_t ath6kl_fwlog_block_read(struct file *file,
437 				       char __user *user_buf,
438 				       size_t count,
439 				       loff_t *ppos)
440 {
441 	struct ath6kl *ar = file->private_data;
442 	struct sk_buff *skb;
443 	ssize_t ret_cnt;
444 	size_t len = 0, not_copied;
445 	char *buf;
446 	int ret;
447 
448 	buf = vmalloc(count);
449 	if (!buf)
450 		return -ENOMEM;
451 
452 	spin_lock(&ar->debug.fwlog_queue.lock);
453 
454 	if (skb_queue_len(&ar->debug.fwlog_queue) == 0) {
455 		/* we must init under queue lock */
456 		init_completion(&ar->debug.fwlog_completion);
457 
458 		spin_unlock(&ar->debug.fwlog_queue.lock);
459 
460 		ret = wait_for_completion_interruptible(
461 			&ar->debug.fwlog_completion);
462 		if (ret == -ERESTARTSYS) {
463 			vfree(buf);
464 			return ret;
465 		}
466 
467 		spin_lock(&ar->debug.fwlog_queue.lock);
468 	}
469 
470 	while ((skb = __skb_dequeue(&ar->debug.fwlog_queue))) {
471 		if (skb->len > count - len) {
472 			/* not enough space, put skb back and leave */
473 			__skb_queue_head(&ar->debug.fwlog_queue, skb);
474 			break;
475 		}
476 
477 
478 		memcpy(buf + len, skb->data, skb->len);
479 		len += skb->len;
480 
481 		kfree_skb(skb);
482 	}
483 
484 	spin_unlock(&ar->debug.fwlog_queue.lock);
485 
486 	/* FIXME: what to do if len == 0? */
487 
488 	not_copied = copy_to_user(user_buf, buf, len);
489 	if (not_copied != 0) {
490 		ret_cnt = -EFAULT;
491 		goto out;
492 	}
493 
494 	*ppos = *ppos + len;
495 
496 	ret_cnt = len;
497 
498 out:
499 	vfree(buf);
500 
501 	return ret_cnt;
502 }
503 
504 static const struct file_operations fops_fwlog_block = {
505 	.open = ath6kl_fwlog_open,
506 	.release = ath6kl_fwlog_release,
507 	.read = ath6kl_fwlog_block_read,
508 	.owner = THIS_MODULE,
509 	.llseek = default_llseek,
510 };
511 
512 static ssize_t ath6kl_fwlog_mask_read(struct file *file, char __user *user_buf,
513 				      size_t count, loff_t *ppos)
514 {
515 	struct ath6kl *ar = file->private_data;
516 	char buf[16];
517 	int len;
518 
519 	len = snprintf(buf, sizeof(buf), "0x%x\n", ar->debug.fwlog_mask);
520 
521 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
522 }
523 
524 static ssize_t ath6kl_fwlog_mask_write(struct file *file,
525 				       const char __user *user_buf,
526 				       size_t count, loff_t *ppos)
527 {
528 	struct ath6kl *ar = file->private_data;
529 	int ret;
530 
531 	ret = kstrtou32_from_user(user_buf, count, 0, &ar->debug.fwlog_mask);
532 	if (ret)
533 		return ret;
534 
535 	ret = ath6kl_wmi_config_debug_module_cmd(ar->wmi,
536 						 ATH6KL_FWLOG_VALID_MASK,
537 						 ar->debug.fwlog_mask);
538 	if (ret)
539 		return ret;
540 
541 	return count;
542 }
543 
544 static const struct file_operations fops_fwlog_mask = {
545 	.open = simple_open,
546 	.read = ath6kl_fwlog_mask_read,
547 	.write = ath6kl_fwlog_mask_write,
548 	.owner = THIS_MODULE,
549 	.llseek = default_llseek,
550 };
551 
552 static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
553 				   size_t count, loff_t *ppos)
554 {
555 	struct ath6kl *ar = file->private_data;
556 	struct ath6kl_vif *vif;
557 	struct target_stats *tgt_stats;
558 	char *buf;
559 	unsigned int len = 0, buf_len = 1500;
560 	int i;
561 	long left;
562 	ssize_t ret_cnt;
563 
564 	vif = ath6kl_vif_first(ar);
565 	if (!vif)
566 		return -EIO;
567 
568 	tgt_stats = &vif->target_stats;
569 
570 	buf = kzalloc(buf_len, GFP_KERNEL);
571 	if (!buf)
572 		return -ENOMEM;
573 
574 	if (down_interruptible(&ar->sem)) {
575 		kfree(buf);
576 		return -EBUSY;
577 	}
578 
579 	set_bit(STATS_UPDATE_PEND, &vif->flags);
580 
581 	if (ath6kl_wmi_get_stats_cmd(ar->wmi, 0)) {
582 		up(&ar->sem);
583 		kfree(buf);
584 		return -EIO;
585 	}
586 
587 	left = wait_event_interruptible_timeout(ar->event_wq,
588 						!test_bit(STATS_UPDATE_PEND,
589 						&vif->flags), WMI_TIMEOUT);
590 
591 	up(&ar->sem);
592 
593 	if (left <= 0) {
594 		kfree(buf);
595 		return -ETIMEDOUT;
596 	}
597 
598 	len += scnprintf(buf + len, buf_len - len, "\n");
599 	len += scnprintf(buf + len, buf_len - len, "%25s\n",
600 			 "Target Tx stats");
601 	len += scnprintf(buf + len, buf_len - len, "%25s\n\n",
602 			 "=================");
603 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
604 			 "Ucast packets", tgt_stats->tx_ucast_pkt);
605 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
606 			 "Bcast packets", tgt_stats->tx_bcast_pkt);
607 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
608 			 "Ucast byte", tgt_stats->tx_ucast_byte);
609 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
610 			 "Bcast byte", tgt_stats->tx_bcast_byte);
611 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
612 			 "Rts success cnt", tgt_stats->tx_rts_success_cnt);
613 	for (i = 0; i < 4; i++)
614 		len += scnprintf(buf + len, buf_len - len,
615 				 "%18s %d %10llu\n", "PER on ac",
616 				 i, tgt_stats->tx_pkt_per_ac[i]);
617 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
618 			 "Error", tgt_stats->tx_err);
619 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
620 			 "Fail count", tgt_stats->tx_fail_cnt);
621 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
622 			 "Retry count", tgt_stats->tx_retry_cnt);
623 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
624 			 "Multi retry cnt", tgt_stats->tx_mult_retry_cnt);
625 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
626 			 "Rts fail cnt", tgt_stats->tx_rts_fail_cnt);
627 	len += scnprintf(buf + len, buf_len - len, "%25s %10llu\n\n",
628 			 "TKIP counter measure used",
629 			 tgt_stats->tkip_cnter_measures_invoked);
630 
631 	len += scnprintf(buf + len, buf_len - len, "%25s\n",
632 			 "Target Rx stats");
633 	len += scnprintf(buf + len, buf_len - len, "%25s\n",
634 			 "=================");
635 
636 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
637 			 "Ucast packets", tgt_stats->rx_ucast_pkt);
638 	len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
639 			 "Ucast Rate", tgt_stats->rx_ucast_rate);
640 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
641 			 "Bcast packets", tgt_stats->rx_bcast_pkt);
642 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
643 			 "Ucast byte", tgt_stats->rx_ucast_byte);
644 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
645 			 "Bcast byte", tgt_stats->rx_bcast_byte);
646 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
647 			 "Fragmented pkt", tgt_stats->rx_frgment_pkt);
648 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
649 			 "Error", tgt_stats->rx_err);
650 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
651 			 "CRC Err", tgt_stats->rx_crc_err);
652 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
653 			 "Key chache miss", tgt_stats->rx_key_cache_miss);
654 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
655 			 "Decrypt Err", tgt_stats->rx_decrypt_err);
656 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
657 			 "Duplicate frame", tgt_stats->rx_dupl_frame);
658 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
659 			 "Tkip Mic failure", tgt_stats->tkip_local_mic_fail);
660 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
661 			 "TKIP format err", tgt_stats->tkip_fmt_err);
662 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
663 			 "CCMP format Err", tgt_stats->ccmp_fmt_err);
664 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n",
665 			 "CCMP Replay Err", tgt_stats->ccmp_replays);
666 
667 	len += scnprintf(buf + len, buf_len - len, "%25s\n",
668 			 "Misc Target stats");
669 	len += scnprintf(buf + len, buf_len - len, "%25s\n",
670 			 "=================");
671 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
672 			 "Beacon Miss count", tgt_stats->cs_bmiss_cnt);
673 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
674 			 "Num Connects", tgt_stats->cs_connect_cnt);
675 	len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
676 			 "Num disconnects", tgt_stats->cs_discon_cnt);
677 	len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
678 			 "Beacon avg rssi", tgt_stats->cs_ave_beacon_rssi);
679 	len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
680 			 "ARP pkt received", tgt_stats->arp_received);
681 	len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
682 			 "ARP pkt matched", tgt_stats->arp_matched);
683 	len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
684 			 "ARP pkt replied", tgt_stats->arp_replied);
685 
686 	if (len > buf_len)
687 		len = buf_len;
688 
689 	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
690 
691 	kfree(buf);
692 	return ret_cnt;
693 }
694 
695 static const struct file_operations fops_tgt_stats = {
696 	.read = read_file_tgt_stats,
697 	.open = simple_open,
698 	.owner = THIS_MODULE,
699 	.llseek = default_llseek,
700 };
701 
702 #define print_credit_info(fmt_str, ep_list_field)		\
703 	(len += scnprintf(buf + len, buf_len - len, fmt_str,	\
704 			 ep_list->ep_list_field))
705 #define CREDIT_INFO_DISPLAY_STRING_LEN	200
706 #define CREDIT_INFO_LEN	128
707 
708 static ssize_t read_file_credit_dist_stats(struct file *file,
709 					   char __user *user_buf,
710 					   size_t count, loff_t *ppos)
711 {
712 	struct ath6kl *ar = file->private_data;
713 	struct htc_target *target = ar->htc_target;
714 	struct htc_endpoint_credit_dist *ep_list;
715 	char *buf;
716 	unsigned int buf_len, len = 0;
717 	ssize_t ret_cnt;
718 
719 	buf_len = CREDIT_INFO_DISPLAY_STRING_LEN +
720 		  get_queue_depth(&target->cred_dist_list) * CREDIT_INFO_LEN;
721 	buf = kzalloc(buf_len, GFP_KERNEL);
722 	if (!buf)
723 		return -ENOMEM;
724 
725 	len += scnprintf(buf + len, buf_len - len, "%25s%5d\n",
726 			 "Total Avail Credits: ",
727 			 target->credit_info->total_avail_credits);
728 	len += scnprintf(buf + len, buf_len - len, "%25s%5d\n",
729 			 "Free credits :",
730 			 target->credit_info->cur_free_credits);
731 
732 	len += scnprintf(buf + len, buf_len - len,
733 			 " Epid  Flags    Cred_norm  Cred_min  Credits  Cred_assngd"
734 			 "  Seek_cred  Cred_sz  Cred_per_msg  Cred_to_dist"
735 			 "  qdepth\n");
736 
737 	list_for_each_entry(ep_list, &target->cred_dist_list, list) {
738 		print_credit_info("  %2d", endpoint);
739 		print_credit_info("%10x", dist_flags);
740 		print_credit_info("%8d", cred_norm);
741 		print_credit_info("%9d", cred_min);
742 		print_credit_info("%9d", credits);
743 		print_credit_info("%10d", cred_assngd);
744 		print_credit_info("%13d", seek_cred);
745 		print_credit_info("%12d", cred_sz);
746 		print_credit_info("%9d", cred_per_msg);
747 		print_credit_info("%14d", cred_to_dist);
748 		len += scnprintf(buf + len, buf_len - len, "%12d\n",
749 				 get_queue_depth(&ep_list->htc_ep->txq));
750 	}
751 
752 	if (len > buf_len)
753 		len = buf_len;
754 
755 	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
756 	kfree(buf);
757 	return ret_cnt;
758 }
759 
760 static const struct file_operations fops_credit_dist_stats = {
761 	.read = read_file_credit_dist_stats,
762 	.open = simple_open,
763 	.owner = THIS_MODULE,
764 	.llseek = default_llseek,
765 };
766 
767 static unsigned int print_endpoint_stat(struct htc_target *target, char *buf,
768 					unsigned int buf_len, unsigned int len,
769 					int offset, const char *name)
770 {
771 	int i;
772 	struct htc_endpoint_stats *ep_st;
773 	u32 *counter;
774 
775 	len += scnprintf(buf + len, buf_len - len, "%s:", name);
776 	for (i = 0; i < ENDPOINT_MAX; i++) {
777 		ep_st = &target->endpoint[i].ep_st;
778 		counter = ((u32 *) ep_st) + (offset / 4);
779 		len += scnprintf(buf + len, buf_len - len, " %u", *counter);
780 	}
781 	len += scnprintf(buf + len, buf_len - len, "\n");
782 
783 	return len;
784 }
785 
786 static ssize_t ath6kl_endpoint_stats_read(struct file *file,
787 					  char __user *user_buf,
788 					  size_t count, loff_t *ppos)
789 {
790 	struct ath6kl *ar = file->private_data;
791 	struct htc_target *target = ar->htc_target;
792 	char *buf;
793 	unsigned int buf_len, len = 0;
794 	ssize_t ret_cnt;
795 
796 	buf_len = sizeof(struct htc_endpoint_stats) / sizeof(u32) *
797 		(25 + ENDPOINT_MAX * 11);
798 	buf = kmalloc(buf_len, GFP_KERNEL);
799 	if (!buf)
800 		return -ENOMEM;
801 
802 #define EPSTAT(name)							\
803 	do {								\
804 		len = print_endpoint_stat(target, buf, buf_len, len,	\
805 					  offsetof(struct htc_endpoint_stats, \
806 						   name),		\
807 					  #name);			\
808 	} while (0)
809 
810 	EPSTAT(cred_low_indicate);
811 	EPSTAT(tx_issued);
812 	EPSTAT(tx_pkt_bundled);
813 	EPSTAT(tx_bundles);
814 	EPSTAT(tx_dropped);
815 	EPSTAT(tx_cred_rpt);
816 	EPSTAT(cred_rpt_from_rx);
817 	EPSTAT(cred_rpt_from_other);
818 	EPSTAT(cred_rpt_ep0);
819 	EPSTAT(cred_from_rx);
820 	EPSTAT(cred_from_other);
821 	EPSTAT(cred_from_ep0);
822 	EPSTAT(cred_cosumd);
823 	EPSTAT(cred_retnd);
824 	EPSTAT(rx_pkts);
825 	EPSTAT(rx_lkahds);
826 	EPSTAT(rx_bundl);
827 	EPSTAT(rx_bundle_lkahd);
828 	EPSTAT(rx_bundle_from_hdr);
829 	EPSTAT(rx_alloc_thresh_hit);
830 	EPSTAT(rxalloc_thresh_byte);
831 #undef EPSTAT
832 
833 	if (len > buf_len)
834 		len = buf_len;
835 
836 	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
837 	kfree(buf);
838 	return ret_cnt;
839 }
840 
841 static ssize_t ath6kl_endpoint_stats_write(struct file *file,
842 					   const char __user *user_buf,
843 					   size_t count, loff_t *ppos)
844 {
845 	struct ath6kl *ar = file->private_data;
846 	struct htc_target *target = ar->htc_target;
847 	int ret, i;
848 	u32 val;
849 	struct htc_endpoint_stats *ep_st;
850 
851 	ret = kstrtou32_from_user(user_buf, count, 0, &val);
852 	if (ret)
853 		return ret;
854 	if (val == 0) {
855 		for (i = 0; i < ENDPOINT_MAX; i++) {
856 			ep_st = &target->endpoint[i].ep_st;
857 			memset(ep_st, 0, sizeof(*ep_st));
858 		}
859 	}
860 
861 	return count;
862 }
863 
864 static const struct file_operations fops_endpoint_stats = {
865 	.open = simple_open,
866 	.read = ath6kl_endpoint_stats_read,
867 	.write = ath6kl_endpoint_stats_write,
868 	.owner = THIS_MODULE,
869 	.llseek = default_llseek,
870 };
871 
872 static unsigned long ath6kl_get_num_reg(void)
873 {
874 	int i;
875 	unsigned long n_reg = 0;
876 
877 	for (i = 0; i < ARRAY_SIZE(diag_reg); i++)
878 		n_reg = n_reg +
879 		     (diag_reg[i].reg_end - diag_reg[i].reg_start) / 4 + 1;
880 
881 	return n_reg;
882 }
883 
884 static bool ath6kl_dbg_is_diag_reg_valid(u32 reg_addr)
885 {
886 	int i;
887 
888 	for (i = 0; i < ARRAY_SIZE(diag_reg); i++) {
889 		if (reg_addr >= diag_reg[i].reg_start &&
890 		    reg_addr <= diag_reg[i].reg_end)
891 			return true;
892 	}
893 
894 	return false;
895 }
896 
897 static ssize_t ath6kl_regread_read(struct file *file, char __user *user_buf,
898 				    size_t count, loff_t *ppos)
899 {
900 	struct ath6kl *ar = file->private_data;
901 	u8 buf[50];
902 	unsigned int len = 0;
903 
904 	if (ar->debug.dbgfs_diag_reg)
905 		len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n",
906 				ar->debug.dbgfs_diag_reg);
907 	else
908 		len += scnprintf(buf + len, sizeof(buf) - len,
909 				 "All diag registers\n");
910 
911 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
912 }
913 
914 static ssize_t ath6kl_regread_write(struct file *file,
915 				    const char __user *user_buf,
916 				    size_t count, loff_t *ppos)
917 {
918 	struct ath6kl *ar = file->private_data;
919 	unsigned long reg_addr;
920 
921 	if (kstrtoul_from_user(user_buf, count, 0, &reg_addr))
922 		return -EINVAL;
923 
924 	if ((reg_addr % 4) != 0)
925 		return -EINVAL;
926 
927 	if (reg_addr && !ath6kl_dbg_is_diag_reg_valid(reg_addr))
928 		return -EINVAL;
929 
930 	ar->debug.dbgfs_diag_reg = reg_addr;
931 
932 	return count;
933 }
934 
935 static const struct file_operations fops_diag_reg_read = {
936 	.read = ath6kl_regread_read,
937 	.write = ath6kl_regread_write,
938 	.open = simple_open,
939 	.owner = THIS_MODULE,
940 	.llseek = default_llseek,
941 };
942 
943 static int ath6kl_regdump_open(struct inode *inode, struct file *file)
944 {
945 	struct ath6kl *ar = inode->i_private;
946 	u8 *buf;
947 	unsigned long int reg_len;
948 	unsigned int len = 0, n_reg;
949 	u32 addr;
950 	__le32 reg_val;
951 	int i, status;
952 
953 	/* Dump all the registers if no register is specified */
954 	if (!ar->debug.dbgfs_diag_reg)
955 		n_reg = ath6kl_get_num_reg();
956 	else
957 		n_reg = 1;
958 
959 	reg_len = n_reg * REG_OUTPUT_LEN_PER_LINE;
960 	if (n_reg > 1)
961 		reg_len += REGTYPE_STR_LEN;
962 
963 	buf = vmalloc(reg_len);
964 	if (!buf)
965 		return -ENOMEM;
966 
967 	if (n_reg == 1) {
968 		addr = ar->debug.dbgfs_diag_reg;
969 
970 		status = ath6kl_diag_read32(ar,
971 				TARG_VTOP(ar->target_type, addr),
972 				(u32 *)&reg_val);
973 		if (status)
974 			goto fail_reg_read;
975 
976 		len += scnprintf(buf + len, reg_len - len,
977 				 "0x%06x 0x%08x\n", addr, le32_to_cpu(reg_val));
978 		goto done;
979 	}
980 
981 	for (i = 0; i < ARRAY_SIZE(diag_reg); i++) {
982 		len += scnprintf(buf + len, reg_len - len,
983 				"%s\n", diag_reg[i].reg_info);
984 		for (addr = diag_reg[i].reg_start;
985 		     addr <= diag_reg[i].reg_end; addr += 4) {
986 			status = ath6kl_diag_read32(ar,
987 					TARG_VTOP(ar->target_type, addr),
988 					(u32 *)&reg_val);
989 			if (status)
990 				goto fail_reg_read;
991 
992 			len += scnprintf(buf + len, reg_len - len,
993 					"0x%06x 0x%08x\n",
994 					addr, le32_to_cpu(reg_val));
995 		}
996 	}
997 
998 done:
999 	file->private_data = buf;
1000 	return 0;
1001 
1002 fail_reg_read:
1003 	ath6kl_warn("Unable to read memory:%u\n", addr);
1004 	vfree(buf);
1005 	return -EIO;
1006 }
1007 
1008 static ssize_t ath6kl_regdump_read(struct file *file, char __user *user_buf,
1009 				  size_t count, loff_t *ppos)
1010 {
1011 	u8 *buf = file->private_data;
1012 	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
1013 }
1014 
1015 static int ath6kl_regdump_release(struct inode *inode, struct file *file)
1016 {
1017 	vfree(file->private_data);
1018 	return 0;
1019 }
1020 
1021 static const struct file_operations fops_reg_dump = {
1022 	.open = ath6kl_regdump_open,
1023 	.read = ath6kl_regdump_read,
1024 	.release = ath6kl_regdump_release,
1025 	.owner = THIS_MODULE,
1026 	.llseek = default_llseek,
1027 };
1028 
1029 static ssize_t ath6kl_lrssi_roam_write(struct file *file,
1030 				       const char __user *user_buf,
1031 				       size_t count, loff_t *ppos)
1032 {
1033 	struct ath6kl *ar = file->private_data;
1034 	unsigned long lrssi_roam_threshold;
1035 
1036 	if (kstrtoul_from_user(user_buf, count, 0, &lrssi_roam_threshold))
1037 		return -EINVAL;
1038 
1039 	ar->lrssi_roam_threshold = lrssi_roam_threshold;
1040 
1041 	ath6kl_wmi_set_roam_lrssi_cmd(ar->wmi, ar->lrssi_roam_threshold);
1042 
1043 	return count;
1044 }
1045 
1046 static ssize_t ath6kl_lrssi_roam_read(struct file *file,
1047 				      char __user *user_buf,
1048 				      size_t count, loff_t *ppos)
1049 {
1050 	struct ath6kl *ar = file->private_data;
1051 	char buf[32];
1052 	unsigned int len;
1053 
1054 	len = snprintf(buf, sizeof(buf), "%u\n", ar->lrssi_roam_threshold);
1055 
1056 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1057 }
1058 
1059 static const struct file_operations fops_lrssi_roam_threshold = {
1060 	.read = ath6kl_lrssi_roam_read,
1061 	.write = ath6kl_lrssi_roam_write,
1062 	.open = simple_open,
1063 	.owner = THIS_MODULE,
1064 	.llseek = default_llseek,
1065 };
1066 
1067 static ssize_t ath6kl_regwrite_read(struct file *file,
1068 				    char __user *user_buf,
1069 				    size_t count, loff_t *ppos)
1070 {
1071 	struct ath6kl *ar = file->private_data;
1072 	u8 buf[32];
1073 	unsigned int len = 0;
1074 
1075 	len = scnprintf(buf, sizeof(buf), "Addr: 0x%x Val: 0x%x\n",
1076 			ar->debug.diag_reg_addr_wr, ar->debug.diag_reg_val_wr);
1077 
1078 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1079 }
1080 
1081 static ssize_t ath6kl_regwrite_write(struct file *file,
1082 				     const char __user *user_buf,
1083 				     size_t count, loff_t *ppos)
1084 {
1085 	struct ath6kl *ar = file->private_data;
1086 	char buf[32];
1087 	char *sptr, *token;
1088 	unsigned int len = 0;
1089 	u32 reg_addr, reg_val;
1090 
1091 	len = min(count, sizeof(buf) - 1);
1092 	if (copy_from_user(buf, user_buf, len))
1093 		return -EFAULT;
1094 
1095 	buf[len] = '\0';
1096 	sptr = buf;
1097 
1098 	token = strsep(&sptr, "=");
1099 	if (!token)
1100 		return -EINVAL;
1101 
1102 	if (kstrtou32(token, 0, &reg_addr))
1103 		return -EINVAL;
1104 
1105 	if (!ath6kl_dbg_is_diag_reg_valid(reg_addr))
1106 		return -EINVAL;
1107 
1108 	if (kstrtou32(sptr, 0, &reg_val))
1109 		return -EINVAL;
1110 
1111 	ar->debug.diag_reg_addr_wr = reg_addr;
1112 	ar->debug.diag_reg_val_wr = reg_val;
1113 
1114 	if (ath6kl_diag_write32(ar, ar->debug.diag_reg_addr_wr,
1115 				cpu_to_le32(ar->debug.diag_reg_val_wr)))
1116 		return -EIO;
1117 
1118 	return count;
1119 }
1120 
1121 static const struct file_operations fops_diag_reg_write = {
1122 	.read = ath6kl_regwrite_read,
1123 	.write = ath6kl_regwrite_write,
1124 	.open = simple_open,
1125 	.owner = THIS_MODULE,
1126 	.llseek = default_llseek,
1127 };
1128 
1129 int ath6kl_debug_roam_tbl_event(struct ath6kl *ar, const void *buf,
1130 				size_t len)
1131 {
1132 	const struct wmi_target_roam_tbl *tbl;
1133 	u16 num_entries;
1134 
1135 	if (len < sizeof(*tbl))
1136 		return -EINVAL;
1137 
1138 	tbl = (const struct wmi_target_roam_tbl *) buf;
1139 	num_entries = le16_to_cpu(tbl->num_entries);
1140 	if (sizeof(*tbl) + num_entries * sizeof(struct wmi_bss_roam_info) >
1141 	    len)
1142 		return -EINVAL;
1143 
1144 	if (ar->debug.roam_tbl == NULL ||
1145 	    ar->debug.roam_tbl_len < (unsigned int) len) {
1146 		kfree(ar->debug.roam_tbl);
1147 		ar->debug.roam_tbl = kmalloc(len, GFP_ATOMIC);
1148 		if (ar->debug.roam_tbl == NULL)
1149 			return -ENOMEM;
1150 	}
1151 
1152 	memcpy(ar->debug.roam_tbl, buf, len);
1153 	ar->debug.roam_tbl_len = len;
1154 
1155 	if (test_bit(ROAM_TBL_PEND, &ar->flag)) {
1156 		clear_bit(ROAM_TBL_PEND, &ar->flag);
1157 		wake_up(&ar->event_wq);
1158 	}
1159 
1160 	return 0;
1161 }
1162 
1163 static ssize_t ath6kl_roam_table_read(struct file *file, char __user *user_buf,
1164 				      size_t count, loff_t *ppos)
1165 {
1166 	struct ath6kl *ar = file->private_data;
1167 	int ret;
1168 	long left;
1169 	struct wmi_target_roam_tbl *tbl;
1170 	u16 num_entries, i;
1171 	char *buf;
1172 	unsigned int len, buf_len;
1173 	ssize_t ret_cnt;
1174 
1175 	if (down_interruptible(&ar->sem))
1176 		return -EBUSY;
1177 
1178 	set_bit(ROAM_TBL_PEND, &ar->flag);
1179 
1180 	ret = ath6kl_wmi_get_roam_tbl_cmd(ar->wmi);
1181 	if (ret) {
1182 		up(&ar->sem);
1183 		return ret;
1184 	}
1185 
1186 	left = wait_event_interruptible_timeout(
1187 		ar->event_wq, !test_bit(ROAM_TBL_PEND, &ar->flag), WMI_TIMEOUT);
1188 	up(&ar->sem);
1189 
1190 	if (left <= 0)
1191 		return -ETIMEDOUT;
1192 
1193 	if (ar->debug.roam_tbl == NULL)
1194 		return -ENOMEM;
1195 
1196 	tbl = (struct wmi_target_roam_tbl *) ar->debug.roam_tbl;
1197 	num_entries = le16_to_cpu(tbl->num_entries);
1198 
1199 	buf_len = 100 + num_entries * 100;
1200 	buf = kzalloc(buf_len, GFP_KERNEL);
1201 	if (buf == NULL)
1202 		return -ENOMEM;
1203 	len = 0;
1204 	len += scnprintf(buf + len, buf_len - len,
1205 			 "roam_mode=%u\n\n"
1206 			 "# roam_util bssid rssi rssidt last_rssi util bias\n",
1207 			 le16_to_cpu(tbl->roam_mode));
1208 
1209 	for (i = 0; i < num_entries; i++) {
1210 		struct wmi_bss_roam_info *info = &tbl->info[i];
1211 		len += scnprintf(buf + len, buf_len - len,
1212 				 "%d %pM %d %d %d %d %d\n",
1213 				 a_sle32_to_cpu(info->roam_util), info->bssid,
1214 				 info->rssi, info->rssidt, info->last_rssi,
1215 				 info->util, info->bias);
1216 	}
1217 
1218 	if (len > buf_len)
1219 		len = buf_len;
1220 
1221 	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1222 
1223 	kfree(buf);
1224 	return ret_cnt;
1225 }
1226 
1227 static const struct file_operations fops_roam_table = {
1228 	.read = ath6kl_roam_table_read,
1229 	.open = simple_open,
1230 	.owner = THIS_MODULE,
1231 	.llseek = default_llseek,
1232 };
1233 
1234 static ssize_t ath6kl_force_roam_write(struct file *file,
1235 				       const char __user *user_buf,
1236 				       size_t count, loff_t *ppos)
1237 {
1238 	struct ath6kl *ar = file->private_data;
1239 	int ret;
1240 	char buf[20];
1241 	size_t len;
1242 	u8 bssid[ETH_ALEN];
1243 	int i;
1244 	int addr[ETH_ALEN];
1245 
1246 	len = min(count, sizeof(buf) - 1);
1247 	if (copy_from_user(buf, user_buf, len))
1248 		return -EFAULT;
1249 	buf[len] = '\0';
1250 
1251 	if (sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
1252 		   &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5])
1253 	    != ETH_ALEN)
1254 		return -EINVAL;
1255 	for (i = 0; i < ETH_ALEN; i++)
1256 		bssid[i] = addr[i];
1257 
1258 	ret = ath6kl_wmi_force_roam_cmd(ar->wmi, bssid);
1259 	if (ret)
1260 		return ret;
1261 
1262 	return count;
1263 }
1264 
1265 static const struct file_operations fops_force_roam = {
1266 	.write = ath6kl_force_roam_write,
1267 	.open = simple_open,
1268 	.owner = THIS_MODULE,
1269 	.llseek = default_llseek,
1270 };
1271 
1272 static ssize_t ath6kl_roam_mode_write(struct file *file,
1273 				      const char __user *user_buf,
1274 				      size_t count, loff_t *ppos)
1275 {
1276 	struct ath6kl *ar = file->private_data;
1277 	int ret;
1278 	char buf[20];
1279 	size_t len;
1280 	enum wmi_roam_mode mode;
1281 
1282 	len = min(count, sizeof(buf) - 1);
1283 	if (copy_from_user(buf, user_buf, len))
1284 		return -EFAULT;
1285 	buf[len] = '\0';
1286 	if (len > 0 && buf[len - 1] == '\n')
1287 		buf[len - 1] = '\0';
1288 
1289 	if (strcasecmp(buf, "default") == 0)
1290 		mode = WMI_DEFAULT_ROAM_MODE;
1291 	else if (strcasecmp(buf, "bssbias") == 0)
1292 		mode = WMI_HOST_BIAS_ROAM_MODE;
1293 	else if (strcasecmp(buf, "lock") == 0)
1294 		mode = WMI_LOCK_BSS_MODE;
1295 	else
1296 		return -EINVAL;
1297 
1298 	ret = ath6kl_wmi_set_roam_mode_cmd(ar->wmi, mode);
1299 	if (ret)
1300 		return ret;
1301 
1302 	return count;
1303 }
1304 
1305 static const struct file_operations fops_roam_mode = {
1306 	.write = ath6kl_roam_mode_write,
1307 	.open = simple_open,
1308 	.owner = THIS_MODULE,
1309 	.llseek = default_llseek,
1310 };
1311 
1312 void ath6kl_debug_set_keepalive(struct ath6kl *ar, u8 keepalive)
1313 {
1314 	ar->debug.keepalive = keepalive;
1315 }
1316 
1317 static ssize_t ath6kl_keepalive_read(struct file *file, char __user *user_buf,
1318 				     size_t count, loff_t *ppos)
1319 {
1320 	struct ath6kl *ar = file->private_data;
1321 	char buf[16];
1322 	int len;
1323 
1324 	len = snprintf(buf, sizeof(buf), "%u\n", ar->debug.keepalive);
1325 
1326 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1327 }
1328 
1329 static ssize_t ath6kl_keepalive_write(struct file *file,
1330 				      const char __user *user_buf,
1331 				      size_t count, loff_t *ppos)
1332 {
1333 	struct ath6kl *ar = file->private_data;
1334 	int ret;
1335 	u8 val;
1336 
1337 	ret = kstrtou8_from_user(user_buf, count, 0, &val);
1338 	if (ret)
1339 		return ret;
1340 
1341 	ret = ath6kl_wmi_set_keepalive_cmd(ar->wmi, 0, val);
1342 	if (ret)
1343 		return ret;
1344 
1345 	return count;
1346 }
1347 
1348 static const struct file_operations fops_keepalive = {
1349 	.open = simple_open,
1350 	.read = ath6kl_keepalive_read,
1351 	.write = ath6kl_keepalive_write,
1352 	.owner = THIS_MODULE,
1353 	.llseek = default_llseek,
1354 };
1355 
1356 void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar, u8 timeout)
1357 {
1358 	ar->debug.disc_timeout = timeout;
1359 }
1360 
1361 static ssize_t ath6kl_disconnect_timeout_read(struct file *file,
1362 					      char __user *user_buf,
1363 					      size_t count, loff_t *ppos)
1364 {
1365 	struct ath6kl *ar = file->private_data;
1366 	char buf[16];
1367 	int len;
1368 
1369 	len = snprintf(buf, sizeof(buf), "%u\n", ar->debug.disc_timeout);
1370 
1371 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1372 }
1373 
1374 static ssize_t ath6kl_disconnect_timeout_write(struct file *file,
1375 					       const char __user *user_buf,
1376 					       size_t count, loff_t *ppos)
1377 {
1378 	struct ath6kl *ar = file->private_data;
1379 	int ret;
1380 	u8 val;
1381 
1382 	ret = kstrtou8_from_user(user_buf, count, 0, &val);
1383 	if (ret)
1384 		return ret;
1385 
1386 	ret = ath6kl_wmi_disctimeout_cmd(ar->wmi, 0, val);
1387 	if (ret)
1388 		return ret;
1389 
1390 	return count;
1391 }
1392 
1393 static const struct file_operations fops_disconnect_timeout = {
1394 	.open = simple_open,
1395 	.read = ath6kl_disconnect_timeout_read,
1396 	.write = ath6kl_disconnect_timeout_write,
1397 	.owner = THIS_MODULE,
1398 	.llseek = default_llseek,
1399 };
1400 
1401 static ssize_t ath6kl_create_qos_write(struct file *file,
1402 						const char __user *user_buf,
1403 						size_t count, loff_t *ppos)
1404 {
1405 
1406 	struct ath6kl *ar = file->private_data;
1407 	struct ath6kl_vif *vif;
1408 	char buf[200];
1409 	ssize_t len;
1410 	char *sptr, *token;
1411 	struct wmi_create_pstream_cmd pstream;
1412 	u32 val32;
1413 	u16 val16;
1414 
1415 	vif = ath6kl_vif_first(ar);
1416 	if (!vif)
1417 		return -EIO;
1418 
1419 	len = min(count, sizeof(buf) - 1);
1420 	if (copy_from_user(buf, user_buf, len))
1421 		return -EFAULT;
1422 	buf[len] = '\0';
1423 	sptr = buf;
1424 
1425 	token = strsep(&sptr, " ");
1426 	if (!token)
1427 		return -EINVAL;
1428 	if (kstrtou8(token, 0, &pstream.user_pri))
1429 		return -EINVAL;
1430 
1431 	token = strsep(&sptr, " ");
1432 	if (!token)
1433 		return -EINVAL;
1434 	if (kstrtou8(token, 0, &pstream.traffic_direc))
1435 		return -EINVAL;
1436 
1437 	token = strsep(&sptr, " ");
1438 	if (!token)
1439 		return -EINVAL;
1440 	if (kstrtou8(token, 0, &pstream.traffic_class))
1441 		return -EINVAL;
1442 
1443 	token = strsep(&sptr, " ");
1444 	if (!token)
1445 		return -EINVAL;
1446 	if (kstrtou8(token, 0, &pstream.traffic_type))
1447 		return -EINVAL;
1448 
1449 	token = strsep(&sptr, " ");
1450 	if (!token)
1451 		return -EINVAL;
1452 	if (kstrtou8(token, 0, &pstream.voice_psc_cap))
1453 		return -EINVAL;
1454 
1455 	token = strsep(&sptr, " ");
1456 	if (!token)
1457 		return -EINVAL;
1458 	if (kstrtou32(token, 0, &val32))
1459 		return -EINVAL;
1460 	pstream.min_service_int = cpu_to_le32(val32);
1461 
1462 	token = strsep(&sptr, " ");
1463 	if (!token)
1464 		return -EINVAL;
1465 	if (kstrtou32(token, 0, &val32))
1466 		return -EINVAL;
1467 	pstream.max_service_int = cpu_to_le32(val32);
1468 
1469 	token = strsep(&sptr, " ");
1470 	if (!token)
1471 		return -EINVAL;
1472 	if (kstrtou32(token, 0, &val32))
1473 		return -EINVAL;
1474 	pstream.inactivity_int = cpu_to_le32(val32);
1475 
1476 	token = strsep(&sptr, " ");
1477 	if (!token)
1478 		return -EINVAL;
1479 	if (kstrtou32(token, 0, &val32))
1480 		return -EINVAL;
1481 	pstream.suspension_int = cpu_to_le32(val32);
1482 
1483 	token = strsep(&sptr, " ");
1484 	if (!token)
1485 		return -EINVAL;
1486 	if (kstrtou32(token, 0, &val32))
1487 		return -EINVAL;
1488 	pstream.service_start_time = cpu_to_le32(val32);
1489 
1490 	token = strsep(&sptr, " ");
1491 	if (!token)
1492 		return -EINVAL;
1493 	if (kstrtou8(token, 0, &pstream.tsid))
1494 		return -EINVAL;
1495 
1496 	token = strsep(&sptr, " ");
1497 	if (!token)
1498 		return -EINVAL;
1499 	if (kstrtou16(token, 0, &val16))
1500 		return -EINVAL;
1501 	pstream.nominal_msdu = cpu_to_le16(val16);
1502 
1503 	token = strsep(&sptr, " ");
1504 	if (!token)
1505 		return -EINVAL;
1506 	if (kstrtou16(token, 0, &val16))
1507 		return -EINVAL;
1508 	pstream.max_msdu = cpu_to_le16(val16);
1509 
1510 	token = strsep(&sptr, " ");
1511 	if (!token)
1512 		return -EINVAL;
1513 	if (kstrtou32(token, 0, &val32))
1514 		return -EINVAL;
1515 	pstream.min_data_rate = cpu_to_le32(val32);
1516 
1517 	token = strsep(&sptr, " ");
1518 	if (!token)
1519 		return -EINVAL;
1520 	if (kstrtou32(token, 0, &val32))
1521 		return -EINVAL;
1522 	pstream.mean_data_rate = cpu_to_le32(val32);
1523 
1524 	token = strsep(&sptr, " ");
1525 	if (!token)
1526 		return -EINVAL;
1527 	if (kstrtou32(token, 0, &val32))
1528 		return -EINVAL;
1529 	pstream.peak_data_rate = cpu_to_le32(val32);
1530 
1531 	token = strsep(&sptr, " ");
1532 	if (!token)
1533 		return -EINVAL;
1534 	if (kstrtou32(token, 0, &val32))
1535 		return -EINVAL;
1536 	pstream.max_burst_size = cpu_to_le32(val32);
1537 
1538 	token = strsep(&sptr, " ");
1539 	if (!token)
1540 		return -EINVAL;
1541 	if (kstrtou32(token, 0, &val32))
1542 		return -EINVAL;
1543 	pstream.delay_bound = cpu_to_le32(val32);
1544 
1545 	token = strsep(&sptr, " ");
1546 	if (!token)
1547 		return -EINVAL;
1548 	if (kstrtou32(token, 0, &val32))
1549 		return -EINVAL;
1550 	pstream.min_phy_rate = cpu_to_le32(val32);
1551 
1552 	token = strsep(&sptr, " ");
1553 	if (!token)
1554 		return -EINVAL;
1555 	if (kstrtou32(token, 0, &val32))
1556 		return -EINVAL;
1557 	pstream.sba = cpu_to_le32(val32);
1558 
1559 	token = strsep(&sptr, " ");
1560 	if (!token)
1561 		return -EINVAL;
1562 	if (kstrtou32(token, 0, &val32))
1563 		return -EINVAL;
1564 	pstream.medium_time = cpu_to_le32(val32);
1565 
1566 	pstream.nominal_phy = le32_to_cpu(pstream.min_phy_rate) / 1000000;
1567 
1568 	ath6kl_wmi_create_pstream_cmd(ar->wmi, vif->fw_vif_idx, &pstream);
1569 
1570 	return count;
1571 }
1572 
1573 static const struct file_operations fops_create_qos = {
1574 	.write = ath6kl_create_qos_write,
1575 	.open = simple_open,
1576 	.owner = THIS_MODULE,
1577 	.llseek = default_llseek,
1578 };
1579 
1580 static ssize_t ath6kl_delete_qos_write(struct file *file,
1581 				const char __user *user_buf,
1582 				size_t count, loff_t *ppos)
1583 {
1584 
1585 	struct ath6kl *ar = file->private_data;
1586 	struct ath6kl_vif *vif;
1587 	char buf[100];
1588 	ssize_t len;
1589 	char *sptr, *token;
1590 	u8 traffic_class;
1591 	u8 tsid;
1592 
1593 	vif = ath6kl_vif_first(ar);
1594 	if (!vif)
1595 		return -EIO;
1596 
1597 	len = min(count, sizeof(buf) - 1);
1598 	if (copy_from_user(buf, user_buf, len))
1599 		return -EFAULT;
1600 	buf[len] = '\0';
1601 	sptr = buf;
1602 
1603 	token = strsep(&sptr, " ");
1604 	if (!token)
1605 		return -EINVAL;
1606 	if (kstrtou8(token, 0, &traffic_class))
1607 		return -EINVAL;
1608 
1609 	token = strsep(&sptr, " ");
1610 	if (!token)
1611 		return -EINVAL;
1612 	if (kstrtou8(token, 0, &tsid))
1613 		return -EINVAL;
1614 
1615 	ath6kl_wmi_delete_pstream_cmd(ar->wmi, vif->fw_vif_idx,
1616 				      traffic_class, tsid);
1617 
1618 	return count;
1619 }
1620 
1621 static const struct file_operations fops_delete_qos = {
1622 	.write = ath6kl_delete_qos_write,
1623 	.open = simple_open,
1624 	.owner = THIS_MODULE,
1625 	.llseek = default_llseek,
1626 };
1627 
1628 static ssize_t ath6kl_bgscan_int_write(struct file *file,
1629 				const char __user *user_buf,
1630 				size_t count, loff_t *ppos)
1631 {
1632 	struct ath6kl *ar = file->private_data;
1633 	struct ath6kl_vif *vif;
1634 	u16 bgscan_int;
1635 	char buf[32];
1636 	ssize_t len;
1637 
1638 	vif = ath6kl_vif_first(ar);
1639 	if (!vif)
1640 		return -EIO;
1641 
1642 	len = min(count, sizeof(buf) - 1);
1643 	if (copy_from_user(buf, user_buf, len))
1644 		return -EFAULT;
1645 
1646 	buf[len] = '\0';
1647 	if (kstrtou16(buf, 0, &bgscan_int))
1648 		return -EINVAL;
1649 
1650 	if (bgscan_int == 0)
1651 		bgscan_int = 0xffff;
1652 
1653 	vif->bg_scan_period = bgscan_int;
1654 
1655 	ath6kl_wmi_scanparams_cmd(ar->wmi, 0, 0, 0, bgscan_int, 0, 0, 0, 3,
1656 				  0, 0, 0);
1657 
1658 	return count;
1659 }
1660 
1661 static const struct file_operations fops_bgscan_int = {
1662 	.write = ath6kl_bgscan_int_write,
1663 	.open = simple_open,
1664 	.owner = THIS_MODULE,
1665 	.llseek = default_llseek,
1666 };
1667 
1668 static ssize_t ath6kl_listen_int_write(struct file *file,
1669 				       const char __user *user_buf,
1670 				       size_t count, loff_t *ppos)
1671 {
1672 	struct ath6kl *ar = file->private_data;
1673 	struct ath6kl_vif *vif;
1674 	u16 listen_interval;
1675 	char buf[32];
1676 	ssize_t len;
1677 
1678 	vif = ath6kl_vif_first(ar);
1679 	if (!vif)
1680 		return -EIO;
1681 
1682 	len = min(count, sizeof(buf) - 1);
1683 	if (copy_from_user(buf, user_buf, len))
1684 		return -EFAULT;
1685 
1686 	buf[len] = '\0';
1687 	if (kstrtou16(buf, 0, &listen_interval))
1688 		return -EINVAL;
1689 
1690 	if ((listen_interval < 15) || (listen_interval > 3000))
1691 		return -EINVAL;
1692 
1693 	vif->listen_intvl_t = listen_interval;
1694 	ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
1695 				      vif->listen_intvl_t, 0);
1696 
1697 	return count;
1698 }
1699 
1700 static ssize_t ath6kl_listen_int_read(struct file *file,
1701 				      char __user *user_buf,
1702 				      size_t count, loff_t *ppos)
1703 {
1704 	struct ath6kl *ar = file->private_data;
1705 	struct ath6kl_vif *vif;
1706 	char buf[32];
1707 	int len;
1708 
1709 	vif = ath6kl_vif_first(ar);
1710 	if (!vif)
1711 		return -EIO;
1712 
1713 	len = scnprintf(buf, sizeof(buf), "%u\n", vif->listen_intvl_t);
1714 
1715 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1716 }
1717 
1718 static const struct file_operations fops_listen_int = {
1719 	.read = ath6kl_listen_int_read,
1720 	.write = ath6kl_listen_int_write,
1721 	.open = simple_open,
1722 	.owner = THIS_MODULE,
1723 	.llseek = default_llseek,
1724 };
1725 
1726 static ssize_t ath6kl_power_params_write(struct file *file,
1727 						const char __user *user_buf,
1728 						size_t count, loff_t *ppos)
1729 {
1730 	struct ath6kl *ar = file->private_data;
1731 	u8 buf[100];
1732 	unsigned int len = 0;
1733 	char *sptr, *token;
1734 	u16 idle_period, ps_poll_num, dtim,
1735 		tx_wakeup, num_tx;
1736 
1737 	len = min(count, sizeof(buf) - 1);
1738 	if (copy_from_user(buf, user_buf, len))
1739 		return -EFAULT;
1740 	buf[len] = '\0';
1741 	sptr = buf;
1742 
1743 	token = strsep(&sptr, " ");
1744 	if (!token)
1745 		return -EINVAL;
1746 	if (kstrtou16(token, 0, &idle_period))
1747 		return -EINVAL;
1748 
1749 	token = strsep(&sptr, " ");
1750 	if (!token)
1751 		return -EINVAL;
1752 	if (kstrtou16(token, 0, &ps_poll_num))
1753 		return -EINVAL;
1754 
1755 	token = strsep(&sptr, " ");
1756 	if (!token)
1757 		return -EINVAL;
1758 	if (kstrtou16(token, 0, &dtim))
1759 		return -EINVAL;
1760 
1761 	token = strsep(&sptr, " ");
1762 	if (!token)
1763 		return -EINVAL;
1764 	if (kstrtou16(token, 0, &tx_wakeup))
1765 		return -EINVAL;
1766 
1767 	token = strsep(&sptr, " ");
1768 	if (!token)
1769 		return -EINVAL;
1770 	if (kstrtou16(token, 0, &num_tx))
1771 		return -EINVAL;
1772 
1773 	ath6kl_wmi_pmparams_cmd(ar->wmi, 0, idle_period, ps_poll_num,
1774 				dtim, tx_wakeup, num_tx, 0);
1775 
1776 	return count;
1777 }
1778 
1779 static const struct file_operations fops_power_params = {
1780 	.write = ath6kl_power_params_write,
1781 	.open = simple_open,
1782 	.owner = THIS_MODULE,
1783 	.llseek = default_llseek,
1784 };
1785 
1786 void ath6kl_debug_init(struct ath6kl *ar)
1787 {
1788 	skb_queue_head_init(&ar->debug.fwlog_queue);
1789 	init_completion(&ar->debug.fwlog_completion);
1790 
1791 	/*
1792 	 * Actually we are lying here but don't know how to read the mask
1793 	 * value from the firmware.
1794 	 */
1795 	ar->debug.fwlog_mask = 0;
1796 }
1797 
1798 /*
1799  * Initialisation needs to happen in two stages as fwlog events can come
1800  * before cfg80211 is initialised, and debugfs depends on cfg80211
1801  * initialisation.
1802  */
1803 int ath6kl_debug_init_fs(struct ath6kl *ar)
1804 {
1805 	ar->debugfs_phy = debugfs_create_dir("ath6kl",
1806 					     ar->wiphy->debugfsdir);
1807 	if (!ar->debugfs_phy)
1808 		return -ENOMEM;
1809 
1810 	debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar,
1811 			    &fops_tgt_stats);
1812 
1813 	debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar,
1814 			    &fops_credit_dist_stats);
1815 
1816 	debugfs_create_file("endpoint_stats", S_IRUSR | S_IWUSR,
1817 			    ar->debugfs_phy, ar, &fops_endpoint_stats);
1818 
1819 	debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar,
1820 			    &fops_fwlog);
1821 
1822 	debugfs_create_file("fwlog_block", S_IRUSR, ar->debugfs_phy, ar,
1823 			    &fops_fwlog_block);
1824 
1825 	debugfs_create_file("fwlog_mask", S_IRUSR | S_IWUSR, ar->debugfs_phy,
1826 			    ar, &fops_fwlog_mask);
1827 
1828 	debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar,
1829 			    &fops_diag_reg_read);
1830 
1831 	debugfs_create_file("reg_dump", S_IRUSR, ar->debugfs_phy, ar,
1832 			    &fops_reg_dump);
1833 
1834 	debugfs_create_file("lrssi_roam_threshold", S_IRUSR | S_IWUSR,
1835 			    ar->debugfs_phy, ar, &fops_lrssi_roam_threshold);
1836 
1837 	debugfs_create_file("reg_write", S_IRUSR | S_IWUSR,
1838 			    ar->debugfs_phy, ar, &fops_diag_reg_write);
1839 
1840 	debugfs_create_file("war_stats", S_IRUSR, ar->debugfs_phy, ar,
1841 			    &fops_war_stats);
1842 
1843 	debugfs_create_file("roam_table", S_IRUSR, ar->debugfs_phy, ar,
1844 			    &fops_roam_table);
1845 
1846 	debugfs_create_file("force_roam", S_IWUSR, ar->debugfs_phy, ar,
1847 			    &fops_force_roam);
1848 
1849 	debugfs_create_file("roam_mode", S_IWUSR, ar->debugfs_phy, ar,
1850 			    &fops_roam_mode);
1851 
1852 	debugfs_create_file("keepalive", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar,
1853 			    &fops_keepalive);
1854 
1855 	debugfs_create_file("disconnect_timeout", S_IRUSR | S_IWUSR,
1856 			    ar->debugfs_phy, ar, &fops_disconnect_timeout);
1857 
1858 	debugfs_create_file("create_qos", S_IWUSR, ar->debugfs_phy, ar,
1859 			    &fops_create_qos);
1860 
1861 	debugfs_create_file("delete_qos", S_IWUSR, ar->debugfs_phy, ar,
1862 			    &fops_delete_qos);
1863 
1864 	debugfs_create_file("bgscan_interval", S_IWUSR,
1865 			    ar->debugfs_phy, ar, &fops_bgscan_int);
1866 
1867 	debugfs_create_file("listen_interval", S_IRUSR | S_IWUSR,
1868 			    ar->debugfs_phy, ar, &fops_listen_int);
1869 
1870 	debugfs_create_file("power_params", S_IWUSR, ar->debugfs_phy, ar,
1871 			    &fops_power_params);
1872 
1873 	return 0;
1874 }
1875 
1876 void ath6kl_debug_cleanup(struct ath6kl *ar)
1877 {
1878 	skb_queue_purge(&ar->debug.fwlog_queue);
1879 	complete(&ar->debug.fwlog_completion);
1880 	kfree(ar->debug.roam_tbl);
1881 }
1882 
1883 #endif
1884