diff options
Diffstat (limited to 'drivers/net/wireless/ti/wlcore/debugfs.c')
| -rw-r--r-- | drivers/net/wireless/ti/wlcore/debugfs.c | 215 |
1 files changed, 111 insertions, 104 deletions
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index e17630c2a849..bbfd2725215b 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c @@ -1,24 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * This file is part of wl1271 * * Copyright (C) 2009 Nokia Corporation * * Contact: Luciano Coelho <luciano.coelho@nokia.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * */ #include "debugfs.h" @@ -26,6 +12,7 @@ #include <linux/skbuff.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/pm_runtime.h> #include "wlcore.h" #include "debug.h" @@ -65,7 +52,7 @@ void wl1271_debugfs_update_stats(struct wl1271 *wl) if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; - ret = wl1271_ps_elp_wakeup(wl); + ret = pm_runtime_resume_and_get(wl->dev); if (ret < 0) goto out; @@ -76,7 +63,7 @@ void wl1271_debugfs_update_stats(struct wl1271 *wl) wl->stats.fw_stats_update = jiffies; } - wl1271_ps_elp_sleep(wl); + pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -118,21 +105,14 @@ static void chip_op_handler(struct wl1271 *wl, unsigned long value, return; } - ret = wl1271_ps_elp_wakeup(wl); + ret = pm_runtime_resume_and_get(wl->dev); if (ret < 0) return; chip_op = arg; chip_op(wl); - wl1271_ps_elp_sleep(wl); -} - - -static inline void no_write_handler(struct wl1271 *wl, - unsigned long value, - unsigned long param) -{ + pm_runtime_put_autosuspend(wl->dev); } #define WL12XX_CONF_DEBUGFS(param, conf_sub_struct, \ @@ -281,7 +261,7 @@ static ssize_t dynamic_ps_timeout_write(struct file *file, } if (value < 1 || value > 65535) { - wl1271_warning("dyanmic_ps_timeout is not in valid range"); + wl1271_warning("dynamic_ps_timeout is not in valid range"); return -ERANGE; } @@ -292,7 +272,7 @@ static ssize_t dynamic_ps_timeout_write(struct file *file, if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; - ret = wl1271_ps_elp_wakeup(wl); + ret = pm_runtime_resume_and_get(wl->dev); if (ret < 0) goto out; @@ -305,7 +285,7 @@ static ssize_t dynamic_ps_timeout_write(struct file *file, wl1271_ps_set_mode(wl, wlvif, STATION_AUTO_PS_MODE); } - wl1271_ps_elp_sleep(wl); + pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -359,7 +339,7 @@ static ssize_t forced_ps_write(struct file *file, if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; - ret = wl1271_ps_elp_wakeup(wl); + ret = pm_runtime_resume_and_get(wl->dev); if (ret < 0) goto out; @@ -374,7 +354,7 @@ static ssize_t forced_ps_write(struct file *file, wl1271_ps_set_mode(wl, wlvif, ps_mode); } - wl1271_ps_elp_sleep(wl); + pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -437,6 +417,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, int res = 0; ssize_t ret; char *buf; + struct wl12xx_vif *wlvif; #define DRIVER_STATE_BUF_LEN 1024 @@ -450,12 +431,28 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, (res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\ #x " = " fmt "\n", wl->x)) +#define DRIVER_STATE_PRINT_GENERIC(x, fmt, args...) \ + (res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\ + #x " = " fmt "\n", args)) + #define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld") #define DRIVER_STATE_PRINT_INT(x) DRIVER_STATE_PRINT(x, "%d") #define DRIVER_STATE_PRINT_STR(x) DRIVER_STATE_PRINT(x, "%s") #define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx") #define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x") + wl12xx_for_each_wlvif_sta(wl, wlvif) { + if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) + continue; + + DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel, + wlvif->p2p ? "P2P-CL" : "STA"); + } + + wl12xx_for_each_wlvif_ap(wl, wlvif) + DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel, + wlvif->p2p ? "P2P-GO" : "AP"); + DRIVER_STATE_PRINT_INT(tx_blocks_available); DRIVER_STATE_PRINT_INT(tx_allocated_blocks); DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]); @@ -474,19 +471,18 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(tx_blocks_freed); DRIVER_STATE_PRINT_INT(rx_counter); DRIVER_STATE_PRINT_INT(state); - DRIVER_STATE_PRINT_INT(channel); DRIVER_STATE_PRINT_INT(band); DRIVER_STATE_PRINT_INT(power_level); DRIVER_STATE_PRINT_INT(sg_enabled); DRIVER_STATE_PRINT_INT(enable_11a); DRIVER_STATE_PRINT_INT(noise); - DRIVER_STATE_PRINT_HEX(ap_fw_ps_map); + DRIVER_STATE_PRINT_LHEX(ap_fw_ps_map); DRIVER_STATE_PRINT_LHEX(ap_ps_map); DRIVER_STATE_PRINT_HEX(quirks); DRIVER_STATE_PRINT_HEX(irq); /* TODO: ref_clock and tcxo_clock were moved to wl12xx priv */ DRIVER_STATE_PRINT_HEX(hw_pg_ver); - DRIVER_STATE_PRINT_HEX(platform_quirks); + DRIVER_STATE_PRINT_HEX(irq_flags); DRIVER_STATE_PRINT_HEX(chip.id); DRIVER_STATE_PRINT_STR(chip.fw_ver_str); DRIVER_STATE_PRINT_STR(chip.phy_fw_ver_str); @@ -822,7 +818,7 @@ static ssize_t rx_streaming_interval_write(struct file *file, wl->conf.rx_streaming.interval = value; - ret = wl1271_ps_elp_wakeup(wl); + ret = pm_runtime_resume_and_get(wl->dev); if (ret < 0) goto out; @@ -830,7 +826,7 @@ static ssize_t rx_streaming_interval_write(struct file *file, wl1271_recalc_rx_streaming(wl, wlvif); } - wl1271_ps_elp_sleep(wl); + pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); return count; @@ -877,7 +873,7 @@ static ssize_t rx_streaming_always_write(struct file *file, wl->conf.rx_streaming.always = value; - ret = wl1271_ps_elp_wakeup(wl); + ret = pm_runtime_resume_and_get(wl->dev); if (ret < 0) goto out; @@ -885,7 +881,7 @@ static ssize_t rx_streaming_always_write(struct file *file, wl1271_recalc_rx_streaming(wl, wlvif); } - wl1271_ps_elp_sleep(wl); + pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); return count; @@ -913,17 +909,10 @@ static ssize_t beacon_filtering_write(struct file *file, { struct wl1271 *wl = file->private_data; struct wl12xx_vif *wlvif; - char buf[10]; - size_t len; unsigned long value; int ret; - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - buf[len] = '\0'; - - ret = kstrtoul(buf, 0, &value); + ret = kstrtoul_from_user(user_buf, count, 0, &value); if (ret < 0) { wl1271_warning("illegal value for beacon_filtering!"); return -EINVAL; @@ -931,7 +920,7 @@ static ssize_t beacon_filtering_write(struct file *file, mutex_lock(&wl->mutex); - ret = wl1271_ps_elp_wakeup(wl); + ret = pm_runtime_resume_and_get(wl->dev); if (ret < 0) goto out; @@ -939,7 +928,7 @@ static ssize_t beacon_filtering_write(struct file *file, ret = wl1271_acx_beacon_filter_opt(wl, wlvif, !!value); } - wl1271_ps_elp_sleep(wl); + pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); return count; @@ -1010,7 +999,7 @@ static ssize_t sleep_auth_write(struct file *file, goto out; } - ret = wl1271_ps_elp_wakeup(wl); + ret = pm_runtime_resume_and_get(wl->dev); if (ret < 0) goto out; @@ -1019,7 +1008,7 @@ static ssize_t sleep_auth_write(struct file *file, goto out_sleep; out_sleep: - wl1271_ps_elp_sleep(wl); + pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); return count; @@ -1074,7 +1063,7 @@ static ssize_t dev_mem_read(struct file *file, * Don't fail if elp_wakeup returns an error, so the device's memory * could be read even if the FW crashed */ - wl1271_ps_elp_wakeup(wl); + pm_runtime_get_sync(wl->dev); /* store current partition and switch partition */ memcpy(&old_part, &wl->curr_part, sizeof(old_part)); @@ -1093,7 +1082,7 @@ read_err: goto part_err; part_err: - wl1271_ps_elp_sleep(wl); + pm_runtime_put_autosuspend(wl->dev); skip_read: mutex_unlock(&wl->mutex); @@ -1140,15 +1129,9 @@ static ssize_t dev_mem_write(struct file *file, const char __user *user_buf, part.mem.start = *ppos; part.mem.size = bytes; - buf = kmalloc(bytes, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - ret = copy_from_user(buf, user_buf, bytes); - if (ret) { - ret = -EFAULT; - goto err_out; - } + buf = memdup_user(user_buf, bytes); + if (IS_ERR(buf)) + return PTR_ERR(buf); mutex_lock(&wl->mutex); @@ -1161,7 +1144,7 @@ static ssize_t dev_mem_write(struct file *file, const char __user *user_buf, * Don't fail if elp_wakeup returns an error, so the device's memory * could be read even if the FW crashed */ - wl1271_ps_elp_wakeup(wl); + pm_runtime_get_sync(wl->dev); /* store current partition and switch partition */ memcpy(&old_part, &wl->curr_part, sizeof(old_part)); @@ -1180,7 +1163,7 @@ write_err: goto part_err; part_err: - wl1271_ps_elp_sleep(wl); + pm_runtime_put_autosuspend(wl->dev); skip_write: mutex_unlock(&wl->mutex); @@ -1188,7 +1171,6 @@ skip_write: if (ret == 0) *ppos += bytes; -err_out: kfree(buf); return ((ret == 0) ? bytes : ret); @@ -1196,26 +1178,11 @@ err_out: static loff_t dev_mem_seek(struct file *file, loff_t offset, int orig) { - loff_t ret; - /* only requests of dword-aligned size and offset are supported */ if (offset % 4) return -EINVAL; - switch (orig) { - case SEEK_SET: - file->f_pos = offset; - ret = file->f_pos; - break; - case SEEK_CUR: - file->f_pos += offset; - ret = file->f_pos; - break; - default: - ret = -EINVAL; - } - - return ret; + return no_seek_end_llseek(file, offset, orig); } static const struct file_operations dev_mem_ops = { @@ -1225,11 +1192,69 @@ static const struct file_operations dev_mem_ops = { .llseek = dev_mem_seek, }; -static int wl1271_debugfs_add_files(struct wl1271 *wl, - struct dentry *rootdir) +static ssize_t fw_logger_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct wl1271 *wl = file->private_data; + + return wl1271_format_buffer(user_buf, count, + ppos, "%d\n", + wl->conf.fwlog.output); +} + +static ssize_t fw_logger_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct wl1271 *wl = file->private_data; + unsigned long value; + int ret; + + ret = kstrtoul_from_user(user_buf, count, 0, &value); + if (ret < 0) { + wl1271_warning("illegal value in fw_logger"); + return -EINVAL; + } + + if ((value > 2) || (value == 0)) { + wl1271_warning("fw_logger value must be 1-UART 2-SDIO"); + return -ERANGE; + } + + if (wl->conf.fwlog.output == 0) { + wl1271_warning("invalid operation - fw logger disabled by default, please change mode via wlconf"); + return -EINVAL; + } + + mutex_lock(&wl->mutex); + ret = pm_runtime_resume_and_get(wl->dev); + if (ret < 0) { + count = ret; + goto out; + } + + wl->conf.fwlog.output = value; + + ret = wl12xx_cmd_config_fwlog(wl); + + pm_runtime_put_autosuspend(wl->dev); + +out: + mutex_unlock(&wl->mutex); + return count; +} + +static const struct file_operations fw_logger_ops = { + .open = simple_open, + .read = fw_logger_read, + .write = fw_logger_write, + .llseek = default_llseek, +}; + +static void wl1271_debugfs_add_files(struct wl1271 *wl, + struct dentry *rootdir) { - int ret = 0; - struct dentry *entry, *streaming; + struct dentry *streaming; DEBUGFS_ADD(tx_queue_len, rootdir); DEBUGFS_ADD(retry_count, rootdir); @@ -1251,25 +1276,14 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, DEBUGFS_ADD(irq_timeout, rootdir); DEBUGFS_ADD(fw_stats_raw, rootdir); DEBUGFS_ADD(sleep_auth, rootdir); + DEBUGFS_ADD(fw_logger, rootdir); streaming = debugfs_create_dir("rx_streaming", rootdir); - if (!streaming || IS_ERR(streaming)) - goto err; DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming); DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming); DEBUGFS_ADD_PREFIX(dev, mem, rootdir); - - return 0; - -err: - if (IS_ERR(entry)) - ret = PTR_ERR(entry); - else - ret = -ENOMEM; - - return ret; } void wl1271_debugfs_reset(struct wl1271 *wl) @@ -1290,11 +1304,6 @@ int wl1271_debugfs_init(struct wl1271 *wl) rootdir = debugfs_create_dir(KBUILD_MODNAME, wl->hw->wiphy->debugfsdir); - if (IS_ERR(rootdir)) { - ret = PTR_ERR(rootdir); - goto out; - } - wl->stats.fw_stats = kzalloc(wl->stats.fw_stats_len, GFP_KERNEL); if (!wl->stats.fw_stats) { ret = -ENOMEM; @@ -1303,9 +1312,7 @@ int wl1271_debugfs_init(struct wl1271 *wl) wl->stats.fw_stats_update = jiffies; - ret = wl1271_debugfs_add_files(wl, rootdir); - if (ret < 0) - goto out_exit; + wl1271_debugfs_add_files(wl, rootdir); ret = wlcore_debugfs_init(wl, rootdir); if (ret < 0) |
