mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 14:19:09 -04:00
cnss2: Add debugfs support to send WFC call status QMI message
Expose a debugfs node so that user can manually input WFC call status QMI message for debug purpose. Change-Id: I02d2b0064a0ba5622c2ee3523e577ec2f3fec36b Signed-off-by: Yue Ma <yuem@codeaurora.org>
This commit is contained in:
parent
ad8b0e3fc3
commit
f1ea1257a6
3 changed files with 129 additions and 4 deletions
|
|
@ -1,5 +1,5 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */
|
||||
/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
|
@ -10,10 +10,28 @@
|
|||
#include "pci.h"
|
||||
|
||||
#define MMIO_REG_ACCESS_MEM_TYPE 0xFF
|
||||
#define HEX_DUMP_ROW_SIZE 16
|
||||
|
||||
void *cnss_ipc_log_context;
|
||||
void *cnss_ipc_log_long_context;
|
||||
|
||||
static void cnss_print_hex_dump(const void *buf, int len)
|
||||
{
|
||||
const u8 *ptr = buf;
|
||||
int i, linelen, remaining = len, rowsize = HEX_DUMP_ROW_SIZE;
|
||||
unsigned char linebuf[HEX_DUMP_ROW_SIZE * 3 + 1];
|
||||
|
||||
for (i = 0; i < len; i += rowsize) {
|
||||
linelen = min(remaining, rowsize);
|
||||
remaining -= rowsize;
|
||||
|
||||
hex_dump_to_buffer(ptr + i, linelen, rowsize, 1,
|
||||
linebuf, sizeof(linebuf), false);
|
||||
|
||||
cnss_pr_dbg("%.8x: %s\n", i, linebuf);
|
||||
}
|
||||
}
|
||||
|
||||
static int cnss_pin_connect_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct cnss_plat_data *cnss_priv = s->private;
|
||||
|
|
@ -750,6 +768,95 @@ static const struct file_operations cnss_dynamic_feature_fops = {
|
|||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
static int cnss_wfc_call_status_debug_show(struct seq_file *s, void *data)
|
||||
{
|
||||
seq_puts(s, "\nUsage: echo <data_len> <hex data> > <debugfs_path>/cnss/wfc_call_status\n");
|
||||
seq_puts(s, "e.g. Send 4 bytes of hex data for WFC call status using QMI message:\n");
|
||||
seq_puts(s, "echo '0x4 0xA 0xB 0xC 0xD' > /d/cnss/wfc_call_status\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t cnss_wfc_call_status_debug_write(struct file *fp,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *off)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv =
|
||||
((struct seq_file *)fp->private_data)->private;
|
||||
char buf[(QMI_WLFW_MAX_WFC_CALL_STATUS_DATA_SIZE_V01 + 1) * 5];
|
||||
char *sptr, *token;
|
||||
unsigned int len = 0;
|
||||
const char *delim = " ";
|
||||
u32 data_len;
|
||||
u8 data[QMI_WLFW_MAX_WFC_CALL_STATUS_DATA_SIZE_V01] = {0}, data_byte;
|
||||
int ret = 0, i;
|
||||
|
||||
if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
|
||||
cnss_pr_err("Firmware is not ready yet\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
sptr = buf;
|
||||
|
||||
token = strsep(&sptr, delim);
|
||||
if (!token || !sptr)
|
||||
return -EINVAL;
|
||||
|
||||
if (kstrtou32(token, 0, &data_len))
|
||||
return -EINVAL;
|
||||
|
||||
cnss_pr_dbg("Parsing 0x%x bytes data for WFC call status\n", data_len);
|
||||
|
||||
if (data_len > QMI_WLFW_MAX_WFC_CALL_STATUS_DATA_SIZE_V01 ||
|
||||
data_len == 0) {
|
||||
cnss_pr_err("Invalid data length 0x%x\n", data_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < data_len; i++) {
|
||||
token = strsep(&sptr, delim);
|
||||
if (!token || (!sptr && i < data_len - 1)) {
|
||||
cnss_pr_err("Input data is less than length\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (kstrtou8(token, 0, &data_byte)) {
|
||||
cnss_pr_err("Data format is incorrect\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data[i] = data_byte;
|
||||
}
|
||||
|
||||
cnss_print_hex_dump(data, data_len);
|
||||
|
||||
ret = cnss_wlfw_wfc_call_status_send_sync(plat_priv, data_len, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int cnss_wfc_call_status_debug_open(struct inode *inode,
|
||||
struct file *file)
|
||||
{
|
||||
return single_open(file, cnss_wfc_call_status_debug_show,
|
||||
inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations cnss_wfc_call_status_debug_fops = {
|
||||
.read = seq_read,
|
||||
.write = cnss_wfc_call_status_debug_write,
|
||||
.open = cnss_wfc_call_status_debug_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_CNSS2_DEBUG
|
||||
static int cnss_create_debug_only_node(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
|
|
@ -767,6 +874,8 @@ static int cnss_create_debug_only_node(struct cnss_plat_data *plat_priv)
|
|||
&cnss_control_params_debug_fops);
|
||||
debugfs_create_file("dynamic_feature", 0600, root_dentry, plat_priv,
|
||||
&cnss_dynamic_feature_fops);
|
||||
debugfs_create_file("wfc_call_status", 0600, root_dentry, plat_priv,
|
||||
&cnss_wfc_call_status_debug_fops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1469,8 +1469,8 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int cnss_wlfw_wfc_call_status_send_sync(struct cnss_plat_data *plat_priv,
|
||||
u32 data_len, const void *data)
|
||||
int cnss_wlfw_wfc_call_status_send_sync(struct cnss_plat_data *plat_priv,
|
||||
u32 data_len, const void *data)
|
||||
{
|
||||
struct wlfw_wfc_call_status_req_msg_v01 *req;
|
||||
struct wlfw_wfc_call_status_resp_msg_v01 *resp;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. */
|
||||
/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef _CNSS_QMI_H
|
||||
#define _CNSS_QMI_H
|
||||
|
|
@ -61,6 +61,8 @@ int cnss_wlfw_antenna_grant_send_sync(struct cnss_plat_data *plat_priv);
|
|||
int cnss_wlfw_dynamic_feature_mask_send_sync(struct cnss_plat_data *plat_priv);
|
||||
int cnss_wlfw_get_info_send_sync(struct cnss_plat_data *plat_priv, int type,
|
||||
void *cmd, int cmd_len);
|
||||
int cnss_wlfw_wfc_call_status_send_sync(struct cnss_plat_data *plat_priv,
|
||||
u32 data_len, const void *data);
|
||||
int cnss_register_coex_service(struct cnss_plat_data *plat_priv);
|
||||
void cnss_unregister_coex_service(struct cnss_plat_data *plat_priv);
|
||||
int coex_antenna_switch_to_wlan_send_sync_msg(struct cnss_plat_data *plat_priv);
|
||||
|
|
@ -175,6 +177,20 @@ int cnss_wlfw_dynamic_feature_mask_send_sync(struct cnss_plat_data *plat_priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_wlfw_get_info_send_sync(struct cnss_plat_data *plat_priv, int type,
|
||||
void *cmd, int cmd_len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_wlfw_wfc_call_status_send_sync(struct cnss_plat_data *plat_priv,
|
||||
u32 data_len, const void *data);
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int cnss_register_coex_service(struct cnss_plat_data *plat_priv)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue