qcacld-3.0: Create debugfs file for crash_inject

Create crash_inject file to replace iwpriv cmd.

file path: /sys/kernel/debug/wlan_xx/crash_inject
           wlan_xx is adapter name

Change-Id: Iad8b52bd67345b47717a776759ad6156d654bb93
CRs-Fixed: 2636352
This commit is contained in:
Jingxiang Ge 2020-03-06 14:29:47 +08:00 committed by nshrivas
parent 389250b911
commit b5caac2e85
8 changed files with 275 additions and 58 deletions

3
Kbuild
View File

@ -122,6 +122,9 @@ HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_debugfs_unit_test.o
ifeq ($(CONFIG_WLAN_MWS_INFO_DEBUGFS), y)
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_debugfs_coex.o
endif
ifeq ($(CONFIG_WLAN_DEBUG_CRASH_INJECT), y)
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_debugfs_crash_inject.o
endif
endif
ifeq ($(CONFIG_WLAN_CONV_SPECTRAL_ENABLE),y)

View File

@ -4206,4 +4206,27 @@ void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx,
{
}
#endif /* WLAN_FEATURE_PKT_CAPTURE */
#ifdef CONFIG_WLAN_DEBUG_CRASH_INJECT
/**
* hdd_crash_inject() - Inject a crash
* @adapter: Adapter upon which the command was received
* @v1: first value to inject
* @v2: second value to inject
*
* This function is the handler for the crash inject debug feature.
* This feature only exists for internal testing and must not be
* enabled on a production device.
*
* Return: 0 on success and errno on failure
*/
int hdd_crash_inject(struct hdd_adapter *adapter, uint32_t v1, uint32_t v2);
#else
static inline
int hdd_crash_inject(struct hdd_adapter *adapter, uint32_t v1, uint32_t v2)
{
return -ENOTSUPP;
}
#endif
#endif /* end #if !defined(WLAN_HDD_MAIN_H) */

View File

@ -347,28 +347,6 @@ struct iw_request_info;
int hdd_check_private_wext_control(struct hdd_context *hdd_ctx,
struct iw_request_info *info);
/**
* hdd_crash_inject() - Inject a crash
* @adapter: Adapter upon which the command was received
* @v1: first value to inject
* @v2: second value to inject
*
* This function is the handler for the crash inject debug feature.
* This feature only exists for internal testing and must not be
* enabled on a production device.
*
* Return: result of the command
*/
#ifdef CONFIG_WLAN_DEBUG_CRASH_INJECT
int hdd_crash_inject(struct hdd_adapter *adapter, uint32_t v1, uint32_t v2);
#else
static inline
int hdd_crash_inject(struct hdd_adapter *adapter, uint32_t v1, uint32_t v2)
{
return -ENOTSUPP;
}
#endif
#ifdef CONFIG_DP_TRACE
void hdd_set_dump_dp_trace(uint16_t cmd_type, uint16_t count);
#else

View File

@ -35,6 +35,8 @@
#include <wlan_hdd_debugfs_llstat.h>
#include <wlan_hdd_debugfs_mibstat.h>
#include "wlan_hdd_debugfs_unit_test.h"
#include "wlan_hdd_debugfs_crash_inject.h"
#define MAX_USER_COMMAND_SIZE_WOWL_ENABLE 8
#define MAX_USER_COMMAND_SIZE_WOWL_PATTERN 512
@ -562,6 +564,9 @@ QDF_STATUS hdd_debugfs_init(struct hdd_adapter *adapter)
if (wlan_hdd_debugfs_resume_create(adapter))
return QDF_STATUS_E_FAILURE;
if (wlan_hdd_debugfs_crash_inject_create(adapter))
return QDF_STATUS_E_FAILURE;
return QDF_STATUS_SUCCESS;
}

View File

@ -0,0 +1,159 @@
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: wlan_hdd_debugfs_crash_inject.c
*
* implementation for creating debugfs file crash_inject
*/
#include <wlan_hdd_includes.h>
#include "osif_vdev_sync.h"
#include "wlan_hdd_debugfs_crash_inject.h"
#define MAX_USER_COMMAND_SIZE_CRASH_INJECT 32
/**
* __wlan_hdd_write_crash_inject_debugfs()
* - crash inject test debugfs handler
*
* @net_dev: net_device context used to register the debugfs file
* @buf: text being written to the debugfs
* @count: size of @buf
* @ppos: (unused) offset into the virtual file system
*
* Return: number of bytes processed
*/
static ssize_t __wlan_hdd_write_crash_inject_debugfs(
struct net_device *net_dev,
const char __user *buf, size_t count,
loff_t *ppos)
{
struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(net_dev);
struct hdd_context *hdd_ctx;
char buf_local[MAX_USER_COMMAND_SIZE_CRASH_INJECT + 1];
char *sptr, *token;
uint32_t val1, val2;
int ret;
if (hdd_validate_adapter(adapter)) {
hdd_err_rl("adapter validate fail");
return -EINVAL;
}
hdd_ctx = WLAN_HDD_GET_CTX(adapter);
ret = wlan_hdd_validate_context(hdd_ctx);
if (ret != 0)
return ret;
if (!wlan_hdd_validate_modules_state(hdd_ctx))
return -EINVAL;
if (count > MAX_USER_COMMAND_SIZE_CRASH_INJECT) {
hdd_err_rl("Command length is larger than %d bytes",
MAX_USER_COMMAND_SIZE_CRASH_INJECT);
return -EINVAL;
}
/* Get command from user */
if (copy_from_user(buf_local, buf, count))
return -EFAULT;
/* default 'echo' cmd takes new line character to here*/
if (buf_local[count - 1] == '\n')
buf_local[count - 1] = '\0';
else
buf_local[count] = '\0';
sptr = buf_local;
hdd_nofl_info("unit_test: count %zu buf_local:(%s) net_devname %s",
count, buf_local, net_dev->name);
/* Get val1 */
token = strsep(&sptr, " ");
if (!token)
return -EINVAL;
if (kstrtou32(token, 0, &val1))
return -EINVAL;
/* Get val2 */
token = strsep(&sptr, " ");
if (!token)
return -EINVAL;
if (kstrtou32(token, 0, &val2))
return -EINVAL;
ret = hdd_crash_inject(adapter, val1, val2);
if (ret != 0) {
hdd_err_rl("hdd_crash_inject returned %d", ret);
return -EINVAL;
}
return count;
}
/**
* wlan_hdd_write_crash_inject_debugfs()
* - wrapper for __wlan_hdd_write_crash_inject_debugfs
*
* @file: file pointer
* @buf: buffer
* @count: count
* @ppos: position pointer
*
* Return: number of bytes processed or errno
*/
static ssize_t wlan_hdd_write_crash_inject_debugfs(
struct file *file,
const char __user *buf,
size_t count, loff_t *ppos)
{
struct net_device *net_dev = file_inode(file)->i_private;
struct osif_vdev_sync *vdev_sync;
ssize_t errno_size;
errno_size = osif_vdev_sync_op_start(net_dev, &vdev_sync);
if (errno_size)
return errno_size;
errno_size = __wlan_hdd_write_crash_inject_debugfs(
net_dev, buf, count, ppos);
if (errno_size < 0)
hdd_err_rl("errno_size %zd", errno_size);
osif_vdev_sync_op_stop(vdev_sync);
return errno_size;
}
static const struct file_operations fops_crash_inject_debugfs = {
.write = wlan_hdd_write_crash_inject_debugfs,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
int wlan_hdd_debugfs_crash_inject_create(struct hdd_adapter *adapter)
{
struct net_device *net_dev = adapter->dev;
if (!debugfs_create_file("crash_inject", 00400 | 00200,
adapter->debugfs_phy,
net_dev, &fops_crash_inject_debugfs))
return -EINVAL;
return 0;
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: wlan_hdd_debugfs_crash_inject.h
*
* implementation for creating debugfs file crash_inject
*/
#ifndef _WLAN_HDD_DEBUGFS_CRASH_INJECT_H
#define _WLAN_HDD_DEBUGFS_CRASH_INJECT_H
#if defined(WLAN_DEBUGFS) && defined(CONFIG_WLAN_DEBUG_CRASH_INJECT)
/**
* wlan_hdd_debugfs_crash_inject_create() - API to create crash_inject
* @adapter: hdd adapter
*
* this file is created per adapter.
* file path: /sys/kernel/debug/wlan_xx/crash_inject
* (wlan_xx is adapter name)
* usage:
* echo [arg_0] [arg_1] > crash_inject
*
* Return: 0 on success and errno on failure
*/
int wlan_hdd_debugfs_crash_inject_create(struct hdd_adapter *adapter);
#else
static inline int
wlan_hdd_debugfs_crash_inject_create(struct hdd_adapter *adapter)
{
return 0;
}
#endif
#endif /* #ifndef _WLAN_HDD_DEBUGFS_CRASH_INJECT_H */

View File

@ -16762,6 +16762,42 @@ wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx,
return 0;
}
#endif /* WLAN_FEATURE_PKT_CAPTURE */
#ifdef CONFIG_WLAN_DEBUG_CRASH_INJECT
int hdd_crash_inject(struct hdd_adapter *adapter, uint32_t v1, uint32_t v2)
{
struct hdd_context *hdd_ctx;
int ret;
bool crash_inject;
QDF_STATUS status;
hdd_debug("v1: %d v2: %d", v1, v2);
pr_err("SSR is triggered by CRASH_INJECT: %d %d\n",
v1, v2);
hdd_ctx = WLAN_HDD_GET_CTX(adapter);
status = ucfg_mlme_get_crash_inject(hdd_ctx->psoc, &crash_inject);
if (QDF_IS_STATUS_ERROR(status)) {
hdd_err("Failed to get crash inject ini config");
return 0;
}
if (!crash_inject) {
hdd_err("Crash Inject ini disabled, Ignore Crash Inject");
return 0;
}
if (v1 == 3) {
cds_trigger_recovery(QDF_REASON_UNSPECIFIED);
return 0;
}
ret = wma_cli_set2_command(adapter->vdev_id,
GEN_PARAM_CRASH_INJECT,
v1, v2, GEN_CMD);
return ret;
}
#endif
/* Register the module init/exit functions */
module_init(hdd_module_init);
module_exit(hdd_module_exit);

View File

@ -9537,42 +9537,6 @@ static void hdd_ioctl_log_buffer(int log_id, uint32_t count)
}
}
#ifdef CONFIG_WLAN_DEBUG_CRASH_INJECT
int hdd_crash_inject(struct hdd_adapter *adapter, uint32_t v1, uint32_t v2)
{
struct hdd_context *hdd_ctx;
int ret;
bool crash_inject;
QDF_STATUS status;
hdd_debug("WE_SET_FW_CRASH_INJECT: %d %d",
v1, v2);
pr_err("SSR is triggered by iwpriv CRASH_INJECT: %d %d\n",
v1, v2);
hdd_ctx = WLAN_HDD_GET_CTX(adapter);
status = ucfg_mlme_get_crash_inject(hdd_ctx->psoc, &crash_inject);
if (QDF_IS_STATUS_ERROR(status)) {
hdd_err("Failed to get crash inject ini config");
return 0;
}
if (!crash_inject) {
hdd_err("Crash Inject ini disabled, Ignore Crash Inject");
return 0;
}
if (v1 == 3) {
cds_trigger_recovery(QDF_REASON_UNSPECIFIED);
return 0;
}
ret = wma_cli_set2_command(adapter->vdev_id,
GEN_PARAM_CRASH_INJECT,
v1, v2, GEN_CMD);
return ret;
}
#endif
#ifdef CONFIG_DP_TRACE
void hdd_set_dump_dp_trace(uint16_t cmd_type, uint16_t count)
{