linux/drivers/net/wireless/ath/wcn36xx/debug.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16
  17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  18
  19#include <linux/debugfs.h>
  20#include <linux/uaccess.h>
  21#include "wcn36xx.h"
  22#include "debug.h"
  23#include "pmc.h"
  24
  25#ifdef CONFIG_WCN36XX_DEBUGFS
  26
  27static ssize_t read_file_bool_bmps(struct file *file, char __user *user_buf,
  28                                   size_t count, loff_t *ppos)
  29{
  30        struct wcn36xx *wcn = file->private_data;
  31        struct wcn36xx_vif *vif_priv = NULL;
  32        struct ieee80211_vif *vif = NULL;
  33        char buf[3];
  34
  35        list_for_each_entry(vif_priv, &wcn->vif_list, list) {
  36                        vif = wcn36xx_priv_to_vif(vif_priv);
  37                        if (NL80211_IFTYPE_STATION == vif->type) {
  38                                if (vif_priv->pw_state == WCN36XX_BMPS)
  39                                        buf[0] = '1';
  40                                else
  41                                        buf[0] = '0';
  42                                break;
  43                        }
  44        }
  45        buf[1] = '\n';
  46        buf[2] = 0x00;
  47
  48        return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
  49}
  50
  51static ssize_t write_file_bool_bmps(struct file *file,
  52                                    const char __user *user_buf,
  53                                    size_t count, loff_t *ppos)
  54{
  55        struct wcn36xx *wcn = file->private_data;
  56        struct wcn36xx_vif *vif_priv = NULL;
  57        struct ieee80211_vif *vif = NULL;
  58
  59        char buf[32];
  60        int buf_size;
  61
  62        buf_size = min(count, (sizeof(buf)-1));
  63        if (copy_from_user(buf, user_buf, buf_size))
  64                return -EFAULT;
  65
  66        switch (buf[0]) {
  67        case 'y':
  68        case 'Y':
  69        case '1':
  70                list_for_each_entry(vif_priv, &wcn->vif_list, list) {
  71                        vif = wcn36xx_priv_to_vif(vif_priv);
  72                        if (NL80211_IFTYPE_STATION == vif->type) {
  73                                wcn36xx_enable_keep_alive_null_packet(wcn, vif);
  74                                wcn36xx_pmc_enter_bmps_state(wcn, vif);
  75                        }
  76                }
  77                break;
  78        case 'n':
  79        case 'N':
  80        case '0':
  81                list_for_each_entry(vif_priv, &wcn->vif_list, list) {
  82                        vif = wcn36xx_priv_to_vif(vif_priv);
  83                        if (NL80211_IFTYPE_STATION == vif->type)
  84                                wcn36xx_pmc_exit_bmps_state(wcn, vif);
  85                }
  86                break;
  87        }
  88
  89        return count;
  90}
  91
  92static const struct file_operations fops_wcn36xx_bmps = {
  93        .open = simple_open,
  94        .read  =       read_file_bool_bmps,
  95        .write =       write_file_bool_bmps,
  96};
  97
  98static ssize_t write_file_dump(struct file *file,
  99                                    const char __user *user_buf,
 100                                    size_t count, loff_t *ppos)
 101{
 102        struct wcn36xx *wcn = file->private_data;
 103        char buf[255], *tmp;
 104        int buf_size;
 105        u32 arg[WCN36xx_MAX_DUMP_ARGS];
 106        int i;
 107
 108        memset(buf, 0, sizeof(buf));
 109        memset(arg, 0, sizeof(arg));
 110
 111        buf_size = min(count, (sizeof(buf) - 1));
 112        if (copy_from_user(buf, user_buf, buf_size))
 113                return -EFAULT;
 114
 115        tmp = buf;
 116
 117        for (i = 0; i < WCN36xx_MAX_DUMP_ARGS; i++) {
 118                char *begin;
 119                begin = strsep(&tmp, " ");
 120                if (begin == NULL)
 121                        break;
 122
 123                if (kstrtou32(begin, 0, &arg[i]) != 0)
 124                        break;
 125        }
 126
 127        wcn36xx_info("DUMP args is %d %d %d %d %d\n", arg[0], arg[1], arg[2],
 128                     arg[3], arg[4]);
 129        wcn36xx_smd_dump_cmd_req(wcn, arg[0], arg[1], arg[2], arg[3], arg[4]);
 130
 131        return count;
 132}
 133
 134static const struct file_operations fops_wcn36xx_dump = {
 135        .open = simple_open,
 136        .write =       write_file_dump,
 137};
 138
 139#define ADD_FILE(name, mode, fop, priv_data)            \
 140        do {                                                    \
 141                struct dentry *d;                               \
 142                d = debugfs_create_file(__stringify(name),      \
 143                                        mode, dfs->rootdir,     \
 144                                        priv_data, fop);        \
 145                dfs->file_##name.dentry = d;                    \
 146                if (IS_ERR(d)) {                                \
 147                        wcn36xx_warn("Create the debugfs entry failed");\
 148                        dfs->file_##name.dentry = NULL;         \
 149                }                                               \
 150        } while (0)
 151
 152
 153void wcn36xx_debugfs_init(struct wcn36xx *wcn)
 154{
 155        struct wcn36xx_dfs_entry *dfs = &wcn->dfs;
 156
 157        dfs->rootdir = debugfs_create_dir(KBUILD_MODNAME,
 158                                          wcn->hw->wiphy->debugfsdir);
 159        if (IS_ERR(dfs->rootdir)) {
 160                wcn36xx_warn("Create the debugfs failed\n");
 161                dfs->rootdir = NULL;
 162        }
 163
 164        ADD_FILE(bmps_switcher, 0600, &fops_wcn36xx_bmps, wcn);
 165        ADD_FILE(dump, 0200, &fops_wcn36xx_dump, wcn);
 166}
 167
 168void wcn36xx_debugfs_exit(struct wcn36xx *wcn)
 169{
 170        struct wcn36xx_dfs_entry *dfs = &wcn->dfs;
 171        debugfs_remove_recursive(dfs->rootdir);
 172}
 173
 174#endif /* CONFIG_WCN36XX_DEBUGFS */
 175