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 = container_of((void *)vif_priv,
  37                                   struct ieee80211_vif,
  38                                   drv_priv);
  39                        if (NL80211_IFTYPE_STATION == vif->type) {
  40                                if (vif_priv->pw_state == WCN36XX_BMPS)
  41                                        buf[0] = '1';
  42                                else
  43                                        buf[0] = '0';
  44                                break;
  45                        }
  46        }
  47        buf[1] = '\n';
  48        buf[2] = 0x00;
  49
  50        return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
  51}
  52
  53static ssize_t write_file_bool_bmps(struct file *file,
  54                                    const char __user *user_buf,
  55                                    size_t count, loff_t *ppos)
  56{
  57        struct wcn36xx *wcn = file->private_data;
  58        struct wcn36xx_vif *vif_priv = NULL;
  59        struct ieee80211_vif *vif = NULL;
  60
  61        char buf[32];
  62        int buf_size;
  63
  64        buf_size = min(count, (sizeof(buf)-1));
  65        if (copy_from_user(buf, user_buf, buf_size))
  66                return -EFAULT;
  67
  68        switch (buf[0]) {
  69        case 'y':
  70        case 'Y':
  71        case '1':
  72                list_for_each_entry(vif_priv, &wcn->vif_list, list) {
  73                        vif = container_of((void *)vif_priv,
  74                                   struct ieee80211_vif,
  75                                   drv_priv);
  76                        if (NL80211_IFTYPE_STATION == vif->type) {
  77                                wcn36xx_enable_keep_alive_null_packet(wcn, vif);
  78                                wcn36xx_pmc_enter_bmps_state(wcn, vif);
  79                        }
  80                }
  81                break;
  82        case 'n':
  83        case 'N':
  84        case '0':
  85                list_for_each_entry(vif_priv, &wcn->vif_list, list) {
  86                        vif = container_of((void *)vif_priv,
  87                                   struct ieee80211_vif,
  88                                   drv_priv);
  89                        if (NL80211_IFTYPE_STATION == vif->type)
  90                                wcn36xx_pmc_exit_bmps_state(wcn, vif);
  91                }
  92                break;
  93        }
  94
  95        return count;
  96}
  97
  98static const struct file_operations fops_wcn36xx_bmps = {
  99        .open = simple_open,
 100        .read  =       read_file_bool_bmps,
 101        .write =       write_file_bool_bmps,
 102};
 103
 104static ssize_t write_file_dump(struct file *file,
 105                                    const char __user *user_buf,
 106                                    size_t count, loff_t *ppos)
 107{
 108        struct wcn36xx *wcn = file->private_data;
 109        char buf[255], *tmp;
 110        int buf_size;
 111        u32 arg[WCN36xx_MAX_DUMP_ARGS];
 112        int i;
 113
 114        memset(buf, 0, sizeof(buf));
 115        memset(arg, 0, sizeof(arg));
 116
 117        buf_size = min(count, (sizeof(buf) - 1));
 118        if (copy_from_user(buf, user_buf, buf_size))
 119                return -EFAULT;
 120
 121        tmp = buf;
 122
 123        for (i = 0; i < WCN36xx_MAX_DUMP_ARGS; i++) {
 124                char *begin;
 125                begin = strsep(&tmp, " ");
 126                if (begin == NULL)
 127                        break;
 128
 129                if (kstrtou32(begin, 0, &arg[i]) != 0)
 130                        break;
 131        }
 132
 133        wcn36xx_info("DUMP args is %d %d %d %d %d\n", arg[0], arg[1], arg[2],
 134                     arg[3], arg[4]);
 135        wcn36xx_smd_dump_cmd_req(wcn, arg[0], arg[1], arg[2], arg[3], arg[4]);
 136
 137        return count;
 138}
 139
 140static const struct file_operations fops_wcn36xx_dump = {
 141        .open = simple_open,
 142        .write =       write_file_dump,
 143};
 144
 145#define ADD_FILE(name, mode, fop, priv_data)            \
 146        do {                                                    \
 147                struct dentry *d;                               \
 148                d = debugfs_create_file(__stringify(name),      \
 149                                        mode, dfs->rootdir,     \
 150                                        priv_data, fop);        \
 151                dfs->file_##name.dentry = d;                    \
 152                if (IS_ERR(d)) {                                \
 153                        wcn36xx_warn("Create the debugfs entry failed");\
 154                        dfs->file_##name.dentry = NULL;         \
 155                }                                               \
 156        } while (0)
 157
 158
 159void wcn36xx_debugfs_init(struct wcn36xx *wcn)
 160{
 161        struct wcn36xx_dfs_entry *dfs = &wcn->dfs;
 162
 163        dfs->rootdir = debugfs_create_dir(KBUILD_MODNAME,
 164                                          wcn->hw->wiphy->debugfsdir);
 165        if (IS_ERR(dfs->rootdir)) {
 166                wcn36xx_warn("Create the debugfs failed\n");
 167                dfs->rootdir = NULL;
 168        }
 169
 170        ADD_FILE(bmps_switcher, S_IRUSR | S_IWUSR,
 171                 &fops_wcn36xx_bmps, wcn);
 172        ADD_FILE(dump, S_IWUSR, &fops_wcn36xx_dump, wcn);
 173}
 174
 175void wcn36xx_debugfs_exit(struct wcn36xx *wcn)
 176{
 177        struct wcn36xx_dfs_entry *dfs = &wcn->dfs;
 178        debugfs_remove_recursive(dfs->rootdir);
 179}
 180
 181#endif /* CONFIG_WCN36XX_DEBUGFS */
 182