brintos

brintos / linux-shallow public Read only

0
0
Text · 5.4 KiB · 58b3c05 Raw
214 lines · c
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 any5 * purpose with or without fee is hereby granted, provided that the above6 * copyright notice and this permission notice appear in all copies.7 *8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.15 */16 17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt18 19#include <linux/debugfs.h>20#include <linux/uaccess.h>21#include "wcn36xx.h"22#include "debug.h"23#include "pmc.h"24#include "firmware.h"25 26#ifdef CONFIG_WCN36XX_DEBUGFS27 28static ssize_t read_file_bool_bmps(struct file *file, char __user *user_buf,29				   size_t count, loff_t *ppos)30{31	struct wcn36xx *wcn = file->private_data;32	struct wcn36xx_vif *vif_priv = NULL;33	struct ieee80211_vif *vif = NULL;34	char buf[3];35 36	list_for_each_entry(vif_priv, &wcn->vif_list, list) {37			vif = wcn36xx_priv_to_vif(vif_priv);38			if (NL80211_IFTYPE_STATION == vif->type) {39				if (vif_priv->pw_state == WCN36XX_BMPS)40					buf[0] = '1';41				else42					buf[0] = '0';43				break;44			}45	}46	buf[1] = '\n';47	buf[2] = 0x00;48 49	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);50}51 52static ssize_t write_file_bool_bmps(struct file *file,53				    const char __user *user_buf,54				    size_t count, loff_t *ppos)55{56	struct wcn36xx *wcn = file->private_data;57	struct wcn36xx_vif *vif_priv = NULL;58	struct ieee80211_vif *vif = NULL;59 60	char buf[32];61	int buf_size;62 63	buf_size = min(count, (sizeof(buf)-1));64	if (copy_from_user(buf, user_buf, buf_size))65		return -EFAULT;66 67	switch (buf[0]) {68	case 'y':69	case 'Y':70	case '1':71		list_for_each_entry(vif_priv, &wcn->vif_list, list) {72			vif = wcn36xx_priv_to_vif(vif_priv);73			if (NL80211_IFTYPE_STATION == vif->type) {74				wcn36xx_enable_keep_alive_null_packet(wcn, vif);75				wcn36xx_pmc_enter_bmps_state(wcn, vif);76			}77		}78		break;79	case 'n':80	case 'N':81	case '0':82		list_for_each_entry(vif_priv, &wcn->vif_list, list) {83			vif = wcn36xx_priv_to_vif(vif_priv);84			if (NL80211_IFTYPE_STATION == vif->type)85				wcn36xx_pmc_exit_bmps_state(wcn, vif);86		}87		break;88	}89 90	return count;91}92 93static const struct file_operations fops_wcn36xx_bmps = {94	.open = simple_open,95	.read  =       read_file_bool_bmps,96	.write =       write_file_bool_bmps,97};98 99static ssize_t write_file_dump(struct file *file,100				    const char __user *user_buf,101				    size_t count, loff_t *ppos)102{103	struct wcn36xx *wcn = file->private_data;104	char buf[255], *tmp;105	int buf_size;106	u32 arg[WCN36xx_MAX_DUMP_ARGS];107	int i;108 109	memset(buf, 0, sizeof(buf));110	memset(arg, 0, sizeof(arg));111 112	buf_size = min(count, (sizeof(buf) - 1));113	if (copy_from_user(buf, user_buf, buf_size))114		return -EFAULT;115 116	tmp = buf;117 118	for (i = 0; i < WCN36xx_MAX_DUMP_ARGS; i++) {119		char *begin;120		begin = strsep(&tmp, " ");121		if (begin == NULL)122			break;123 124		if (kstrtos32(begin, 0, &arg[i]) != 0)125			break;126	}127 128	wcn36xx_info("DUMP args is %d %d %d %d %d\n", arg[0], arg[1], arg[2],129		     arg[3], arg[4]);130	wcn36xx_smd_dump_cmd_req(wcn, arg[0], arg[1], arg[2], arg[3], arg[4]);131 132	return count;133}134 135static const struct file_operations fops_wcn36xx_dump = {136	.open = simple_open,137	.write =       write_file_dump,138};139 140static ssize_t read_file_firmware_feature_caps(struct file *file,141					       char __user *user_buf,142					       size_t count, loff_t *ppos)143{144	struct wcn36xx *wcn = file->private_data;145	size_t len = 0, buf_len = 2048;146	char *buf;147	int i;148	int ret;149 150	buf = kzalloc(buf_len, GFP_KERNEL);151	if (!buf)152		return -ENOMEM;153 154	mutex_lock(&wcn->hal_mutex);155	for (i = 0; i < MAX_FEATURE_SUPPORTED; i++) {156		if (wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, i)) {157			len += scnprintf(buf + len, buf_len - len, "%s\n",158					 wcn36xx_firmware_get_cap_name(i));159		}160		if (len >= buf_len)161			break;162	}163	mutex_unlock(&wcn->hal_mutex);164 165	ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);166	kfree(buf);167 168	return ret;169}170 171static const struct file_operations fops_wcn36xx_firmware_feat_caps = {172	.open = simple_open,173	.read = read_file_firmware_feature_caps,174};175 176#define ADD_FILE(name, mode, fop, priv_data)		\177	do {							\178		struct dentry *d;				\179		d = debugfs_create_file(__stringify(name),	\180					mode, dfs->rootdir,	\181					priv_data, fop);	\182		dfs->file_##name.dentry = d;			\183		if (IS_ERR(d)) {				\184			wcn36xx_warn("Create the debugfs entry failed");\185			dfs->file_##name.dentry = NULL;		\186		}						\187	} while (0)188 189 190void wcn36xx_debugfs_init(struct wcn36xx *wcn)191{192	struct wcn36xx_dfs_entry *dfs = &wcn->dfs;193 194	dfs->rootdir = debugfs_create_dir(KBUILD_MODNAME,195					  wcn->hw->wiphy->debugfsdir);196	if (IS_ERR(dfs->rootdir)) {197		wcn36xx_warn("Create the debugfs failed\n");198		dfs->rootdir = NULL;199	}200 201	ADD_FILE(bmps_switcher, 0600, &fops_wcn36xx_bmps, wcn);202	ADD_FILE(dump, 0200, &fops_wcn36xx_dump, wcn);203	ADD_FILE(firmware_feat_caps, 0200,204		 &fops_wcn36xx_firmware_feat_caps, wcn);205}206 207void wcn36xx_debugfs_exit(struct wcn36xx *wcn)208{209	struct wcn36xx_dfs_entry *dfs = &wcn->dfs;210	debugfs_remove_recursive(dfs->rootdir);211}212 213#endif /* CONFIG_WCN36XX_DEBUGFS */214