1bdcd8170SKalle Valo /* 2bdcd8170SKalle Valo * Copyright (c) 2004-2011 Atheros Communications Inc. 3bdcd8170SKalle Valo * 4bdcd8170SKalle Valo * Permission to use, copy, modify, and/or distribute this software for any 5bdcd8170SKalle Valo * purpose with or without fee is hereby granted, provided that the above 6bdcd8170SKalle Valo * copyright notice and this permission notice appear in all copies. 7bdcd8170SKalle Valo * 8bdcd8170SKalle Valo * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9bdcd8170SKalle Valo * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10bdcd8170SKalle Valo * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11bdcd8170SKalle Valo * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12bdcd8170SKalle Valo * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13bdcd8170SKalle Valo * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14bdcd8170SKalle Valo * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15bdcd8170SKalle Valo */ 16bdcd8170SKalle Valo 17bdcd8170SKalle Valo #include "core.h" 18bdf5396bSKalle Valo 19bdf5396bSKalle Valo #include <linux/circ_buf.h> 20939f1cceSKalle Valo #include <linux/fs.h> 2162c83ac4SKalle Valo #include <linux/vmalloc.h> 22ee40fa06SPaul Gortmaker #include <linux/export.h> 23bdf5396bSKalle Valo 24bdcd8170SKalle Valo #include "debug.h" 25bdf5396bSKalle Valo #include "target.h" 26bdf5396bSKalle Valo 27bdf5396bSKalle Valo struct ath6kl_fwlog_slot { 28bdf5396bSKalle Valo __le32 timestamp; 29bdf5396bSKalle Valo __le32 length; 30bdf5396bSKalle Valo 31bdf5396bSKalle Valo /* max ATH6KL_FWLOG_PAYLOAD_SIZE bytes */ 32bdf5396bSKalle Valo u8 payload[0]; 33bdf5396bSKalle Valo }; 34bdf5396bSKalle Valo 35bdf5396bSKalle Valo #define ATH6KL_FWLOG_SIZE 32768 36bdf5396bSKalle Valo #define ATH6KL_FWLOG_SLOT_SIZE (sizeof(struct ath6kl_fwlog_slot) + \ 37bdf5396bSKalle Valo ATH6KL_FWLOG_PAYLOAD_SIZE) 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 } 57bdcd8170SKalle Valo 58bdcd8170SKalle Valo #ifdef CONFIG_ATH6KL_DEBUG 5991d57de5SVasanthakumar Thiagarajan 603b1b7d09SKalle Valo void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) 613b1b7d09SKalle Valo { 623b1b7d09SKalle Valo struct va_format vaf; 633b1b7d09SKalle Valo va_list args; 643b1b7d09SKalle Valo 653b1b7d09SKalle Valo if (!(debug_mask & mask)) 663b1b7d09SKalle Valo return; 673b1b7d09SKalle Valo 683b1b7d09SKalle Valo va_start(args, fmt); 693b1b7d09SKalle Valo 703b1b7d09SKalle Valo vaf.fmt = fmt; 713b1b7d09SKalle Valo vaf.va = &args; 723b1b7d09SKalle Valo 733b1b7d09SKalle Valo ath6kl_printk(KERN_DEBUG, "%pV", &vaf); 743b1b7d09SKalle Valo 753b1b7d09SKalle Valo va_end(args); 763b1b7d09SKalle Valo } 773b1b7d09SKalle Valo 783b1b7d09SKalle Valo void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, 793b1b7d09SKalle Valo const char *msg, const char *prefix, 803b1b7d09SKalle Valo const void *buf, size_t len) 813b1b7d09SKalle Valo { 823b1b7d09SKalle Valo if (debug_mask & mask) { 833b1b7d09SKalle Valo if (msg) 843b1b7d09SKalle Valo ath6kl_dbg(mask, "%s\n", msg); 853b1b7d09SKalle Valo 863b1b7d09SKalle Valo print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); 873b1b7d09SKalle Valo } 883b1b7d09SKalle Valo } 893b1b7d09SKalle Valo 9091d57de5SVasanthakumar Thiagarajan #define REG_OUTPUT_LEN_PER_LINE 25 9191d57de5SVasanthakumar Thiagarajan #define REGTYPE_STR_LEN 100 9291d57de5SVasanthakumar Thiagarajan 9391d57de5SVasanthakumar Thiagarajan struct ath6kl_diag_reg_info { 9491d57de5SVasanthakumar Thiagarajan u32 reg_start; 9591d57de5SVasanthakumar Thiagarajan u32 reg_end; 9691d57de5SVasanthakumar Thiagarajan const char *reg_info; 9791d57de5SVasanthakumar Thiagarajan }; 9891d57de5SVasanthakumar Thiagarajan 9991d57de5SVasanthakumar Thiagarajan static const struct ath6kl_diag_reg_info diag_reg[] = { 10091d57de5SVasanthakumar Thiagarajan { 0x20000, 0x200fc, "General DMA and Rx registers" }, 10191d57de5SVasanthakumar Thiagarajan { 0x28000, 0x28900, "MAC PCU register & keycache" }, 10291d57de5SVasanthakumar Thiagarajan { 0x20800, 0x20a40, "QCU" }, 10391d57de5SVasanthakumar Thiagarajan { 0x21000, 0x212f0, "DCU" }, 10491d57de5SVasanthakumar Thiagarajan { 0x4000, 0x42e4, "RTC" }, 10591d57de5SVasanthakumar Thiagarajan { 0x540000, 0x540000 + (256 * 1024), "RAM" }, 10691d57de5SVasanthakumar Thiagarajan { 0x29800, 0x2B210, "Base Band" }, 10791d57de5SVasanthakumar Thiagarajan { 0x1C000, 0x1C748, "Analog" }, 10891d57de5SVasanthakumar Thiagarajan }; 10991d57de5SVasanthakumar Thiagarajan 110bdcd8170SKalle Valo void ath6kl_dump_registers(struct ath6kl_device *dev, 111bdcd8170SKalle Valo struct ath6kl_irq_proc_registers *irq_proc_reg, 112bdcd8170SKalle Valo struct ath6kl_irq_enable_reg *irq_enable_reg) 113bdcd8170SKalle Valo { 114bdcd8170SKalle Valo 1155afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, ("<------- Register Table -------->\n")); 116bdcd8170SKalle Valo 117bdcd8170SKalle Valo if (irq_proc_reg != NULL) { 1185afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 119bdcd8170SKalle Valo "Host Int status: 0x%x\n", 120bdcd8170SKalle Valo irq_proc_reg->host_int_status); 1215afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 122bdcd8170SKalle Valo "CPU Int status: 0x%x\n", 123bdcd8170SKalle Valo irq_proc_reg->cpu_int_status); 1245afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 125bdcd8170SKalle Valo "Error Int status: 0x%x\n", 126bdcd8170SKalle Valo irq_proc_reg->error_int_status); 1275afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 128bdcd8170SKalle Valo "Counter Int status: 0x%x\n", 129bdcd8170SKalle Valo irq_proc_reg->counter_int_status); 1305afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 131bdcd8170SKalle Valo "Mbox Frame: 0x%x\n", 132bdcd8170SKalle Valo irq_proc_reg->mbox_frame); 1335afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 134bdcd8170SKalle Valo "Rx Lookahead Valid: 0x%x\n", 135bdcd8170SKalle Valo irq_proc_reg->rx_lkahd_valid); 1365afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 137bdcd8170SKalle Valo "Rx Lookahead 0: 0x%x\n", 138bdcd8170SKalle Valo irq_proc_reg->rx_lkahd[0]); 1395afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 140bdcd8170SKalle Valo "Rx Lookahead 1: 0x%x\n", 141bdcd8170SKalle Valo irq_proc_reg->rx_lkahd[1]); 142bdcd8170SKalle Valo 143bdcd8170SKalle Valo if (dev->ar->mbox_info.gmbox_addr != 0) { 144bdcd8170SKalle Valo /* 145bdcd8170SKalle Valo * If the target supports GMBOX hardware, dump some 146bdcd8170SKalle Valo * additional state. 147bdcd8170SKalle Valo */ 1485afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 149bdcd8170SKalle Valo "GMBOX Host Int status 2: 0x%x\n", 150bdcd8170SKalle Valo irq_proc_reg->host_int_status2); 1515afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 152bdcd8170SKalle Valo "GMBOX RX Avail: 0x%x\n", 153bdcd8170SKalle Valo irq_proc_reg->gmbox_rx_avail); 1545afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 155bdcd8170SKalle Valo "GMBOX lookahead alias 0: 0x%x\n", 156bdcd8170SKalle Valo irq_proc_reg->rx_gmbox_lkahd_alias[0]); 1575afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 158bdcd8170SKalle Valo "GMBOX lookahead alias 1: 0x%x\n", 159bdcd8170SKalle Valo irq_proc_reg->rx_gmbox_lkahd_alias[1]); 160bdcd8170SKalle Valo } 161bdcd8170SKalle Valo 162bdcd8170SKalle Valo } 163bdcd8170SKalle Valo 164bdcd8170SKalle Valo if (irq_enable_reg != NULL) { 1655afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, 166bdcd8170SKalle Valo "Int status Enable: 0x%x\n", 167bdcd8170SKalle Valo irq_enable_reg->int_status_en); 1685afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, "Counter Int status Enable: 0x%x\n", 169bdcd8170SKalle Valo irq_enable_reg->cntr_int_status_en); 170bdcd8170SKalle Valo } 1715afa5aa7SKalle Valo ath6kl_dbg(ATH6KL_DBG_IRQ, "<------------------------------->\n"); 172bdcd8170SKalle Valo } 173bdcd8170SKalle Valo 174bdcd8170SKalle Valo static void dump_cred_dist(struct htc_endpoint_credit_dist *ep_dist) 175bdcd8170SKalle Valo { 17602f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, 177bdcd8170SKalle Valo "--- endpoint: %d svc_id: 0x%X ---\n", 178bdcd8170SKalle Valo ep_dist->endpoint, ep_dist->svc_id); 17902f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " dist_flags : 0x%X\n", 180bdcd8170SKalle Valo ep_dist->dist_flags); 18102f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_norm : %d\n", 182bdcd8170SKalle Valo ep_dist->cred_norm); 18302f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_min : %d\n", 184bdcd8170SKalle Valo ep_dist->cred_min); 18502f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " credits : %d\n", 186bdcd8170SKalle Valo ep_dist->credits); 18702f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_assngd : %d\n", 188bdcd8170SKalle Valo ep_dist->cred_assngd); 18902f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " seek_cred : %d\n", 190bdcd8170SKalle Valo ep_dist->seek_cred); 19102f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_sz : %d\n", 192bdcd8170SKalle Valo ep_dist->cred_sz); 19302f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_per_msg : %d\n", 194bdcd8170SKalle Valo ep_dist->cred_per_msg); 19502f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_to_dist : %d\n", 196bdcd8170SKalle Valo ep_dist->cred_to_dist); 19702f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, " txq_depth : %d\n", 198e8c39790SKalle Valo get_queue_depth(&ep_dist->htc_ep->txq)); 19902f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, 200bdcd8170SKalle Valo "----------------------------------\n"); 201bdcd8170SKalle Valo } 202bdcd8170SKalle Valo 20302f0d6fcSKalle Valo /* FIXME: move to htc.c */ 204bdcd8170SKalle Valo void dump_cred_dist_stats(struct htc_target *target) 205bdcd8170SKalle Valo { 206bdcd8170SKalle Valo struct htc_endpoint_credit_dist *ep_list; 207bdcd8170SKalle Valo 208bdcd8170SKalle Valo list_for_each_entry(ep_list, &target->cred_dist_list, list) 209bdcd8170SKalle Valo dump_cred_dist(ep_list); 210bdcd8170SKalle Valo 21102f0d6fcSKalle Valo ath6kl_dbg(ATH6KL_DBG_CREDIT, 21202f0d6fcSKalle Valo "credit distribution total %d free %d\n", 2133c370398SKalle Valo target->credit_info->total_avail_credits, 2143c370398SKalle Valo target->credit_info->cur_free_credits); 215bdcd8170SKalle Valo } 216bdcd8170SKalle Valo 21703f68a95SVasanthakumar Thiagarajan static int ath6kl_debugfs_open(struct inode *inode, struct file *file) 21803f68a95SVasanthakumar Thiagarajan { 21903f68a95SVasanthakumar Thiagarajan file->private_data = inode->i_private; 22003f68a95SVasanthakumar Thiagarajan return 0; 22103f68a95SVasanthakumar Thiagarajan } 22203f68a95SVasanthakumar Thiagarajan 2239a730834SKalle Valo void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war) 2249a730834SKalle Valo { 2259a730834SKalle Valo switch (war) { 2269a730834SKalle Valo case ATH6KL_WAR_INVALID_RATE: 2279a730834SKalle Valo ar->debug.war_stats.invalid_rate++; 2289a730834SKalle Valo break; 2299a730834SKalle Valo } 2309a730834SKalle Valo } 2319a730834SKalle Valo 2329a730834SKalle Valo static ssize_t read_file_war_stats(struct file *file, char __user *user_buf, 2339a730834SKalle Valo size_t count, loff_t *ppos) 2349a730834SKalle Valo { 2359a730834SKalle Valo struct ath6kl *ar = file->private_data; 2369a730834SKalle Valo char *buf; 2379a730834SKalle Valo unsigned int len = 0, buf_len = 1500; 2389a730834SKalle Valo ssize_t ret_cnt; 2399a730834SKalle Valo 2409a730834SKalle Valo buf = kzalloc(buf_len, GFP_KERNEL); 2419a730834SKalle Valo if (!buf) 2429a730834SKalle Valo return -ENOMEM; 2439a730834SKalle Valo 2449a730834SKalle Valo len += scnprintf(buf + len, buf_len - len, "\n"); 2459a730834SKalle Valo len += scnprintf(buf + len, buf_len - len, "%25s\n", 2469a730834SKalle Valo "Workaround stats"); 2479a730834SKalle Valo len += scnprintf(buf + len, buf_len - len, "%25s\n\n", 2489a730834SKalle Valo "================="); 2499a730834SKalle Valo len += scnprintf(buf + len, buf_len - len, "%20s %10u\n", 2509a730834SKalle Valo "Invalid rates", ar->debug.war_stats.invalid_rate); 2519a730834SKalle Valo 2529a730834SKalle Valo if (WARN_ON(len > buf_len)) 2539a730834SKalle Valo len = buf_len; 2549a730834SKalle Valo 2559a730834SKalle Valo ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); 2569a730834SKalle Valo 2579a730834SKalle Valo kfree(buf); 2589a730834SKalle Valo return ret_cnt; 2599a730834SKalle Valo } 2609a730834SKalle Valo 2619a730834SKalle Valo static const struct file_operations fops_war_stats = { 2629a730834SKalle Valo .read = read_file_war_stats, 2639a730834SKalle Valo .open = ath6kl_debugfs_open, 2649a730834SKalle Valo .owner = THIS_MODULE, 2659a730834SKalle Valo .llseek = default_llseek, 2669a730834SKalle Valo }; 2679a730834SKalle Valo 268bdf5396bSKalle Valo static void ath6kl_debug_fwlog_add(struct ath6kl *ar, const void *buf, 269bdf5396bSKalle Valo size_t buf_len) 270bdf5396bSKalle Valo { 271bdf5396bSKalle Valo struct circ_buf *fwlog = &ar->debug.fwlog_buf; 272bdf5396bSKalle Valo size_t space; 273bdf5396bSKalle Valo int i; 274bdf5396bSKalle Valo 275bdf5396bSKalle Valo /* entries must all be equal size */ 276bdf5396bSKalle Valo if (WARN_ON(buf_len != ATH6KL_FWLOG_SLOT_SIZE)) 277bdf5396bSKalle Valo return; 278bdf5396bSKalle Valo 279bdf5396bSKalle Valo space = CIRC_SPACE(fwlog->head, fwlog->tail, ATH6KL_FWLOG_SIZE); 280bdf5396bSKalle Valo if (space < buf_len) 281bdf5396bSKalle Valo /* discard oldest slot */ 282bdf5396bSKalle Valo fwlog->tail = (fwlog->tail + ATH6KL_FWLOG_SLOT_SIZE) & 283bdf5396bSKalle Valo (ATH6KL_FWLOG_SIZE - 1); 284bdf5396bSKalle Valo 285bdf5396bSKalle Valo for (i = 0; i < buf_len; i += space) { 286bdf5396bSKalle Valo space = CIRC_SPACE_TO_END(fwlog->head, fwlog->tail, 287bdf5396bSKalle Valo ATH6KL_FWLOG_SIZE); 288bdf5396bSKalle Valo 289bdf5396bSKalle Valo if ((size_t) space > buf_len - i) 290bdf5396bSKalle Valo space = buf_len - i; 291bdf5396bSKalle Valo 292bdf5396bSKalle Valo memcpy(&fwlog->buf[fwlog->head], buf, space); 293bdf5396bSKalle Valo fwlog->head = (fwlog->head + space) & (ATH6KL_FWLOG_SIZE - 1); 294bdf5396bSKalle Valo } 295bdf5396bSKalle Valo 296bdf5396bSKalle Valo } 297bdf5396bSKalle Valo 298bdf5396bSKalle Valo void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len) 299bdf5396bSKalle Valo { 300bdf5396bSKalle Valo struct ath6kl_fwlog_slot *slot = ar->debug.fwlog_tmp; 301bdf5396bSKalle Valo size_t slot_len; 302bdf5396bSKalle Valo 303bdf5396bSKalle Valo if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE)) 304bdf5396bSKalle Valo return; 305bdf5396bSKalle Valo 306bdf5396bSKalle Valo spin_lock_bh(&ar->debug.fwlog_lock); 307bdf5396bSKalle Valo 308bdf5396bSKalle Valo slot->timestamp = cpu_to_le32(jiffies); 309bdf5396bSKalle Valo slot->length = cpu_to_le32(len); 310bdf5396bSKalle Valo memcpy(slot->payload, buf, len); 311bdf5396bSKalle Valo 312bdf5396bSKalle Valo slot_len = sizeof(*slot) + len; 313bdf5396bSKalle Valo 314bdf5396bSKalle Valo if (slot_len < ATH6KL_FWLOG_SLOT_SIZE) 315bdf5396bSKalle Valo memset(slot->payload + len, 0, 316bdf5396bSKalle Valo ATH6KL_FWLOG_SLOT_SIZE - slot_len); 317bdf5396bSKalle Valo 318bdf5396bSKalle Valo ath6kl_debug_fwlog_add(ar, slot, ATH6KL_FWLOG_SLOT_SIZE); 319bdf5396bSKalle Valo 320bdf5396bSKalle Valo spin_unlock_bh(&ar->debug.fwlog_lock); 321bdf5396bSKalle Valo } 322bdf5396bSKalle Valo 323bdf5396bSKalle Valo static bool ath6kl_debug_fwlog_empty(struct ath6kl *ar) 324bdf5396bSKalle Valo { 325bdf5396bSKalle Valo return CIRC_CNT(ar->debug.fwlog_buf.head, 326bdf5396bSKalle Valo ar->debug.fwlog_buf.tail, 327bdf5396bSKalle Valo ATH6KL_FWLOG_SLOT_SIZE) == 0; 328bdf5396bSKalle Valo } 329bdf5396bSKalle Valo 330bdf5396bSKalle Valo static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf, 331bdf5396bSKalle Valo size_t count, loff_t *ppos) 332bdf5396bSKalle Valo { 333bdf5396bSKalle Valo struct ath6kl *ar = file->private_data; 334bdf5396bSKalle Valo struct circ_buf *fwlog = &ar->debug.fwlog_buf; 335bdf5396bSKalle Valo size_t len = 0, buf_len = count; 336bdf5396bSKalle Valo ssize_t ret_cnt; 337bdf5396bSKalle Valo char *buf; 338bdf5396bSKalle Valo int ccnt; 339bdf5396bSKalle Valo 340bdf5396bSKalle Valo buf = vmalloc(buf_len); 341bdf5396bSKalle Valo if (!buf) 342bdf5396bSKalle Valo return -ENOMEM; 343bdf5396bSKalle Valo 344bc07ddb2SKalle Valo /* read undelivered logs from firmware */ 345bc07ddb2SKalle Valo ath6kl_read_fwlogs(ar); 346bc07ddb2SKalle Valo 347bdf5396bSKalle Valo spin_lock_bh(&ar->debug.fwlog_lock); 348bdf5396bSKalle Valo 349bdf5396bSKalle Valo while (len < buf_len && !ath6kl_debug_fwlog_empty(ar)) { 350bdf5396bSKalle Valo ccnt = CIRC_CNT_TO_END(fwlog->head, fwlog->tail, 351bdf5396bSKalle Valo ATH6KL_FWLOG_SIZE); 352bdf5396bSKalle Valo 353bdf5396bSKalle Valo if ((size_t) ccnt > buf_len - len) 354bdf5396bSKalle Valo ccnt = buf_len - len; 355bdf5396bSKalle Valo 356bdf5396bSKalle Valo memcpy(buf + len, &fwlog->buf[fwlog->tail], ccnt); 357bdf5396bSKalle Valo len += ccnt; 358bdf5396bSKalle Valo 359bdf5396bSKalle Valo fwlog->tail = (fwlog->tail + ccnt) & 360bdf5396bSKalle Valo (ATH6KL_FWLOG_SIZE - 1); 361bdf5396bSKalle Valo } 362bdf5396bSKalle Valo 363bdf5396bSKalle Valo spin_unlock_bh(&ar->debug.fwlog_lock); 364bdf5396bSKalle Valo 365bdf5396bSKalle Valo if (WARN_ON(len > buf_len)) 366bdf5396bSKalle Valo len = buf_len; 367bdf5396bSKalle Valo 368bdf5396bSKalle Valo ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); 369bdf5396bSKalle Valo 370bdf5396bSKalle Valo vfree(buf); 371bdf5396bSKalle Valo 372bdf5396bSKalle Valo return ret_cnt; 373bdf5396bSKalle Valo } 374bdf5396bSKalle Valo 375bdf5396bSKalle Valo static const struct file_operations fops_fwlog = { 376bdf5396bSKalle Valo .open = ath6kl_debugfs_open, 377bdf5396bSKalle Valo .read = ath6kl_fwlog_read, 378bdf5396bSKalle Valo .owner = THIS_MODULE, 379bdf5396bSKalle Valo .llseek = default_llseek, 380bdf5396bSKalle Valo }; 381bdf5396bSKalle Valo 382939f1cceSKalle Valo static ssize_t ath6kl_fwlog_mask_read(struct file *file, char __user *user_buf, 383939f1cceSKalle Valo size_t count, loff_t *ppos) 384939f1cceSKalle Valo { 385939f1cceSKalle Valo struct ath6kl *ar = file->private_data; 386939f1cceSKalle Valo char buf[16]; 387939f1cceSKalle Valo int len; 388939f1cceSKalle Valo 389939f1cceSKalle Valo len = snprintf(buf, sizeof(buf), "0x%x\n", ar->debug.fwlog_mask); 390939f1cceSKalle Valo 391939f1cceSKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, len); 392939f1cceSKalle Valo } 393939f1cceSKalle Valo 394939f1cceSKalle Valo static ssize_t ath6kl_fwlog_mask_write(struct file *file, 395939f1cceSKalle Valo const char __user *user_buf, 396939f1cceSKalle Valo size_t count, loff_t *ppos) 397939f1cceSKalle Valo { 398939f1cceSKalle Valo struct ath6kl *ar = file->private_data; 399939f1cceSKalle Valo int ret; 400939f1cceSKalle Valo 401939f1cceSKalle Valo ret = kstrtou32_from_user(user_buf, count, 0, &ar->debug.fwlog_mask); 402939f1cceSKalle Valo if (ret) 403939f1cceSKalle Valo return ret; 404939f1cceSKalle Valo 405939f1cceSKalle Valo ret = ath6kl_wmi_config_debug_module_cmd(ar->wmi, 406939f1cceSKalle Valo ATH6KL_FWLOG_VALID_MASK, 407939f1cceSKalle Valo ar->debug.fwlog_mask); 408939f1cceSKalle Valo if (ret) 409939f1cceSKalle Valo return ret; 410939f1cceSKalle Valo 411939f1cceSKalle Valo return count; 412939f1cceSKalle Valo } 413939f1cceSKalle Valo 414939f1cceSKalle Valo static const struct file_operations fops_fwlog_mask = { 415939f1cceSKalle Valo .open = ath6kl_debugfs_open, 416939f1cceSKalle Valo .read = ath6kl_fwlog_mask_read, 417939f1cceSKalle Valo .write = ath6kl_fwlog_mask_write, 418939f1cceSKalle Valo .owner = THIS_MODULE, 419939f1cceSKalle Valo .llseek = default_llseek, 420939f1cceSKalle Valo }; 421939f1cceSKalle Valo 42203f68a95SVasanthakumar Thiagarajan static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, 42303f68a95SVasanthakumar Thiagarajan size_t count, loff_t *ppos) 42403f68a95SVasanthakumar Thiagarajan { 42503f68a95SVasanthakumar Thiagarajan struct ath6kl *ar = file->private_data; 426990bd915SVasanthakumar Thiagarajan struct ath6kl_vif *vif; 427990bd915SVasanthakumar Thiagarajan struct target_stats *tgt_stats; 42803f68a95SVasanthakumar Thiagarajan char *buf; 42903f68a95SVasanthakumar Thiagarajan unsigned int len = 0, buf_len = 1500; 43003f68a95SVasanthakumar Thiagarajan int i; 43103f68a95SVasanthakumar Thiagarajan long left; 43203f68a95SVasanthakumar Thiagarajan ssize_t ret_cnt; 43303f68a95SVasanthakumar Thiagarajan 434990bd915SVasanthakumar Thiagarajan vif = ath6kl_vif_first(ar); 435990bd915SVasanthakumar Thiagarajan if (!vif) 436990bd915SVasanthakumar Thiagarajan return -EIO; 437990bd915SVasanthakumar Thiagarajan 438990bd915SVasanthakumar Thiagarajan tgt_stats = &vif->target_stats; 439990bd915SVasanthakumar Thiagarajan 44003f68a95SVasanthakumar Thiagarajan buf = kzalloc(buf_len, GFP_KERNEL); 44103f68a95SVasanthakumar Thiagarajan if (!buf) 44203f68a95SVasanthakumar Thiagarajan return -ENOMEM; 44303f68a95SVasanthakumar Thiagarajan 44403f68a95SVasanthakumar Thiagarajan if (down_interruptible(&ar->sem)) { 44503f68a95SVasanthakumar Thiagarajan kfree(buf); 44603f68a95SVasanthakumar Thiagarajan return -EBUSY; 44703f68a95SVasanthakumar Thiagarajan } 44803f68a95SVasanthakumar Thiagarajan 449b95907a7SVasanthakumar Thiagarajan set_bit(STATS_UPDATE_PEND, &vif->flags); 45003f68a95SVasanthakumar Thiagarajan 451334234b5SVasanthakumar Thiagarajan if (ath6kl_wmi_get_stats_cmd(ar->wmi, 0)) { 45203f68a95SVasanthakumar Thiagarajan up(&ar->sem); 45303f68a95SVasanthakumar Thiagarajan kfree(buf); 45403f68a95SVasanthakumar Thiagarajan return -EIO; 45503f68a95SVasanthakumar Thiagarajan } 45603f68a95SVasanthakumar Thiagarajan 45703f68a95SVasanthakumar Thiagarajan left = wait_event_interruptible_timeout(ar->event_wq, 45803f68a95SVasanthakumar Thiagarajan !test_bit(STATS_UPDATE_PEND, 459b95907a7SVasanthakumar Thiagarajan &vif->flags), WMI_TIMEOUT); 46003f68a95SVasanthakumar Thiagarajan 46103f68a95SVasanthakumar Thiagarajan up(&ar->sem); 46203f68a95SVasanthakumar Thiagarajan 46303f68a95SVasanthakumar Thiagarajan if (left <= 0) { 46403f68a95SVasanthakumar Thiagarajan kfree(buf); 46503f68a95SVasanthakumar Thiagarajan return -ETIMEDOUT; 46603f68a95SVasanthakumar Thiagarajan } 46703f68a95SVasanthakumar Thiagarajan 46803f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "\n"); 46903f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s\n", 47003f68a95SVasanthakumar Thiagarajan "Target Tx stats"); 47103f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s\n\n", 47203f68a95SVasanthakumar Thiagarajan "================="); 47303f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 47403f68a95SVasanthakumar Thiagarajan "Ucast packets", tgt_stats->tx_ucast_pkt); 47503f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 47603f68a95SVasanthakumar Thiagarajan "Bcast packets", tgt_stats->tx_bcast_pkt); 47703f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 47803f68a95SVasanthakumar Thiagarajan "Ucast byte", tgt_stats->tx_ucast_byte); 47903f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 48003f68a95SVasanthakumar Thiagarajan "Bcast byte", tgt_stats->tx_bcast_byte); 48103f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 48203f68a95SVasanthakumar Thiagarajan "Rts success cnt", tgt_stats->tx_rts_success_cnt); 48303f68a95SVasanthakumar Thiagarajan for (i = 0; i < 4; i++) 48403f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, 48503f68a95SVasanthakumar Thiagarajan "%18s %d %10llu\n", "PER on ac", 48603f68a95SVasanthakumar Thiagarajan i, tgt_stats->tx_pkt_per_ac[i]); 48703f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 48803f68a95SVasanthakumar Thiagarajan "Error", tgt_stats->tx_err); 48903f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 49003f68a95SVasanthakumar Thiagarajan "Fail count", tgt_stats->tx_fail_cnt); 49103f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 49203f68a95SVasanthakumar Thiagarajan "Retry count", tgt_stats->tx_retry_cnt); 49303f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 49403f68a95SVasanthakumar Thiagarajan "Multi retry cnt", tgt_stats->tx_mult_retry_cnt); 49503f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 49603f68a95SVasanthakumar Thiagarajan "Rts fail cnt", tgt_stats->tx_rts_fail_cnt); 49703f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s %10llu\n\n", 49803f68a95SVasanthakumar Thiagarajan "TKIP counter measure used", 49903f68a95SVasanthakumar Thiagarajan tgt_stats->tkip_cnter_measures_invoked); 50003f68a95SVasanthakumar Thiagarajan 50103f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s\n", 50203f68a95SVasanthakumar Thiagarajan "Target Rx stats"); 50303f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s\n", 50403f68a95SVasanthakumar Thiagarajan "================="); 50503f68a95SVasanthakumar Thiagarajan 50603f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 50703f68a95SVasanthakumar Thiagarajan "Ucast packets", tgt_stats->rx_ucast_pkt); 50803f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", 50903f68a95SVasanthakumar Thiagarajan "Ucast Rate", tgt_stats->rx_ucast_rate); 51003f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 51103f68a95SVasanthakumar Thiagarajan "Bcast packets", tgt_stats->rx_bcast_pkt); 51203f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 51303f68a95SVasanthakumar Thiagarajan "Ucast byte", tgt_stats->rx_ucast_byte); 51403f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 51503f68a95SVasanthakumar Thiagarajan "Bcast byte", tgt_stats->rx_bcast_byte); 51603f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 51703f68a95SVasanthakumar Thiagarajan "Fragmented pkt", tgt_stats->rx_frgment_pkt); 51803f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 51903f68a95SVasanthakumar Thiagarajan "Error", tgt_stats->rx_err); 52003f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 52103f68a95SVasanthakumar Thiagarajan "CRC Err", tgt_stats->rx_crc_err); 52203f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 52303f68a95SVasanthakumar Thiagarajan "Key chache miss", tgt_stats->rx_key_cache_miss); 52403f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 52503f68a95SVasanthakumar Thiagarajan "Decrypt Err", tgt_stats->rx_decrypt_err); 52603f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 52703f68a95SVasanthakumar Thiagarajan "Duplicate frame", tgt_stats->rx_dupl_frame); 52803f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 52903f68a95SVasanthakumar Thiagarajan "Tkip Mic failure", tgt_stats->tkip_local_mic_fail); 53003f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 53103f68a95SVasanthakumar Thiagarajan "TKIP format err", tgt_stats->tkip_fmt_err); 53203f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 53303f68a95SVasanthakumar Thiagarajan "CCMP format Err", tgt_stats->ccmp_fmt_err); 53403f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n", 53503f68a95SVasanthakumar Thiagarajan "CCMP Replay Err", tgt_stats->ccmp_replays); 53603f68a95SVasanthakumar Thiagarajan 53703f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s\n", 53803f68a95SVasanthakumar Thiagarajan "Misc Target stats"); 53903f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s\n", 54003f68a95SVasanthakumar Thiagarajan "================="); 54103f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 54203f68a95SVasanthakumar Thiagarajan "Beacon Miss count", tgt_stats->cs_bmiss_cnt); 54303f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 54403f68a95SVasanthakumar Thiagarajan "Num Connects", tgt_stats->cs_connect_cnt); 54503f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n", 54603f68a95SVasanthakumar Thiagarajan "Num disconnects", tgt_stats->cs_discon_cnt); 54703f68a95SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", 54803f68a95SVasanthakumar Thiagarajan "Beacon avg rssi", tgt_stats->cs_ave_beacon_rssi); 54903f68a95SVasanthakumar Thiagarajan 55003f68a95SVasanthakumar Thiagarajan if (len > buf_len) 55103f68a95SVasanthakumar Thiagarajan len = buf_len; 55203f68a95SVasanthakumar Thiagarajan 55303f68a95SVasanthakumar Thiagarajan ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); 55403f68a95SVasanthakumar Thiagarajan 55503f68a95SVasanthakumar Thiagarajan kfree(buf); 55603f68a95SVasanthakumar Thiagarajan return ret_cnt; 55703f68a95SVasanthakumar Thiagarajan } 55803f68a95SVasanthakumar Thiagarajan 55903f68a95SVasanthakumar Thiagarajan static const struct file_operations fops_tgt_stats = { 56003f68a95SVasanthakumar Thiagarajan .read = read_file_tgt_stats, 56103f68a95SVasanthakumar Thiagarajan .open = ath6kl_debugfs_open, 56203f68a95SVasanthakumar Thiagarajan .owner = THIS_MODULE, 56303f68a95SVasanthakumar Thiagarajan .llseek = default_llseek, 56403f68a95SVasanthakumar Thiagarajan }; 56503f68a95SVasanthakumar Thiagarajan 56678fc4856SVasanthakumar Thiagarajan #define print_credit_info(fmt_str, ep_list_field) \ 56778fc4856SVasanthakumar Thiagarajan (len += scnprintf(buf + len, buf_len - len, fmt_str, \ 56878fc4856SVasanthakumar Thiagarajan ep_list->ep_list_field)) 56978fc4856SVasanthakumar Thiagarajan #define CREDIT_INFO_DISPLAY_STRING_LEN 200 57078fc4856SVasanthakumar Thiagarajan #define CREDIT_INFO_LEN 128 57178fc4856SVasanthakumar Thiagarajan 57278fc4856SVasanthakumar Thiagarajan static ssize_t read_file_credit_dist_stats(struct file *file, 57378fc4856SVasanthakumar Thiagarajan char __user *user_buf, 57478fc4856SVasanthakumar Thiagarajan size_t count, loff_t *ppos) 57578fc4856SVasanthakumar Thiagarajan { 57678fc4856SVasanthakumar Thiagarajan struct ath6kl *ar = file->private_data; 57778fc4856SVasanthakumar Thiagarajan struct htc_target *target = ar->htc_target; 57878fc4856SVasanthakumar Thiagarajan struct htc_endpoint_credit_dist *ep_list; 57978fc4856SVasanthakumar Thiagarajan char *buf; 58078fc4856SVasanthakumar Thiagarajan unsigned int buf_len, len = 0; 58178fc4856SVasanthakumar Thiagarajan ssize_t ret_cnt; 58278fc4856SVasanthakumar Thiagarajan 58378fc4856SVasanthakumar Thiagarajan buf_len = CREDIT_INFO_DISPLAY_STRING_LEN + 58478fc4856SVasanthakumar Thiagarajan get_queue_depth(&target->cred_dist_list) * CREDIT_INFO_LEN; 58578fc4856SVasanthakumar Thiagarajan buf = kzalloc(buf_len, GFP_KERNEL); 58678fc4856SVasanthakumar Thiagarajan if (!buf) 58778fc4856SVasanthakumar Thiagarajan return -ENOMEM; 58878fc4856SVasanthakumar Thiagarajan 58978fc4856SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s%5d\n", 59078fc4856SVasanthakumar Thiagarajan "Total Avail Credits: ", 5913c370398SKalle Valo target->credit_info->total_avail_credits); 59278fc4856SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%25s%5d\n", 59378fc4856SVasanthakumar Thiagarajan "Free credits :", 5943c370398SKalle Valo target->credit_info->cur_free_credits); 59578fc4856SVasanthakumar Thiagarajan 59678fc4856SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, 59778fc4856SVasanthakumar Thiagarajan " Epid Flags Cred_norm Cred_min Credits Cred_assngd" 59878fc4856SVasanthakumar Thiagarajan " Seek_cred Cred_sz Cred_per_msg Cred_to_dist" 59978fc4856SVasanthakumar Thiagarajan " qdepth\n"); 60078fc4856SVasanthakumar Thiagarajan 60178fc4856SVasanthakumar Thiagarajan list_for_each_entry(ep_list, &target->cred_dist_list, list) { 60278fc4856SVasanthakumar Thiagarajan print_credit_info(" %2d", endpoint); 60378fc4856SVasanthakumar Thiagarajan print_credit_info("%10x", dist_flags); 60478fc4856SVasanthakumar Thiagarajan print_credit_info("%8d", cred_norm); 60578fc4856SVasanthakumar Thiagarajan print_credit_info("%9d", cred_min); 60678fc4856SVasanthakumar Thiagarajan print_credit_info("%9d", credits); 60778fc4856SVasanthakumar Thiagarajan print_credit_info("%10d", cred_assngd); 60878fc4856SVasanthakumar Thiagarajan print_credit_info("%13d", seek_cred); 60978fc4856SVasanthakumar Thiagarajan print_credit_info("%12d", cred_sz); 61078fc4856SVasanthakumar Thiagarajan print_credit_info("%9d", cred_per_msg); 61178fc4856SVasanthakumar Thiagarajan print_credit_info("%14d", cred_to_dist); 61278fc4856SVasanthakumar Thiagarajan len += scnprintf(buf + len, buf_len - len, "%12d\n", 613e8c39790SKalle Valo get_queue_depth(&ep_list->htc_ep->txq)); 61478fc4856SVasanthakumar Thiagarajan } 61578fc4856SVasanthakumar Thiagarajan 61678fc4856SVasanthakumar Thiagarajan if (len > buf_len) 61778fc4856SVasanthakumar Thiagarajan len = buf_len; 61878fc4856SVasanthakumar Thiagarajan 61978fc4856SVasanthakumar Thiagarajan ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); 62078fc4856SVasanthakumar Thiagarajan kfree(buf); 62178fc4856SVasanthakumar Thiagarajan return ret_cnt; 62278fc4856SVasanthakumar Thiagarajan } 62378fc4856SVasanthakumar Thiagarajan 62478fc4856SVasanthakumar Thiagarajan static const struct file_operations fops_credit_dist_stats = { 62578fc4856SVasanthakumar Thiagarajan .read = read_file_credit_dist_stats, 62678fc4856SVasanthakumar Thiagarajan .open = ath6kl_debugfs_open, 62778fc4856SVasanthakumar Thiagarajan .owner = THIS_MODULE, 62878fc4856SVasanthakumar Thiagarajan .llseek = default_llseek, 62978fc4856SVasanthakumar Thiagarajan }; 63078fc4856SVasanthakumar Thiagarajan 631e8091281SJouni Malinen static unsigned int print_endpoint_stat(struct htc_target *target, char *buf, 632e8091281SJouni Malinen unsigned int buf_len, unsigned int len, 633e8091281SJouni Malinen int offset, const char *name) 634e8091281SJouni Malinen { 635e8091281SJouni Malinen int i; 636e8091281SJouni Malinen struct htc_endpoint_stats *ep_st; 637e8091281SJouni Malinen u32 *counter; 638e8091281SJouni Malinen 639e8091281SJouni Malinen len += scnprintf(buf + len, buf_len - len, "%s:", name); 640e8091281SJouni Malinen for (i = 0; i < ENDPOINT_MAX; i++) { 641e8091281SJouni Malinen ep_st = &target->endpoint[i].ep_st; 642e8091281SJouni Malinen counter = ((u32 *) ep_st) + (offset / 4); 643e8091281SJouni Malinen len += scnprintf(buf + len, buf_len - len, " %u", *counter); 644e8091281SJouni Malinen } 645e8091281SJouni Malinen len += scnprintf(buf + len, buf_len - len, "\n"); 646e8091281SJouni Malinen 647e8091281SJouni Malinen return len; 648e8091281SJouni Malinen } 649e8091281SJouni Malinen 650e8091281SJouni Malinen static ssize_t ath6kl_endpoint_stats_read(struct file *file, 651e8091281SJouni Malinen char __user *user_buf, 652e8091281SJouni Malinen size_t count, loff_t *ppos) 653e8091281SJouni Malinen { 654e8091281SJouni Malinen struct ath6kl *ar = file->private_data; 655e8091281SJouni Malinen struct htc_target *target = ar->htc_target; 656e8091281SJouni Malinen char *buf; 657e8091281SJouni Malinen unsigned int buf_len, len = 0; 658e8091281SJouni Malinen ssize_t ret_cnt; 659e8091281SJouni Malinen 66017169329SJouni Malinen buf_len = sizeof(struct htc_endpoint_stats) / sizeof(u32) * 66117169329SJouni Malinen (25 + ENDPOINT_MAX * 11); 66217169329SJouni Malinen buf = kmalloc(buf_len, GFP_KERNEL); 663e8091281SJouni Malinen if (!buf) 664e8091281SJouni Malinen return -ENOMEM; 665e8091281SJouni Malinen 666e8091281SJouni Malinen #define EPSTAT(name) \ 667e8091281SJouni Malinen len = print_endpoint_stat(target, buf, buf_len, len, \ 668e8091281SJouni Malinen offsetof(struct htc_endpoint_stats, name), \ 669e8091281SJouni Malinen #name) 670e8091281SJouni Malinen EPSTAT(cred_low_indicate); 671e8091281SJouni Malinen EPSTAT(tx_issued); 672e8091281SJouni Malinen EPSTAT(tx_pkt_bundled); 673e8091281SJouni Malinen EPSTAT(tx_bundles); 674e8091281SJouni Malinen EPSTAT(tx_dropped); 675e8091281SJouni Malinen EPSTAT(tx_cred_rpt); 676e8091281SJouni Malinen EPSTAT(cred_rpt_from_rx); 67717169329SJouni Malinen EPSTAT(cred_rpt_from_other); 678e8091281SJouni Malinen EPSTAT(cred_rpt_ep0); 679e8091281SJouni Malinen EPSTAT(cred_from_rx); 680e8091281SJouni Malinen EPSTAT(cred_from_other); 681e8091281SJouni Malinen EPSTAT(cred_from_ep0); 682e8091281SJouni Malinen EPSTAT(cred_cosumd); 683e8091281SJouni Malinen EPSTAT(cred_retnd); 684e8091281SJouni Malinen EPSTAT(rx_pkts); 685e8091281SJouni Malinen EPSTAT(rx_lkahds); 686e8091281SJouni Malinen EPSTAT(rx_bundl); 687e8091281SJouni Malinen EPSTAT(rx_bundle_lkahd); 688e8091281SJouni Malinen EPSTAT(rx_bundle_from_hdr); 689e8091281SJouni Malinen EPSTAT(rx_alloc_thresh_hit); 690e8091281SJouni Malinen EPSTAT(rxalloc_thresh_byte); 691e8091281SJouni Malinen #undef EPSTAT 692e8091281SJouni Malinen 693e8091281SJouni Malinen if (len > buf_len) 694e8091281SJouni Malinen len = buf_len; 695e8091281SJouni Malinen 696e8091281SJouni Malinen ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); 697e8091281SJouni Malinen kfree(buf); 698e8091281SJouni Malinen return ret_cnt; 699e8091281SJouni Malinen } 700e8091281SJouni Malinen 701e8091281SJouni Malinen static ssize_t ath6kl_endpoint_stats_write(struct file *file, 702e8091281SJouni Malinen const char __user *user_buf, 703e8091281SJouni Malinen size_t count, loff_t *ppos) 704e8091281SJouni Malinen { 705e8091281SJouni Malinen struct ath6kl *ar = file->private_data; 706e8091281SJouni Malinen struct htc_target *target = ar->htc_target; 707e8091281SJouni Malinen int ret, i; 708e8091281SJouni Malinen u32 val; 709e8091281SJouni Malinen struct htc_endpoint_stats *ep_st; 710e8091281SJouni Malinen 711e8091281SJouni Malinen ret = kstrtou32_from_user(user_buf, count, 0, &val); 712e8091281SJouni Malinen if (ret) 713e8091281SJouni Malinen return ret; 714e8091281SJouni Malinen if (val == 0) { 715e8091281SJouni Malinen for (i = 0; i < ENDPOINT_MAX; i++) { 716e8091281SJouni Malinen ep_st = &target->endpoint[i].ep_st; 717e8091281SJouni Malinen memset(ep_st, 0, sizeof(*ep_st)); 718e8091281SJouni Malinen } 719e8091281SJouni Malinen } 720e8091281SJouni Malinen 721e8091281SJouni Malinen return count; 722e8091281SJouni Malinen } 723e8091281SJouni Malinen 724e8091281SJouni Malinen static const struct file_operations fops_endpoint_stats = { 725e8091281SJouni Malinen .open = ath6kl_debugfs_open, 726e8091281SJouni Malinen .read = ath6kl_endpoint_stats_read, 727e8091281SJouni Malinen .write = ath6kl_endpoint_stats_write, 728e8091281SJouni Malinen .owner = THIS_MODULE, 729e8091281SJouni Malinen .llseek = default_llseek, 730e8091281SJouni Malinen }; 731e8091281SJouni Malinen 73291d57de5SVasanthakumar Thiagarajan static unsigned long ath6kl_get_num_reg(void) 73391d57de5SVasanthakumar Thiagarajan { 73491d57de5SVasanthakumar Thiagarajan int i; 73591d57de5SVasanthakumar Thiagarajan unsigned long n_reg = 0; 73691d57de5SVasanthakumar Thiagarajan 73791d57de5SVasanthakumar Thiagarajan for (i = 0; i < ARRAY_SIZE(diag_reg); i++) 73891d57de5SVasanthakumar Thiagarajan n_reg = n_reg + 73991d57de5SVasanthakumar Thiagarajan (diag_reg[i].reg_end - diag_reg[i].reg_start) / 4 + 1; 74091d57de5SVasanthakumar Thiagarajan 74191d57de5SVasanthakumar Thiagarajan return n_reg; 74291d57de5SVasanthakumar Thiagarajan } 74391d57de5SVasanthakumar Thiagarajan 74491d57de5SVasanthakumar Thiagarajan static bool ath6kl_dbg_is_diag_reg_valid(u32 reg_addr) 74591d57de5SVasanthakumar Thiagarajan { 74691d57de5SVasanthakumar Thiagarajan int i; 74791d57de5SVasanthakumar Thiagarajan 74891d57de5SVasanthakumar Thiagarajan for (i = 0; i < ARRAY_SIZE(diag_reg); i++) { 74991d57de5SVasanthakumar Thiagarajan if (reg_addr >= diag_reg[i].reg_start && 75091d57de5SVasanthakumar Thiagarajan reg_addr <= diag_reg[i].reg_end) 75191d57de5SVasanthakumar Thiagarajan return true; 75291d57de5SVasanthakumar Thiagarajan } 75391d57de5SVasanthakumar Thiagarajan 75491d57de5SVasanthakumar Thiagarajan return false; 75591d57de5SVasanthakumar Thiagarajan } 75691d57de5SVasanthakumar Thiagarajan 75791d57de5SVasanthakumar Thiagarajan static ssize_t ath6kl_regread_read(struct file *file, char __user *user_buf, 75891d57de5SVasanthakumar Thiagarajan size_t count, loff_t *ppos) 75991d57de5SVasanthakumar Thiagarajan { 76091d57de5SVasanthakumar Thiagarajan struct ath6kl *ar = file->private_data; 76191d57de5SVasanthakumar Thiagarajan u8 buf[50]; 76291d57de5SVasanthakumar Thiagarajan unsigned int len = 0; 76391d57de5SVasanthakumar Thiagarajan 76491d57de5SVasanthakumar Thiagarajan if (ar->debug.dbgfs_diag_reg) 76591d57de5SVasanthakumar Thiagarajan len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", 76691d57de5SVasanthakumar Thiagarajan ar->debug.dbgfs_diag_reg); 76791d57de5SVasanthakumar Thiagarajan else 76891d57de5SVasanthakumar Thiagarajan len += scnprintf(buf + len, sizeof(buf) - len, 76991d57de5SVasanthakumar Thiagarajan "All diag registers\n"); 77091d57de5SVasanthakumar Thiagarajan 77191d57de5SVasanthakumar Thiagarajan return simple_read_from_buffer(user_buf, count, ppos, buf, len); 77291d57de5SVasanthakumar Thiagarajan } 77391d57de5SVasanthakumar Thiagarajan 77491d57de5SVasanthakumar Thiagarajan static ssize_t ath6kl_regread_write(struct file *file, 77591d57de5SVasanthakumar Thiagarajan const char __user *user_buf, 77691d57de5SVasanthakumar Thiagarajan size_t count, loff_t *ppos) 77791d57de5SVasanthakumar Thiagarajan { 77891d57de5SVasanthakumar Thiagarajan struct ath6kl *ar = file->private_data; 77991d57de5SVasanthakumar Thiagarajan u8 buf[50]; 78091d57de5SVasanthakumar Thiagarajan unsigned int len; 78191d57de5SVasanthakumar Thiagarajan unsigned long reg_addr; 78291d57de5SVasanthakumar Thiagarajan 78391d57de5SVasanthakumar Thiagarajan len = min(count, sizeof(buf) - 1); 78491d57de5SVasanthakumar Thiagarajan if (copy_from_user(buf, user_buf, len)) 78591d57de5SVasanthakumar Thiagarajan return -EFAULT; 78691d57de5SVasanthakumar Thiagarajan 78791d57de5SVasanthakumar Thiagarajan buf[len] = '\0'; 78891d57de5SVasanthakumar Thiagarajan 78991d57de5SVasanthakumar Thiagarajan if (strict_strtoul(buf, 0, ®_addr)) 79091d57de5SVasanthakumar Thiagarajan return -EINVAL; 79191d57de5SVasanthakumar Thiagarajan 79291d57de5SVasanthakumar Thiagarajan if ((reg_addr % 4) != 0) 79391d57de5SVasanthakumar Thiagarajan return -EINVAL; 79491d57de5SVasanthakumar Thiagarajan 79591d57de5SVasanthakumar Thiagarajan if (reg_addr && !ath6kl_dbg_is_diag_reg_valid(reg_addr)) 79691d57de5SVasanthakumar Thiagarajan return -EINVAL; 79791d57de5SVasanthakumar Thiagarajan 79891d57de5SVasanthakumar Thiagarajan ar->debug.dbgfs_diag_reg = reg_addr; 79991d57de5SVasanthakumar Thiagarajan 80091d57de5SVasanthakumar Thiagarajan return count; 80191d57de5SVasanthakumar Thiagarajan } 80291d57de5SVasanthakumar Thiagarajan 80391d57de5SVasanthakumar Thiagarajan static const struct file_operations fops_diag_reg_read = { 80491d57de5SVasanthakumar Thiagarajan .read = ath6kl_regread_read, 80591d57de5SVasanthakumar Thiagarajan .write = ath6kl_regread_write, 80691d57de5SVasanthakumar Thiagarajan .open = ath6kl_debugfs_open, 80791d57de5SVasanthakumar Thiagarajan .owner = THIS_MODULE, 80891d57de5SVasanthakumar Thiagarajan .llseek = default_llseek, 80991d57de5SVasanthakumar Thiagarajan }; 81091d57de5SVasanthakumar Thiagarajan 81191d57de5SVasanthakumar Thiagarajan static int ath6kl_regdump_open(struct inode *inode, struct file *file) 81291d57de5SVasanthakumar Thiagarajan { 81391d57de5SVasanthakumar Thiagarajan struct ath6kl *ar = inode->i_private; 81491d57de5SVasanthakumar Thiagarajan u8 *buf; 81591d57de5SVasanthakumar Thiagarajan unsigned long int reg_len; 81691d57de5SVasanthakumar Thiagarajan unsigned int len = 0, n_reg; 81791d57de5SVasanthakumar Thiagarajan u32 addr; 81891d57de5SVasanthakumar Thiagarajan __le32 reg_val; 81991d57de5SVasanthakumar Thiagarajan int i, status; 82091d57de5SVasanthakumar Thiagarajan 82191d57de5SVasanthakumar Thiagarajan /* Dump all the registers if no register is specified */ 82291d57de5SVasanthakumar Thiagarajan if (!ar->debug.dbgfs_diag_reg) 82391d57de5SVasanthakumar Thiagarajan n_reg = ath6kl_get_num_reg(); 82491d57de5SVasanthakumar Thiagarajan else 82591d57de5SVasanthakumar Thiagarajan n_reg = 1; 82691d57de5SVasanthakumar Thiagarajan 82791d57de5SVasanthakumar Thiagarajan reg_len = n_reg * REG_OUTPUT_LEN_PER_LINE; 82891d57de5SVasanthakumar Thiagarajan if (n_reg > 1) 82991d57de5SVasanthakumar Thiagarajan reg_len += REGTYPE_STR_LEN; 83091d57de5SVasanthakumar Thiagarajan 83191d57de5SVasanthakumar Thiagarajan buf = vmalloc(reg_len); 83291d57de5SVasanthakumar Thiagarajan if (!buf) 83391d57de5SVasanthakumar Thiagarajan return -ENOMEM; 83491d57de5SVasanthakumar Thiagarajan 83591d57de5SVasanthakumar Thiagarajan if (n_reg == 1) { 83691d57de5SVasanthakumar Thiagarajan addr = ar->debug.dbgfs_diag_reg; 83791d57de5SVasanthakumar Thiagarajan 83891d57de5SVasanthakumar Thiagarajan status = ath6kl_diag_read32(ar, 83991d57de5SVasanthakumar Thiagarajan TARG_VTOP(ar->target_type, addr), 84091d57de5SVasanthakumar Thiagarajan (u32 *)®_val); 84191d57de5SVasanthakumar Thiagarajan if (status) 84291d57de5SVasanthakumar Thiagarajan goto fail_reg_read; 84391d57de5SVasanthakumar Thiagarajan 84491d57de5SVasanthakumar Thiagarajan len += scnprintf(buf + len, reg_len - len, 84591d57de5SVasanthakumar Thiagarajan "0x%06x 0x%08x\n", addr, le32_to_cpu(reg_val)); 84691d57de5SVasanthakumar Thiagarajan goto done; 84791d57de5SVasanthakumar Thiagarajan } 84891d57de5SVasanthakumar Thiagarajan 84991d57de5SVasanthakumar Thiagarajan for (i = 0; i < ARRAY_SIZE(diag_reg); i++) { 85091d57de5SVasanthakumar Thiagarajan len += scnprintf(buf + len, reg_len - len, 85191d57de5SVasanthakumar Thiagarajan "%s\n", diag_reg[i].reg_info); 85291d57de5SVasanthakumar Thiagarajan for (addr = diag_reg[i].reg_start; 85391d57de5SVasanthakumar Thiagarajan addr <= diag_reg[i].reg_end; addr += 4) { 85491d57de5SVasanthakumar Thiagarajan status = ath6kl_diag_read32(ar, 85591d57de5SVasanthakumar Thiagarajan TARG_VTOP(ar->target_type, addr), 85691d57de5SVasanthakumar Thiagarajan (u32 *)®_val); 85791d57de5SVasanthakumar Thiagarajan if (status) 85891d57de5SVasanthakumar Thiagarajan goto fail_reg_read; 85991d57de5SVasanthakumar Thiagarajan 86091d57de5SVasanthakumar Thiagarajan len += scnprintf(buf + len, reg_len - len, 86191d57de5SVasanthakumar Thiagarajan "0x%06x 0x%08x\n", 86291d57de5SVasanthakumar Thiagarajan addr, le32_to_cpu(reg_val)); 86391d57de5SVasanthakumar Thiagarajan } 86491d57de5SVasanthakumar Thiagarajan } 86591d57de5SVasanthakumar Thiagarajan 86691d57de5SVasanthakumar Thiagarajan done: 86791d57de5SVasanthakumar Thiagarajan file->private_data = buf; 86891d57de5SVasanthakumar Thiagarajan return 0; 86991d57de5SVasanthakumar Thiagarajan 87091d57de5SVasanthakumar Thiagarajan fail_reg_read: 87191d57de5SVasanthakumar Thiagarajan ath6kl_warn("Unable to read memory:%u\n", addr); 87291d57de5SVasanthakumar Thiagarajan vfree(buf); 87391d57de5SVasanthakumar Thiagarajan return -EIO; 87491d57de5SVasanthakumar Thiagarajan } 87591d57de5SVasanthakumar Thiagarajan 87691d57de5SVasanthakumar Thiagarajan static ssize_t ath6kl_regdump_read(struct file *file, char __user *user_buf, 87791d57de5SVasanthakumar Thiagarajan size_t count, loff_t *ppos) 87891d57de5SVasanthakumar Thiagarajan { 87991d57de5SVasanthakumar Thiagarajan u8 *buf = file->private_data; 88091d57de5SVasanthakumar Thiagarajan return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); 88191d57de5SVasanthakumar Thiagarajan } 88291d57de5SVasanthakumar Thiagarajan 88391d57de5SVasanthakumar Thiagarajan static int ath6kl_regdump_release(struct inode *inode, struct file *file) 88491d57de5SVasanthakumar Thiagarajan { 88591d57de5SVasanthakumar Thiagarajan vfree(file->private_data); 88691d57de5SVasanthakumar Thiagarajan return 0; 88791d57de5SVasanthakumar Thiagarajan } 88891d57de5SVasanthakumar Thiagarajan 88991d57de5SVasanthakumar Thiagarajan static const struct file_operations fops_reg_dump = { 89091d57de5SVasanthakumar Thiagarajan .open = ath6kl_regdump_open, 89191d57de5SVasanthakumar Thiagarajan .read = ath6kl_regdump_read, 89291d57de5SVasanthakumar Thiagarajan .release = ath6kl_regdump_release, 89391d57de5SVasanthakumar Thiagarajan .owner = THIS_MODULE, 89491d57de5SVasanthakumar Thiagarajan .llseek = default_llseek, 89591d57de5SVasanthakumar Thiagarajan }; 89691d57de5SVasanthakumar Thiagarajan 897e5090444SVivek Natarajan static ssize_t ath6kl_lrssi_roam_write(struct file *file, 898e5090444SVivek Natarajan const char __user *user_buf, 899e5090444SVivek Natarajan size_t count, loff_t *ppos) 900e5090444SVivek Natarajan { 901e5090444SVivek Natarajan struct ath6kl *ar = file->private_data; 902e5090444SVivek Natarajan unsigned long lrssi_roam_threshold; 903e5090444SVivek Natarajan char buf[32]; 904e5090444SVivek Natarajan ssize_t len; 905e5090444SVivek Natarajan 906e5090444SVivek Natarajan len = min(count, sizeof(buf) - 1); 907e5090444SVivek Natarajan if (copy_from_user(buf, user_buf, len)) 908e5090444SVivek Natarajan return -EFAULT; 909e5090444SVivek Natarajan 910e5090444SVivek Natarajan buf[len] = '\0'; 911e5090444SVivek Natarajan if (strict_strtoul(buf, 0, &lrssi_roam_threshold)) 912e5090444SVivek Natarajan return -EINVAL; 913e5090444SVivek Natarajan 914e5090444SVivek Natarajan ar->lrssi_roam_threshold = lrssi_roam_threshold; 915e5090444SVivek Natarajan 916e5090444SVivek Natarajan ath6kl_wmi_set_roam_lrssi_cmd(ar->wmi, ar->lrssi_roam_threshold); 917e5090444SVivek Natarajan 918e5090444SVivek Natarajan return count; 919e5090444SVivek Natarajan } 920e5090444SVivek Natarajan 921e5090444SVivek Natarajan static ssize_t ath6kl_lrssi_roam_read(struct file *file, 922e5090444SVivek Natarajan char __user *user_buf, 923e5090444SVivek Natarajan size_t count, loff_t *ppos) 924e5090444SVivek Natarajan { 925e5090444SVivek Natarajan struct ath6kl *ar = file->private_data; 926e5090444SVivek Natarajan char buf[32]; 927e5090444SVivek Natarajan unsigned int len; 928e5090444SVivek Natarajan 929e5090444SVivek Natarajan len = snprintf(buf, sizeof(buf), "%u\n", ar->lrssi_roam_threshold); 930e5090444SVivek Natarajan 931e5090444SVivek Natarajan return simple_read_from_buffer(user_buf, count, ppos, buf, len); 932e5090444SVivek Natarajan } 933e5090444SVivek Natarajan 934e5090444SVivek Natarajan static const struct file_operations fops_lrssi_roam_threshold = { 935e5090444SVivek Natarajan .read = ath6kl_lrssi_roam_read, 936e5090444SVivek Natarajan .write = ath6kl_lrssi_roam_write, 937e5090444SVivek Natarajan .open = ath6kl_debugfs_open, 938e5090444SVivek Natarajan .owner = THIS_MODULE, 939e5090444SVivek Natarajan .llseek = default_llseek, 940e5090444SVivek Natarajan }; 941e5090444SVivek Natarajan 942252c068bSVasanthakumar Thiagarajan static ssize_t ath6kl_regwrite_read(struct file *file, 943252c068bSVasanthakumar Thiagarajan char __user *user_buf, 944252c068bSVasanthakumar Thiagarajan size_t count, loff_t *ppos) 945252c068bSVasanthakumar Thiagarajan { 946252c068bSVasanthakumar Thiagarajan struct ath6kl *ar = file->private_data; 947252c068bSVasanthakumar Thiagarajan u8 buf[32]; 948252c068bSVasanthakumar Thiagarajan unsigned int len = 0; 949252c068bSVasanthakumar Thiagarajan 950252c068bSVasanthakumar Thiagarajan len = scnprintf(buf, sizeof(buf), "Addr: 0x%x Val: 0x%x\n", 951252c068bSVasanthakumar Thiagarajan ar->debug.diag_reg_addr_wr, ar->debug.diag_reg_val_wr); 952252c068bSVasanthakumar Thiagarajan 953252c068bSVasanthakumar Thiagarajan return simple_read_from_buffer(user_buf, count, ppos, buf, len); 954252c068bSVasanthakumar Thiagarajan } 955252c068bSVasanthakumar Thiagarajan 956252c068bSVasanthakumar Thiagarajan static ssize_t ath6kl_regwrite_write(struct file *file, 957252c068bSVasanthakumar Thiagarajan const char __user *user_buf, 958252c068bSVasanthakumar Thiagarajan size_t count, loff_t *ppos) 959252c068bSVasanthakumar Thiagarajan { 960252c068bSVasanthakumar Thiagarajan struct ath6kl *ar = file->private_data; 961252c068bSVasanthakumar Thiagarajan char buf[32]; 962252c068bSVasanthakumar Thiagarajan char *sptr, *token; 963252c068bSVasanthakumar Thiagarajan unsigned int len = 0; 964252c068bSVasanthakumar Thiagarajan u32 reg_addr, reg_val; 965252c068bSVasanthakumar Thiagarajan 966252c068bSVasanthakumar Thiagarajan len = min(count, sizeof(buf) - 1); 967252c068bSVasanthakumar Thiagarajan if (copy_from_user(buf, user_buf, len)) 968252c068bSVasanthakumar Thiagarajan return -EFAULT; 969252c068bSVasanthakumar Thiagarajan 970252c068bSVasanthakumar Thiagarajan buf[len] = '\0'; 971252c068bSVasanthakumar Thiagarajan sptr = buf; 972252c068bSVasanthakumar Thiagarajan 973252c068bSVasanthakumar Thiagarajan token = strsep(&sptr, "="); 974252c068bSVasanthakumar Thiagarajan if (!token) 975252c068bSVasanthakumar Thiagarajan return -EINVAL; 976252c068bSVasanthakumar Thiagarajan 977252c068bSVasanthakumar Thiagarajan if (kstrtou32(token, 0, ®_addr)) 978252c068bSVasanthakumar Thiagarajan return -EINVAL; 979252c068bSVasanthakumar Thiagarajan 980252c068bSVasanthakumar Thiagarajan if (!ath6kl_dbg_is_diag_reg_valid(reg_addr)) 981252c068bSVasanthakumar Thiagarajan return -EINVAL; 982252c068bSVasanthakumar Thiagarajan 983252c068bSVasanthakumar Thiagarajan if (kstrtou32(sptr, 0, ®_val)) 984252c068bSVasanthakumar Thiagarajan return -EINVAL; 985252c068bSVasanthakumar Thiagarajan 986252c068bSVasanthakumar Thiagarajan ar->debug.diag_reg_addr_wr = reg_addr; 987252c068bSVasanthakumar Thiagarajan ar->debug.diag_reg_val_wr = reg_val; 988252c068bSVasanthakumar Thiagarajan 989252c068bSVasanthakumar Thiagarajan if (ath6kl_diag_write32(ar, ar->debug.diag_reg_addr_wr, 990252c068bSVasanthakumar Thiagarajan cpu_to_le32(ar->debug.diag_reg_val_wr))) 991252c068bSVasanthakumar Thiagarajan return -EIO; 992252c068bSVasanthakumar Thiagarajan 993252c068bSVasanthakumar Thiagarajan return count; 994252c068bSVasanthakumar Thiagarajan } 995252c068bSVasanthakumar Thiagarajan 996252c068bSVasanthakumar Thiagarajan static const struct file_operations fops_diag_reg_write = { 997252c068bSVasanthakumar Thiagarajan .read = ath6kl_regwrite_read, 998252c068bSVasanthakumar Thiagarajan .write = ath6kl_regwrite_write, 999252c068bSVasanthakumar Thiagarajan .open = ath6kl_debugfs_open, 1000252c068bSVasanthakumar Thiagarajan .owner = THIS_MODULE, 1001252c068bSVasanthakumar Thiagarajan .llseek = default_llseek, 1002252c068bSVasanthakumar Thiagarajan }; 1003252c068bSVasanthakumar Thiagarajan 10044b28a80dSJouni Malinen int ath6kl_debug_roam_tbl_event(struct ath6kl *ar, const void *buf, 10054b28a80dSJouni Malinen size_t len) 10064b28a80dSJouni Malinen { 10074b28a80dSJouni Malinen const struct wmi_target_roam_tbl *tbl; 10084b28a80dSJouni Malinen u16 num_entries; 10094b28a80dSJouni Malinen 10104b28a80dSJouni Malinen if (len < sizeof(*tbl)) 10114b28a80dSJouni Malinen return -EINVAL; 10124b28a80dSJouni Malinen 10134b28a80dSJouni Malinen tbl = (const struct wmi_target_roam_tbl *) buf; 10144b28a80dSJouni Malinen num_entries = le16_to_cpu(tbl->num_entries); 10154b28a80dSJouni Malinen if (sizeof(*tbl) + num_entries * sizeof(struct wmi_bss_roam_info) > 10164b28a80dSJouni Malinen len) 10174b28a80dSJouni Malinen return -EINVAL; 10184b28a80dSJouni Malinen 10194b28a80dSJouni Malinen if (ar->debug.roam_tbl == NULL || 10204b28a80dSJouni Malinen ar->debug.roam_tbl_len < (unsigned int) len) { 10214b28a80dSJouni Malinen kfree(ar->debug.roam_tbl); 10224b28a80dSJouni Malinen ar->debug.roam_tbl = kmalloc(len, GFP_ATOMIC); 10234b28a80dSJouni Malinen if (ar->debug.roam_tbl == NULL) 10244b28a80dSJouni Malinen return -ENOMEM; 10254b28a80dSJouni Malinen } 10264b28a80dSJouni Malinen 10274b28a80dSJouni Malinen memcpy(ar->debug.roam_tbl, buf, len); 10284b28a80dSJouni Malinen ar->debug.roam_tbl_len = len; 10294b28a80dSJouni Malinen 10304b28a80dSJouni Malinen if (test_bit(ROAM_TBL_PEND, &ar->flag)) { 10314b28a80dSJouni Malinen clear_bit(ROAM_TBL_PEND, &ar->flag); 10324b28a80dSJouni Malinen wake_up(&ar->event_wq); 10334b28a80dSJouni Malinen } 10344b28a80dSJouni Malinen 10354b28a80dSJouni Malinen return 0; 10364b28a80dSJouni Malinen } 10374b28a80dSJouni Malinen 10384b28a80dSJouni Malinen static ssize_t ath6kl_roam_table_read(struct file *file, char __user *user_buf, 10394b28a80dSJouni Malinen size_t count, loff_t *ppos) 10404b28a80dSJouni Malinen { 10414b28a80dSJouni Malinen struct ath6kl *ar = file->private_data; 10424b28a80dSJouni Malinen int ret; 10434b28a80dSJouni Malinen long left; 10444b28a80dSJouni Malinen struct wmi_target_roam_tbl *tbl; 10454b28a80dSJouni Malinen u16 num_entries, i; 10464b28a80dSJouni Malinen char *buf; 10474b28a80dSJouni Malinen unsigned int len, buf_len; 10484b28a80dSJouni Malinen ssize_t ret_cnt; 10494b28a80dSJouni Malinen 10504b28a80dSJouni Malinen if (down_interruptible(&ar->sem)) 10514b28a80dSJouni Malinen return -EBUSY; 10524b28a80dSJouni Malinen 10534b28a80dSJouni Malinen set_bit(ROAM_TBL_PEND, &ar->flag); 10544b28a80dSJouni Malinen 10554b28a80dSJouni Malinen ret = ath6kl_wmi_get_roam_tbl_cmd(ar->wmi); 10564b28a80dSJouni Malinen if (ret) { 10574b28a80dSJouni Malinen up(&ar->sem); 10584b28a80dSJouni Malinen return ret; 10594b28a80dSJouni Malinen } 10604b28a80dSJouni Malinen 10614b28a80dSJouni Malinen left = wait_event_interruptible_timeout( 10624b28a80dSJouni Malinen ar->event_wq, !test_bit(ROAM_TBL_PEND, &ar->flag), WMI_TIMEOUT); 10634b28a80dSJouni Malinen up(&ar->sem); 10644b28a80dSJouni Malinen 10654b28a80dSJouni Malinen if (left <= 0) 10664b28a80dSJouni Malinen return -ETIMEDOUT; 10674b28a80dSJouni Malinen 10684b28a80dSJouni Malinen if (ar->debug.roam_tbl == NULL) 10694b28a80dSJouni Malinen return -ENOMEM; 10704b28a80dSJouni Malinen 10714b28a80dSJouni Malinen tbl = (struct wmi_target_roam_tbl *) ar->debug.roam_tbl; 10724b28a80dSJouni Malinen num_entries = le16_to_cpu(tbl->num_entries); 10734b28a80dSJouni Malinen 10744b28a80dSJouni Malinen buf_len = 100 + num_entries * 100; 10754b28a80dSJouni Malinen buf = kzalloc(buf_len, GFP_KERNEL); 10764b28a80dSJouni Malinen if (buf == NULL) 10774b28a80dSJouni Malinen return -ENOMEM; 10784b28a80dSJouni Malinen len = 0; 10794b28a80dSJouni Malinen len += scnprintf(buf + len, buf_len - len, 10804b28a80dSJouni Malinen "roam_mode=%u\n\n" 10814b28a80dSJouni Malinen "# roam_util bssid rssi rssidt last_rssi util bias\n", 10824b28a80dSJouni Malinen le16_to_cpu(tbl->roam_mode)); 10834b28a80dSJouni Malinen 10844b28a80dSJouni Malinen for (i = 0; i < num_entries; i++) { 10854b28a80dSJouni Malinen struct wmi_bss_roam_info *info = &tbl->info[i]; 10864b28a80dSJouni Malinen len += scnprintf(buf + len, buf_len - len, 10874b28a80dSJouni Malinen "%d %pM %d %d %d %d %d\n", 10884b28a80dSJouni Malinen a_sle32_to_cpu(info->roam_util), info->bssid, 10894b28a80dSJouni Malinen info->rssi, info->rssidt, info->last_rssi, 10904b28a80dSJouni Malinen info->util, info->bias); 10914b28a80dSJouni Malinen } 10924b28a80dSJouni Malinen 10934b28a80dSJouni Malinen if (len > buf_len) 10944b28a80dSJouni Malinen len = buf_len; 10954b28a80dSJouni Malinen 10964b28a80dSJouni Malinen ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); 10974b28a80dSJouni Malinen 10984b28a80dSJouni Malinen kfree(buf); 10994b28a80dSJouni Malinen return ret_cnt; 11004b28a80dSJouni Malinen } 11014b28a80dSJouni Malinen 11024b28a80dSJouni Malinen static const struct file_operations fops_roam_table = { 11034b28a80dSJouni Malinen .read = ath6kl_roam_table_read, 11044b28a80dSJouni Malinen .open = ath6kl_debugfs_open, 11054b28a80dSJouni Malinen .owner = THIS_MODULE, 11064b28a80dSJouni Malinen .llseek = default_llseek, 11074b28a80dSJouni Malinen }; 11084b28a80dSJouni Malinen 11091261875fSJouni Malinen static ssize_t ath6kl_force_roam_write(struct file *file, 11101261875fSJouni Malinen const char __user *user_buf, 11111261875fSJouni Malinen size_t count, loff_t *ppos) 11121261875fSJouni Malinen { 11131261875fSJouni Malinen struct ath6kl *ar = file->private_data; 11141261875fSJouni Malinen int ret; 11151261875fSJouni Malinen char buf[20]; 11161261875fSJouni Malinen size_t len; 11171261875fSJouni Malinen u8 bssid[ETH_ALEN]; 11181261875fSJouni Malinen int i; 11191261875fSJouni Malinen int addr[ETH_ALEN]; 11201261875fSJouni Malinen 11211261875fSJouni Malinen len = min(count, sizeof(buf) - 1); 11221261875fSJouni Malinen if (copy_from_user(buf, user_buf, len)) 11231261875fSJouni Malinen return -EFAULT; 11241261875fSJouni Malinen buf[len] = '\0'; 11251261875fSJouni Malinen 11261261875fSJouni Malinen if (sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", 11271261875fSJouni Malinen &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) 11281261875fSJouni Malinen != ETH_ALEN) 11291261875fSJouni Malinen return -EINVAL; 11301261875fSJouni Malinen for (i = 0; i < ETH_ALEN; i++) 11311261875fSJouni Malinen bssid[i] = addr[i]; 11321261875fSJouni Malinen 11331261875fSJouni Malinen ret = ath6kl_wmi_force_roam_cmd(ar->wmi, bssid); 11341261875fSJouni Malinen if (ret) 11351261875fSJouni Malinen return ret; 11361261875fSJouni Malinen 11371261875fSJouni Malinen return count; 11381261875fSJouni Malinen } 11391261875fSJouni Malinen 11401261875fSJouni Malinen static const struct file_operations fops_force_roam = { 11411261875fSJouni Malinen .write = ath6kl_force_roam_write, 11421261875fSJouni Malinen .open = ath6kl_debugfs_open, 11431261875fSJouni Malinen .owner = THIS_MODULE, 11441261875fSJouni Malinen .llseek = default_llseek, 11451261875fSJouni Malinen }; 11461261875fSJouni Malinen 11471261875fSJouni Malinen static ssize_t ath6kl_roam_mode_write(struct file *file, 11481261875fSJouni Malinen const char __user *user_buf, 11491261875fSJouni Malinen size_t count, loff_t *ppos) 11501261875fSJouni Malinen { 11511261875fSJouni Malinen struct ath6kl *ar = file->private_data; 11521261875fSJouni Malinen int ret; 11531261875fSJouni Malinen char buf[20]; 11541261875fSJouni Malinen size_t len; 11551261875fSJouni Malinen enum wmi_roam_mode mode; 11561261875fSJouni Malinen 11571261875fSJouni Malinen len = min(count, sizeof(buf) - 1); 11581261875fSJouni Malinen if (copy_from_user(buf, user_buf, len)) 11591261875fSJouni Malinen return -EFAULT; 11601261875fSJouni Malinen buf[len] = '\0'; 11611261875fSJouni Malinen if (len > 0 && buf[len - 1] == '\n') 11621261875fSJouni Malinen buf[len - 1] = '\0'; 11631261875fSJouni Malinen 11641261875fSJouni Malinen if (strcasecmp(buf, "default") == 0) 11651261875fSJouni Malinen mode = WMI_DEFAULT_ROAM_MODE; 11661261875fSJouni Malinen else if (strcasecmp(buf, "bssbias") == 0) 11671261875fSJouni Malinen mode = WMI_HOST_BIAS_ROAM_MODE; 11681261875fSJouni Malinen else if (strcasecmp(buf, "lock") == 0) 11691261875fSJouni Malinen mode = WMI_LOCK_BSS_MODE; 11701261875fSJouni Malinen else 11711261875fSJouni Malinen return -EINVAL; 11721261875fSJouni Malinen 11731261875fSJouni Malinen ret = ath6kl_wmi_set_roam_mode_cmd(ar->wmi, mode); 11741261875fSJouni Malinen if (ret) 11751261875fSJouni Malinen return ret; 11761261875fSJouni Malinen 11771261875fSJouni Malinen return count; 11781261875fSJouni Malinen } 11791261875fSJouni Malinen 11801261875fSJouni Malinen static const struct file_operations fops_roam_mode = { 11811261875fSJouni Malinen .write = ath6kl_roam_mode_write, 11821261875fSJouni Malinen .open = ath6kl_debugfs_open, 11831261875fSJouni Malinen .owner = THIS_MODULE, 11841261875fSJouni Malinen .llseek = default_llseek, 11851261875fSJouni Malinen }; 11861261875fSJouni Malinen 1187ff0b0075SJouni Malinen void ath6kl_debug_set_keepalive(struct ath6kl *ar, u8 keepalive) 1188ff0b0075SJouni Malinen { 1189ff0b0075SJouni Malinen ar->debug.keepalive = keepalive; 1190ff0b0075SJouni Malinen } 1191ff0b0075SJouni Malinen 1192ff0b0075SJouni Malinen static ssize_t ath6kl_keepalive_read(struct file *file, char __user *user_buf, 1193ff0b0075SJouni Malinen size_t count, loff_t *ppos) 1194ff0b0075SJouni Malinen { 1195ff0b0075SJouni Malinen struct ath6kl *ar = file->private_data; 1196ff0b0075SJouni Malinen char buf[16]; 1197ff0b0075SJouni Malinen int len; 1198ff0b0075SJouni Malinen 1199ff0b0075SJouni Malinen len = snprintf(buf, sizeof(buf), "%u\n", ar->debug.keepalive); 1200ff0b0075SJouni Malinen 1201ff0b0075SJouni Malinen return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1202ff0b0075SJouni Malinen } 1203ff0b0075SJouni Malinen 1204ff0b0075SJouni Malinen static ssize_t ath6kl_keepalive_write(struct file *file, 1205ff0b0075SJouni Malinen const char __user *user_buf, 1206ff0b0075SJouni Malinen size_t count, loff_t *ppos) 1207ff0b0075SJouni Malinen { 1208ff0b0075SJouni Malinen struct ath6kl *ar = file->private_data; 1209ff0b0075SJouni Malinen int ret; 1210ff0b0075SJouni Malinen u8 val; 1211ff0b0075SJouni Malinen 1212ff0b0075SJouni Malinen ret = kstrtou8_from_user(user_buf, count, 0, &val); 1213ff0b0075SJouni Malinen if (ret) 1214ff0b0075SJouni Malinen return ret; 1215ff0b0075SJouni Malinen 12160ce59445SVasanthakumar Thiagarajan ret = ath6kl_wmi_set_keepalive_cmd(ar->wmi, 0, val); 1217ff0b0075SJouni Malinen if (ret) 1218ff0b0075SJouni Malinen return ret; 1219ff0b0075SJouni Malinen 1220ff0b0075SJouni Malinen return count; 1221ff0b0075SJouni Malinen } 1222ff0b0075SJouni Malinen 1223ff0b0075SJouni Malinen static const struct file_operations fops_keepalive = { 1224ff0b0075SJouni Malinen .open = ath6kl_debugfs_open, 1225ff0b0075SJouni Malinen .read = ath6kl_keepalive_read, 1226ff0b0075SJouni Malinen .write = ath6kl_keepalive_write, 1227ff0b0075SJouni Malinen .owner = THIS_MODULE, 1228ff0b0075SJouni Malinen .llseek = default_llseek, 1229ff0b0075SJouni Malinen }; 1230ff0b0075SJouni Malinen 1231ff0b0075SJouni Malinen void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar, u8 timeout) 1232ff0b0075SJouni Malinen { 1233ff0b0075SJouni Malinen ar->debug.disc_timeout = timeout; 1234ff0b0075SJouni Malinen } 1235ff0b0075SJouni Malinen 1236ff0b0075SJouni Malinen static ssize_t ath6kl_disconnect_timeout_read(struct file *file, 1237ff0b0075SJouni Malinen char __user *user_buf, 1238ff0b0075SJouni Malinen size_t count, loff_t *ppos) 1239ff0b0075SJouni Malinen { 1240ff0b0075SJouni Malinen struct ath6kl *ar = file->private_data; 1241ff0b0075SJouni Malinen char buf[16]; 1242ff0b0075SJouni Malinen int len; 1243ff0b0075SJouni Malinen 1244ff0b0075SJouni Malinen len = snprintf(buf, sizeof(buf), "%u\n", ar->debug.disc_timeout); 1245ff0b0075SJouni Malinen 1246ff0b0075SJouni Malinen return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1247ff0b0075SJouni Malinen } 1248ff0b0075SJouni Malinen 1249ff0b0075SJouni Malinen static ssize_t ath6kl_disconnect_timeout_write(struct file *file, 1250ff0b0075SJouni Malinen const char __user *user_buf, 1251ff0b0075SJouni Malinen size_t count, loff_t *ppos) 1252ff0b0075SJouni Malinen { 1253ff0b0075SJouni Malinen struct ath6kl *ar = file->private_data; 1254ff0b0075SJouni Malinen int ret; 1255ff0b0075SJouni Malinen u8 val; 1256ff0b0075SJouni Malinen 1257ff0b0075SJouni Malinen ret = kstrtou8_from_user(user_buf, count, 0, &val); 1258ff0b0075SJouni Malinen if (ret) 1259ff0b0075SJouni Malinen return ret; 1260ff0b0075SJouni Malinen 12610ce59445SVasanthakumar Thiagarajan ret = ath6kl_wmi_disctimeout_cmd(ar->wmi, 0, val); 1262ff0b0075SJouni Malinen if (ret) 1263ff0b0075SJouni Malinen return ret; 1264ff0b0075SJouni Malinen 1265ff0b0075SJouni Malinen return count; 1266ff0b0075SJouni Malinen } 1267ff0b0075SJouni Malinen 1268ff0b0075SJouni Malinen static const struct file_operations fops_disconnect_timeout = { 1269ff0b0075SJouni Malinen .open = ath6kl_debugfs_open, 1270ff0b0075SJouni Malinen .read = ath6kl_disconnect_timeout_read, 1271ff0b0075SJouni Malinen .write = ath6kl_disconnect_timeout_write, 1272ff0b0075SJouni Malinen .owner = THIS_MODULE, 1273ff0b0075SJouni Malinen .llseek = default_llseek, 1274ff0b0075SJouni Malinen }; 1275ff0b0075SJouni Malinen 12768fffd9e5SRishi Panjwani static ssize_t ath6kl_create_qos_write(struct file *file, 12778fffd9e5SRishi Panjwani const char __user *user_buf, 12788fffd9e5SRishi Panjwani size_t count, loff_t *ppos) 12798fffd9e5SRishi Panjwani { 12808fffd9e5SRishi Panjwani 12818fffd9e5SRishi Panjwani struct ath6kl *ar = file->private_data; 1282990bd915SVasanthakumar Thiagarajan struct ath6kl_vif *vif; 12838cb6d991SVasanthakumar Thiagarajan char buf[200]; 12848fffd9e5SRishi Panjwani ssize_t len; 12858fffd9e5SRishi Panjwani char *sptr, *token; 12868fffd9e5SRishi Panjwani struct wmi_create_pstream_cmd pstream; 12878fffd9e5SRishi Panjwani u32 val32; 12888fffd9e5SRishi Panjwani u16 val16; 12898fffd9e5SRishi Panjwani 1290990bd915SVasanthakumar Thiagarajan vif = ath6kl_vif_first(ar); 1291990bd915SVasanthakumar Thiagarajan if (!vif) 1292990bd915SVasanthakumar Thiagarajan return -EIO; 1293990bd915SVasanthakumar Thiagarajan 12948fffd9e5SRishi Panjwani len = min(count, sizeof(buf) - 1); 12958fffd9e5SRishi Panjwani if (copy_from_user(buf, user_buf, len)) 12968fffd9e5SRishi Panjwani return -EFAULT; 12978fffd9e5SRishi Panjwani buf[len] = '\0'; 12988fffd9e5SRishi Panjwani sptr = buf; 12998fffd9e5SRishi Panjwani 13008fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13018fffd9e5SRishi Panjwani if (!token) 13028fffd9e5SRishi Panjwani return -EINVAL; 13038fffd9e5SRishi Panjwani if (kstrtou8(token, 0, &pstream.user_pri)) 13048fffd9e5SRishi Panjwani return -EINVAL; 13058fffd9e5SRishi Panjwani 13068fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13078fffd9e5SRishi Panjwani if (!token) 13088fffd9e5SRishi Panjwani return -EINVAL; 13098fffd9e5SRishi Panjwani if (kstrtou8(token, 0, &pstream.traffic_direc)) 13108fffd9e5SRishi Panjwani return -EINVAL; 13118fffd9e5SRishi Panjwani 13128fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13138fffd9e5SRishi Panjwani if (!token) 13148fffd9e5SRishi Panjwani return -EINVAL; 13158fffd9e5SRishi Panjwani if (kstrtou8(token, 0, &pstream.traffic_class)) 13168fffd9e5SRishi Panjwani return -EINVAL; 13178fffd9e5SRishi Panjwani 13188fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13198fffd9e5SRishi Panjwani if (!token) 13208fffd9e5SRishi Panjwani return -EINVAL; 13218fffd9e5SRishi Panjwani if (kstrtou8(token, 0, &pstream.traffic_type)) 13228fffd9e5SRishi Panjwani return -EINVAL; 13238fffd9e5SRishi Panjwani 13248fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13258fffd9e5SRishi Panjwani if (!token) 13268fffd9e5SRishi Panjwani return -EINVAL; 13278fffd9e5SRishi Panjwani if (kstrtou8(token, 0, &pstream.voice_psc_cap)) 13288fffd9e5SRishi Panjwani return -EINVAL; 13298fffd9e5SRishi Panjwani 13308fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13318fffd9e5SRishi Panjwani if (!token) 13328fffd9e5SRishi Panjwani return -EINVAL; 13338fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 13348fffd9e5SRishi Panjwani return -EINVAL; 13358fffd9e5SRishi Panjwani pstream.min_service_int = cpu_to_le32(val32); 13368fffd9e5SRishi Panjwani 13378fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13388fffd9e5SRishi Panjwani if (!token) 13398fffd9e5SRishi Panjwani return -EINVAL; 13408fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 13418fffd9e5SRishi Panjwani return -EINVAL; 13428fffd9e5SRishi Panjwani pstream.max_service_int = cpu_to_le32(val32); 13438fffd9e5SRishi Panjwani 13448fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13458fffd9e5SRishi Panjwani if (!token) 13468fffd9e5SRishi Panjwani return -EINVAL; 13478fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 13488fffd9e5SRishi Panjwani return -EINVAL; 13498fffd9e5SRishi Panjwani pstream.inactivity_int = cpu_to_le32(val32); 13508fffd9e5SRishi Panjwani 13518fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13528fffd9e5SRishi Panjwani if (!token) 13538fffd9e5SRishi Panjwani return -EINVAL; 13548fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 13558fffd9e5SRishi Panjwani return -EINVAL; 13568fffd9e5SRishi Panjwani pstream.suspension_int = cpu_to_le32(val32); 13578fffd9e5SRishi Panjwani 13588fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13598fffd9e5SRishi Panjwani if (!token) 13608fffd9e5SRishi Panjwani return -EINVAL; 13618fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 13628fffd9e5SRishi Panjwani return -EINVAL; 13638fffd9e5SRishi Panjwani pstream.service_start_time = cpu_to_le32(val32); 13648fffd9e5SRishi Panjwani 13658fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13668fffd9e5SRishi Panjwani if (!token) 13678fffd9e5SRishi Panjwani return -EINVAL; 13688fffd9e5SRishi Panjwani if (kstrtou8(token, 0, &pstream.tsid)) 13698fffd9e5SRishi Panjwani return -EINVAL; 13708fffd9e5SRishi Panjwani 13718fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13728fffd9e5SRishi Panjwani if (!token) 13738fffd9e5SRishi Panjwani return -EINVAL; 13748fffd9e5SRishi Panjwani if (kstrtou16(token, 0, &val16)) 13758fffd9e5SRishi Panjwani return -EINVAL; 13768fffd9e5SRishi Panjwani pstream.nominal_msdu = cpu_to_le16(val16); 13778fffd9e5SRishi Panjwani 13788fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13798fffd9e5SRishi Panjwani if (!token) 13808fffd9e5SRishi Panjwani return -EINVAL; 13818fffd9e5SRishi Panjwani if (kstrtou16(token, 0, &val16)) 13828fffd9e5SRishi Panjwani return -EINVAL; 13838fffd9e5SRishi Panjwani pstream.max_msdu = cpu_to_le16(val16); 13848fffd9e5SRishi Panjwani 13858fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13868fffd9e5SRishi Panjwani if (!token) 13878fffd9e5SRishi Panjwani return -EINVAL; 13888fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 13898fffd9e5SRishi Panjwani return -EINVAL; 13908fffd9e5SRishi Panjwani pstream.min_data_rate = cpu_to_le32(val32); 13918fffd9e5SRishi Panjwani 13928fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 13938fffd9e5SRishi Panjwani if (!token) 13948fffd9e5SRishi Panjwani return -EINVAL; 13958fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 13968fffd9e5SRishi Panjwani return -EINVAL; 13978fffd9e5SRishi Panjwani pstream.mean_data_rate = cpu_to_le32(val32); 13988fffd9e5SRishi Panjwani 13998fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14008fffd9e5SRishi Panjwani if (!token) 14018fffd9e5SRishi Panjwani return -EINVAL; 14028fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14038fffd9e5SRishi Panjwani return -EINVAL; 14048fffd9e5SRishi Panjwani pstream.peak_data_rate = cpu_to_le32(val32); 14058fffd9e5SRishi Panjwani 14068fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14078fffd9e5SRishi Panjwani if (!token) 14088fffd9e5SRishi Panjwani return -EINVAL; 14098fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14108fffd9e5SRishi Panjwani return -EINVAL; 14118fffd9e5SRishi Panjwani pstream.max_burst_size = cpu_to_le32(val32); 14128fffd9e5SRishi Panjwani 14138fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14148fffd9e5SRishi Panjwani if (!token) 14158fffd9e5SRishi Panjwani return -EINVAL; 14168fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14178fffd9e5SRishi Panjwani return -EINVAL; 14188fffd9e5SRishi Panjwani pstream.delay_bound = cpu_to_le32(val32); 14198fffd9e5SRishi Panjwani 14208fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14218fffd9e5SRishi Panjwani if (!token) 14228fffd9e5SRishi Panjwani return -EINVAL; 14238fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14248fffd9e5SRishi Panjwani return -EINVAL; 14258fffd9e5SRishi Panjwani pstream.min_phy_rate = cpu_to_le32(val32); 14268fffd9e5SRishi Panjwani 14278fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14288fffd9e5SRishi Panjwani if (!token) 14298fffd9e5SRishi Panjwani return -EINVAL; 14308fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14318fffd9e5SRishi Panjwani return -EINVAL; 14328fffd9e5SRishi Panjwani pstream.sba = cpu_to_le32(val32); 14338fffd9e5SRishi Panjwani 14348fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14358fffd9e5SRishi Panjwani if (!token) 14368fffd9e5SRishi Panjwani return -EINVAL; 14378fffd9e5SRishi Panjwani if (kstrtou32(token, 0, &val32)) 14388fffd9e5SRishi Panjwani return -EINVAL; 14398fffd9e5SRishi Panjwani pstream.medium_time = cpu_to_le32(val32); 14408fffd9e5SRishi Panjwani 1441240d2799SVasanthakumar Thiagarajan ath6kl_wmi_create_pstream_cmd(ar->wmi, vif->fw_vif_idx, &pstream); 14428fffd9e5SRishi Panjwani 14438fffd9e5SRishi Panjwani return count; 14448fffd9e5SRishi Panjwani } 14458fffd9e5SRishi Panjwani 14468fffd9e5SRishi Panjwani static const struct file_operations fops_create_qos = { 14478fffd9e5SRishi Panjwani .write = ath6kl_create_qos_write, 14488fffd9e5SRishi Panjwani .open = ath6kl_debugfs_open, 14498fffd9e5SRishi Panjwani .owner = THIS_MODULE, 14508fffd9e5SRishi Panjwani .llseek = default_llseek, 14518fffd9e5SRishi Panjwani }; 14528fffd9e5SRishi Panjwani 14538fffd9e5SRishi Panjwani static ssize_t ath6kl_delete_qos_write(struct file *file, 14548fffd9e5SRishi Panjwani const char __user *user_buf, 14558fffd9e5SRishi Panjwani size_t count, loff_t *ppos) 14568fffd9e5SRishi Panjwani { 14578fffd9e5SRishi Panjwani 14588fffd9e5SRishi Panjwani struct ath6kl *ar = file->private_data; 1459990bd915SVasanthakumar Thiagarajan struct ath6kl_vif *vif; 14608fffd9e5SRishi Panjwani char buf[100]; 14618fffd9e5SRishi Panjwani ssize_t len; 14628fffd9e5SRishi Panjwani char *sptr, *token; 14638fffd9e5SRishi Panjwani u8 traffic_class; 14648fffd9e5SRishi Panjwani u8 tsid; 14658fffd9e5SRishi Panjwani 1466990bd915SVasanthakumar Thiagarajan vif = ath6kl_vif_first(ar); 1467990bd915SVasanthakumar Thiagarajan if (!vif) 1468990bd915SVasanthakumar Thiagarajan return -EIO; 1469990bd915SVasanthakumar Thiagarajan 14708fffd9e5SRishi Panjwani len = min(count, sizeof(buf) - 1); 14718fffd9e5SRishi Panjwani if (copy_from_user(buf, user_buf, len)) 14728fffd9e5SRishi Panjwani return -EFAULT; 14738fffd9e5SRishi Panjwani buf[len] = '\0'; 14748fffd9e5SRishi Panjwani sptr = buf; 14758fffd9e5SRishi Panjwani 14768fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14778fffd9e5SRishi Panjwani if (!token) 14788fffd9e5SRishi Panjwani return -EINVAL; 14798fffd9e5SRishi Panjwani if (kstrtou8(token, 0, &traffic_class)) 14808fffd9e5SRishi Panjwani return -EINVAL; 14818fffd9e5SRishi Panjwani 14828fffd9e5SRishi Panjwani token = strsep(&sptr, " "); 14838fffd9e5SRishi Panjwani if (!token) 14848fffd9e5SRishi Panjwani return -EINVAL; 14858fffd9e5SRishi Panjwani if (kstrtou8(token, 0, &tsid)) 14868fffd9e5SRishi Panjwani return -EINVAL; 14878fffd9e5SRishi Panjwani 1488240d2799SVasanthakumar Thiagarajan ath6kl_wmi_delete_pstream_cmd(ar->wmi, vif->fw_vif_idx, 1489240d2799SVasanthakumar Thiagarajan traffic_class, tsid); 14908fffd9e5SRishi Panjwani 14918fffd9e5SRishi Panjwani return count; 14928fffd9e5SRishi Panjwani } 14938fffd9e5SRishi Panjwani 14948fffd9e5SRishi Panjwani static const struct file_operations fops_delete_qos = { 14958fffd9e5SRishi Panjwani .write = ath6kl_delete_qos_write, 14968fffd9e5SRishi Panjwani .open = ath6kl_debugfs_open, 14978fffd9e5SRishi Panjwani .owner = THIS_MODULE, 14988fffd9e5SRishi Panjwani .llseek = default_llseek, 14998fffd9e5SRishi Panjwani }; 15008fffd9e5SRishi Panjwani 1501116b3a2eSRishi Panjwani static ssize_t ath6kl_bgscan_int_write(struct file *file, 1502116b3a2eSRishi Panjwani const char __user *user_buf, 1503116b3a2eSRishi Panjwani size_t count, loff_t *ppos) 1504116b3a2eSRishi Panjwani { 1505116b3a2eSRishi Panjwani struct ath6kl *ar = file->private_data; 1506116b3a2eSRishi Panjwani u16 bgscan_int; 1507116b3a2eSRishi Panjwani char buf[32]; 1508116b3a2eSRishi Panjwani ssize_t len; 1509116b3a2eSRishi Panjwani 1510116b3a2eSRishi Panjwani len = min(count, sizeof(buf) - 1); 1511116b3a2eSRishi Panjwani if (copy_from_user(buf, user_buf, len)) 1512116b3a2eSRishi Panjwani return -EFAULT; 1513116b3a2eSRishi Panjwani 1514116b3a2eSRishi Panjwani buf[len] = '\0'; 1515116b3a2eSRishi Panjwani if (kstrtou16(buf, 0, &bgscan_int)) 1516116b3a2eSRishi Panjwani return -EINVAL; 1517116b3a2eSRishi Panjwani 1518116b3a2eSRishi Panjwani if (bgscan_int == 0) 1519116b3a2eSRishi Panjwani bgscan_int = 0xffff; 1520116b3a2eSRishi Panjwani 1521334234b5SVasanthakumar Thiagarajan ath6kl_wmi_scanparams_cmd(ar->wmi, 0, 0, 0, bgscan_int, 0, 0, 0, 3, 1522116b3a2eSRishi Panjwani 0, 0, 0); 1523116b3a2eSRishi Panjwani 1524116b3a2eSRishi Panjwani return count; 1525116b3a2eSRishi Panjwani } 1526116b3a2eSRishi Panjwani 1527116b3a2eSRishi Panjwani static const struct file_operations fops_bgscan_int = { 1528116b3a2eSRishi Panjwani .write = ath6kl_bgscan_int_write, 1529116b3a2eSRishi Panjwani .open = ath6kl_debugfs_open, 1530116b3a2eSRishi Panjwani .owner = THIS_MODULE, 1531116b3a2eSRishi Panjwani .llseek = default_llseek, 1532116b3a2eSRishi Panjwani }; 1533116b3a2eSRishi Panjwani 1534ef8f0ebaSRishi Panjwani static ssize_t ath6kl_listen_int_write(struct file *file, 1535ef8f0ebaSRishi Panjwani const char __user *user_buf, 1536ef8f0ebaSRishi Panjwani size_t count, loff_t *ppos) 1537ef8f0ebaSRishi Panjwani { 1538ef8f0ebaSRishi Panjwani struct ath6kl *ar = file->private_data; 15398232736dSSujith Manoharan struct ath6kl_vif *vif; 15408232736dSSujith Manoharan u16 listen_interval; 1541ef8f0ebaSRishi Panjwani char buf[32]; 1542ef8f0ebaSRishi Panjwani ssize_t len; 1543ef8f0ebaSRishi Panjwani 15448232736dSSujith Manoharan vif = ath6kl_vif_first(ar); 15458232736dSSujith Manoharan if (!vif) 15468232736dSSujith Manoharan return -EIO; 15478232736dSSujith Manoharan 1548ef8f0ebaSRishi Panjwani len = min(count, sizeof(buf) - 1); 1549ef8f0ebaSRishi Panjwani if (copy_from_user(buf, user_buf, len)) 1550ef8f0ebaSRishi Panjwani return -EFAULT; 1551ef8f0ebaSRishi Panjwani 1552ef8f0ebaSRishi Panjwani buf[len] = '\0'; 15538232736dSSujith Manoharan if (kstrtou16(buf, 0, &listen_interval)) 1554ef8f0ebaSRishi Panjwani return -EINVAL; 1555ef8f0ebaSRishi Panjwani 15568232736dSSujith Manoharan if ((listen_interval < 1) || (listen_interval > 50)) 1557ef8f0ebaSRishi Panjwani return -EINVAL; 1558ef8f0ebaSRishi Panjwani 15598232736dSSujith Manoharan ar->listen_intvl_b = listen_interval; 15608232736dSSujith Manoharan ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, 0, 1561ef8f0ebaSRishi Panjwani ar->listen_intvl_b); 1562ef8f0ebaSRishi Panjwani 1563ef8f0ebaSRishi Panjwani return count; 1564ef8f0ebaSRishi Panjwani } 1565ef8f0ebaSRishi Panjwani 1566ef8f0ebaSRishi Panjwani static ssize_t ath6kl_listen_int_read(struct file *file, 1567ef8f0ebaSRishi Panjwani char __user *user_buf, 1568ef8f0ebaSRishi Panjwani size_t count, loff_t *ppos) 1569ef8f0ebaSRishi Panjwani { 1570ef8f0ebaSRishi Panjwani struct ath6kl *ar = file->private_data; 157150553c2cSDan Carpenter char buf[32]; 1572ef8f0ebaSRishi Panjwani int len; 1573ef8f0ebaSRishi Panjwani 15748232736dSSujith Manoharan len = scnprintf(buf, sizeof(buf), "%u\n", ar->listen_intvl_b); 1575ef8f0ebaSRishi Panjwani 1576ef8f0ebaSRishi Panjwani return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1577ef8f0ebaSRishi Panjwani } 1578ef8f0ebaSRishi Panjwani 1579ef8f0ebaSRishi Panjwani static const struct file_operations fops_listen_int = { 1580ef8f0ebaSRishi Panjwani .read = ath6kl_listen_int_read, 1581ef8f0ebaSRishi Panjwani .write = ath6kl_listen_int_write, 1582ef8f0ebaSRishi Panjwani .open = ath6kl_debugfs_open, 1583ef8f0ebaSRishi Panjwani .owner = THIS_MODULE, 1584ef8f0ebaSRishi Panjwani .llseek = default_llseek, 1585ef8f0ebaSRishi Panjwani }; 1586ef8f0ebaSRishi Panjwani 1587a24fc7c3SRishi Panjwani static ssize_t ath6kl_power_params_write(struct file *file, 1588a24fc7c3SRishi Panjwani const char __user *user_buf, 1589a24fc7c3SRishi Panjwani size_t count, loff_t *ppos) 1590a24fc7c3SRishi Panjwani { 1591a24fc7c3SRishi Panjwani struct ath6kl *ar = file->private_data; 1592a24fc7c3SRishi Panjwani u8 buf[100]; 1593a24fc7c3SRishi Panjwani unsigned int len = 0; 1594a24fc7c3SRishi Panjwani char *sptr, *token; 1595a24fc7c3SRishi Panjwani u16 idle_period, ps_poll_num, dtim, 1596a24fc7c3SRishi Panjwani tx_wakeup, num_tx; 1597a24fc7c3SRishi Panjwani 1598a24fc7c3SRishi Panjwani len = min(count, sizeof(buf) - 1); 1599a24fc7c3SRishi Panjwani if (copy_from_user(buf, user_buf, len)) 1600a24fc7c3SRishi Panjwani return -EFAULT; 1601a24fc7c3SRishi Panjwani buf[len] = '\0'; 1602a24fc7c3SRishi Panjwani sptr = buf; 1603a24fc7c3SRishi Panjwani 1604a24fc7c3SRishi Panjwani token = strsep(&sptr, " "); 1605a24fc7c3SRishi Panjwani if (!token) 1606a24fc7c3SRishi Panjwani return -EINVAL; 1607a24fc7c3SRishi Panjwani if (kstrtou16(token, 0, &idle_period)) 1608a24fc7c3SRishi Panjwani return -EINVAL; 1609a24fc7c3SRishi Panjwani 1610a24fc7c3SRishi Panjwani token = strsep(&sptr, " "); 1611a24fc7c3SRishi Panjwani if (!token) 1612a24fc7c3SRishi Panjwani return -EINVAL; 1613a24fc7c3SRishi Panjwani if (kstrtou16(token, 0, &ps_poll_num)) 1614a24fc7c3SRishi Panjwani return -EINVAL; 1615a24fc7c3SRishi Panjwani 1616a24fc7c3SRishi Panjwani token = strsep(&sptr, " "); 1617a24fc7c3SRishi Panjwani if (!token) 1618a24fc7c3SRishi Panjwani return -EINVAL; 1619a24fc7c3SRishi Panjwani if (kstrtou16(token, 0, &dtim)) 1620a24fc7c3SRishi Panjwani return -EINVAL; 1621a24fc7c3SRishi Panjwani 1622a24fc7c3SRishi Panjwani token = strsep(&sptr, " "); 1623a24fc7c3SRishi Panjwani if (!token) 1624a24fc7c3SRishi Panjwani return -EINVAL; 1625a24fc7c3SRishi Panjwani if (kstrtou16(token, 0, &tx_wakeup)) 1626a24fc7c3SRishi Panjwani return -EINVAL; 1627a24fc7c3SRishi Panjwani 1628a24fc7c3SRishi Panjwani token = strsep(&sptr, " "); 1629a24fc7c3SRishi Panjwani if (!token) 1630a24fc7c3SRishi Panjwani return -EINVAL; 1631a24fc7c3SRishi Panjwani if (kstrtou16(token, 0, &num_tx)) 1632a24fc7c3SRishi Panjwani return -EINVAL; 1633a24fc7c3SRishi Panjwani 1634a24fc7c3SRishi Panjwani ath6kl_wmi_pmparams_cmd(ar->wmi, 0, idle_period, ps_poll_num, 1635a24fc7c3SRishi Panjwani dtim, tx_wakeup, num_tx, 0); 1636a24fc7c3SRishi Panjwani 1637a24fc7c3SRishi Panjwani return count; 1638a24fc7c3SRishi Panjwani } 1639a24fc7c3SRishi Panjwani 1640a24fc7c3SRishi Panjwani static const struct file_operations fops_power_params = { 1641a24fc7c3SRishi Panjwani .write = ath6kl_power_params_write, 1642a24fc7c3SRishi Panjwani .open = ath6kl_debugfs_open, 1643a24fc7c3SRishi Panjwani .owner = THIS_MODULE, 1644a24fc7c3SRishi Panjwani .llseek = default_llseek, 1645a24fc7c3SRishi Panjwani }; 1646a24fc7c3SRishi Panjwani 1647d999ba3eSVasanthakumar Thiagarajan int ath6kl_debug_init(struct ath6kl *ar) 1648d999ba3eSVasanthakumar Thiagarajan { 1649bdf5396bSKalle Valo ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE); 1650bdf5396bSKalle Valo if (ar->debug.fwlog_buf.buf == NULL) 1651bdf5396bSKalle Valo return -ENOMEM; 1652bdf5396bSKalle Valo 1653bdf5396bSKalle Valo ar->debug.fwlog_tmp = kmalloc(ATH6KL_FWLOG_SLOT_SIZE, GFP_KERNEL); 1654bdf5396bSKalle Valo if (ar->debug.fwlog_tmp == NULL) { 1655bdf5396bSKalle Valo vfree(ar->debug.fwlog_buf.buf); 1656bdf5396bSKalle Valo return -ENOMEM; 1657bdf5396bSKalle Valo } 1658bdf5396bSKalle Valo 1659bdf5396bSKalle Valo spin_lock_init(&ar->debug.fwlog_lock); 1660bdf5396bSKalle Valo 1661939f1cceSKalle Valo /* 1662939f1cceSKalle Valo * Actually we are lying here but don't know how to read the mask 1663939f1cceSKalle Valo * value from the firmware. 1664939f1cceSKalle Valo */ 1665939f1cceSKalle Valo ar->debug.fwlog_mask = 0; 1666939f1cceSKalle Valo 1667d999ba3eSVasanthakumar Thiagarajan ar->debugfs_phy = debugfs_create_dir("ath6kl", 1668be98e3a4SVasanthakumar Thiagarajan ar->wiphy->debugfsdir); 1669bdf5396bSKalle Valo if (!ar->debugfs_phy) { 1670bdf5396bSKalle Valo vfree(ar->debug.fwlog_buf.buf); 1671bdf5396bSKalle Valo kfree(ar->debug.fwlog_tmp); 1672d999ba3eSVasanthakumar Thiagarajan return -ENOMEM; 1673bdf5396bSKalle Valo } 1674d999ba3eSVasanthakumar Thiagarajan 167503f68a95SVasanthakumar Thiagarajan debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar, 167603f68a95SVasanthakumar Thiagarajan &fops_tgt_stats); 167703f68a95SVasanthakumar Thiagarajan 167878fc4856SVasanthakumar Thiagarajan debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar, 167978fc4856SVasanthakumar Thiagarajan &fops_credit_dist_stats); 168078fc4856SVasanthakumar Thiagarajan 1681e8091281SJouni Malinen debugfs_create_file("endpoint_stats", S_IRUSR | S_IWUSR, 1682e8091281SJouni Malinen ar->debugfs_phy, ar, &fops_endpoint_stats); 1683e8091281SJouni Malinen 1684bdf5396bSKalle Valo debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar, 1685bdf5396bSKalle Valo &fops_fwlog); 1686bdf5396bSKalle Valo 1687939f1cceSKalle Valo debugfs_create_file("fwlog_mask", S_IRUSR | S_IWUSR, ar->debugfs_phy, 1688939f1cceSKalle Valo ar, &fops_fwlog_mask); 1689939f1cceSKalle Valo 169091d57de5SVasanthakumar Thiagarajan debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar, 169191d57de5SVasanthakumar Thiagarajan &fops_diag_reg_read); 169291d57de5SVasanthakumar Thiagarajan 169391d57de5SVasanthakumar Thiagarajan debugfs_create_file("reg_dump", S_IRUSR, ar->debugfs_phy, ar, 169491d57de5SVasanthakumar Thiagarajan &fops_reg_dump); 169591d57de5SVasanthakumar Thiagarajan 1696e5090444SVivek Natarajan debugfs_create_file("lrssi_roam_threshold", S_IRUSR | S_IWUSR, 1697e5090444SVivek Natarajan ar->debugfs_phy, ar, &fops_lrssi_roam_threshold); 1698252c068bSVasanthakumar Thiagarajan 1699252c068bSVasanthakumar Thiagarajan debugfs_create_file("reg_write", S_IRUSR | S_IWUSR, 1700252c068bSVasanthakumar Thiagarajan ar->debugfs_phy, ar, &fops_diag_reg_write); 1701252c068bSVasanthakumar Thiagarajan 17029a730834SKalle Valo debugfs_create_file("war_stats", S_IRUSR, ar->debugfs_phy, ar, 17039a730834SKalle Valo &fops_war_stats); 17049a730834SKalle Valo 17054b28a80dSJouni Malinen debugfs_create_file("roam_table", S_IRUSR, ar->debugfs_phy, ar, 17064b28a80dSJouni Malinen &fops_roam_table); 17074b28a80dSJouni Malinen 17081261875fSJouni Malinen debugfs_create_file("force_roam", S_IWUSR, ar->debugfs_phy, ar, 17091261875fSJouni Malinen &fops_force_roam); 17101261875fSJouni Malinen 17111261875fSJouni Malinen debugfs_create_file("roam_mode", S_IWUSR, ar->debugfs_phy, ar, 17121261875fSJouni Malinen &fops_roam_mode); 17131261875fSJouni Malinen 1714ff0b0075SJouni Malinen debugfs_create_file("keepalive", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar, 1715ff0b0075SJouni Malinen &fops_keepalive); 1716ff0b0075SJouni Malinen 1717ff0b0075SJouni Malinen debugfs_create_file("disconnect_timeout", S_IRUSR | S_IWUSR, 1718ff0b0075SJouni Malinen ar->debugfs_phy, ar, &fops_disconnect_timeout); 1719ff0b0075SJouni Malinen 17208fffd9e5SRishi Panjwani debugfs_create_file("create_qos", S_IWUSR, ar->debugfs_phy, ar, 17218fffd9e5SRishi Panjwani &fops_create_qos); 17228fffd9e5SRishi Panjwani 17238fffd9e5SRishi Panjwani debugfs_create_file("delete_qos", S_IWUSR, ar->debugfs_phy, ar, 17248fffd9e5SRishi Panjwani &fops_delete_qos); 17258fffd9e5SRishi Panjwani 1726116b3a2eSRishi Panjwani debugfs_create_file("bgscan_interval", S_IWUSR, 1727116b3a2eSRishi Panjwani ar->debugfs_phy, ar, &fops_bgscan_int); 1728116b3a2eSRishi Panjwani 17298232736dSSujith Manoharan debugfs_create_file("listen_interval", S_IRUSR | S_IWUSR, 17308232736dSSujith Manoharan ar->debugfs_phy, ar, &fops_listen_int); 17318232736dSSujith Manoharan 1732a24fc7c3SRishi Panjwani debugfs_create_file("power_params", S_IWUSR, ar->debugfs_phy, ar, 1733a24fc7c3SRishi Panjwani &fops_power_params); 1734a24fc7c3SRishi Panjwani 1735d999ba3eSVasanthakumar Thiagarajan return 0; 1736d999ba3eSVasanthakumar Thiagarajan } 1737bdf5396bSKalle Valo 1738bdf5396bSKalle Valo void ath6kl_debug_cleanup(struct ath6kl *ar) 1739bdf5396bSKalle Valo { 1740bdf5396bSKalle Valo vfree(ar->debug.fwlog_buf.buf); 1741bdf5396bSKalle Valo kfree(ar->debug.fwlog_tmp); 17424b28a80dSJouni Malinen kfree(ar->debug.roam_tbl); 1743bdf5396bSKalle Valo } 1744bdf5396bSKalle Valo 1745bdcd8170SKalle Valo #endif 1746