1bdcd8170SKalle Valo /* 2bdcd8170SKalle Valo * Copyright (c) 2004-2011 Atheros Communications Inc. 31b2df407SVasanthakumar Thiagarajan * Copyright (c) 2011-2012 Qualcomm Atheros, Inc. 4bdcd8170SKalle Valo * 5bdcd8170SKalle Valo * Permission to use, copy, modify, and/or distribute this software for any 6bdcd8170SKalle Valo * purpose with or without fee is hereby granted, provided that the above 7bdcd8170SKalle Valo * copyright notice and this permission notice appear in all copies. 8bdcd8170SKalle Valo * 9bdcd8170SKalle Valo * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10bdcd8170SKalle Valo * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11bdcd8170SKalle Valo * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12bdcd8170SKalle Valo * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13bdcd8170SKalle Valo * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14bdcd8170SKalle Valo * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15bdcd8170SKalle Valo * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16bdcd8170SKalle Valo */ 17bdcd8170SKalle Valo 18bdcd8170SKalle Valo #include "core.h" 19bdf5396bSKalle Valo 209b9a4f2aSKalle Valo #include <linux/skbuff.h> 21939f1cceSKalle Valo #include <linux/fs.h> 2262c83ac4SKalle Valo #include <linux/vmalloc.h> 23ee40fa06SPaul Gortmaker #include <linux/export.h> 24bdf5396bSKalle Valo 25bdcd8170SKalle Valo #include "debug.h" 26bdf5396bSKalle Valo #include "target.h" 27bdf5396bSKalle Valo 28bdf5396bSKalle Valo struct ath6kl_fwlog_slot { 29bdf5396bSKalle Valo __le32 timestamp; 30bdf5396bSKalle Valo __le32 length; 31bdf5396bSKalle Valo 32bdf5396bSKalle Valo /* max ATH6KL_FWLOG_PAYLOAD_SIZE bytes */ 33bdf5396bSKalle Valo u8 payload[0]; 34bdf5396bSKalle Valo }; 35bdf5396bSKalle Valo 369b9a4f2aSKalle Valo #define ATH6KL_FWLOG_MAX_ENTRIES 20 379b9a4f2aSKalle Valo 38939f1cceSKalle Valo #define ATH6KL_FWLOG_VALID_MASK 0x1ffff 39bdcd8170SKalle Valo 40bdcd8170SKalle Valo int ath6kl_printk(const char *level, const char *fmt, ...) 41bdcd8170SKalle Valo { 42bdcd8170SKalle Valo struct va_format vaf; 43bdcd8170SKalle Valo va_list args; 44bdcd8170SKalle Valo int rtn; 45bdcd8170SKalle Valo 46bdcd8170SKalle Valo va_start(args, fmt); 47bdcd8170SKalle Valo 48bdcd8170SKalle Valo vaf.fmt = fmt; 49bdcd8170SKalle Valo vaf.va = &args; 50bdcd8170SKalle Valo 51bdcd8170SKalle Valo rtn = printk("%sath6kl: %pV", level, &vaf); 52bdcd8170SKalle Valo 53bdcd8170SKalle Valo va_end(args); 54bdcd8170SKalle Valo 55bdcd8170SKalle Valo return rtn; 56bdcd8170SKalle Valo } 57d6a434d6SKalle Valo EXPORT_SYMBOL(ath6kl_printk); 58bdcd8170SKalle Valo 59bdcd8170SKalle Valo #ifdef CONFIG_ATH6KL_DEBUG 6091d57de5SVasanthakumar Thiagarajan 613b1b7d09SKalle Valo void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) 623b1b7d09SKalle Valo { 633b1b7d09SKalle Valo struct va_format vaf; 643b1b7d09SKalle Valo va_list args; 653b1b7d09SKalle Valo 663b1b7d09SKalle Valo if (!(debug_mask & mask)) 673b1b7d09SKalle Valo return; 683b1b7d09SKalle Valo 693b1b7d09SKalle Valo va_start(args, fmt); 703b1b7d09SKalle Valo 713b1b7d09SKalle Valo vaf.fmt = fmt; 723b1b7d09SKalle Valo vaf.va = &args; 733b1b7d09SKalle Valo 743b1b7d09SKalle Valo ath6kl_printk(KERN_DEBUG, "%pV", &vaf); 753b1b7d09SKalle Valo 763b1b7d09SKalle Valo va_end(args); 773b1b7d09SKalle Valo } 78d6a434d6SKalle Valo EXPORT_SYMBOL(ath6kl_dbg); 793b1b7d09SKalle Valo 803b1b7d09SKalle Valo void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, 813b1b7d09SKalle Valo const char *msg, const char *prefix, 823b1b7d09SKalle Valo const void *buf, size_t len) 833b1b7d09SKalle Valo { 843b1b7d09SKalle Valo if (debug_mask & mask) { 853b1b7d09SKalle Valo if (msg) 863b1b7d09SKalle Valo ath6kl_dbg(mask, "%s\n", msg); 873b1b7d09SKalle Valo 883b1b7d09SKalle Valo print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); 893b1b7d09SKalle Valo } 903b1b7d09SKalle Valo } 91d6a434d6SKalle Valo EXPORT_SYMBOL(ath6kl_dbg_dump); 923b1b7d09SKalle Valo 9391d57de5SVasanthakumar Thiagarajan #define REG_OUTPUT_LEN_PER_LINE 25 9491d57de5SVasanthakumar Thiagarajan #define REGTYPE_STR_LEN 100 9591d57de5SVasanthakumar Thiagarajan 9691d57de5SVasanthakumar Thiagarajan struct ath6kl_diag_reg_info { 9791d57de5SVasanthakumar Thiagarajan u32 reg_start; 9891d57de5SVasanthakumar Thiagarajan u32 reg_end; 9991d57de5SVasanthakumar Thiagarajan const char *reg_info; 10091d57de5SVasanthakumar Thiagarajan }; 10191d57de5SVasanthakumar Thiagarajan 10291d57de5SVasanthakumar Thiagarajan static const struct ath6kl_diag_reg_info diag_reg[] = { 10391d57de5SVasanthakumar Thiagarajan { 0x20000, 0x200fc, "General DMA and Rx registers" }, 10491d57de5SVasanthakumar Thiagarajan { 0x28000, 0x28900, "MAC PCU register & keycache" }, 10591d57de5SVasanthakumar Thiagarajan { 0x20800, 0x20a40, "QCU" }, 10691d57de5SVasanthakumar Thiagarajan { 0x21000, 0x212f0, "DCU" }, 10791d57de5SVasanthakumar Thiagarajan { 0x4000, 0x42e4, "RTC" }, 10891d57de5SVasanthakumar Thiagarajan { 0x540000, 0x540000 + (256 * 1024), "RAM" }, 10991d57de5SVasanthakumar Thiagarajan { 0x29800, 0x2B210, "Base Band" }, 11091d57de5SVasanthakumar Thiagarajan { 0x1C000, 0x1C748, "Analog" }, 11191d57de5SVasanthakumar Thiagarajan }; 11291d57de5SVasanthakumar Thiagarajan 113bdcd8170SKalle Valo void ath6kl_dump_registers(struct ath6kl_device *dev, 114bdcd8170SKalle Valo struct ath6kl_irq_proc_registers *irq_proc_reg, 115bdcd8170SKalle Valo struct ath6kl_irq_enable_reg *irq_enable_reg) 116bdcd8170SKalle Valo { 117bdcd8170SKalle Valo 1185afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, ("<------- Register Table -------->\n")); 119bdcd8170SKalle Valo 120bdcd8170SKalle Valo if (irq_proc_reg != NULL) { 1215afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 122bdcd8170SKalle Valo "Host Int status: 0x%x\n", 123bdcd8170SKalle Valo irq_proc_reg->host_int_status); 1245afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 125bdcd8170SKalle Valo "CPU Int status: 0x%x\n", 126bdcd8170SKalle Valo irq_proc_reg->cpu_int_status); 1275afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 128bdcd8170SKalle Valo "Error Int status: 0x%x\n", 129bdcd8170SKalle Valo irq_proc_reg->error_int_status); 1305afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 131bdcd8170SKalle Valo "Counter Int status: 0x%x\n", 132bdcd8170SKalle Valo irq_proc_reg->counter_int_status); 1335afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 134bdcd8170SKalle Valo "Mbox Frame: 0x%x\n", 135bdcd8170SKalle Valo irq_proc_reg->mbox_frame); 1365afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 137bdcd8170SKalle Valo "Rx Lookahead Valid: 0x%x\n", 138bdcd8170SKalle Valo irq_proc_reg->rx_lkahd_valid); 1395afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 140bdcd8170SKalle Valo "Rx Lookahead 0: 0x%x\n", 141bdcd8170SKalle Valo irq_proc_reg->rx_lkahd[0]); 1425afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 143bdcd8170SKalle Valo "Rx Lookahead 1: 0x%x\n", 144bdcd8170SKalle Valo irq_proc_reg->rx_lkahd[1]); 145bdcd8170SKalle Valo 146bdcd8170SKalle Valo if (dev->ar->mbox_info.gmbox_addr != 0) { 147bdcd8170SKalle Valo /* 148bdcd8170SKalle Valo * If the target supports GMBOX hardware, dump some 149bdcd8170SKalle Valo * additional state. 150bdcd8170SKalle Valo */ 1515afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 152bdcd8170SKalle Valo "GMBOX Host Int status 2: 0x%x\n", 153bdcd8170SKalle Valo irq_proc_reg->host_int_status2); 1545afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 155bdcd8170SKalle Valo "GMBOX RX Avail: 0x%x\n", 156bdcd8170SKalle Valo irq_proc_reg->gmbox_rx_avail); 1575afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 158bdcd8170SKalle Valo "GMBOX lookahead alias 0: 0x%x\n", 159bdcd8170SKalle Valo irq_proc_reg->rx_gmbox_lkahd_alias[0]); 1605afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 161bdcd8170SKalle Valo "GMBOX lookahead alias 1: 0x%x\n", 162bdcd8170SKalle Valo irq_proc_reg->rx_gmbox_lkahd_alias[1]); 163bdcd8170SKalle Valo } 164bdcd8170SKalle Valo 165bdcd8170SKalle Valo } 166bdcd8170SKalle Valo 167bdcd8170SKalle Valo if (irq_enable_reg != NULL) { 1685afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 169bdcd8170SKalle Valo "Int status Enable: 0x%x\n", 170bdcd8170SKalle Valo irq_enable_reg->int_status_en); 1715afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, "Counter Int status Enable: 0x%x\n", 172bdcd8170SKalle Valo irq_enable_reg->cntr_int_status_en); 173bdcd8170SKalle Valo } 1745afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, "<------------------------------->\n"); 175bdcd8170SKalle Valo } 176bdcd8170SKalle Valo 177bdcd8170SKalle Valo static void dump_cred_dist(struct htc_endpoint_credit_dist *ep_dist) 178bdcd8170SKalle Valo { 17902f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, 180bdcd8170SKalle Valo "--- endpoint: %d svc_id: 0x%X ---\n", 181bdcd8170SKalle Valo ep_dist->endpoint, ep_dist->svc_id); 18202f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " dist_flags : 0x%X\n", 183bdcd8170SKalle Valo ep_dist->dist_flags); 18402f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_norm : %d\n", 185bdcd8170SKalle Valo ep_dist->cred_norm); 18602f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_min : %d\n", 187bdcd8170SKalle Valo ep_dist->cred_min); 18802f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " credits : %d\n", 189bdcd8170SKalle Valo ep_dist->credits); 19002f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_assngd : %d\n", 191bdcd8170SKalle Valo ep_dist->cred_assngd); 19202f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " seek_cred : %d\n", 193bdcd8170SKalle Valo ep_dist->seek_cred); 19402f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_sz : %d\n", 195bdcd8170SKalle Valo ep_dist->cred_sz); 19602f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_per_msg : %d\n", 197bdcd8170SKalle Valo ep_dist->cred_per_msg); 19802f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_to_dist : %d\n", 199bdcd8170SKalle Valo ep_dist->cred_to_dist); 20002f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " txq_depth : %d\n", 201e8c39790SKalle Valo get_queue_depth(&ep_dist->htc_ep->txq)); 20202f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, 203bdcd8170SKalle Valo "----------------------------------\n"); 204bdcd8170SKalle Valo } 205bdcd8170SKalle Valo 20602f0d6fcSKalle Valo /* FIXME: move to htc.c */ 207bdcd8170SKalle Valo void dump_cred_dist_stats(struct htc_target *target) 208bdcd8170SKalle Valo { 209bdcd8170SKalle Valo struct htc_endpoint_credit_dist *ep_list; 210bdcd8170SKalle Valo 211bdcd8170SKalle Valo list_for_each_entry(ep_list, &target->cred_dist_list, list) 212bdcd8170SKalle Valo dump_cred_dist(ep_list); 213bdcd8170SKalle Valo 21402f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, 21502f0d6fcSKalle Valo "credit distribution total %d free %d\n", 2163c370398SKalle Valo target->credit_info->total_avail_credits, 2173c370398SKalle Valo target->credit_info->cur_free_credits); 218bdcd8170SKalle Valo } 219bdcd8170SKalle Valo 22003f68a95SVasanthakumar Thiagarajan static int ath6kl_debugfs_open(struct inode *inode, struct file *file) 22103f68a95SVasanthakumar Thiagarajan { 22203f68a95SVasanthakumar Thiagarajan file->private_data = inode->i_private; 22303f68a95SVasanthakumar Thiagarajan return 0; 22403f68a95SVasanthakumar Thiagarajan } 22503f68a95SVasanthakumar Thiagarajan 2269a730834SKalle Valo void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war) 2279a730834SKalle Valo { 2289a730834SKalle Valo switch (war) { 2299a730834SKalle Valo case ATH6KL_WAR_INVALID_RATE: 2309a730834SKalle Valo ar->debug.war_stats.invalid_rate++; 2319a730834SKalle Valo break; 2329a730834SKalle Valo } 2339a730834SKalle Valo } 2349a730834SKalle Valo 2359a730834SKalle Valo static ssize_t read_file_war_stats(struct file *file, char __user *user_buf, 2369a730834SKalle Valo size_t count, loff_t *ppos) 2379a730834SKalle Valo { 2389a730834SKalle Valo struct ath6kl *ar = file->private_data; 2399a730834SKalle Valo char *buf; 2409a730834SKalle Valo unsigned int len = 0, buf_len = 1500; 2419a730834SKalle Valo ssize_t ret_cnt; 2429a730834SKalle Valo 2439a730834SKalle Valo buf = kzalloc(buf_len, GFP_KERNEL); 2449a730834SKalle Valo if (!buf) 2459a730834SKalle Valo return -ENOMEM; 2469a730834SKalle Valo 2479a730834SKalle Valo len += scnprintf(buf + len, buf_len - len, "\n"); 2489a730834SKalle Valo len += scnprintf(buf + len, buf_len - len, "%25s\n", 2499a730834SKalle Valo "Workaround stats"); 2509a730834SKalle Valo len += scnprintf(buf + len, buf_len - len, "%25s\n\n", 2519a730834SKalle Valo "================="); 2529a730834SKalle Valo len += scnprintf(buf + len, buf_len - len, "%20s %10u\n", 2539a730834SKalle Valo "Invalid rates", ar->debug.war_stats.invalid_rate); 2549a730834SKalle Valo 2559a730834SKalle Valo if (WARN_ON(len > buf_len)) 2569a730834SKalle Valo len = buf_len; 2579a730834SKalle Valo 2589a730834SKalle Valo ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); 2599a730834SKalle Valo 2609a730834SKalle Valo kfree(buf); 2619a730834SKalle Valo return ret_cnt; 2629a730834SKalle Valo } 2639a730834SKalle Valo 2649a730834SKalle Valo static const struct file_operations fops_war_stats = { 2659a730834SKalle Valo .read = read_file_war_stats, 2669a730834SKalle Valo .open = ath6kl_debugfs_open, 2679a730834SKalle Valo .owner = THIS_MODULE, 2689a730834SKalle Valo .llseek = default_llseek, 2699a730834SKalle Valo }; 2709a730834SKalle Valo 271bdf5396bSKalle Valo void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len) 272bdf5396bSKalle Valo { 2739b9a4f2aSKalle Valo struct ath6kl_fwlog_slot *slot; 2749b9a4f2aSKalle Valo struct sk_buff *skb; 275bdf5396bSKalle Valo size_t slot_len; 276bdf5396bSKalle Valo 277bdf5396bSKalle Valo if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE)) 278bdf5396bSKalle Valo return; 279bdf5396bSKalle Valo 2807504a3e1SEtay Luz slot_len = sizeof(*slot) + ATH6KL_FWLOG_PAYLOAD_SIZE; 281bdf5396bSKalle Valo 2829b9a4f2aSKalle Valo skb = alloc_skb(slot_len, GFP_KERNEL); 2839b9a4f2aSKalle Valo if (!skb) 2849b9a4f2aSKalle Valo return; 2859b9a4f2aSKalle Valo 2869b9a4f2aSKalle Valo slot = (struct ath6kl_fwlog_slot *) skb_put(skb, slot_len); 287bdf5396bSKalle Valo slot->timestamp = cpu_to_le32(jiffies); 288bdf5396bSKalle Valo slot->length = cpu_to_le32(len); 289bdf5396bSKalle Valo memcpy(slot->payload, buf, len); 290bdf5396bSKalle Valo 2917504a3e1SEtay Luz /* Need to pad each record to fixed length ATH6KL_FWLOG_PAYLOAD_SIZE */ 2927504a3e1SEtay Luz memset(slot->payload + len, 0, ATH6KL_FWLOG_PAYLOAD_SIZE - len); 2937504a3e1SEtay Luz 2949b9a4f2aSKalle Valo spin_lock(&ar->debug.fwlog_queue.lock); 295bdf5396bSKalle Valo 2969b9a4f2aSKalle Valo __skb_queue_tail(&ar->debug.fwlog_queue, skb); 297c807b30dSKalle Valo complete(&ar->debug.fwlog_completion); 298bdf5396bSKalle Valo 2999b9a4f2aSKalle Valo /* drop oldest entries */ 3009b9a4f2aSKalle Valo while (skb_queue_len(&ar->debug.fwlog_queue) > 3019b9a4f2aSKalle Valo ATH6KL_FWLOG_MAX_ENTRIES) { 3029b9a4f2aSKalle Valo skb = __skb_dequeue(&ar->debug.fwlog_queue); 3039b9a4f2aSKalle Valo kfree_skb(skb); 304bdf5396bSKalle Valo } 305bdf5396bSKalle Valo 3069b9a4f2aSKalle Valo spin_unlock(&ar->debug.fwlog_queue.lock); 3079b9a4f2aSKalle Valo 3089b9a4f2aSKalle Valo return; 309bdf5396bSKalle Valo } 310bdf5396bSKalle Valo 311c807b30dSKalle Valo static int ath6kl_fwlog_open(struct inode *inode, struct file *file) 312c807b30dSKalle Valo { 313c807b30dSKalle Valo struct ath6kl *ar = inode->i_private; 314c807b30dSKalle Valo 315c807b30dSKalle Valo if (ar->debug.fwlog_open) 316c807b30dSKalle Valo return -EBUSY; 317c807b30dSKalle Valo 318c807b30dSKalle Valo ar->debug.fwlog_open = true; 319c807b30dSKalle Valo 320c807b30dSKalle Valo file->private_data = inode->i_private; 321c807b30dSKalle Valo return 0; 322c807b30dSKalle Valo } 323c807b30dSKalle Valo 324c807b30dSKalle Valo static int ath6kl_fwlog_release(struct inode *inode, struct file *file) 325c807b30dSKalle Valo { 326c807b30dSKalle Valo struct ath6kl *ar = inode->i_private; 327c807b30dSKalle Valo 328c807b30dSKalle Valo ar->debug.fwlog_open = false; 329c807b30dSKalle Valo 330c807b30dSKalle Valo return 0; 331c807b30dSKalle Valo } 332c807b30dSKalle Valo 333bdf5396bSKalle Valo static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf, 334bdf5396bSKalle Valo size_t count, loff_t *ppos) 335bdf5396bSKalle Valo { 336bdf5396bSKalle Valo struct ath6kl *ar = file->private_data; 3379b9a4f2aSKalle Valo struct sk_buff *skb; 338bdf5396bSKalle Valo ssize_t ret_cnt; 3399b9a4f2aSKalle Valo size_t len = 0; 340bdf5396bSKalle Valo char *buf; 341bdf5396bSKalle Valo 3429b9a4f2aSKalle Valo buf = vmalloc(count); 343bdf5396bSKalle Valo if (!buf) 344bdf5396bSKalle Valo return -ENOMEM; 345bdf5396bSKalle Valo 346bc07ddb2SKalle Valo /* read undelivered logs from firmware */ 347bc07ddb2SKalle Valo ath6kl_read_fwlogs(ar); 348bc07ddb2SKalle Valo 3499b9a4f2aSKalle Valo spin_lock(&ar->debug.fwlog_queue.lock); 350bdf5396bSKalle Valo 3519b9a4f2aSKalle Valo while ((skb = __skb_dequeue(&ar->debug.fwlog_queue))) { 3529b9a4f2aSKalle Valo if (skb->len > count - len) { 3539b9a4f2aSKalle Valo /* not enough space, put skb back and leave */ 3549b9a4f2aSKalle Valo __skb_queue_head(&ar->debug.fwlog_queue, skb); 3559b9a4f2aSKalle Valo break; 356bdf5396bSKalle Valo } 357bdf5396bSKalle Valo 358bdf5396bSKalle Valo 3599b9a4f2aSKalle Valo memcpy(buf + len, skb->data, skb->len); 3609b9a4f2aSKalle Valo len += skb->len; 3619b9a4f2aSKalle Valo 3629b9a4f2aSKalle Valo kfree_skb(skb); 3639b9a4f2aSKalle Valo } 3649b9a4f2aSKalle Valo 3659b9a4f2aSKalle Valo spin_unlock(&ar->debug.fwlog_queue.lock); 3669b9a4f2aSKalle Valo 3679b9a4f2aSKalle Valo /* FIXME: what to do if len == 0? */ 368bdf5396bSKalle Valo 369bdf5396bSKalle Valo ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); 370bdf5396bSKalle Valo 371bdf5396bSKalle Valo vfree(buf); 372bdf5396bSKalle Valo 373bdf5396bSKalle Valo return ret_cnt; 374bdf5396bSKalle Valo } 375bdf5396bSKalle Valo 376bdf5396bSKalle Valo static const struct file_operations fops_fwlog = { 377c807b30dSKalle Valo .open = ath6kl_fwlog_open, 378c807b30dSKalle Valo .release = ath6kl_fwlog_release, 379bdf5396bSKalle Valo .read = ath6kl_fwlog_read, 380bdf5396bSKalle Valo .owner = THIS_MODULE, 381bdf5396bSKalle Valo .llseek = default_llseek, 382bdf5396bSKalle Valo }; 383bdf5396bSKalle Valo 384c807b30dSKalle Valo static ssize_t ath6kl_fwlog_block_read(struct file *file, 385c807b30dSKalle Valo char __user *user_buf, 386c807b30dSKalle Valo size_t count, 387c807b30dSKalle Valo loff_t *ppos) 388c807b30dSKalle Valo { 389c807b30dSKalle Valo struct ath6kl *ar = file->private_data; 390c807b30dSKalle Valo struct sk_buff *skb; 391c807b30dSKalle Valo ssize_t ret_cnt; 392c807b30dSKalle Valo size_t len = 0, not_copied; 393c807b30dSKalle Valo char *buf; 394c807b30dSKalle Valo int ret; 395c807b30dSKalle Valo 396c807b30dSKalle Valo buf = vmalloc(count); 397c807b30dSKalle Valo if (!buf) 398c807b30dSKalle Valo return -ENOMEM; 399c807b30dSKalle Valo 400c807b30dSKalle Valo spin_lock(&ar->debug.fwlog_queue.lock); 401c807b30dSKalle Valo 402c807b30dSKalle Valo if (skb_queue_len(&ar->debug.fwlog_queue) == 0) { 403c807b30dSKalle Valo /* we must init under queue lock */ 404c807b30dSKalle Valo init_completion(&ar->debug.fwlog_completion); 405c807b30dSKalle Valo 406c807b30dSKalle Valo spin_unlock(&ar->debug.fwlog_queue.lock); 407c807b30dSKalle Valo 408c807b30dSKalle Valo ret = wait_for_completion_interruptible( 409c807b30dSKalle Valo &ar->debug.fwlog_completion); 410*ae9a3405SJesper Juhl if (ret == -ERESTARTSYS) { 411*ae9a3405SJesper Juhl vfree(buf); 412c807b30dSKalle Valo return ret; 413*ae9a3405SJesper Juhl } 414c807b30dSKalle Valo 415c807b30dSKalle Valo spin_lock(&ar->debug.fwlog_queue.lock); 416c807b30dSKalle Valo } 417c807b30dSKalle Valo 418c807b30dSKalle Valo while ((skb = __skb_dequeue(&ar->debug.fwlog_queue))) { 419c807b30dSKalle Valo if (skb->len > count - len) { 420c807b30dSKalle Valo /* not enough space, put skb back and leave */ 421c807b30dSKalle Valo __skb_queue_head(&ar->debug.fwlog_queue, skb); 422c807b30dSKalle Valo break; 423c807b30dSKalle Valo } 424c807b30dSKalle Valo 425c807b30dSKalle Valo 426c807b30dSKalle Valo memcpy(buf + len, skb->data, skb->len); 427c807b30dSKalle Valo len += skb->len; 428c807b30dSKalle Valo 429c807b30dSKalle Valo kfree_skb(skb); 430c807b30dSKalle Valo } 431c807b30dSKalle Valo 432c807b30dSKalle Valo spin_unlock(&ar->debug.fwlog_queue.lock); 433c807b30dSKalle Valo 434c807b30dSKalle Valo /* FIXME: what to do if len == 0? */ 435c807b30dSKalle Valo 436c807b30dSKalle Valo not_copied = copy_to_user(user_buf, buf, len); 437c807b30dSKalle Valo if (not_copied != 0) { 438c807b30dSKalle Valo ret_cnt = -EFAULT; 439c807b30dSKalle Valo goto out; 440c807b30dSKalle Valo } 441c807b30dSKalle Valo 442c807b30dSKalle Valo *ppos = *ppos + len; 443c807b30dSKalle Valo 444c807b30dSKalle Valo ret_cnt = len; 445c807b30dSKalle Valo 446c807b30dSKalle Valo out: 447c807b30dSKalle Valo vfree(buf); 448c807b30dSKalle Valo 449c807b30dSKalle Valo return ret_cnt; 450c807b30dSKalle Valo } 451c807b30dSKalle Valo 452c807b30dSKalle Valo static const struct file_operations fops_fwlog_block = { 453c807b30dSKalle Valo .open = ath6kl_fwlog_open, 454c807b30dSKalle Valo .release = ath6kl_fwlog_release, 455c807b30dSKalle Valo .read = ath6kl_fwlog_block_read, 456c807b30dSKalle Valo .owner = THIS_MODULE, 457c807b30dSKalle Valo .llseek = default_llseek, 458c807b30dSKalle Valo }; 459c807b30dSKalle Valo 460939f1cceSKalle Valo static ssize_t ath6kl_fwlog_mask_read(struct file *file, char __user *user_buf, 461939f1cceSKalle Valo size_t count, loff_t *ppos) 462939f1cceSKalle Valo { 463939f1cceSKalle Valo struct ath6kl *ar = file->private_data; 464939f1cceSKalle Valo char buf[16]; 465939f1cceSKalle Valo int len; 466939f1cceSKalle Valo 467939f1cceSKalle Valo len = snprintf(buf, sizeof(buf), "0x%x\n", ar->debug.fwlog_mask); 468939f1cceSKalle Valo 469939f1cceSKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, len); 470939f1cceSKalle Valo } 471939f1cceSKalle Valo 472939f1cceSKalle Valo static ssize_t ath6kl_fwlog_mask_write(struct file *file, 473939f1cceSKalle Valo const char __user *user_buf, 474939f1cceSKalle Valo size_t count, loff_t *ppos) 475939f1cceSKalle Valo { 476939f1cceSKalle Valo struct ath6kl *ar = file->private_data; 477939f1cceSKalle Valo int ret; 478939f1cceSKalle Valo 479939f1cceSKalle Valo ret = kstrtou32_from_user(user_buf, count, 0, &ar->debug.fwlog_mask); 480939f1cceSKalle Valo if (ret) 481939f1cceSKalle Valo return ret; 482939f1cceSKalle Valo 483939f1cceSKalle Valo ret = ath6kl_wmi_config_debug_module_cmd(ar->wmi, 484939f1cceSKalle Valo ATH6KL_FWLOG_VALID_MASK, 485939f1cceSKalle Valo ar->debug.fwlog_mask); 486939f1cceSKalle Valo if (ret) 487939f1cceSKalle Valo return ret; 488939f1cceSKalle Valo 489939f1cceSKalle Valo return count; 490939f1cceSKalle Valo } 491939f1cceSKalle Valo 492939f1cceSKalle Valo static const struct file_operations fops_fwlog_mask = { 493939f1cceSKalle Valo .open = ath6kl_debugfs_open, 494939f1cceSKalle Valo .read = ath6kl_fwlog_mask_read, 495939f1cceSKalle Valo .write = ath6kl_fwlog_mask_write, 496939f1cceSKalle Valo .owner = THIS_MODULE, 497939f1cceSKalle Valo .llseek = default_llseek, 498939f1cceSKalle Valo }; 499939f1cceSKalle Valo 50003f68a95SVasanthakumar Thiagarajan static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, 50103f68a95SVasanthakumar Thiagarajan size_t count, loff_t *ppos) 50203f68a95SVasanthakumar Thiagarajan { 50303f68a95SVasanthakumar Thiagarajan struct ath6kl *ar = file->private_data; 504990bd915SVasanthakumar Thiagarajan struct ath6kl_vif *vif; 505990bd915SVasanthakumar Thiagarajan struct target_stats *tgt_stats; 50603f68a95SVasanthakumar Thiagarajan char *buf; 50703f68a95SVasanthakumar Thiagarajan unsigned int len = 0, buf_len = 1500; 50803f68a95SVasanthakumar Thiagarajan int i; 50903f68a95SVasanthakumar Thiagarajan long left; 51003f68a95SVasanthakumar Thiagarajan ssize_t ret_cnt; 51103f68a95SVasanthakumar Thiagarajan 512990bd915SVasanthakumar Thiagarajan vif = ath6kl_vif_first(ar); 513990bd915SVasanthakumar Thiagarajan if (!vif) 514990bd915SVasanthakumar Thiagarajan return -EIO; 515990bd915SVasanthakumar Thiagarajan 516990bd915SVasanthakumar Thiagarajan tgt_stats = &vif->target_stats; 517990bd915SVasanthakumar Thiagarajan 51803f68a95SVasanthakumar Thiagarajan buf = kzalloc(buf_len, GFP_KERNEL); 51903f68a95SVasanthakumar Thiagarajan if (!buf) 52003f68a95SVasanthakumar Thiagarajan return -ENOMEM; 52103f68a95SVasanthakumar Thiagarajan 52203f68a95SVasanthakumar Thiagarajan if (down_interruptible(&ar->sem)) { 52303f68a95SVasanthakumar Thiagarajan kfree(buf); 52403f68a95SVasanthakumar Thiagarajan return -EBUSY; 52503f68a95SVasanthakumar Thiagarajan } 52603f68a95SVasanthakumar Thiagarajan 527b95907a7SVasanthakumar Thiagarajan set_bit(STATS_UPDATE_PEND, &vif->flags); 52803f68a95SVasanthakumar Thiagarajan 529334234b5SVasanthakumar Thiagarajan if (ath6kl_wmi_get_stats_cmd(ar->wmi, 0)) { 53003f68a95SVasanthakumar Thiagarajan up(&ar->sem); 53103f68a95SVasanthakumar Thiagarajan kfree(buf); 53203f68a95SVasanthakumar Thiagarajan return -EIO; 53303f68a95SVasanthakumar Thiagarajan } 53403f68a95SVasanthakumar Thiagarajan 53503f68a95SVasanthakumar Thiagarajan left = wait_event_interruptible_timeout(ar->event_wq, 53603f68a95SVasanthakumar Thiagarajan !test_bit(STATS_UPDATE_PEND, 537b95907a7SVasanthakumar Thiagarajan &vif->flags), WMI_TIMEOUT); 53803f68a95SVasanthakumar Thiagarajan 53903f68a95SVasanthakumar Thiagarajan up(&ar->sem); 54003f68a95SVasanthakumar Thiagarajan 54103f68a95SVasanthakumar Thiagarajan if (left <= 0) { 54203f68a95SVasanthakumar Thiagarajan kfree(buf); 54303f68a95SVasanthakumar Thiagarajan return -ETIMEDOUT; 54403f68a95SVasanthakumar Thiagarajan } 54503f68a95SVasanthakumar Thiagarajan 54603f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "\n"); 54703f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s\n", 54803f68a95SVasanthakumar Thiagarajan "Target Tx stats"); 54903f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s\n\n", 55003f68a95SVasanthakumar Thiagarajan "================="); 55103f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 55203f68a95SVasanthakumar Thiagarajan "Ucast packets", tgt_stats->tx_ucast_pkt); 55303f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 55403f68a95SVasanthakumar Thiagarajan "Bcast packets", tgt_stats->tx_bcast_pkt); 55503f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 55603f68a95SVasanthakumar Thiagarajan "Ucast byte", tgt_stats->tx_ucast_byte); 55703f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 55803f68a95SVasanthakumar Thiagarajan "Bcast byte", tgt_stats->tx_bcast_byte); 55903f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 56003f68a95SVasanthakumar Thiagarajan "Rts success cnt", tgt_stats->tx_rts_success_cnt); 56103f68a95SVasanthakumar Thiagarajan for (i = 0; i < 4; i++) 56203f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, 56303f68a95SVasanthakumar Thiagarajan "%18s %d %10llu\n", "PER on ac", 56403f68a95SVasanthakumar Thiagarajan i, tgt_stats->tx_pkt_per_ac[i]); 56503f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 56603f68a95SVasanthakumar Thiagarajan "Error", tgt_stats->tx_err); 56703f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 56803f68a95SVasanthakumar Thiagarajan "Fail count", tgt_stats->tx_fail_cnt); 56903f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 57003f68a95SVasanthakumar Thiagarajan "Retry count", tgt_stats->tx_retry_cnt); 57103f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 57203f68a95SVasanthakumar Thiagarajan "Multi retry cnt", tgt_stats->tx_mult_retry_cnt); 57303f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 57403f68a95SVasanthakumar Thiagarajan "Rts fail cnt", tgt_stats->tx_rts_fail_cnt); 57503f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s %10llu\n\n", 57603f68a95SVasanthakumar Thiagarajan "TKIP counter measure used", 57703f68a95SVasanthakumar Thiagarajan tgt_stats->tkip_cnter_measures_invoked); 57803f68a95SVasanthakumar Thiagarajan 57903f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s\n", 58003f68a95SVasanthakumar Thiagarajan "Target Rx stats"); 58103f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s\n", 58203f68a95SVasanthakumar Thiagarajan "================="); 58303f68a95SVasanthakumar Thiagarajan 58403f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 58503f68a95SVasanthakumar Thiagarajan "Ucast packets", tgt_stats->rx_ucast_pkt); 58603f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", 58703f68a95SVasanthakumar Thiagarajan "Ucast Rate", tgt_stats->rx_ucast_rate); 58803f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 58903f68a95SVasanthakumar Thiagarajan "Bcast packets", tgt_stats->rx_bcast_pkt); 59003f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 59103f68a95SVasanthakumar Thiagarajan "Ucast byte", tgt_stats->rx_ucast_byte); 59203f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 59303f68a95SVasanthakumar Thiagarajan "Bcast byte", tgt_stats->rx_bcast_byte); 59403f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 59503f68a95SVasanthakumar Thiagarajan "Fragmented pkt", tgt_stats->rx_frgment_pkt); 59603f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 59703f68a95SVasanthakumar Thiagarajan "Error", tgt_stats->rx_err); 59803f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 59903f68a95SVasanthakumar Thiagarajan "CRC Err", tgt_stats->rx_crc_err); 60003f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 60103f68a95SVasanthakumar Thiagarajan "Key chache miss", tgt_stats->rx_key_cache_miss); 60203f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 60303f68a95SVasanthakumar Thiagarajan "Decrypt Err", tgt_stats->rx_decrypt_err); 60403f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 60503f68a95SVasanthakumar Thiagarajan "Duplicate frame", tgt_stats->rx_dupl_frame); 60603f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 60703f68a95SVasanthakumar Thiagarajan "Tkip Mic failure", tgt_stats->tkip_local_mic_fail); 60803f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 60903f68a95SVasanthakumar Thiagarajan "TKIP format err", tgt_stats->tkip_fmt_err); 61003f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 61103f68a95SVasanthakumar Thiagarajan "CCMP format Err", tgt_stats->ccmp_fmt_err); 61203f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n", 61303f68a95SVasanthakumar Thiagarajan "CCMP Replay Err", tgt_stats->ccmp_replays); 61403f68a95SVasanthakumar Thiagarajan 61503f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s\n", 61603f68a95SVasanthakumar Thiagarajan "Misc Target stats"); 61703f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s\n", 61803f68a95SVasanthakumar Thiagarajan "================="); 61903f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 62003f68a95SVasanthakumar Thiagarajan "Beacon Miss count", tgt_stats->cs_bmiss_cnt); 62103f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 62203f68a95SVasanthakumar Thiagarajan "Num Connects", tgt_stats->cs_connect_cnt); 62303f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 62403f68a95SVasanthakumar Thiagarajan "Num disconnects", tgt_stats->cs_discon_cnt); 62503f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", 62603f68a95SVasanthakumar Thiagarajan "Beacon avg rssi", tgt_stats->cs_ave_beacon_rssi); 627f0446ea9SRaja Mani len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", 628f0446ea9SRaja Mani "ARP pkt received", tgt_stats->arp_received); 629f0446ea9SRaja Mani len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", 630f0446ea9SRaja Mani "ARP pkt matched", tgt_stats->arp_matched); 631f0446ea9SRaja Mani len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", 632f0446ea9SRaja Mani "ARP pkt replied", tgt_stats->arp_replied); 63303f68a95SVasanthakumar Thiagarajan 63403f68a95SVasanthakumar Thiagarajan if (len > buf_len) 63503f68a95SVasanthakumar Thiagarajan len = buf_len; 63603f68a95SVasanthakumar Thiagarajan 63703f68a95SVasanthakumar Thiagarajan ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); 63803f68a95SVasanthakumar Thiagarajan 63903f68a95SVasanthakumar Thiagarajan kfree(buf); 64003f68a95SVasanthakumar Thiagarajan return ret_cnt; 64103f68a95SVasanthakumar Thiagarajan } 64203f68a95SVasanthakumar Thiagarajan 64303f68a95SVasanthakumar Thiagarajan static const struct file_operations fops_tgt_stats = { 64403f68a95SVasanthakumar Thiagarajan .read = read_file_tgt_stats, 64503f68a95SVasanthakumar Thiagarajan .open = ath6kl_debugfs_open, 64603f68a95SVasanthakumar Thiagarajan .owner = THIS_MODULE, 64703f68a95SVasanthakumar Thiagarajan .llseek = default_llseek, 64803f68a95SVasanthakumar Thiagarajan }; 64903f68a95SVasanthakumar Thiagarajan 65078fc4856SVasanthakumar Thiagarajan #define print_credit_info(fmt_str, ep_list_field) \ 65178fc4856SVasanthakumar Thiagarajan (len += scnprintf(buf + len, buf_len - len, fmt_str, \ 65278fc4856SVasanthakumar Thiagarajan ep_list->ep_list_field)) 65378fc4856SVasanthakumar Thiagarajan #define CREDIT_INFO_DISPLAY_STRING_LEN 200 65478fc4856SVasanthakumar Thiagarajan #define CREDIT_INFO_LEN 128 65578fc4856SVasanthakumar Thiagarajan 65678fc4856SVasanthakumar Thiagarajan static ssize_t read_file_credit_dist_stats(struct file *file, 65778fc4856SVasanthakumar Thiagarajan char __user *user_buf, 65878fc4856SVasanthakumar Thiagarajan size_t count, loff_t *ppos) 65978fc4856SVasanthakumar Thiagarajan { 66078fc4856SVasanthakumar Thiagarajan struct ath6kl *ar = file->private_data; 66178fc4856SVasanthakumar Thiagarajan struct htc_target *target = ar->htc_target; 66278fc4856SVasanthakumar Thiagarajan struct htc_endpoint_credit_dist *ep_list; 66378fc4856SVasanthakumar Thiagarajan char *buf; 66478fc4856SVasanthakumar Thiagarajan unsigned int buf_len, len = 0; 66578fc4856SVasanthakumar Thiagarajan ssize_t ret_cnt; 66678fc4856SVasanthakumar Thiagarajan 66778fc4856SVasanthakumar Thiagarajan buf_len = CREDIT_INFO_DISPLAY_STRING_LEN + 66878fc4856SVasanthakumar Thiagarajan get_queue_depth(&target->cred_dist_list) * CREDIT_INFO_LEN; 66978fc4856SVasanthakumar Thiagarajan buf = kzalloc(buf_len, GFP_KERNEL); 67078fc4856SVasanthakumar Thiagarajan if (!buf) 67178fc4856SVasanthakumar Thiagarajan return -ENOMEM; 67278fc4856SVasanthakumar Thiagarajan 67378fc4856SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s%5d\n", 67478fc4856SVasanthakumar Thiagarajan "Total Avail Credits: ", 6753c370398SKalle Valo target->credit_info->total_avail_credits); 67678fc4856SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s%5d\n", 67778fc4856SVasanthakumar Thiagarajan "Free credits :", 6783c370398SKalle Valo target->credit_info->cur_free_credits); 67978fc4856SVasanthakumar Thiagarajan 68078fc4856SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, 68178fc4856SVasanthakumar Thiagarajan " Epid Flags Cred_norm Cred_min Credits Cred_assngd" 68278fc4856SVasanthakumar Thiagarajan " Seek_cred Cred_sz Cred_per_msg Cred_to_dist" 68378fc4856SVasanthakumar Thiagarajan " qdepth\n"); 68478fc4856SVasanthakumar Thiagarajan 68578fc4856SVasanthakumar Thiagarajan list_for_each_entry(ep_list, &target->cred_dist_list, list) { 68678fc4856SVasanthakumar Thiagarajan print_credit_info(" %2d", endpoint); 68778fc4856SVasanthakumar Thiagarajan print_credit_info("%10x", dist_flags); 68878fc4856SVasanthakumar Thiagarajan print_credit_info("%8d", cred_norm); 68978fc4856SVasanthakumar Thiagarajan print_credit_info("%9d", cred_min); 69078fc4856SVasanthakumar Thiagarajan print_credit_info("%9d", credits); 69178fc4856SVasanthakumar Thiagarajan print_credit_info("%10d", cred_assngd); 69278fc4856SVasanthakumar Thiagarajan print_credit_info("%13d", seek_cred); 69378fc4856SVasanthakumar Thiagarajan print_credit_info("%12d", cred_sz); 69478fc4856SVasanthakumar Thiagarajan print_credit_info("%9d", cred_per_msg); 69578fc4856SVasanthakumar Thiagarajan print_credit_info("%14d", cred_to_dist); 69678fc4856SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%12d\n", 697e8c39790SKalle Valo get_queue_depth(&ep_list->htc_ep->txq)); 69878fc4856SVasanthakumar Thiagarajan } 69978fc4856SVasanthakumar Thiagarajan 70078fc4856SVasanthakumar Thiagarajan if (len > buf_len) 70178fc4856SVasanthakumar Thiagarajan len = buf_len; 70278fc4856SVasanthakumar Thiagarajan 70378fc4856SVasanthakumar Thiagarajan ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); 70478fc4856SVasanthakumar Thiagarajan kfree(buf); 70578fc4856SVasanthakumar Thiagarajan return ret_cnt; 70678fc4856SVasanthakumar Thiagarajan } 70778fc4856SVasanthakumar Thiagarajan 70878fc4856SVasanthakumar Thiagarajan static const struct file_operations fops_credit_dist_stats = { 70978fc4856SVasanthakumar Thiagarajan .read = read_file_credit_dist_stats, 71078fc4856SVasanthakumar Thiagarajan .open = ath6kl_debugfs_open, 71178fc4856SVasanthakumar Thiagarajan .owner = THIS_MODULE, 71278fc4856SVasanthakumar Thiagarajan .llseek = default_llseek, 71378fc4856SVasanthakumar Thiagarajan }; 71478fc4856SVasanthakumar Thiagarajan 715e8091281SJouni Malinen static unsigned int print_endpoint_stat(struct htc_target *target, char *buf, 716e8091281SJouni Malinen unsigned int buf_len, unsigned int len, 717e8091281SJouni Malinen int offset, const char *name) 718e8091281SJouni Malinen { 719e8091281SJouni Malinen int i; 720e8091281SJouni Malinen struct htc_endpoint_stats *ep_st; 721e8091281SJouni Malinen u32 *counter; 722e8091281SJouni Malinen 723e8091281SJouni Malinen len += scnprintf(buf + len, buf_len - len, "%s:", name); 724e8091281SJouni Malinen for (i = 0; i < ENDPOINT_MAX; i++) { 725e8091281SJouni Malinen ep_st = &target->endpoint[i].ep_st; 726e8091281SJouni Malinen counter = ((u32 *) ep_st) + (offset / 4); 727e8091281SJouni Malinen len += scnprintf(buf + len, buf_len - len, " %u", *counter); 728e8091281SJouni Malinen } 729e8091281SJouni Malinen len += scnprintf(buf + len, buf_len - len, "\n"); 730e8091281SJouni Malinen 731e8091281SJouni Malinen return len; 732e8091281SJouni Malinen } 733e8091281SJouni Malinen 734e8091281SJouni Malinen static ssize_t ath6kl_endpoint_stats_read(struct file *file, 735e8091281SJouni Malinen char __user *user_buf, 736e8091281SJouni Malinen size_t count, loff_t *ppos) 737e8091281SJouni Malinen { 738e8091281SJouni Malinen struct ath6kl *ar = file->private_data; 739e8091281SJouni Malinen struct htc_target *target = ar->htc_target; 740e8091281SJouni Malinen char *buf; 741e8091281SJouni Malinen unsigned int buf_len, len = 0; 742e8091281SJouni Malinen ssize_t ret_cnt; 743e8091281SJouni Malinen 74417169329SJouni Malinen buf_len = sizeof(struct htc_endpoint_stats) / sizeof(u32) * 74517169329SJouni Malinen (25 + ENDPOINT_MAX * 11); 74617169329SJouni Malinen buf = kmalloc(buf_len, GFP_KERNEL); 747e8091281SJouni Malinen if (!buf) 748e8091281SJouni Malinen return -ENOMEM; 749e8091281SJouni Malinen 750e8091281SJouni Malinen #define EPSTAT(name) \ 751c650538fSKalle Valo do { \ 752e8091281SJouni Malinen len = print_endpoint_stat(target, buf, buf_len, len, \ 753c650538fSKalle Valo offsetof(struct htc_endpoint_stats, \ 754c650538fSKalle Valo name), \ 755c650538fSKalle Valo #name); \ 756c650538fSKalle Valo } while (0) 757c650538fSKalle Valo 758e8091281SJouni Malinen EPSTAT(cred_low_indicate); 759e8091281SJouni Malinen EPSTAT(tx_issued); 760e8091281SJouni Malinen EPSTAT(tx_pkt_bundled); 761e8091281SJouni Malinen EPSTAT(tx_bundles); 762e8091281SJouni Malinen EPSTAT(tx_dropped); 763e8091281SJouni Malinen EPSTAT(tx_cred_rpt); 764e8091281SJouni Malinen EPSTAT(cred_rpt_from_rx); 76517169329SJouni Malinen EPSTAT(cred_rpt_from_other); 766e8091281SJouni Malinen EPSTAT(cred_rpt_ep0); 767e8091281SJouni Malinen EPSTAT(cred_from_rx); 768e8091281SJouni Malinen EPSTAT(cred_from_other); 769e8091281SJouni Malinen EPSTAT(cred_from_ep0); 770e8091281SJouni Malinen EPSTAT(cred_cosumd); 771e8091281SJouni Malinen EPSTAT(cred_retnd); 772e8091281SJouni Malinen EPSTAT(rx_pkts); 773e8091281SJouni Malinen EPSTAT(rx_lkahds); 774e8091281SJouni Malinen EPSTAT(rx_bundl); 775e8091281SJouni Malinen EPSTAT(rx_bundle_lkahd); 776e8091281SJouni Malinen EPSTAT(rx_bundle_from_hdr); 777e8091281SJouni Malinen EPSTAT(rx_alloc_thresh_hit); 778e8091281SJouni Malinen EPSTAT(rxalloc_thresh_byte); 779e8091281SJouni Malinen #undef EPSTAT 780e8091281SJouni Malinen 781e8091281SJouni Malinen if (len > buf_len) 782e8091281SJouni Malinen len = buf_len; 783e8091281SJouni Malinen 784e8091281SJouni Malinen ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); 785e8091281SJouni Malinen kfree(buf); 786e8091281SJouni Malinen return ret_cnt; 787e8091281SJouni Malinen } 788e8091281SJouni Malinen 789e8091281SJouni Malinen static ssize_t ath6kl_endpoint_stats_write(struct file *file, 790e8091281SJouni Malinen const char __user *user_buf, 791e8091281SJouni Malinen size_t count, loff_t *ppos) 792e8091281SJouni Malinen { 793e8091281SJouni Malinen struct ath6kl *ar = file->private_data; 794e8091281SJouni Malinen struct htc_target *target = ar->htc_target; 795e8091281SJouni Malinen int ret, i; 796e8091281SJouni Malinen u32 val; 797e8091281SJouni Malinen struct htc_endpoint_stats *ep_st; 798e8091281SJouni Malinen 799e8091281SJouni Malinen ret = kstrtou32_from_user(user_buf, count, 0, &val); 800e8091281SJouni Malinen if (ret) 801e8091281SJouni Malinen return ret; 802e8091281SJouni Malinen if (val == 0) { 803e8091281SJouni Malinen for (i = 0; i < ENDPOINT_MAX; i++) { 804e8091281SJouni Malinen ep_st = &target->endpoint[i].ep_st; 805e8091281SJouni Malinen memset(ep_st, 0, sizeof(*ep_st)); 806e8091281SJouni Malinen } 807e8091281SJouni Malinen } 808e8091281SJouni Malinen 809e8091281SJouni Malinen return count; 810e8091281SJouni Malinen } 811e8091281SJouni Malinen 812e8091281SJouni Malinen static const struct file_operations fops_endpoint_stats = { 813e8091281SJouni Malinen .open = ath6kl_debugfs_open, 814e8091281SJouni Malinen .read = ath6kl_endpoint_stats_read, 815e8091281SJouni Malinen .write = ath6kl_endpoint_stats_write, 816e8091281SJouni Malinen .owner = THIS_MODULE, 817e8091281SJouni Malinen .llseek = default_llseek, 818e8091281SJouni Malinen }; 819e8091281SJouni Malinen 82091d57de5SVasanthakumar Thiagarajan static unsigned long ath6kl_get_num_reg(void) 82191d57de5SVasanthakumar Thiagarajan { 82291d57de5SVasanthakumar Thiagarajan int i; 82391d57de5SVasanthakumar Thiagarajan unsigned long n_reg = 0; 82491d57de5SVasanthakumar Thiagarajan 82591d57de5SVasanthakumar Thiagarajan for (i = 0; i < ARRAY_SIZE(diag_reg); i++) 82691d57de5SVasanthakumar Thiagarajan n_reg = n_reg + 82791d57de5SVasanthakumar Thiagarajan (diag_reg[i].reg_end - diag_reg[i].reg_start) / 4 + 1; 82891d57de5SVasanthakumar Thiagarajan 82991d57de5SVasanthakumar Thiagarajan return n_reg; 83091d57de5SVasanthakumar Thiagarajan } 83191d57de5SVasanthakumar Thiagarajan 83291d57de5SVasanthakumar Thiagarajan static bool ath6kl_dbg_is_diag_reg_valid(u32 reg_addr) 83391d57de5SVasanthakumar Thiagarajan { 83491d57de5SVasanthakumar Thiagarajan int i; 83591d57de5SVasanthakumar Thiagarajan 83691d57de5SVasanthakumar Thiagarajan for (i = 0; i < ARRAY_SIZE(diag_reg); i++) { 83791d57de5SVasanthakumar Thiagarajan if (reg_addr >= diag_reg[i].reg_start && 83891d57de5SVasanthakumar Thiagarajan reg_addr <= diag_reg[i].reg_end) 83991d57de5SVasanthakumar Thiagarajan return true; 84091d57de5SVasanthakumar Thiagarajan } 84191d57de5SVasanthakumar Thiagarajan 84291d57de5SVasanthakumar Thiagarajan return false; 84391d57de5SVasanthakumar Thiagarajan } 84491d57de5SVasanthakumar Thiagarajan 84591d57de5SVasanthakumar Thiagarajan static ssize_t ath6kl_regread_read(struct file *file, char __user *user_buf, 84691d57de5SVasanthakumar Thiagarajan size_t count, loff_t *ppos) 84791d57de5SVasanthakumar Thiagarajan { 84891d57de5SVasanthakumar Thiagarajan struct ath6kl *ar = file->private_data; 84991d57de5SVasanthakumar Thiagarajan u8 buf[50]; 85091d57de5SVasanthakumar Thiagarajan unsigned int len = 0; 85191d57de5SVasanthakumar Thiagarajan 85291d57de5SVasanthakumar Thiagarajan if (ar->debug.dbgfs_diag_reg) 85391d57de5SVasanthakumar Thiagarajan len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", 85491d57de5SVasanthakumar Thiagarajan ar->debug.dbgfs_diag_reg); 85591d57de5SVasanthakumar Thiagarajan else 85691d57de5SVasanthakumar Thiagarajan len += scnprintf(buf + len, sizeof(buf) - len, 85791d57de5SVasanthakumar Thiagarajan "All diag registers\n"); 85891d57de5SVasanthakumar Thiagarajan 85991d57de5SVasanthakumar Thiagarajan return simple_read_from_buffer(user_buf, count, ppos, buf, len); 86091d57de5SVasanthakumar Thiagarajan } 86191d57de5SVasanthakumar Thiagarajan 86291d57de5SVasanthakumar Thiagarajan static ssize_t ath6kl_regread_write(struct file *file, 86391d57de5SVasanthakumar Thiagarajan const char __user *user_buf, 86491d57de5SVasanthakumar Thiagarajan size_t count, loff_t *ppos) 86591d57de5SVasanthakumar Thiagarajan { 86691d57de5SVasanthakumar Thiagarajan struct ath6kl *ar = file->private_data; 86791d57de5SVasanthakumar Thiagarajan unsigned long reg_addr; 86891d57de5SVasanthakumar Thiagarajan 86906f33f13SKalle Valo if (kstrtoul_from_user(user_buf, count, 0, ®_addr)) 87091d57de5SVasanthakumar Thiagarajan return -EINVAL; 87191d57de5SVasanthakumar Thiagarajan 87291d57de5SVasanthakumar Thiagarajan if ((reg_addr % 4) != 0) 87391d57de5SVasanthakumar Thiagarajan return -EINVAL; 87491d57de5SVasanthakumar Thiagarajan 87591d57de5SVasanthakumar Thiagarajan if (reg_addr && !ath6kl_dbg_is_diag_reg_valid(reg_addr)) 87691d57de5SVasanthakumar Thiagarajan return -EINVAL; 87791d57de5SVasanthakumar Thiagarajan 87891d57de5SVasanthakumar Thiagarajan ar->debug.dbgfs_diag_reg = reg_addr; 87991d57de5SVasanthakumar Thiagarajan 88091d57de5SVasanthakumar Thiagarajan return count; 88191d57de5SVasanthakumar Thiagarajan } 88291d57de5SVasanthakumar Thiagarajan 88391d57de5SVasanthakumar Thiagarajan static const struct file_operations fops_diag_reg_read = { 88491d57de5SVasanthakumar Thiagarajan .read = ath6kl_regread_read, 88591d57de5SVasanthakumar Thiagarajan .write = ath6kl_regread_write, 88691d57de5SVasanthakumar Thiagarajan .open = ath6kl_debugfs_open, 88791d57de5SVasanthakumar Thiagarajan .owner = THIS_MODULE, 88891d57de5SVasanthakumar Thiagarajan .llseek = default_llseek, 88991d57de5SVasanthakumar Thiagarajan }; 89091d57de5SVasanthakumar Thiagarajan 89191d57de5SVasanthakumar Thiagarajan static int ath6kl_regdump_open(struct inode *inode, struct file *file) 89291d57de5SVasanthakumar Thiagarajan { 89391d57de5SVasanthakumar Thiagarajan struct ath6kl *ar = inode->i_private; 89491d57de5SVasanthakumar Thiagarajan u8 *buf; 89591d57de5SVasanthakumar Thiagarajan unsigned long int reg_len; 89691d57de5SVasanthakumar Thiagarajan unsigned int len = 0, n_reg; 89791d57de5SVasanthakumar Thiagarajan u32 addr; 89891d57de5SVasanthakumar Thiagarajan __le32 reg_val; 89991d57de5SVasanthakumar Thiagarajan int i, status; 90091d57de5SVasanthakumar Thiagarajan 90191d57de5SVasanthakumar Thiagarajan /* Dump all the registers if no register is specified */ 90291d57de5SVasanthakumar Thiagarajan if (!ar->debug.dbgfs_diag_reg) 90391d57de5SVasanthakumar Thiagarajan n_reg = ath6kl_get_num_reg(); 90491d57de5SVasanthakumar Thiagarajan else 90591d57de5SVasanthakumar Thiagarajan n_reg = 1; 90691d57de5SVasanthakumar Thiagarajan 90791d57de5SVasanthakumar Thiagarajan reg_len = n_reg * REG_OUTPUT_LEN_PER_LINE; 90891d57de5SVasanthakumar Thiagarajan if (n_reg > 1) 90991d57de5SVasanthakumar Thiagarajan reg_len += REGTYPE_STR_LEN; 91091d57de5SVasanthakumar Thiagarajan 91191d57de5SVasanthakumar Thiagarajan buf = vmalloc(reg_len); 91291d57de5SVasanthakumar Thiagarajan if (!buf) 91391d57de5SVasanthakumar Thiagarajan return -ENOMEM; 91491d57de5SVasanthakumar Thiagarajan 91591d57de5SVasanthakumar Thiagarajan if (n_reg == 1) { 91691d57de5SVasanthakumar Thiagarajan addr = ar->debug.dbgfs_diag_reg; 91791d57de5SVasanthakumar Thiagarajan 91891d57de5SVasanthakumar Thiagarajan status = ath6kl_diag_read32(ar, 91991d57de5SVasanthakumar Thiagarajan TARG_VTOP(ar->target_type, addr), 92091d57de5SVasanthakumar Thiagarajan (u32 *)®_val); 92191d57de5SVasanthakumar Thiagarajan if (status) 92291d57de5SVasanthakumar Thiagarajan goto fail_reg_read; 92391d57de5SVasanthakumar Thiagarajan 92491d57de5SVasanthakumar Thiagarajan len += scnprintf(buf + len, reg_len - len, 92591d57de5SVasanthakumar Thiagarajan "0x%06x 0x%08x\n", addr, le32_to_cpu(reg_val)); 92691d57de5SVasanthakumar Thiagarajan goto done; 92791d57de5SVasanthakumar Thiagarajan } 92891d57de5SVasanthakumar Thiagarajan 92991d57de5SVasanthakumar Thiagarajan for (i = 0; i < ARRAY_SIZE(diag_reg); i++) { 93091d57de5SVasanthakumar Thiagarajan len += scnprintf(buf + len, reg_len - len, 93191d57de5SVasanthakumar Thiagarajan "%s\n", diag_reg[i].reg_info); 93291d57de5SVasanthakumar Thiagarajan for (addr = diag_reg[i].reg_start; 93391d57de5SVasanthakumar Thiagarajan addr <= diag_reg[i].reg_end; addr += 4) { 93491d57de5SVasanthakumar Thiagarajan status = ath6kl_diag_read32(ar, 93591d57de5SVasanthakumar Thiagarajan TARG_VTOP(ar->target_type, addr), 93691d57de5SVasanthakumar Thiagarajan (u32 *)®_val); 93791d57de5SVasanthakumar Thiagarajan if (status) 93891d57de5SVasanthakumar Thiagarajan goto fail_reg_read; 93991d57de5SVasanthakumar Thiagarajan 94091d57de5SVasanthakumar Thiagarajan len += scnprintf(buf + len, reg_len - len, 94191d57de5SVasanthakumar Thiagarajan "0x%06x 0x%08x\n", 94291d57de5SVasanthakumar Thiagarajan addr, le32_to_cpu(reg_val)); 94391d57de5SVasanthakumar Thiagarajan } 94491d57de5SVasanthakumar Thiagarajan } 94591d57de5SVasanthakumar Thiagarajan 94691d57de5SVasanthakumar Thiagarajan done: 94791d57de5SVasanthakumar Thiagarajan file->private_data = buf; 94891d57de5SVasanthakumar Thiagarajan return 0; 94991d57de5SVasanthakumar Thiagarajan 95091d57de5SVasanthakumar Thiagarajan fail_reg_read: 95191d57de5SVasanthakumar Thiagarajan ath6kl_warn("Unable to read memory:%u\n", addr); 95291d57de5SVasanthakumar Thiagarajan vfree(buf); 95391d57de5SVasanthakumar Thiagarajan return -EIO; 95491d57de5SVasanthakumar Thiagarajan } 95591d57de5SVasanthakumar Thiagarajan 95691d57de5SVasanthakumar Thiagarajan static ssize_t ath6kl_regdump_read(struct file *file, char __user *user_buf, 95791d57de5SVasanthakumar Thiagarajan size_t count, loff_t *ppos) 95891d57de5SVasanthakumar Thiagarajan { 95991d57de5SVasanthakumar Thiagarajan u8 *buf = file->private_data; 96091d57de5SVasanthakumar Thiagarajan return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); 96191d57de5SVasanthakumar Thiagarajan } 96291d57de5SVasanthakumar Thiagarajan 96391d57de5SVasanthakumar Thiagarajan static int ath6kl_regdump_release(struct inode *inode, struct file *file) 96491d57de5SVasanthakumar Thiagarajan { 96591d57de5SVasanthakumar Thiagarajan vfree(file->private_data); 96691d57de5SVasanthakumar Thiagarajan return 0; 96791d57de5SVasanthakumar Thiagarajan } 96891d57de5SVasanthakumar Thiagarajan 96991d57de5SVasanthakumar Thiagarajan static const struct file_operations fops_reg_dump = { 97091d57de5SVasanthakumar Thiagarajan .open = ath6kl_regdump_open, 97191d57de5SVasanthakumar Thiagarajan .read = ath6kl_regdump_read, 97291d57de5SVasanthakumar Thiagarajan .release = ath6kl_regdump_release, 97391d57de5SVasanthakumar Thiagarajan .owner = THIS_MODULE, 97491d57de5SVasanthakumar Thiagarajan .llseek = default_llseek, 97591d57de5SVasanthakumar Thiagarajan }; 97691d57de5SVasanthakumar Thiagarajan 977e5090444SVivek Natarajan static ssize_t ath6kl_lrssi_roam_write(struct file *file, 978e5090444SVivek Natarajan const char __user *user_buf, 979e5090444SVivek Natarajan size_t count, loff_t *ppos) 980e5090444SVivek Natarajan { 981e5090444SVivek Natarajan struct ath6kl *ar = file->private_data; 982e5090444SVivek Natarajan unsigned long lrssi_roam_threshold; 983e5090444SVivek Natarajan 98406f33f13SKalle Valo if (kstrtoul_from_user(user_buf, count, 0, &lrssi_roam_threshold)) 985e5090444SVivek Natarajan return -EINVAL; 986e5090444SVivek Natarajan 987e5090444SVivek Natarajan ar->lrssi_roam_threshold = lrssi_roam_threshold; 988e5090444SVivek Natarajan 989e5090444SVivek Natarajan ath6kl_wmi_set_roam_lrssi_cmd(ar->wmi, ar->lrssi_roam_threshold); 990e5090444SVivek Natarajan 991e5090444SVivek Natarajan return count; 992e5090444SVivek Natarajan } 993e5090444SVivek Natarajan 994e5090444SVivek Natarajan static ssize_t ath6kl_lrssi_roam_read(struct file *file, 995e5090444SVivek Natarajan char __user *user_buf, 996e5090444SVivek Natarajan size_t count, loff_t *ppos) 997e5090444SVivek Natarajan { 998e5090444SVivek Natarajan struct ath6kl *ar = file->private_data; 999e5090444SVivek Natarajan char buf[32]; 1000e5090444SVivek Natarajan unsigned int len; 1001e5090444SVivek Natarajan 1002e5090444SVivek Natarajan len = snprintf(buf, sizeof(buf), "%u\n", ar->lrssi_roam_threshold); 1003e5090444SVivek Natarajan 1004e5090444SVivek Natarajan return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1005e5090444SVivek Natarajan } 1006e5090444SVivek Natarajan 1007e5090444SVivek Natarajan static const struct file_operations fops_lrssi_roam_threshold = { 1008e5090444SVivek Natarajan .read = ath6kl_lrssi_roam_read, 1009e5090444SVivek Natarajan .write = ath6kl_lrssi_roam_write, 1010e5090444SVivek Natarajan .open = ath6kl_debugfs_open, 1011e5090444SVivek Natarajan .owner = THIS_MODULE, 1012e5090444SVivek Natarajan .llseek = default_llseek, 1013e5090444SVivek Natarajan }; 1014e5090444SVivek Natarajan 1015252c068bSVasanthakumar Thiagarajan static ssize_t ath6kl_regwrite_read(struct file *file, 1016252c068bSVasanthakumar Thiagarajan char __user *user_buf, 1017252c068bSVasanthakumar Thiagarajan size_t count, loff_t *ppos) 1018252c068bSVasanthakumar Thiagarajan { 1019252c068bSVasanthakumar Thiagarajan struct ath6kl *ar = file->private_data; 1020252c068bSVasanthakumar Thiagarajan u8 buf[32]; 1021252c068bSVasanthakumar Thiagarajan unsigned int len = 0; 1022252c068bSVasanthakumar Thiagarajan 1023252c068bSVasanthakumar Thiagarajan len = scnprintf(buf, sizeof(buf), "Addr: 0x%x Val: 0x%x\n", 1024252c068bSVasanthakumar Thiagarajan ar->debug.diag_reg_addr_wr, ar->debug.diag_reg_val_wr); 1025252c068bSVasanthakumar Thiagarajan 1026252c068bSVasanthakumar Thiagarajan return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1027252c068bSVasanthakumar Thiagarajan } 1028252c068bSVasanthakumar Thiagarajan 1029252c068bSVasanthakumar Thiagarajan static ssize_t ath6kl_regwrite_write(struct file *file, 1030252c068bSVasanthakumar Thiagarajan const char __user *user_buf, 1031252c068bSVasanthakumar Thiagarajan size_t count, loff_t *ppos) 1032252c068bSVasanthakumar Thiagarajan { 1033252c068bSVasanthakumar Thiagarajan struct ath6kl *ar = file->private_data; 1034252c068bSVasanthakumar Thiagarajan char buf[32]; 1035252c068bSVasanthakumar Thiagarajan char *sptr, *token; 1036252c068bSVasanthakumar Thiagarajan unsigned int len = 0; 1037252c068bSVasanthakumar Thiagarajan u32 reg_addr, reg_val; 1038252c068bSVasanthakumar Thiagarajan 1039252c068bSVasanthakumar Thiagarajan len = min(count, sizeof(buf) - 1); 1040252c068bSVasanthakumar Thiagarajan if (copy_from_user(buf, user_buf, len)) 1041252c068bSVasanthakumar Thiagarajan return -EFAULT; 1042252c068bSVasanthakumar Thiagarajan 1043252c068bSVasanthakumar Thiagarajan buf[len] = '\0'; 1044252c068bSVasanthakumar Thiagarajan sptr = buf; 1045252c068bSVasanthakumar Thiagarajan 1046252c068bSVasanthakumar Thiagarajan token = strsep(&sptr, "="); 1047252c068bSVasanthakumar Thiagarajan if (!token) 1048252c068bSVasanthakumar Thiagarajan return -EINVAL; 1049252c068bSVasanthakumar Thiagarajan 1050252c068bSVasanthakumar Thiagarajan if (kstrtou32(token, 0, ®_addr)) 1051252c068bSVasanthakumar Thiagarajan return -EINVAL; 1052252c068bSVasanthakumar Thiagarajan 1053252c068bSVasanthakumar Thiagarajan if (!ath6kl_dbg_is_diag_reg_valid(reg_addr)) 1054252c068bSVasanthakumar Thiagarajan return -EINVAL; 1055252c068bSVasanthakumar Thiagarajan 1056252c068bSVasanthakumar Thiagarajan if (kstrtou32(sptr, 0, ®_val)) 1057252c068bSVasanthakumar Thiagarajan return -EINVAL; 1058252c068bSVasanthakumar Thiagarajan 1059252c068bSVasanthakumar Thiagarajan ar->debug.diag_reg_addr_wr = reg_addr; 1060252c068bSVasanthakumar Thiagarajan ar->debug.diag_reg_val_wr = reg_val; 1061252c068bSVasanthakumar Thiagarajan 1062252c068bSVasanthakumar Thiagarajan if (ath6kl_diag_write32(ar, ar->debug.diag_reg_addr_wr, 1063252c068bSVasanthakumar Thiagarajan cpu_to_le32(ar->debug.diag_reg_val_wr))) 1064252c068bSVasanthakumar Thiagarajan return -EIO; 1065252c068bSVasanthakumar Thiagarajan 1066252c068bSVasanthakumar Thiagarajan return count; 1067252c068bSVasanthakumar Thiagarajan } 1068252c068bSVasanthakumar Thiagarajan 1069252c068bSVasanthakumar Thiagarajan static const struct file_operations fops_diag_reg_write = { 1070252c068bSVasanthakumar Thiagarajan .read = ath6kl_regwrite_read, 1071252c068bSVasanthakumar Thiagarajan .write = ath6kl_regwrite_write, 1072252c068bSVasanthakumar Thiagarajan .open = ath6kl_debugfs_open, 1073252c068bSVasanthakumar Thiagarajan .owner = THIS_MODULE, 1074252c068bSVasanthakumar Thiagarajan .llseek = default_llseek, 1075252c068bSVasanthakumar Thiagarajan }; 1076252c068bSVasanthakumar Thiagarajan 10774b28a80dSJouni Malinen int ath6kl_debug_roam_tbl_event(struct ath6kl *ar, const void *buf, 10784b28a80dSJouni Malinen size_t len) 10794b28a80dSJouni Malinen { 10804b28a80dSJouni Malinen const struct wmi_target_roam_tbl *tbl; 10814b28a80dSJouni Malinen u16 num_entries; 10824b28a80dSJouni Malinen 10834b28a80dSJouni Malinen if (len < sizeof(*tbl)) 10844b28a80dSJouni Malinen return -EINVAL; 10854b28a80dSJouni Malinen 10864b28a80dSJouni Malinen tbl = (const struct wmi_target_roam_tbl *) buf; 10874b28a80dSJouni Malinen num_entries = le16_to_cpu(tbl->num_entries); 10884b28a80dSJouni Malinen if (sizeof(*tbl) + num_entries * sizeof(struct wmi_bss_roam_info) > 10894b28a80dSJouni Malinen len) 10904b28a80dSJouni Malinen return -EINVAL; 10914b28a80dSJouni Malinen 10924b28a80dSJouni Malinen if (ar->debug.roam_tbl == NULL || 10934b28a80dSJouni Malinen ar->debug.roam_tbl_len < (unsigned int) len) { 10944b28a80dSJouni Malinen kfree(ar->debug.roam_tbl); 10954b28a80dSJouni Malinen ar->debug.roam_tbl = kmalloc(len, GFP_ATOMIC); 10964b28a80dSJouni Malinen if (ar->debug.roam_tbl == NULL) 10974b28a80dSJouni Malinen return -ENOMEM; 10984b28a80dSJouni Malinen } 10994b28a80dSJouni Malinen 11004b28a80dSJouni Malinen memcpy(ar->debug.roam_tbl, buf, len); 11014b28a80dSJouni Malinen ar->debug.roam_tbl_len = len; 11024b28a80dSJouni Malinen 11034b28a80dSJouni Malinen if (test_bit(ROAM_TBL_PEND, &ar->flag)) { 11044b28a80dSJouni Malinen clear_bit(ROAM_TBL_PEND, &ar->flag); 11054b28a80dSJouni Malinen wake_up(&ar->event_wq); 11064b28a80dSJouni Malinen } 11074b28a80dSJouni Malinen 11084b28a80dSJouni Malinen return 0; 11094b28a80dSJouni Malinen } 11104b28a80dSJouni Malinen 11114b28a80dSJouni Malinen static ssize_t ath6kl_roam_table_read(struct file *file, char __user *user_buf, 11124b28a80dSJouni Malinen size_t count, loff_t *ppos) 11134b28a80dSJouni Malinen { 11144b28a80dSJouni Malinen struct ath6kl *ar = file->private_data; 11154b28a80dSJouni Malinen int ret; 11164b28a80dSJouni Malinen long left; 11174b28a80dSJouni Malinen struct wmi_target_roam_tbl *tbl; 11184b28a80dSJouni Malinen u16 num_entries, i; 11194b28a80dSJouni Malinen char *buf; 11204b28a80dSJouni Malinen unsigned int len, buf_len; 11214b28a80dSJouni Malinen ssize_t ret_cnt; 11224b28a80dSJouni Malinen 11234b28a80dSJouni Malinen if (down_interruptible(&ar->sem)) 11244b28a80dSJouni Malinen return -EBUSY; 11254b28a80dSJouni Malinen 11264b28a80dSJouni Malinen set_bit(ROAM_TBL_PEND, &ar->flag); 11274b28a80dSJouni Malinen 11284b28a80dSJouni Malinen ret = ath6kl_wmi_get_roam_tbl_cmd(ar->wmi); 11294b28a80dSJouni Malinen if (ret) { 11304b28a80dSJouni Malinen up(&ar->sem); 11314b28a80dSJouni Malinen return ret; 11324b28a80dSJouni Malinen } 11334b28a80dSJouni Malinen 11344b28a80dSJouni Malinen left = wait_event_interruptible_timeout( 11354b28a80dSJouni Malinen ar->event_wq, !test_bit(ROAM_TBL_PEND, &ar->flag), WMI_TIMEOUT); 11364b28a80dSJouni Malinen up(&ar->sem); 11374b28a80dSJouni Malinen 11384b28a80dSJouni Malinen if (left <= 0) 11394b28a80dSJouni Malinen return -ETIMEDOUT; 11404b28a80dSJouni Malinen 11414b28a80dSJouni Malinen if (ar->debug.roam_tbl == NULL) 11424b28a80dSJouni Malinen return -ENOMEM; 11434b28a80dSJouni Malinen 11444b28a80dSJouni Malinen tbl = (struct wmi_target_roam_tbl *) ar->debug.roam_tbl; 11454b28a80dSJouni Malinen num_entries = le16_to_cpu(tbl->num_entries); 11464b28a80dSJouni Malinen 11474b28a80dSJouni Malinen buf_len = 100 + num_entries * 100; 11484b28a80dSJouni Malinen buf = kzalloc(buf_len, GFP_KERNEL); 11494b28a80dSJouni Malinen if (buf == NULL) 11504b28a80dSJouni Malinen return -ENOMEM; 11514b28a80dSJouni Malinen len = 0; 11524b28a80dSJouni Malinen len += scnprintf(buf + len, buf_len - len, 11534b28a80dSJouni Malinen "roam_mode=%u\n\n" 11544b28a80dSJouni Malinen "# roam_util bssid rssi rssidt last_rssi util bias\n", 11554b28a80dSJouni Malinen le16_to_cpu(tbl->roam_mode)); 11564b28a80dSJouni Malinen 11574b28a80dSJouni Malinen for (i = 0; i < num_entries; i++) { 11584b28a80dSJouni Malinen struct wmi_bss_roam_info *info = &tbl->info[i]; 11594b28a80dSJouni Malinen len += scnprintf(buf + len, buf_len - len, 11604b28a80dSJouni Malinen "%d %pM %d %d %d %d %d\n", 11614b28a80dSJouni Malinen a_sle32_to_cpu(info->roam_util), info->bssid, 11624b28a80dSJouni Malinen info->rssi, info->rssidt, info->last_rssi, 11634b28a80dSJouni Malinen info->util, info->bias); 11644b28a80dSJouni Malinen } 11654b28a80dSJouni Malinen 11664b28a80dSJouni Malinen if (len > buf_len) 11674b28a80dSJouni Malinen len = buf_len; 11684b28a80dSJouni Malinen 11694b28a80dSJouni Malinen ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); 11704b28a80dSJouni Malinen 11714b28a80dSJouni Malinen kfree(buf); 11724b28a80dSJouni Malinen return ret_cnt; 11734b28a80dSJouni Malinen } 11744b28a80dSJouni Malinen 11754b28a80dSJouni Malinen static const struct file_operations fops_roam_table = { 11764b28a80dSJouni Malinen .read = ath6kl_roam_table_read, 11774b28a80dSJouni Malinen .open = ath6kl_debugfs_open, 11784b28a80dSJouni Malinen .owner = THIS_MODULE, 11794b28a80dSJouni Malinen .llseek = default_llseek, 11804b28a80dSJouni Malinen }; 11814b28a80dSJouni Malinen 11821261875fSJouni Malinen static ssize_t ath6kl_force_roam_write(struct file *file, 11831261875fSJouni Malinen const char __user *user_buf, 11841261875fSJouni Malinen size_t count, loff_t *ppos) 11851261875fSJouni Malinen { 11861261875fSJouni Malinen struct ath6kl *ar = file->private_data; 11871261875fSJouni Malinen int ret; 11881261875fSJouni Malinen char buf[20]; 11891261875fSJouni Malinen size_t len; 11901261875fSJouni Malinen u8 bssid[ETH_ALEN]; 11911261875fSJouni Malinen int i; 11921261875fSJouni Malinen int addr[ETH_ALEN]; 11931261875fSJouni Malinen 11941261875fSJouni Malinen len = min(count, sizeof(buf) - 1); 11951261875fSJouni Malinen if (copy_from_user(buf, user_buf, len)) 11961261875fSJouni Malinen return -EFAULT; 11971261875fSJouni Malinen buf[len] = '\0'; 11981261875fSJouni Malinen 11991261875fSJouni Malinen if (sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", 12001261875fSJouni Malinen &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) 12011261875fSJouni Malinen != ETH_ALEN) 12021261875fSJouni Malinen return -EINVAL; 12031261875fSJouni Malinen for (i = 0; i < ETH_ALEN; i++) 12041261875fSJouni Malinen bssid[i] = addr[i]; 12051261875fSJouni Malinen 12061261875fSJouni Malinen ret = ath6kl_wmi_force_roam_cmd(ar->wmi, bssid); 12071261875fSJouni Malinen if (ret) 12081261875fSJouni Malinen return ret; 12091261875fSJouni Malinen 12101261875fSJouni Malinen return count; 12111261875fSJouni Malinen } 12121261875fSJouni Malinen 12131261875fSJouni Malinen static const struct file_operations fops_force_roam = { 12141261875fSJouni Malinen .write = ath6kl_force_roam_write, 12151261875fSJouni Malinen .open = ath6kl_debugfs_open, 12161261875fSJouni Malinen .owner = THIS_MODULE, 12171261875fSJouni Malinen .llseek = default_llseek, 12181261875fSJouni Malinen }; 12191261875fSJouni Malinen 12201261875fSJouni Malinen static ssize_t ath6kl_roam_mode_write(struct file *file, 12211261875fSJouni Malinen const char __user *user_buf, 12221261875fSJouni Malinen size_t count, loff_t *ppos) 12231261875fSJouni Malinen { 12241261875fSJouni Malinen struct ath6kl *ar = file->private_data; 12251261875fSJouni Malinen int ret; 12261261875fSJouni Malinen char buf[20]; 12271261875fSJouni Malinen size_t len; 12281261875fSJouni Malinen enum wmi_roam_mode mode; 12291261875fSJouni Malinen 12301261875fSJouni Malinen len = min(count, sizeof(buf) - 1); 12311261875fSJouni Malinen if (copy_from_user(buf, user_buf, len)) 12321261875fSJouni Malinen return -EFAULT; 12331261875fSJouni Malinen buf[len] = '\0'; 12341261875fSJouni Malinen if (len > 0 && buf[len - 1] == '\n') 12351261875fSJouni Malinen buf[len - 1] = '\0'; 12361261875fSJouni Malinen 12371261875fSJouni Malinen if (strcasecmp(buf, "default") == 0) 12381261875fSJouni Malinen mode = WMI_DEFAULT_ROAM_MODE; 12391261875fSJouni Malinen else if (strcasecmp(buf, "bssbias") == 0) 12401261875fSJouni Malinen mode = WMI_HOST_BIAS_ROAM_MODE; 12411261875fSJouni Malinen else if (strcasecmp(buf, "lock") == 0) 12421261875fSJouni Malinen mode = WMI_LOCK_BSS_MODE; 12431261875fSJouni Malinen else 12441261875fSJouni Malinen return -EINVAL; 12451261875fSJouni Malinen 12461261875fSJouni Malinen ret = ath6kl_wmi_set_roam_mode_cmd(ar->wmi, mode); 12471261875fSJouni Malinen if (ret) 12481261875fSJouni Malinen return ret; 12491261875fSJouni Malinen 12501261875fSJouni Malinen return count; 12511261875fSJouni Malinen } 12521261875fSJouni Malinen 12531261875fSJouni Malinen static const struct file_operations fops_roam_mode = { 12541261875fSJouni Malinen .write = ath6kl_roam_mode_write, 12551261875fSJouni Malinen .open = ath6kl_debugfs_open, 12561261875fSJouni Malinen .owner = THIS_MODULE, 12571261875fSJouni Malinen .llseek = default_llseek, 12581261875fSJouni Malinen }; 12591261875fSJouni Malinen 1260ff0b0075SJouni Malinen void ath6kl_debug_set_keepalive(struct ath6kl *ar, u8 keepalive) 1261ff0b0075SJouni Malinen { 1262ff0b0075SJouni Malinen ar->debug.keepalive = keepalive; 1263ff0b0075SJouni Malinen } 1264ff0b0075SJouni Malinen 1265ff0b0075SJouni Malinen static ssize_t ath6kl_keepalive_read(struct file *file, char __user *user_buf, 1266ff0b0075SJouni Malinen size_t count, loff_t *ppos) 1267ff0b0075SJouni Malinen { 1268ff0b0075SJouni Malinen struct ath6kl *ar = file->private_data; 1269ff0b0075SJouni Malinen char buf[16]; 1270ff0b0075SJouni Malinen int len; 1271ff0b0075SJouni Malinen 1272ff0b0075SJouni Malinen len = snprintf(buf, sizeof(buf), "%u\n", ar->debug.keepalive); 1273ff0b0075SJouni Malinen 1274ff0b0075SJouni Malinen return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1275ff0b0075SJouni Malinen } 1276ff0b0075SJouni Malinen 1277ff0b0075SJouni Malinen static ssize_t ath6kl_keepalive_write(struct file *file, 1278ff0b0075SJouni Malinen const char __user *user_buf, 1279ff0b0075SJouni Malinen size_t count, loff_t *ppos) 1280ff0b0075SJouni Malinen { 1281ff0b0075SJouni Malinen struct ath6kl *ar = file->private_data; 1282ff0b0075SJouni Malinen int ret; 1283ff0b0075SJouni Malinen u8 val; 1284ff0b0075SJouni Malinen 1285ff0b0075SJouni Malinen ret = kstrtou8_from_user(user_buf, count, 0, &val); 1286ff0b0075SJouni Malinen if (ret) 1287ff0b0075SJouni Malinen return ret; 1288ff0b0075SJouni Malinen 12890ce59445SVasanthakumar Thiagarajan ret = ath6kl_wmi_set_keepalive_cmd(ar->wmi, 0, val); 1290ff0b0075SJouni Malinen if (ret) 1291ff0b0075SJouni Malinen return ret; 1292ff0b0075SJouni Malinen 1293ff0b0075SJouni Malinen return count; 1294ff0b0075SJouni Malinen } 1295ff0b0075SJouni Malinen 1296ff0b0075SJouni Malinen static const struct file_operations fops_keepalive = { 1297ff0b0075SJouni Malinen .open = ath6kl_debugfs_open, 1298ff0b0075SJouni Malinen .read = ath6kl_keepalive_read, 1299ff0b0075SJouni Malinen .write = ath6kl_keepalive_write, 1300ff0b0075SJouni Malinen .owner = THIS_MODULE, 1301ff0b0075SJouni Malinen .llseek = default_llseek, 1302ff0b0075SJouni Malinen }; 1303ff0b0075SJouni Malinen 1304ff0b0075SJouni Malinen void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar, u8 timeout) 1305ff0b0075SJouni Malinen { 1306ff0b0075SJouni Malinen ar->debug.disc_timeout = timeout; 1307ff0b0075SJouni Malinen } 1308ff0b0075SJouni Malinen 1309ff0b0075SJouni Malinen static ssize_t ath6kl_disconnect_timeout_read(struct file *file, 1310ff0b0075SJouni Malinen char __user *user_buf, 1311ff0b0075SJouni Malinen size_t count, loff_t *ppos) 1312ff0b0075SJouni Malinen { 1313ff0b0075SJouni Malinen struct ath6kl *ar = file->private_data; 1314ff0b0075SJouni Malinen char buf[16]; 1315ff0b0075SJouni Malinen int len; 1316ff0b0075SJouni Malinen 1317ff0b0075SJouni Malinen len = snprintf(buf, sizeof(buf), "%u\n", ar->debug.disc_timeout); 1318ff0b0075SJouni Malinen 1319ff0b0075SJouni Malinen return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1320ff0b0075SJouni Malinen } 1321ff0b0075SJouni Malinen 1322ff0b0075SJouni Malinen static ssize_t ath6kl_disconnect_timeout_write(struct file *file, 1323ff0b0075SJouni Malinen const char __user *user_buf, 1324ff0b0075SJouni Malinen size_t count, loff_t *ppos) 1325ff0b0075SJouni Malinen { 1326ff0b0075SJouni Malinen struct ath6kl *ar = file->private_data; 1327ff0b0075SJouni Malinen int ret; 1328ff0b0075SJouni Malinen u8 val; 1329ff0b0075SJouni Malinen 1330ff0b0075SJouni Malinen ret = kstrtou8_from_user(user_buf, count, 0, &val); 1331ff0b0075SJouni Malinen if (ret) 1332ff0b0075SJouni Malinen return ret; 1333ff0b0075SJouni Malinen 13340ce59445SVasanthakumar Thiagarajan ret = ath6kl_wmi_disctimeout_cmd(ar->wmi, 0, val); 1335ff0b0075SJouni Malinen if (ret) 1336ff0b0075SJouni Malinen return ret; 1337ff0b0075SJouni Malinen 1338ff0b0075SJouni Malinen return count; 1339ff0b0075SJouni Malinen } 1340ff0b0075SJouni Malinen 1341ff0b0075SJouni Malinen static const struct file_operations fops_disconnect_timeout = { 1342ff0b0075SJouni Malinen .open = ath6kl_debugfs_open, 1343ff0b0075SJouni Malinen .read = ath6kl_disconnect_timeout_read, 1344ff0b0075SJouni Malinen .write = ath6kl_disconnect_timeout_write, 1345ff0b0075SJouni Malinen .owner = THIS_MODULE, 1346ff0b0075SJouni Malinen .llseek = default_llseek, 1347ff0b0075SJouni Malinen }; 1348ff0b0075SJouni Malinen 13498fffd9e5SRishi Panjwani static ssize_t ath6kl_create_qos_write(struct file *file, 13508fffd9e5SRishi Panjwani const char __user *user_buf, 13518fffd9e5SRishi Panjwani size_t count, loff_t *ppos) 13528fffd9e5SRishi Panjwani { 13538fffd9e5SRishi Panjwani 13548fffd9e5SRishi Panjwani struct ath6kl *ar = file->private_data; 1355990bd915SVasanthakumar Thiagarajan struct ath6kl_vif *vif; 13568cb6d991SVasanthakumar Thiagarajan char buf[200]; 13578fffd9e5SRishi Panjwani ssize_t len; 13588fffd9e5SRishi Panjwani char *sptr, *token; 13598fffd9e5SRishi Panjwani struct wmi_create_pstream_cmd pstream; 13608fffd9e5SRishi Panjwani u32 val32; 13618fffd9e5SRishi Panjwani u16 val16; 13628fffd9e5SRishi Panjwani 1363990bd915SVasanthakumar Thiagarajan vif = ath6kl_vif_first(ar); 1364990bd915SVasanthakumar Thiagarajan if (!vif) 1365990bd915SVasanthakumar Thiagarajan return -EIO; 1366990bd915SVasanthakumar Thiagarajan 13678fffd9e5SRishi Panjwani len = min(count, sizeof(buf) - 1); 13688fffd9e5SRishi Panjwani if (copy_from_user(buf, user_buf, len)) 13698fffd9e5SRishi Panjwani return -EFAULT; 13708fffd9e5SRishi Panjwani buf[len] = '\0'; 13718fffd9e5SRishi Panjwani sptr = buf; 13728fffd9e5SRishi Panjwani 13738fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13748fffd9e5SRishi Panjwani if (!token) 13758fffd9e5SRishi Panjwani return -EINVAL; 13768fffd9e5SRishi Panjwani if (kstrtou8(token, 0, &pstream.user_pri)) 13778fffd9e5SRishi Panjwani return -EINVAL; 13788fffd9e5SRishi Panjwani 13798fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13808fffd9e5SRishi Panjwani if (!token) 13818fffd9e5SRishi Panjwani return -EINVAL; 13828fffd9e5SRishi Panjwani if (kstrtou8(token, 0, &pstream.traffic_direc)) 13838fffd9e5SRishi Panjwani return -EINVAL; 13848fffd9e5SRishi Panjwani 13858fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13868fffd9e5SRishi Panjwani if (!token) 13878fffd9e5SRishi Panjwani return -EINVAL; 13888fffd9e5SRishi Panjwani if (kstrtou8(token, 0, &pstream.traffic_class)) 13898fffd9e5SRishi Panjwani return -EINVAL; 13908fffd9e5SRishi Panjwani 13918fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13928fffd9e5SRishi Panjwani if (!token) 13938fffd9e5SRishi Panjwani return -EINVAL; 13948fffd9e5SRishi Panjwani if (kstrtou8(token, 0, &pstream.traffic_type)) 13958fffd9e5SRishi Panjwani return -EINVAL; 13968fffd9e5SRishi Panjwani 13978fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13988fffd9e5SRishi Panjwani if (!token) 13998fffd9e5SRishi Panjwani return -EINVAL; 14008fffd9e5SRishi Panjwani if (kstrtou8(token, 0, &pstream.voice_psc_cap)) 14018fffd9e5SRishi Panjwani return -EINVAL; 14028fffd9e5SRishi Panjwani 14038fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14048fffd9e5SRishi Panjwani if (!token) 14058fffd9e5SRishi Panjwani return -EINVAL; 14068fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14078fffd9e5SRishi Panjwani return -EINVAL; 14088fffd9e5SRishi Panjwani pstream.min_service_int = cpu_to_le32(val32); 14098fffd9e5SRishi Panjwani 14108fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14118fffd9e5SRishi Panjwani if (!token) 14128fffd9e5SRishi Panjwani return -EINVAL; 14138fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14148fffd9e5SRishi Panjwani return -EINVAL; 14158fffd9e5SRishi Panjwani pstream.max_service_int = cpu_to_le32(val32); 14168fffd9e5SRishi Panjwani 14178fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14188fffd9e5SRishi Panjwani if (!token) 14198fffd9e5SRishi Panjwani return -EINVAL; 14208fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14218fffd9e5SRishi Panjwani return -EINVAL; 14228fffd9e5SRishi Panjwani pstream.inactivity_int = cpu_to_le32(val32); 14238fffd9e5SRishi Panjwani 14248fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14258fffd9e5SRishi Panjwani if (!token) 14268fffd9e5SRishi Panjwani return -EINVAL; 14278fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14288fffd9e5SRishi Panjwani return -EINVAL; 14298fffd9e5SRishi Panjwani pstream.suspension_int = cpu_to_le32(val32); 14308fffd9e5SRishi Panjwani 14318fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14328fffd9e5SRishi Panjwani if (!token) 14338fffd9e5SRishi Panjwani return -EINVAL; 14348fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14358fffd9e5SRishi Panjwani return -EINVAL; 14368fffd9e5SRishi Panjwani pstream.service_start_time = cpu_to_le32(val32); 14378fffd9e5SRishi Panjwani 14388fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14398fffd9e5SRishi Panjwani if (!token) 14408fffd9e5SRishi Panjwani return -EINVAL; 14418fffd9e5SRishi Panjwani if (kstrtou8(token, 0, &pstream.tsid)) 14428fffd9e5SRishi Panjwani return -EINVAL; 14438fffd9e5SRishi Panjwani 14448fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14458fffd9e5SRishi Panjwani if (!token) 14468fffd9e5SRishi Panjwani return -EINVAL; 14478fffd9e5SRishi Panjwani if (kstrtou16(token, 0, &val16)) 14488fffd9e5SRishi Panjwani return -EINVAL; 14498fffd9e5SRishi Panjwani pstream.nominal_msdu = cpu_to_le16(val16); 14508fffd9e5SRishi Panjwani 14518fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14528fffd9e5SRishi Panjwani if (!token) 14538fffd9e5SRishi Panjwani return -EINVAL; 14548fffd9e5SRishi Panjwani if (kstrtou16(token, 0, &val16)) 14558fffd9e5SRishi Panjwani return -EINVAL; 14568fffd9e5SRishi Panjwani pstream.max_msdu = cpu_to_le16(val16); 14578fffd9e5SRishi Panjwani 14588fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14598fffd9e5SRishi Panjwani if (!token) 14608fffd9e5SRishi Panjwani return -EINVAL; 14618fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14628fffd9e5SRishi Panjwani return -EINVAL; 14638fffd9e5SRishi Panjwani pstream.min_data_rate = cpu_to_le32(val32); 14648fffd9e5SRishi Panjwani 14658fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14668fffd9e5SRishi Panjwani if (!token) 14678fffd9e5SRishi Panjwani return -EINVAL; 14688fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14698fffd9e5SRishi Panjwani return -EINVAL; 14708fffd9e5SRishi Panjwani pstream.mean_data_rate = cpu_to_le32(val32); 14718fffd9e5SRishi Panjwani 14728fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14738fffd9e5SRishi Panjwani if (!token) 14748fffd9e5SRishi Panjwani return -EINVAL; 14758fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14768fffd9e5SRishi Panjwani return -EINVAL; 14778fffd9e5SRishi Panjwani pstream.peak_data_rate = cpu_to_le32(val32); 14788fffd9e5SRishi Panjwani 14798fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14808fffd9e5SRishi Panjwani if (!token) 14818fffd9e5SRishi Panjwani return -EINVAL; 14828fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14838fffd9e5SRishi Panjwani return -EINVAL; 14848fffd9e5SRishi Panjwani pstream.max_burst_size = cpu_to_le32(val32); 14858fffd9e5SRishi Panjwani 14868fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14878fffd9e5SRishi Panjwani if (!token) 14888fffd9e5SRishi Panjwani return -EINVAL; 14898fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14908fffd9e5SRishi Panjwani return -EINVAL; 14918fffd9e5SRishi Panjwani pstream.delay_bound = cpu_to_le32(val32); 14928fffd9e5SRishi Panjwani 14938fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14948fffd9e5SRishi Panjwani if (!token) 14958fffd9e5SRishi Panjwani return -EINVAL; 14968fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14978fffd9e5SRishi Panjwani return -EINVAL; 14988fffd9e5SRishi Panjwani pstream.min_phy_rate = cpu_to_le32(val32); 14998fffd9e5SRishi Panjwani 15008fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 15018fffd9e5SRishi Panjwani if (!token) 15028fffd9e5SRishi Panjwani return -EINVAL; 15038fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 15048fffd9e5SRishi Panjwani return -EINVAL; 15058fffd9e5SRishi Panjwani pstream.sba = cpu_to_le32(val32); 15068fffd9e5SRishi Panjwani 15078fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 15088fffd9e5SRishi Panjwani if (!token) 15098fffd9e5SRishi Panjwani return -EINVAL; 15108fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 15118fffd9e5SRishi Panjwani return -EINVAL; 15128fffd9e5SRishi Panjwani pstream.medium_time = cpu_to_le32(val32); 15138fffd9e5SRishi Panjwani 15145fbea5dcSChilam Ng pstream.nominal_phy = le32_to_cpu(pstream.min_phy_rate) / 1000000; 15155fbea5dcSChilam Ng 1516240d2799SVasanthakumar Thiagarajan ath6kl_wmi_create_pstream_cmd(ar->wmi, vif->fw_vif_idx, &pstream); 15178fffd9e5SRishi Panjwani 15188fffd9e5SRishi Panjwani return count; 15198fffd9e5SRishi Panjwani } 15208fffd9e5SRishi Panjwani 15218fffd9e5SRishi Panjwani static const struct file_operations fops_create_qos = { 15228fffd9e5SRishi Panjwani .write = ath6kl_create_qos_write, 15238fffd9e5SRishi Panjwani .open = ath6kl_debugfs_open, 15248fffd9e5SRishi Panjwani .owner = THIS_MODULE, 15258fffd9e5SRishi Panjwani .llseek = default_llseek, 15268fffd9e5SRishi Panjwani }; 15278fffd9e5SRishi Panjwani 15288fffd9e5SRishi Panjwani static ssize_t ath6kl_delete_qos_write(struct file *file, 15298fffd9e5SRishi Panjwani const char __user *user_buf, 15308fffd9e5SRishi Panjwani size_t count, loff_t *ppos) 15318fffd9e5SRishi Panjwani { 15328fffd9e5SRishi Panjwani 15338fffd9e5SRishi Panjwani struct ath6kl *ar = file->private_data; 1534990bd915SVasanthakumar Thiagarajan struct ath6kl_vif *vif; 15358fffd9e5SRishi Panjwani char buf[100]; 15368fffd9e5SRishi Panjwani ssize_t len; 15378fffd9e5SRishi Panjwani char *sptr, *token; 15388fffd9e5SRishi Panjwani u8 traffic_class; 15398fffd9e5SRishi Panjwani u8 tsid; 15408fffd9e5SRishi Panjwani 1541990bd915SVasanthakumar Thiagarajan vif = ath6kl_vif_first(ar); 1542990bd915SVasanthakumar Thiagarajan if (!vif) 1543990bd915SVasanthakumar Thiagarajan return -EIO; 1544990bd915SVasanthakumar Thiagarajan 15458fffd9e5SRishi Panjwani len = min(count, sizeof(buf) - 1); 15468fffd9e5SRishi Panjwani if (copy_from_user(buf, user_buf, len)) 15478fffd9e5SRishi Panjwani return -EFAULT; 15488fffd9e5SRishi Panjwani buf[len] = '\0'; 15498fffd9e5SRishi Panjwani sptr = buf; 15508fffd9e5SRishi Panjwani 15518fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 15528fffd9e5SRishi Panjwani if (!token) 15538fffd9e5SRishi Panjwani return -EINVAL; 15548fffd9e5SRishi Panjwani if (kstrtou8(token, 0, &traffic_class)) 15558fffd9e5SRishi Panjwani return -EINVAL; 15568fffd9e5SRishi Panjwani 15578fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 15588fffd9e5SRishi Panjwani if (!token) 15598fffd9e5SRishi Panjwani return -EINVAL; 15608fffd9e5SRishi Panjwani if (kstrtou8(token, 0, &tsid)) 15618fffd9e5SRishi Panjwani return -EINVAL; 15628fffd9e5SRishi Panjwani 1563240d2799SVasanthakumar Thiagarajan ath6kl_wmi_delete_pstream_cmd(ar->wmi, vif->fw_vif_idx, 1564240d2799SVasanthakumar Thiagarajan traffic_class, tsid); 15658fffd9e5SRishi Panjwani 15668fffd9e5SRishi Panjwani return count; 15678fffd9e5SRishi Panjwani } 15688fffd9e5SRishi Panjwani 15698fffd9e5SRishi Panjwani static const struct file_operations fops_delete_qos = { 15708fffd9e5SRishi Panjwani .write = ath6kl_delete_qos_write, 15718fffd9e5SRishi Panjwani .open = ath6kl_debugfs_open, 15728fffd9e5SRishi Panjwani .owner = THIS_MODULE, 15738fffd9e5SRishi Panjwani .llseek = default_llseek, 15748fffd9e5SRishi Panjwani }; 15758fffd9e5SRishi Panjwani 1576116b3a2eSRishi Panjwani static ssize_t ath6kl_bgscan_int_write(struct file *file, 1577116b3a2eSRishi Panjwani const char __user *user_buf, 1578116b3a2eSRishi Panjwani size_t count, loff_t *ppos) 1579116b3a2eSRishi Panjwani { 1580116b3a2eSRishi Panjwani struct ath6kl *ar = file->private_data; 1581116b3a2eSRishi Panjwani u16 bgscan_int; 1582116b3a2eSRishi Panjwani char buf[32]; 1583116b3a2eSRishi Panjwani ssize_t len; 1584116b3a2eSRishi Panjwani 1585116b3a2eSRishi Panjwani len = min(count, sizeof(buf) - 1); 1586116b3a2eSRishi Panjwani if (copy_from_user(buf, user_buf, len)) 1587116b3a2eSRishi Panjwani return -EFAULT; 1588116b3a2eSRishi Panjwani 1589116b3a2eSRishi Panjwani buf[len] = '\0'; 1590116b3a2eSRishi Panjwani if (kstrtou16(buf, 0, &bgscan_int)) 1591116b3a2eSRishi Panjwani return -EINVAL; 1592116b3a2eSRishi Panjwani 1593116b3a2eSRishi Panjwani if (bgscan_int == 0) 1594116b3a2eSRishi Panjwani bgscan_int = 0xffff; 1595116b3a2eSRishi Panjwani 1596334234b5SVasanthakumar Thiagarajan ath6kl_wmi_scanparams_cmd(ar->wmi, 0, 0, 0, bgscan_int, 0, 0, 0, 3, 1597116b3a2eSRishi Panjwani 0, 0, 0); 1598116b3a2eSRishi Panjwani 1599116b3a2eSRishi Panjwani return count; 1600116b3a2eSRishi Panjwani } 1601116b3a2eSRishi Panjwani 1602116b3a2eSRishi Panjwani static const struct file_operations fops_bgscan_int = { 1603116b3a2eSRishi Panjwani .write = ath6kl_bgscan_int_write, 1604116b3a2eSRishi Panjwani .open = ath6kl_debugfs_open, 1605116b3a2eSRishi Panjwani .owner = THIS_MODULE, 1606116b3a2eSRishi Panjwani .llseek = default_llseek, 1607116b3a2eSRishi Panjwani }; 1608116b3a2eSRishi Panjwani 1609ef8f0ebaSRishi Panjwani static ssize_t ath6kl_listen_int_write(struct file *file, 1610ef8f0ebaSRishi Panjwani const char __user *user_buf, 1611ef8f0ebaSRishi Panjwani size_t count, loff_t *ppos) 1612ef8f0ebaSRishi Panjwani { 1613ef8f0ebaSRishi Panjwani struct ath6kl *ar = file->private_data; 16148232736dSSujith Manoharan struct ath6kl_vif *vif; 16158232736dSSujith Manoharan u16 listen_interval; 1616ef8f0ebaSRishi Panjwani char buf[32]; 1617ef8f0ebaSRishi Panjwani ssize_t len; 1618ef8f0ebaSRishi Panjwani 16198232736dSSujith Manoharan vif = ath6kl_vif_first(ar); 16208232736dSSujith Manoharan if (!vif) 16218232736dSSujith Manoharan return -EIO; 16228232736dSSujith Manoharan 1623ef8f0ebaSRishi Panjwani len = min(count, sizeof(buf) - 1); 1624ef8f0ebaSRishi Panjwani if (copy_from_user(buf, user_buf, len)) 1625ef8f0ebaSRishi Panjwani return -EFAULT; 1626ef8f0ebaSRishi Panjwani 1627ef8f0ebaSRishi Panjwani buf[len] = '\0'; 16288232736dSSujith Manoharan if (kstrtou16(buf, 0, &listen_interval)) 1629ef8f0ebaSRishi Panjwani return -EINVAL; 1630ef8f0ebaSRishi Panjwani 16318f46fccdSRaja Mani if ((listen_interval < 15) || (listen_interval > 3000)) 1632ef8f0ebaSRishi Panjwani return -EINVAL; 1633ef8f0ebaSRishi Panjwani 16348f46fccdSRaja Mani vif->listen_intvl_t = listen_interval; 16358f46fccdSRaja Mani ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, 16368f46fccdSRaja Mani vif->listen_intvl_t, 0); 1637ef8f0ebaSRishi Panjwani 1638ef8f0ebaSRishi Panjwani return count; 1639ef8f0ebaSRishi Panjwani } 1640ef8f0ebaSRishi Panjwani 1641ef8f0ebaSRishi Panjwani static ssize_t ath6kl_listen_int_read(struct file *file, 1642ef8f0ebaSRishi Panjwani char __user *user_buf, 1643ef8f0ebaSRishi Panjwani size_t count, loff_t *ppos) 1644ef8f0ebaSRishi Panjwani { 1645ef8f0ebaSRishi Panjwani struct ath6kl *ar = file->private_data; 16468f46fccdSRaja Mani struct ath6kl_vif *vif; 164750553c2cSDan Carpenter char buf[32]; 1648ef8f0ebaSRishi Panjwani int len; 1649ef8f0ebaSRishi Panjwani 16508f46fccdSRaja Mani vif = ath6kl_vif_first(ar); 16518f46fccdSRaja Mani if (!vif) 16528f46fccdSRaja Mani return -EIO; 16538f46fccdSRaja Mani 16548f46fccdSRaja Mani len = scnprintf(buf, sizeof(buf), "%u\n", vif->listen_intvl_t); 1655ef8f0ebaSRishi Panjwani 1656ef8f0ebaSRishi Panjwani return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1657ef8f0ebaSRishi Panjwani } 1658ef8f0ebaSRishi Panjwani 1659ef8f0ebaSRishi Panjwani static const struct file_operations fops_listen_int = { 1660ef8f0ebaSRishi Panjwani .read = ath6kl_listen_int_read, 1661ef8f0ebaSRishi Panjwani .write = ath6kl_listen_int_write, 1662ef8f0ebaSRishi Panjwani .open = ath6kl_debugfs_open, 1663ef8f0ebaSRishi Panjwani .owner = THIS_MODULE, 1664ef8f0ebaSRishi Panjwani .llseek = default_llseek, 1665ef8f0ebaSRishi Panjwani }; 1666ef8f0ebaSRishi Panjwani 1667a24fc7c3SRishi Panjwani static ssize_t ath6kl_power_params_write(struct file *file, 1668a24fc7c3SRishi Panjwani const char __user *user_buf, 1669a24fc7c3SRishi Panjwani size_t count, loff_t *ppos) 1670a24fc7c3SRishi Panjwani { 1671a24fc7c3SRishi Panjwani struct ath6kl *ar = file->private_data; 1672a24fc7c3SRishi Panjwani u8 buf[100]; 1673a24fc7c3SRishi Panjwani unsigned int len = 0; 1674a24fc7c3SRishi Panjwani char *sptr, *token; 1675a24fc7c3SRishi Panjwani u16 idle_period, ps_poll_num, dtim, 1676a24fc7c3SRishi Panjwani tx_wakeup, num_tx; 1677a24fc7c3SRishi Panjwani 1678a24fc7c3SRishi Panjwani len = min(count, sizeof(buf) - 1); 1679a24fc7c3SRishi Panjwani if (copy_from_user(buf, user_buf, len)) 1680a24fc7c3SRishi Panjwani return -EFAULT; 1681a24fc7c3SRishi Panjwani buf[len] = '\0'; 1682a24fc7c3SRishi Panjwani sptr = buf; 1683a24fc7c3SRishi Panjwani 1684a24fc7c3SRishi Panjwani token = strsep(&sptr, " "); 1685a24fc7c3SRishi Panjwani if (!token) 1686a24fc7c3SRishi Panjwani return -EINVAL; 1687a24fc7c3SRishi Panjwani if (kstrtou16(token, 0, &idle_period)) 1688a24fc7c3SRishi Panjwani return -EINVAL; 1689a24fc7c3SRishi Panjwani 1690a24fc7c3SRishi Panjwani token = strsep(&sptr, " "); 1691a24fc7c3SRishi Panjwani if (!token) 1692a24fc7c3SRishi Panjwani return -EINVAL; 1693a24fc7c3SRishi Panjwani if (kstrtou16(token, 0, &ps_poll_num)) 1694a24fc7c3SRishi Panjwani return -EINVAL; 1695a24fc7c3SRishi Panjwani 1696a24fc7c3SRishi Panjwani token = strsep(&sptr, " "); 1697a24fc7c3SRishi Panjwani if (!token) 1698a24fc7c3SRishi Panjwani return -EINVAL; 1699a24fc7c3SRishi Panjwani if (kstrtou16(token, 0, &dtim)) 1700a24fc7c3SRishi Panjwani return -EINVAL; 1701a24fc7c3SRishi Panjwani 1702a24fc7c3SRishi Panjwani token = strsep(&sptr, " "); 1703a24fc7c3SRishi Panjwani if (!token) 1704a24fc7c3SRishi Panjwani return -EINVAL; 1705a24fc7c3SRishi Panjwani if (kstrtou16(token, 0, &tx_wakeup)) 1706a24fc7c3SRishi Panjwani return -EINVAL; 1707a24fc7c3SRishi Panjwani 1708a24fc7c3SRishi Panjwani token = strsep(&sptr, " "); 1709a24fc7c3SRishi Panjwani if (!token) 1710a24fc7c3SRishi Panjwani return -EINVAL; 1711a24fc7c3SRishi Panjwani if (kstrtou16(token, 0, &num_tx)) 1712a24fc7c3SRishi Panjwani return -EINVAL; 1713a24fc7c3SRishi Panjwani 1714a24fc7c3SRishi Panjwani ath6kl_wmi_pmparams_cmd(ar->wmi, 0, idle_period, ps_poll_num, 1715a24fc7c3SRishi Panjwani dtim, tx_wakeup, num_tx, 0); 1716a24fc7c3SRishi Panjwani 1717a24fc7c3SRishi Panjwani return count; 1718a24fc7c3SRishi Panjwani } 1719a24fc7c3SRishi Panjwani 1720a24fc7c3SRishi Panjwani static const struct file_operations fops_power_params = { 1721a24fc7c3SRishi Panjwani .write = ath6kl_power_params_write, 1722a24fc7c3SRishi Panjwani .open = ath6kl_debugfs_open, 1723a24fc7c3SRishi Panjwani .owner = THIS_MODULE, 1724a24fc7c3SRishi Panjwani .llseek = default_llseek, 1725a24fc7c3SRishi Panjwani }; 1726a24fc7c3SRishi Panjwani 1727068a4633SVasanthakumar Thiagarajan void ath6kl_debug_init(struct ath6kl *ar) 1728d999ba3eSVasanthakumar Thiagarajan { 17299b9a4f2aSKalle Valo skb_queue_head_init(&ar->debug.fwlog_queue); 1730c807b30dSKalle Valo init_completion(&ar->debug.fwlog_completion); 1731bdf5396bSKalle Valo 1732939f1cceSKalle Valo /* 1733939f1cceSKalle Valo * Actually we are lying here but don't know how to read the mask 1734939f1cceSKalle Valo * value from the firmware. 1735939f1cceSKalle Valo */ 1736939f1cceSKalle Valo ar->debug.fwlog_mask = 0; 1737068a4633SVasanthakumar Thiagarajan } 1738939f1cceSKalle Valo 1739068a4633SVasanthakumar Thiagarajan /* 1740068a4633SVasanthakumar Thiagarajan * Initialisation needs to happen in two stages as fwlog events can come 1741068a4633SVasanthakumar Thiagarajan * before cfg80211 is initialised, and debugfs depends on cfg80211 1742068a4633SVasanthakumar Thiagarajan * initialisation. 1743068a4633SVasanthakumar Thiagarajan */ 1744068a4633SVasanthakumar Thiagarajan int ath6kl_debug_init_fs(struct ath6kl *ar) 1745068a4633SVasanthakumar Thiagarajan { 1746d999ba3eSVasanthakumar Thiagarajan ar->debugfs_phy = debugfs_create_dir("ath6kl", 1747be98e3a4SVasanthakumar Thiagarajan ar->wiphy->debugfsdir); 17489b9a4f2aSKalle Valo if (!ar->debugfs_phy) 1749d999ba3eSVasanthakumar Thiagarajan return -ENOMEM; 1750d999ba3eSVasanthakumar Thiagarajan 175103f68a95SVasanthakumar Thiagarajan debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar, 175203f68a95SVasanthakumar Thiagarajan &fops_tgt_stats); 175303f68a95SVasanthakumar Thiagarajan 175478fc4856SVasanthakumar Thiagarajan debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar, 175578fc4856SVasanthakumar Thiagarajan &fops_credit_dist_stats); 175678fc4856SVasanthakumar Thiagarajan 1757e8091281SJouni Malinen debugfs_create_file("endpoint_stats", S_IRUSR | S_IWUSR, 1758e8091281SJouni Malinen ar->debugfs_phy, ar, &fops_endpoint_stats); 1759e8091281SJouni Malinen 1760bdf5396bSKalle Valo debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar, 1761bdf5396bSKalle Valo &fops_fwlog); 1762bdf5396bSKalle Valo 1763c807b30dSKalle Valo debugfs_create_file("fwlog_block", S_IRUSR, ar->debugfs_phy, ar, 1764c807b30dSKalle Valo &fops_fwlog_block); 1765c807b30dSKalle Valo 1766939f1cceSKalle Valo debugfs_create_file("fwlog_mask", S_IRUSR | S_IWUSR, ar->debugfs_phy, 1767939f1cceSKalle Valo ar, &fops_fwlog_mask); 1768939f1cceSKalle Valo 176991d57de5SVasanthakumar Thiagarajan debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar, 177091d57de5SVasanthakumar Thiagarajan &fops_diag_reg_read); 177191d57de5SVasanthakumar Thiagarajan 177291d57de5SVasanthakumar Thiagarajan debugfs_create_file("reg_dump", S_IRUSR, ar->debugfs_phy, ar, 177391d57de5SVasanthakumar Thiagarajan &fops_reg_dump); 177491d57de5SVasanthakumar Thiagarajan 1775e5090444SVivek Natarajan debugfs_create_file("lrssi_roam_threshold", S_IRUSR | S_IWUSR, 1776e5090444SVivek Natarajan ar->debugfs_phy, ar, &fops_lrssi_roam_threshold); 1777252c068bSVasanthakumar Thiagarajan 1778252c068bSVasanthakumar Thiagarajan debugfs_create_file("reg_write", S_IRUSR | S_IWUSR, 1779252c068bSVasanthakumar Thiagarajan ar->debugfs_phy, ar, &fops_diag_reg_write); 1780252c068bSVasanthakumar Thiagarajan 17819a730834SKalle Valo debugfs_create_file("war_stats", S_IRUSR, ar->debugfs_phy, ar, 17829a730834SKalle Valo &fops_war_stats); 17839a730834SKalle Valo 17844b28a80dSJouni Malinen debugfs_create_file("roam_table", S_IRUSR, ar->debugfs_phy, ar, 17854b28a80dSJouni Malinen &fops_roam_table); 17864b28a80dSJouni Malinen 17871261875fSJouni Malinen debugfs_create_file("force_roam", S_IWUSR, ar->debugfs_phy, ar, 17881261875fSJouni Malinen &fops_force_roam); 17891261875fSJouni Malinen 17901261875fSJouni Malinen debugfs_create_file("roam_mode", S_IWUSR, ar->debugfs_phy, ar, 17911261875fSJouni Malinen &fops_roam_mode); 17921261875fSJouni Malinen 1793ff0b0075SJouni Malinen debugfs_create_file("keepalive", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar, 1794ff0b0075SJouni Malinen &fops_keepalive); 1795ff0b0075SJouni Malinen 1796ff0b0075SJouni Malinen debugfs_create_file("disconnect_timeout", S_IRUSR | S_IWUSR, 1797ff0b0075SJouni Malinen ar->debugfs_phy, ar, &fops_disconnect_timeout); 1798ff0b0075SJouni Malinen 17998fffd9e5SRishi Panjwani debugfs_create_file("create_qos", S_IWUSR, ar->debugfs_phy, ar, 18008fffd9e5SRishi Panjwani &fops_create_qos); 18018fffd9e5SRishi Panjwani 18028fffd9e5SRishi Panjwani debugfs_create_file("delete_qos", S_IWUSR, ar->debugfs_phy, ar, 18038fffd9e5SRishi Panjwani &fops_delete_qos); 18048fffd9e5SRishi Panjwani 1805116b3a2eSRishi Panjwani debugfs_create_file("bgscan_interval", S_IWUSR, 1806116b3a2eSRishi Panjwani ar->debugfs_phy, ar, &fops_bgscan_int); 1807116b3a2eSRishi Panjwani 18088232736dSSujith Manoharan debugfs_create_file("listen_interval", S_IRUSR | S_IWUSR, 18098232736dSSujith Manoharan ar->debugfs_phy, ar, &fops_listen_int); 18108232736dSSujith Manoharan 1811a24fc7c3SRishi Panjwani debugfs_create_file("power_params", S_IWUSR, ar->debugfs_phy, ar, 1812a24fc7c3SRishi Panjwani &fops_power_params); 1813a24fc7c3SRishi Panjwani 1814d999ba3eSVasanthakumar Thiagarajan return 0; 1815d999ba3eSVasanthakumar Thiagarajan } 1816bdf5396bSKalle Valo 1817bdf5396bSKalle Valo void ath6kl_debug_cleanup(struct ath6kl *ar) 1818bdf5396bSKalle Valo { 18199b9a4f2aSKalle Valo skb_queue_purge(&ar->debug.fwlog_queue); 18204b28a80dSJouni Malinen kfree(ar->debug.roam_tbl); 1821bdf5396bSKalle Valo } 1822bdf5396bSKalle Valo 1823bdcd8170SKalle Valo #endif 1824