qcacld-3.0: Add debugfs framework support for CSR
Add debugfs framework support to get connect, scan, roam scan statistics and offload info from debugfs. Change-Id: I86bdd7e449488d2bcda1b2eaaeb07aac7465770b CRs-Fixed: 2203626
This commit is contained in:
parent
ac7764bd5e
commit
197d417733
1
Kbuild
1
Kbuild
@ -70,6 +70,7 @@ ifeq ($(CONFIG_WLAN_DEBUGFS), y)
|
||||
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_debugfs.o
|
||||
ifeq ($(CONFIG_WLAN_FEATURE_LINK_LAYER_STATS), y)
|
||||
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_debugfs_llstat.o
|
||||
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_debugfs_csr.o
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include <net/cfg80211.h>
|
||||
#include <linux/ieee80211.h>
|
||||
|
||||
#define HDD_TIME_STRING_LEN 24
|
||||
|
||||
/* Preprocessor Definitions and Constants */
|
||||
#ifdef FEATURE_WLAN_TDLS
|
||||
#define HDD_MAX_NUM_TDLS_STA 8
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2013-2018 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
|
||||
@ -20,8 +20,77 @@
|
||||
#define _WLAN_HDD_DEBUGFS_H
|
||||
|
||||
#ifdef WLAN_DEBUGFS
|
||||
|
||||
#define HDD_DEBUGFS_FILE_NAME_MAX 24
|
||||
|
||||
/**
|
||||
* enum hdd_debugfs_file_id - Debugfs file Identifier
|
||||
* @HDD_DEBUFS_FILE_ID_CONNECT_INFO: connect_info file id
|
||||
* @HDD_DEBUFS_FILE_ID_ROAM_SCAN_STATS_INFO: roam_scan_stats file id
|
||||
* @HDD_DEBUFS_FILE_ID_OFFLOAD_INFO: offload_info file id
|
||||
* @HDD_DEBUGFS_FILE_ID_MAX: maximum id of csr debugfs file
|
||||
*/
|
||||
enum hdd_debugfs_file_id {
|
||||
HDD_DEBUFS_FILE_ID_CONNECT_INFO = 0,
|
||||
HDD_DEBUFS_FILE_ID_ROAM_SCAN_STATS_INFO = 1,
|
||||
HDD_DEBUFS_FILE_ID_OFFLOAD_INFO = 2,
|
||||
|
||||
HDD_DEBUGFS_FILE_ID_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hdd_debugfs_file_info - Debugfs file info
|
||||
* @name: name of debugfs file
|
||||
* @id: id from enum hdd_debugfs_file_id used to identify file
|
||||
* @buf_max_size: max size of buffer from which debugfs file is updated
|
||||
* @entry: dentry pointer to debugfs file
|
||||
*/
|
||||
struct hdd_debugfs_file_info {
|
||||
uint8_t name[HDD_DEBUGFS_FILE_NAME_MAX];
|
||||
enum hdd_debugfs_file_id id;
|
||||
ssize_t buf_max_size;
|
||||
struct dentry *entry;
|
||||
};
|
||||
|
||||
QDF_STATUS hdd_debugfs_init(struct hdd_adapter *adapter);
|
||||
void hdd_debugfs_exit(struct hdd_adapter *adapter);
|
||||
|
||||
/**
|
||||
* hdd_wait_for_debugfs_threads_completion() - Wait for debugfs threads
|
||||
* completion before proceeding further to stop modules
|
||||
*
|
||||
* Return: true if there is no debugfs open
|
||||
* false if there is at least one debugfs open
|
||||
*/
|
||||
bool hdd_wait_for_debugfs_threads_completion(void);
|
||||
|
||||
/**
|
||||
* hdd_return_debugfs_threads_count() - Return active debugfs threads
|
||||
*
|
||||
* Return: total number of active debugfs threads in driver
|
||||
*/
|
||||
int hdd_return_debugfs_threads_count(void);
|
||||
|
||||
/**
|
||||
* hdd_debugfs_thread_increment() - Increment debugfs thread count
|
||||
*
|
||||
* This function is used to increment and keep track of debugfs thread count.
|
||||
* This is invoked for every file open operation.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void hdd_debugfs_thread_increment(void);
|
||||
|
||||
/**
|
||||
* hdd_debugfs_thread_decrement() - Decrement debugfs thread count
|
||||
*
|
||||
* This function is used to decrement and keep track of debugfs thread count.
|
||||
* This is invoked for every file release operation.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void hdd_debugfs_thread_decrement(void);
|
||||
|
||||
#else
|
||||
static inline QDF_STATUS hdd_debugfs_init(struct hdd_adapter *adapter)
|
||||
{
|
||||
@ -31,5 +100,56 @@ static inline QDF_STATUS hdd_debugfs_init(struct hdd_adapter *adapter)
|
||||
static inline void hdd_debugfs_exit(struct hdd_adapter *adapter)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_wait_for_debugfs_threads_completion() - Wait for debugfs threads
|
||||
* completion before proceeding further to stop modules
|
||||
*
|
||||
* Return: true if there is no debugfs open
|
||||
* false if there is at least one debugfs open
|
||||
*/
|
||||
static inline
|
||||
bool hdd_wait_for_debugfs_threads_completion(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_return_debugfs_threads_count() - Return active debugfs threads
|
||||
*
|
||||
* Return: total number of active debugfs threads in driver
|
||||
*/
|
||||
static inline
|
||||
int hdd_return_debugfs_threads_count(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_debugfs_thread_increment() - Increment debugfs thread count
|
||||
*
|
||||
* This function is used to increment and keep track of debugfs thread count.
|
||||
* This is invoked for every file open operation.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static inline
|
||||
void hdd_debugfs_thread_increment(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_debugfs_thread_decrement() - Decrement debugfs thread count
|
||||
*
|
||||
* This function is used to decrement and keep track of debugfs thread count.
|
||||
* This is invoked for every file release operation.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static inline
|
||||
void hdd_debugfs_thread_decrement(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* #ifdef WLAN_DEBUGFS */
|
||||
#endif /* #ifndef _WLAN_HDD_DEBUGFS_H */
|
||||
|
123
core/hdd/inc/wlan_hdd_debugfs_csr.h
Normal file
123
core/hdd/inc/wlan_hdd_debugfs_csr.h
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||
* under proprietary terms before Copyright ownership was assigned
|
||||
* to the Linux Foundation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: wlan_hdd_debugfs_csr.h
|
||||
*
|
||||
* WLAN Host Device Driver implementation to update
|
||||
* debugfs with connect, scan and roam information
|
||||
*/
|
||||
|
||||
#ifndef _WLAN_HDD_DEBUGFS_CSR_H
|
||||
#define _WLAN_HDD_DEBUGFS_CSR_H
|
||||
|
||||
#include <wlan_hdd_includes.h>
|
||||
|
||||
#ifdef WLAN_DEBUGFS
|
||||
|
||||
/**
|
||||
* struct wlan_hdd_debugfs_buffer_info - Debugfs buffer info
|
||||
* @length: current length of the debugfs buffer
|
||||
* @max_buf_len: maximum buffer length of the debugfs buffer
|
||||
* @id: id from enum hdd_debugfs_file_id used to identify file
|
||||
* @data: start of debugfs buffer from which file read starts
|
||||
* @adapter: pointer to adapter
|
||||
*
|
||||
* This structure is used to hold the debugfs buffer details and is stored in
|
||||
* private data of file argument in file open operation.
|
||||
*/
|
||||
struct wlan_hdd_debugfs_buffer_info {
|
||||
ssize_t length;
|
||||
ssize_t max_buf_len;
|
||||
enum hdd_debugfs_file_id id;
|
||||
uint8_t *data;
|
||||
struct hdd_adapter *adapter;
|
||||
};
|
||||
|
||||
/**
|
||||
* wlan_hdd_debugfs_csr_init() - Create wifi diagnostic debugfs files
|
||||
* @adapter: pointer to adapter for which debugfs files are to be created
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void wlan_hdd_debugfs_csr_init(struct hdd_adapter *adapter);
|
||||
|
||||
/**
|
||||
* wlan_hdd_debugfs_csr_deinit() - Remove wifi diagnostic debugfs files
|
||||
* @adapter: pointer to adapter for which debugfs files are to be removed
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void wlan_hdd_debugfs_csr_deinit(struct hdd_adapter *adapter);
|
||||
|
||||
/**
|
||||
* wlan_hdd_current_time_info_debugfs() - API to get time into user buffer
|
||||
* @buf: output buffer to hold current time when queried
|
||||
* @buf_avail_len: available buffer length
|
||||
*
|
||||
* Return: No.of bytes copied
|
||||
*/
|
||||
ssize_t
|
||||
wlan_hdd_current_time_info_debugfs(uint8_t *buf, ssize_t buf_avail_len);
|
||||
|
||||
#else
|
||||
/**
|
||||
* wlan_hdd_debugfs_csr_init() - Create wifi diagnostic debugfs files
|
||||
* @adapter: pointer to adapter for which debugfs files are to be created
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static inline void wlan_hdd_debugfs_csr_init(struct hdd_adapter *adapter)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_hdd_debugfs_csr_deinit() - Remove wifi diagnostic debugfs files
|
||||
* @adapter: pointer to adapter for which debugfs files are to be removed
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static inline void wlan_hdd_debugfs_csr_deinit(struct hdd_adapter *adapter)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_hdd_current_time_info_debugfs() - API to get time into user buffer
|
||||
* @buf: output buffer to hold current time when queried
|
||||
* @buf_avail_len: available buffer length
|
||||
*
|
||||
* Return: No.of bytes copied
|
||||
*/
|
||||
static inline ssize_t
|
||||
wlan_hdd_current_time_info_debugfs(uint8_t *buf, ssize_t buf_avail_len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _WLAN_HDD_DEBUGFS_CSR_H */
|
@ -63,6 +63,7 @@
|
||||
#include "wlan_hdd_tdls.h"
|
||||
#include "wlan_hdd_tsf.h"
|
||||
#include "wlan_hdd_cfg80211.h"
|
||||
#include "wlan_hdd_debugfs.h"
|
||||
#include <qdf_defer.h>
|
||||
#include "sap_api.h"
|
||||
#include <wlan_hdd_lro.h>
|
||||
@ -254,6 +255,8 @@ enum hdd_driver_flags {
|
||||
|
||||
#define WLAN_WAIT_TIME_APF 1000
|
||||
|
||||
#define WLAN_WAIT_TIME_FW_ROAM_STATS 1000
|
||||
|
||||
/* Maximum time(ms) to wait for RSO CMD status event */
|
||||
#define WAIT_TIME_RSO_CMD_STATUS 2000
|
||||
|
||||
@ -1470,6 +1473,10 @@ struct hdd_adapter {
|
||||
#ifdef FEATURE_WLAN_APF
|
||||
struct hdd_apf_context apf_context;
|
||||
#endif /* FEATURE_WLAN_APF */
|
||||
|
||||
#ifdef WLAN_DEBUGFS
|
||||
struct hdd_debugfs_file_info csr_file[HDD_DEBUGFS_FILE_ID_MAX];
|
||||
#endif /* WLAN_DEBUGFS */
|
||||
};
|
||||
|
||||
#define WLAN_HDD_GET_STATION_CTX_PTR(adapter) (&(adapter)->session.station)
|
||||
|
@ -41,6 +41,51 @@
|
||||
#define POWER_DEBUGFS_BUFFER_MAX_LEN 4096
|
||||
#endif
|
||||
|
||||
#define MAX_DEBUGFS_WAIT_ITERATIONS 20
|
||||
#define DEBUGFS_WAIT_SLEEP_TIME 100
|
||||
|
||||
static qdf_atomic_t debugfs_thread_count;
|
||||
|
||||
void hdd_debugfs_thread_increment(void)
|
||||
{
|
||||
qdf_atomic_inc(&debugfs_thread_count);
|
||||
}
|
||||
|
||||
void hdd_debugfs_thread_decrement(void)
|
||||
{
|
||||
qdf_atomic_dec(&debugfs_thread_count);
|
||||
}
|
||||
|
||||
int hdd_return_debugfs_threads_count(void)
|
||||
{
|
||||
return qdf_atomic_read(&debugfs_thread_count);
|
||||
}
|
||||
|
||||
bool hdd_wait_for_debugfs_threads_completion(void)
|
||||
{
|
||||
int count = MAX_DEBUGFS_WAIT_ITERATIONS;
|
||||
int r;
|
||||
|
||||
while (count) {
|
||||
r = hdd_return_debugfs_threads_count();
|
||||
if (!r)
|
||||
break;
|
||||
|
||||
if (--count) {
|
||||
hdd_debug("Waiting for %d debugfs threads to exit", r);
|
||||
qdf_sleep(DEBUGFS_WAIT_SLEEP_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
/* at least one debugfs thread is executing */
|
||||
if (!count) {
|
||||
hdd_err("Timed-out waiting for debugfs threads");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* __wcnss_wowpattern_write() - wow_pattern debugfs handler
|
||||
* @file: debugfs file handle
|
||||
|
340
core/hdd/src/wlan_hdd_debugfs_csr.c
Normal file
340
core/hdd/src/wlan_hdd_debugfs_csr.c
Normal file
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||
*
|
||||
*
|
||||
* 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_csr.c
|
||||
*
|
||||
* WLAN Host Device Driver implementation to update
|
||||
* debugfs with roaming related information
|
||||
*/
|
||||
|
||||
#include <wlan_hdd_debugfs_csr.h>
|
||||
#include <wlan_hdd_main.h>
|
||||
#include <cds_sched.h>
|
||||
#include <wma_api.h>
|
||||
#include "qwlan_version.h"
|
||||
#include "wmi_unified_param.h"
|
||||
#include "wlan_hdd_debugfs.h"
|
||||
|
||||
ssize_t
|
||||
wlan_hdd_current_time_info_debugfs(uint8_t *buf, ssize_t buf_avail_len)
|
||||
{
|
||||
ssize_t length;
|
||||
char time_buffer[HDD_TIME_STRING_LEN];
|
||||
int ret_val;
|
||||
|
||||
qdf_get_time_of_the_day_in_hr_min_sec_usec(time_buffer,
|
||||
sizeof(time_buffer));
|
||||
ret_val = scnprintf(buf, buf_avail_len,
|
||||
"\nTime at which this file generated = %s\n",
|
||||
time_buffer);
|
||||
if (ret_val < 0)
|
||||
return 0;
|
||||
length = ret_val;
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_hdd_debugfs_update_csr() - Function to update internal debugfs buffer
|
||||
* and write into user-space buffer
|
||||
* @hdd_ctx: hdd context
|
||||
* @adapter: adapter
|
||||
* @id: used to identify file for which this info has to be read
|
||||
* @buf: output buffer to write
|
||||
* @buf_avail_len: length of the available buffer
|
||||
*
|
||||
* Return: Number of bytes read on success, zero otherwise
|
||||
*/
|
||||
static ssize_t
|
||||
wlan_hdd_debugfs_update_csr(struct hdd_context *hdd_ctx,
|
||||
struct hdd_adapter *adapter,
|
||||
enum hdd_debugfs_file_id id,
|
||||
uint8_t *buf,
|
||||
ssize_t buf_avail_len)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
|
||||
switch (id) {
|
||||
case HDD_DEBUFS_FILE_ID_CONNECT_INFO:
|
||||
/* populate connect info */
|
||||
break;
|
||||
case HDD_DEBUFS_FILE_ID_ROAM_SCAN_STATS_INFO:
|
||||
/* populate roam scan stats info */
|
||||
break;
|
||||
case HDD_DEBUFS_FILE_ID_OFFLOAD_INFO:
|
||||
/* populate offload info */
|
||||
break;
|
||||
default:
|
||||
hdd_err("Failed to fetch stats, unknown stats type");
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* __wlan_hdd_read_debugfs_csr() - Function to read debug stats
|
||||
* @file: file pointer
|
||||
* @buf: buffer
|
||||
* @count: count
|
||||
* @pos: position pointer
|
||||
*
|
||||
* Return: Number of bytes read on success, zero otherwise
|
||||
*/
|
||||
static ssize_t
|
||||
__wlan_hdd_read_debugfs_csr(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
struct wlan_hdd_debugfs_buffer_info *info;
|
||||
struct hdd_adapter *adapter;
|
||||
struct hdd_context *hdd_ctx;
|
||||
int ret;
|
||||
ssize_t length;
|
||||
|
||||
hdd_enter();
|
||||
|
||||
info = file->private_data;
|
||||
if (!info || !info->data) {
|
||||
hdd_err("No valid private data");
|
||||
return 0;
|
||||
}
|
||||
|
||||
adapter = info->adapter;
|
||||
if ((!adapter) || (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)) {
|
||||
hdd_err("Invalid adapter or adapter has invalid magic");
|
||||
return 0;
|
||||
}
|
||||
|
||||
hdd_ctx = WLAN_HDD_GET_CTX(adapter);
|
||||
ret = wlan_hdd_validate_context(hdd_ctx);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
if (!test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
|
||||
hdd_err("Interface is not enabled");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*pos == 0) {
|
||||
info->length = wlan_hdd_debugfs_update_csr(hdd_ctx, adapter,
|
||||
info->id,
|
||||
info->data,
|
||||
info->max_buf_len);
|
||||
}
|
||||
|
||||
length = simple_read_from_buffer(buf, count, pos,
|
||||
info->data, info->length);
|
||||
hdd_debug("length written = %zu, count: %zu, pos: %lld",
|
||||
length, count, *pos);
|
||||
|
||||
hdd_exit();
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_hdd_read_debugfs_csr() - SSR wrapper function to read stats
|
||||
* @file: file pointer
|
||||
* @buf: buffer
|
||||
* @count: count
|
||||
* @pos: position pointer
|
||||
*
|
||||
* Return: Number of bytes read on success, zero otherwise
|
||||
*/
|
||||
static ssize_t
|
||||
wlan_hdd_read_debugfs_csr(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
int ret;
|
||||
|
||||
cds_ssr_protect(__func__);
|
||||
ret = __wlan_hdd_read_debugfs_csr(file, buf, count, pos);
|
||||
cds_ssr_unprotect(__func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* __wlan_hdd_open_debugfs_csr() - Allocates memory for private data
|
||||
* @inode: Pointer to inode structure
|
||||
* @file: file pointer
|
||||
*
|
||||
* Return: zero
|
||||
*/
|
||||
static int __wlan_hdd_open_debugfs_csr(struct inode *inode,
|
||||
struct file *file)
|
||||
{
|
||||
struct wlan_hdd_debugfs_buffer_info *info;
|
||||
struct hdd_debugfs_file_info *csr;
|
||||
struct hdd_adapter *adapter = NULL;
|
||||
struct hdd_context *hdd_ctx;
|
||||
int ret;
|
||||
|
||||
hdd_enter();
|
||||
|
||||
csr = inode->i_private;
|
||||
if (!csr) {
|
||||
hdd_err("No private data");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
adapter = qdf_container_of(csr, struct hdd_adapter,
|
||||
csr_file[csr->id]);
|
||||
if (!adapter || (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)) {
|
||||
hdd_err("Invalid adapter or adapter has invalid magic");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hdd_ctx = WLAN_HDD_GET_CTX(adapter);
|
||||
ret = wlan_hdd_validate_context(hdd_ctx);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
if (!test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
|
||||
hdd_err("Interface is not enabled");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info = qdf_mem_malloc(sizeof(*info));
|
||||
if (!info) {
|
||||
hdd_err("Not enough memory for file private data");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
info->data = qdf_mem_malloc(csr->buf_max_size);
|
||||
if (!info->data) {
|
||||
hdd_err("roam stats debugfs buffer allocation failed");
|
||||
qdf_mem_free(info);
|
||||
return -ENOMEM;
|
||||
}
|
||||
info->length = 0;
|
||||
info->max_buf_len = csr->buf_max_size;
|
||||
info->id = csr->id;
|
||||
info->adapter = adapter;
|
||||
|
||||
file->private_data = info;
|
||||
hdd_exit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_hdd_open_debugfs_csr() - SSR wrapper function to allocate memory for
|
||||
* private data on file open
|
||||
* @inode: Pointer to inode structure
|
||||
* @file: file pointer
|
||||
*
|
||||
* Return: zero
|
||||
*/
|
||||
static int wlan_hdd_open_debugfs_csr(struct inode *inode,
|
||||
struct file *file)
|
||||
{
|
||||
int ret;
|
||||
|
||||
cds_ssr_protect(__func__);
|
||||
|
||||
hdd_debugfs_thread_increment();
|
||||
ret = __wlan_hdd_open_debugfs_csr(inode, file);
|
||||
if (ret)
|
||||
hdd_debugfs_thread_decrement();
|
||||
|
||||
cds_ssr_unprotect(__func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* __wlan_hdd_release_debugfs_csr() - Function to free private memory on
|
||||
* release
|
||||
* @inode: Pointer to inode structure
|
||||
* @file: file pointer
|
||||
*
|
||||
* Return: zero
|
||||
*/
|
||||
static int __wlan_hdd_release_debugfs_csr(struct inode *inode,
|
||||
struct file *file)
|
||||
{
|
||||
struct wlan_hdd_debugfs_buffer_info *info = file->private_data;
|
||||
|
||||
hdd_enter();
|
||||
|
||||
if (!info)
|
||||
return 0;
|
||||
|
||||
file->private_data = NULL;
|
||||
qdf_mem_free(info->data);
|
||||
qdf_mem_free(info);
|
||||
|
||||
hdd_exit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_hdd_release_debugfs_csr() - SSR wrapper function to free
|
||||
* private data on release
|
||||
* @inode: Pointer to inode structure
|
||||
* @file: file pointer
|
||||
*
|
||||
* Return: zero
|
||||
*/
|
||||
static int wlan_hdd_release_debugfs_csr(struct inode *inode, struct file *file)
|
||||
{
|
||||
int ret;
|
||||
|
||||
cds_ssr_protect(__func__);
|
||||
ret = __wlan_hdd_release_debugfs_csr(inode, file);
|
||||
hdd_debugfs_thread_decrement();
|
||||
cds_ssr_unprotect(__func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_csr_debugfs = {
|
||||
.read = wlan_hdd_read_debugfs_csr,
|
||||
.open = wlan_hdd_open_debugfs_csr,
|
||||
.release = wlan_hdd_release_debugfs_csr,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
void wlan_hdd_debugfs_csr_init(struct hdd_adapter *adapter)
|
||||
{
|
||||
/*
|
||||
* Create debufs diagnostic files for connect, offload info
|
||||
* and roam info and store in csr_file member of adapter
|
||||
*/
|
||||
}
|
||||
|
||||
void wlan_hdd_debugfs_csr_deinit(struct hdd_adapter *adapter)
|
||||
{
|
||||
uint32_t i;
|
||||
struct dentry *entry;
|
||||
|
||||
for (i = 0; i < HDD_DEBUGFS_FILE_ID_MAX; i++) {
|
||||
entry = adapter->csr_file[i].entry;
|
||||
if (!entry)
|
||||
continue;
|
||||
|
||||
adapter->csr_file[i].entry = NULL;
|
||||
debugfs_remove(entry);
|
||||
entry = NULL;
|
||||
}
|
||||
}
|
@ -39,6 +39,7 @@
|
||||
#include "pld_common.h"
|
||||
#include "wlan_hdd_driver_ops.h"
|
||||
#include "wlan_ipa_ucfg_api.h"
|
||||
#include "wlan_hdd_debugfs.h"
|
||||
|
||||
#ifdef MODULE
|
||||
#define WLAN_MODULE_NAME module_name(THIS_MODULE)
|
||||
@ -494,6 +495,9 @@ static void wlan_hdd_remove(struct device *dev)
|
||||
if (!cds_wait_for_external_threads_completion(__func__))
|
||||
hdd_warn("External threads are still active attempting driver unload anyway");
|
||||
|
||||
if (!hdd_wait_for_debugfs_threads_completion())
|
||||
hdd_warn("Debugfs threads are still active attempting driver unload anyway");
|
||||
|
||||
mutex_lock(&hdd_init_deinit_lock);
|
||||
hdd_start_driver_ops_timer(eHDD_DRV_OP_REMOVE);
|
||||
if (QDF_IS_EPPING_ENABLED(cds_get_conparam())) {
|
||||
@ -596,6 +600,9 @@ static void wlan_hdd_shutdown(void)
|
||||
if (!cds_wait_for_external_threads_completion(__func__))
|
||||
hdd_err("Host is not ready for SSR, attempting anyway");
|
||||
|
||||
if (!hdd_wait_for_debugfs_threads_completion())
|
||||
hdd_err("Debufs threads are still pending, attempting SSR anyway");
|
||||
|
||||
if (!QDF_IS_EPPING_ENABLED(cds_get_conparam())) {
|
||||
hif_disable_isr(hif_ctx);
|
||||
hdd_wlan_shutdown();
|
||||
|
@ -91,6 +91,7 @@
|
||||
#include "wlan_hdd_ocb.h"
|
||||
#include "wlan_hdd_nan.h"
|
||||
#include "wlan_hdd_debugfs.h"
|
||||
#include "wlan_hdd_debugfs_csr.h"
|
||||
#include "wlan_hdd_driver_ops.h"
|
||||
#include "epping_main.h"
|
||||
#include "wlan_hdd_data_stall_detection.h"
|
||||
@ -4327,6 +4328,8 @@ static void hdd_cleanup_adapter(struct hdd_context *hdd_ctx, struct hdd_adapter
|
||||
qdf_mutex_destroy(&adapter->disconnection_status_lock);
|
||||
hdd_apf_context_destroy(adapter);
|
||||
|
||||
wlan_hdd_debugfs_csr_deinit(adapter);
|
||||
|
||||
hdd_debugfs_exit(adapter);
|
||||
|
||||
/*
|
||||
@ -4994,6 +4997,9 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio
|
||||
hdd_info("%s interface created. iftype: %d", netdev_name(adapter->dev),
|
||||
session_type);
|
||||
|
||||
if (adapter->device_mode == QDF_STA_MODE)
|
||||
wlan_hdd_debugfs_csr_init(adapter);
|
||||
|
||||
return adapter;
|
||||
|
||||
err_free_netdev:
|
||||
@ -5380,7 +5386,6 @@ QDF_STATUS hdd_stop_adapter_ext(struct hdd_context *hdd_ctx,
|
||||
}
|
||||
|
||||
hdd_exit();
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -9245,6 +9250,7 @@ int hdd_start_station_adapter(struct hdd_adapter *adapter)
|
||||
hdd_tx_flow_control_is_pause);
|
||||
|
||||
hdd_exit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -10926,6 +10932,7 @@ int hdd_wlan_stop_modules(struct hdd_context *hdd_ctx, bool ftm_mode)
|
||||
bool is_recovery_stop = cds_is_driver_recovering();
|
||||
int ret = 0;
|
||||
int active_threads;
|
||||
int debugfs_threads;
|
||||
struct target_psoc_info *tgt_hdl;
|
||||
|
||||
hdd_enter();
|
||||
@ -10943,11 +10950,16 @@ int hdd_wlan_stop_modules(struct hdd_context *hdd_ctx, bool ftm_mode)
|
||||
cds_set_module_stop_in_progress(true);
|
||||
|
||||
active_threads = cds_return_external_threads_count();
|
||||
if (active_threads > 0 || hdd_ctx->is_wiphy_suspended) {
|
||||
hdd_warn("External threads %d wiphy suspend %d",
|
||||
active_threads, hdd_ctx->is_wiphy_suspended);
|
||||
debugfs_threads = hdd_return_debugfs_threads_count();
|
||||
|
||||
cds_print_external_threads();
|
||||
if (active_threads > 0 || debugfs_threads > 0 ||
|
||||
hdd_ctx->is_wiphy_suspended) {
|
||||
hdd_warn("External threads %d, Debugfs threads %d, wiphy suspend %d",
|
||||
active_threads, debugfs_threads,
|
||||
hdd_ctx->is_wiphy_suspended);
|
||||
|
||||
if (active_threads)
|
||||
cds_print_external_threads();
|
||||
|
||||
if (IS_IDLE_STOP && !ftm_mode) {
|
||||
mutex_unlock(&hdd_ctx->iface_change_lock);
|
||||
|
Loading…
Reference in New Issue
Block a user