Add 'qcom/opensource/wlan/qca-wifi-host-cmn/' from commit 'fec800ab539956671af604bdd6e1ee3b84eef491'
git-subtree-dir: qcom/opensource/wlan/qca-wifi-host-cmn git-subtree-mainline:5add812a59
git-subtree-split:fec800ab53
Change-Id: repo: https://git.codelinaro.org/clo/la/platform/vendor/qcom-opensource/wlan/qca-wifi-host-cmn tag: LA.VENDOR.14.3.0.r1-17300-lanai.QSSI15.0
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. 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.
|
||||
*/
|
||||
|
||||
#ifndef EPPING_INTERNAL_H
|
||||
#define EPPING_INTERNAL_H
|
||||
/**
|
||||
* DOC: epping_internal.h
|
||||
* Linux epping internal head file
|
||||
*/
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/semaphore.h>
|
||||
#if defined(CONFIG_HAS_WAKELOCK)
|
||||
#include <linux/wakelock.h>
|
||||
#endif
|
||||
#include "htc_api.h"
|
||||
#include "htc_packet.h"
|
||||
#include "epping_test.h"
|
||||
#include <qdf_atomic.h>
|
||||
#include <sir_mac_prot_def.h>
|
||||
#include <sir_debug.h>
|
||||
|
||||
#define EPPING_LOG_MASK (1<<EPPING_CMD_CAPTURE_RECV_CNT)
|
||||
#define EPPING_STATS_LOG_COUNT 50000
|
||||
#define EPPING_KTID_KILL_WAIT_TIME_MS 50
|
||||
|
||||
#define EPPING_FRAG_PER_MSDU 1
|
||||
#ifndef EPPING_TXBUF
|
||||
#define EPPING_TXBUF (512/EPPING_FRAG_PER_MSDU)
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Preprocessor definitions and constants
|
||||
-------------------------------------------------------------------------*/
|
||||
#define EPPING_MAX_ADAPTERS 1
|
||||
|
||||
#define EPPING_LOG(level, args ...) QDF_TRACE(QDF_MODULE_ID_HDD, level, ## args)
|
||||
#define EPPING_HEX_DUMP(level, data, len) qdf_trace_hex_dump( \
|
||||
QDF_MODULE_ID_HDD, \
|
||||
level, \
|
||||
data, buf_len)
|
||||
|
||||
struct epping_cookie {
|
||||
HTC_PACKET HtcPkt; /* HTC packet wrapper */
|
||||
struct epping_cookie *next;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
EPPING_CTX_STATE_INITIAL = 0,
|
||||
EPPING_CTX_STATE_HIF_INIT,
|
||||
EPPING_CTX_STATE_STARTUP,
|
||||
EPPING_CTX_STATE_STARTED,
|
||||
EPPING_CTX_STATE_STOP
|
||||
} epping_ctx_state_t;
|
||||
|
||||
#define EPPING_MAX_NUM_EPIDS 4
|
||||
#define MAX_COOKIE_SLOTS_NUM 4
|
||||
#define MAX_COOKIE_SLOT_SIZE 512
|
||||
#define MAX_TX_PKT_DUP_NUM 4
|
||||
|
||||
#if defined(HIF_PCI) || defined(HIF_IPCI)
|
||||
#define WLAN_EPPING_DELAY_TIMEOUT_US 10
|
||||
#define EPPING_MAX_CE_NUMS 8
|
||||
#define EPPING_MAX_WATER_MARK 8
|
||||
typedef struct {
|
||||
struct task_struct *pid;
|
||||
void *arg;
|
||||
bool done;
|
||||
qdf_nbuf_t skb;
|
||||
HTC_ENDPOINT_ID eid;
|
||||
struct semaphore sem;
|
||||
bool inited;
|
||||
qdf_atomic_t atm;
|
||||
} epping_poll_t;
|
||||
#endif
|
||||
|
||||
typedef struct epping_context {
|
||||
int32_t con_mode;
|
||||
char *pwlan_module_name;
|
||||
uint32_t target_type;
|
||||
void *p_cds_context; /* CDS context */
|
||||
struct device *parent_dev; /* Pointer to the parent device */
|
||||
epping_ctx_state_t e_ctx_state;
|
||||
bool wow_nack;
|
||||
void *epping_adapter;
|
||||
HTC_HANDLE HTCHandle;
|
||||
HTC_ENDPOINT_ID EppingEndpoint[EPPING_MAX_NUM_EPIDS];
|
||||
unsigned int kperf_num_rx_recv[EPPING_MAX_NUM_EPIDS];
|
||||
unsigned int kperf_num_tx_acks[EPPING_MAX_NUM_EPIDS];
|
||||
unsigned int total_rx_recv;
|
||||
unsigned int total_tx_acks;
|
||||
#if defined(HIF_PCI) || defined(HIF_IPCI)
|
||||
epping_poll_t epping_poll[EPPING_MAX_NUM_EPIDS];
|
||||
#endif
|
||||
struct epping_cookie *cookie_list;
|
||||
int cookie_count;
|
||||
struct epping_cookie *s_cookie_mem[MAX_COOKIE_SLOTS_NUM];
|
||||
qdf_spinlock_t cookie_lock;
|
||||
} epping_context_t;
|
||||
|
||||
typedef enum {
|
||||
EPPING_TX_TIMER_STOPPED,
|
||||
EPPING_TX_TIMER_RUNNING
|
||||
} epping_tx_timer_state_t;
|
||||
|
||||
typedef struct epping_adapter_s {
|
||||
epping_context_t *pEpping_ctx;
|
||||
enum QDF_OPMODE device_mode;
|
||||
/** Handle to the network device */
|
||||
struct net_device *dev;
|
||||
struct qdf_mac_addr macAddressCurrent;
|
||||
uint8_t sessionId;
|
||||
/* for mboxping */
|
||||
qdf_spinlock_t data_lock;
|
||||
qdf_nbuf_queue_t nodrop_queue;
|
||||
qdf_timer_t epping_timer;
|
||||
epping_tx_timer_state_t epping_timer_state;
|
||||
bool registered;
|
||||
bool started;
|
||||
struct net_device_stats stats;
|
||||
} epping_adapter_t;
|
||||
|
||||
/* epping_helper signatures */
|
||||
int epping_cookie_init(epping_context_t *pEpping_ctx);
|
||||
void epping_cookie_cleanup(epping_context_t *pEpping_ctx);
|
||||
void epping_free_cookie(epping_context_t *pEpping_ctx,
|
||||
struct epping_cookie *cookie);
|
||||
struct epping_cookie *epping_alloc_cookie(epping_context_t *pEpping_ctx);
|
||||
void epping_get_dummy_mac_addr(tSirMacAddr macAddr);
|
||||
void epping_hex_dump(void *data, int buf_len, const char *str);
|
||||
void *epping_get_qdf_ctx(void);
|
||||
void epping_log_packet(epping_adapter_t *adapter,
|
||||
EPPING_HEADER *eppingHdr, int ret, const char *str);
|
||||
void epping_log_stats(epping_adapter_t *adapter, const char *str);
|
||||
void epping_set_kperf_flag(epping_adapter_t *adapter,
|
||||
HTC_ENDPOINT_ID eid, uint8_t kperf_flag);
|
||||
|
||||
/* epping_tx signatures */
|
||||
void epping_tx_timer_expire(epping_adapter_t *adapter);
|
||||
void epping_tx_complete(void *ctx, HTC_PACKET *htc_pkt);
|
||||
int epping_tx_send(qdf_nbuf_t skb, epping_adapter_t *adapter);
|
||||
|
||||
#ifdef HIF_SDIO
|
||||
enum htc_send_full_action epping_tx_queue_full(void *Context,
|
||||
struct _HTC_PACKET *pPacket);
|
||||
#endif
|
||||
void epping_tx_dup_pkt(epping_adapter_t *adapter,
|
||||
HTC_ENDPOINT_ID eid, qdf_nbuf_t skb);
|
||||
/* epping_rx signatures */
|
||||
void epping_rx(void *Context, HTC_PACKET *pPacket);
|
||||
|
||||
#ifdef HIF_SDIO
|
||||
void epping_refill(void *ctx, HTC_ENDPOINT_ID Endpoint);
|
||||
#endif
|
||||
|
||||
/* epping_txrx signatures */
|
||||
epping_adapter_t *epping_add_adapter(epping_context_t *pEpping_ctx,
|
||||
tSirMacAddr macAddr,
|
||||
enum QDF_OPMODE device_mode,
|
||||
bool rtnl_held);
|
||||
void epping_destroy_adapter(epping_adapter_t *adapter);
|
||||
int epping_connect_service(epping_context_t *pEpping_ctx);
|
||||
#if defined(HIF_PCI) || defined(HIF_IPCI)
|
||||
void epping_register_tx_copier(HTC_ENDPOINT_ID eid,
|
||||
epping_context_t *pEpping_ctx);
|
||||
void epping_unregister_tx_copier(HTC_ENDPOINT_ID eid,
|
||||
epping_context_t *pEpping_ctx);
|
||||
void epping_tx_copier_schedule(epping_context_t *pEpping_ctx,
|
||||
HTC_ENDPOINT_ID eid, qdf_nbuf_t skb);
|
||||
#endif /* HIF_PCI || HIF_IPCI */
|
||||
#endif /* end #ifndef EPPING_INTERNAL_H */
|
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2019 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.
|
||||
*/
|
||||
|
||||
#ifndef EPPING_MAIN_H
|
||||
#define EPPING_MAIN_H
|
||||
/**===========================================================================
|
||||
|
||||
\file epping_main.h
|
||||
|
||||
\brief Linux epping head file
|
||||
|
||||
==========================================================================*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Include files
|
||||
-------------------------------------------------------------------------*/
|
||||
#include <qdf_lock.h>
|
||||
#include <qdf_types.h>
|
||||
|
||||
/* epping_main signatures */
|
||||
#ifdef WLAN_FEATURE_EPPING
|
||||
int epping_open(void);
|
||||
void epping_close(void);
|
||||
void epping_disable(void);
|
||||
int epping_enable(struct device *parent_dev, bool rtnl_held);
|
||||
void epping_enable_adapter(void);
|
||||
#else
|
||||
static inline int epping_open(void)
|
||||
{
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
static inline int epping_enable(struct device *parent_dev, bool rtnl_held)
|
||||
{
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
static inline void epping_close(void) {}
|
||||
static inline void epping_disable(void) {}
|
||||
static inline void epping_enable_adapter(void) {}
|
||||
#endif
|
||||
#endif /* end #ifndef EPPING_MAIN_H */
|
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2019 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.
|
||||
*/
|
||||
|
||||
/*========================================================================
|
||||
|
||||
\file epping_main.c
|
||||
|
||||
\brief WLAN End Point Ping test tool implementation
|
||||
|
||||
========================================================================*/
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Include Files
|
||||
------------------------------------------------------------------------*/
|
||||
#include <cds_api.h>
|
||||
#include <cds_sched.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/delay.h>
|
||||
#include <wni_api.h>
|
||||
#include <wlan_ptt_sock_svc.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ctype.h>
|
||||
#include "epping_main.h"
|
||||
#include "epping_internal.h"
|
||||
|
||||
int epping_cookie_init(epping_context_t *pEpping_ctx)
|
||||
{
|
||||
uint32_t i, j;
|
||||
|
||||
pEpping_ctx->cookie_list = NULL;
|
||||
pEpping_ctx->cookie_count = 0;
|
||||
for (i = 0; i < MAX_COOKIE_SLOTS_NUM; i++) {
|
||||
pEpping_ctx->s_cookie_mem[i] =
|
||||
qdf_mem_malloc(sizeof(struct epping_cookie) *
|
||||
MAX_COOKIE_SLOT_SIZE);
|
||||
if (!pEpping_ctx->s_cookie_mem[i])
|
||||
goto error;
|
||||
}
|
||||
qdf_spinlock_create(&pEpping_ctx->cookie_lock);
|
||||
|
||||
for (i = 0; i < MAX_COOKIE_SLOTS_NUM; i++) {
|
||||
struct epping_cookie *cookie_mem = pEpping_ctx->s_cookie_mem[i];
|
||||
for (j = 0; j < MAX_COOKIE_SLOT_SIZE; j++) {
|
||||
epping_free_cookie(pEpping_ctx, &cookie_mem[j]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
error:
|
||||
for (i = 0; i < MAX_COOKIE_SLOTS_NUM; i++) {
|
||||
if (pEpping_ctx->s_cookie_mem[i]) {
|
||||
qdf_mem_free(pEpping_ctx->s_cookie_mem[i]);
|
||||
pEpping_ctx->s_cookie_mem[i] = NULL;
|
||||
}
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* cleanup cookie queue */
|
||||
void epping_cookie_cleanup(epping_context_t *pEpping_ctx)
|
||||
{
|
||||
int i;
|
||||
qdf_spin_lock_bh(&pEpping_ctx->cookie_lock);
|
||||
pEpping_ctx->cookie_list = NULL;
|
||||
pEpping_ctx->cookie_count = 0;
|
||||
qdf_spin_unlock_bh(&pEpping_ctx->cookie_lock);
|
||||
for (i = 0; i < MAX_COOKIE_SLOTS_NUM; i++) {
|
||||
if (pEpping_ctx->s_cookie_mem[i]) {
|
||||
qdf_mem_free(pEpping_ctx->s_cookie_mem[i]);
|
||||
pEpping_ctx->s_cookie_mem[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void epping_free_cookie(epping_context_t *pEpping_ctx,
|
||||
struct epping_cookie *cookie)
|
||||
{
|
||||
qdf_spin_lock_bh(&pEpping_ctx->cookie_lock);
|
||||
cookie->next = pEpping_ctx->cookie_list;
|
||||
pEpping_ctx->cookie_list = cookie;
|
||||
pEpping_ctx->cookie_count++;
|
||||
qdf_spin_unlock_bh(&pEpping_ctx->cookie_lock);
|
||||
}
|
||||
|
||||
struct epping_cookie *epping_alloc_cookie(epping_context_t *pEpping_ctx)
|
||||
{
|
||||
struct epping_cookie *cookie;
|
||||
|
||||
qdf_spin_lock_bh(&pEpping_ctx->cookie_lock);
|
||||
cookie = pEpping_ctx->cookie_list;
|
||||
if (cookie) {
|
||||
pEpping_ctx->cookie_list = cookie->next;
|
||||
pEpping_ctx->cookie_count--;
|
||||
}
|
||||
qdf_spin_unlock_bh(&pEpping_ctx->cookie_lock);
|
||||
return cookie;
|
||||
}
|
||||
|
||||
void epping_get_dummy_mac_addr(tSirMacAddr macAddr)
|
||||
{
|
||||
macAddr[0] = 69; /* E */
|
||||
macAddr[1] = 80; /* P */
|
||||
macAddr[2] = 80; /* P */
|
||||
macAddr[3] = 73; /* I */
|
||||
macAddr[4] = 78; /* N */
|
||||
macAddr[5] = 71; /* G */
|
||||
}
|
||||
|
||||
void epping_hex_dump(void *data, int buf_len, const char *str)
|
||||
{
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL, "%s: E, %s", __func__, str);
|
||||
|
||||
EPPING_HEX_DUMP(QDF_TRACE_LEVEL_INFO, data, buf_len);
|
||||
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL, "%s: X %s", __func__, str);
|
||||
}
|
||||
|
||||
void *epping_get_qdf_ctx(void)
|
||||
{
|
||||
qdf_device_t *qdf_ctx;
|
||||
|
||||
qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
|
||||
return qdf_ctx;
|
||||
}
|
||||
|
||||
void epping_log_packet(epping_adapter_t *adapter,
|
||||
EPPING_HEADER *eppingHdr, int ret, const char *str)
|
||||
{
|
||||
if (eppingHdr->Cmd_h & EPPING_LOG_MASK) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: cmd = %d, seqNo = %u, flag = 0x%x, ret = %d, "
|
||||
"txCount = %lu, txDrop = %lu, txBytes = %lu,"
|
||||
"rxCount = %lu, rxDrop = %lu, rxBytes = %lu\n",
|
||||
str, eppingHdr->Cmd_h, eppingHdr->SeqNo,
|
||||
eppingHdr->CmdFlags_h, ret,
|
||||
adapter->stats.tx_packets,
|
||||
adapter->stats.tx_dropped,
|
||||
adapter->stats.tx_bytes,
|
||||
adapter->stats.rx_packets,
|
||||
adapter->stats.rx_dropped,
|
||||
adapter->stats.rx_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
void epping_log_stats(epping_adapter_t *adapter, const char *str)
|
||||
{
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: txCount = %lu, txDrop = %lu, tx_bytes = %lu, "
|
||||
"rxCount = %lu, rxDrop = %lu, rx_bytes = %lu, tx_acks = %u\n",
|
||||
str,
|
||||
adapter->stats.tx_packets,
|
||||
adapter->stats.tx_dropped,
|
||||
adapter->stats.tx_bytes,
|
||||
adapter->stats.rx_packets,
|
||||
adapter->stats.rx_dropped,
|
||||
adapter->stats.rx_bytes,
|
||||
adapter->pEpping_ctx->total_tx_acks);
|
||||
}
|
||||
|
||||
void epping_set_kperf_flag(epping_adapter_t *adapter,
|
||||
HTC_ENDPOINT_ID eid, uint8_t kperf_flag)
|
||||
{
|
||||
adapter->pEpping_ctx->kperf_num_rx_recv[eid] = 0;
|
||||
adapter->pEpping_ctx->kperf_num_tx_acks[eid] = 0;
|
||||
}
|
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2019,2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. 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.
|
||||
*/
|
||||
|
||||
/*========================================================================
|
||||
|
||||
\file epping_main.c
|
||||
|
||||
\brief WLAN End Point Ping test tool implementation
|
||||
|
||||
========================================================================*/
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Include Files
|
||||
------------------------------------------------------------------------*/
|
||||
#include <cds_api.h>
|
||||
#include <cds_sched.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <wni_api.h>
|
||||
#include <wlan_ptt_sock_svc.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/ctype.h>
|
||||
#include "bmi.h"
|
||||
#include "ol_fw.h"
|
||||
#include "ol_if_athvar.h"
|
||||
#include "hif.h"
|
||||
#include "epping_main.h"
|
||||
#include "epping_internal.h"
|
||||
#include "wlan_policy_mgr_api.h"
|
||||
|
||||
#ifdef TIMER_MANAGER
|
||||
#define TIMER_MANAGER_STR " +TIMER_MANAGER"
|
||||
#else
|
||||
#define TIMER_MANAGER_STR ""
|
||||
#endif
|
||||
|
||||
#ifdef MEMORY_DEBUG
|
||||
#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
|
||||
#else
|
||||
#define MEMORY_DEBUG_STR ""
|
||||
#endif
|
||||
|
||||
#ifdef HIF_SDIO
|
||||
#define WLAN_WAIT_TIME_WLANSTART 10000
|
||||
#else
|
||||
#define WLAN_WAIT_TIME_WLANSTART 2000
|
||||
#endif
|
||||
|
||||
#ifdef WLAN_FEATURE_EPPING
|
||||
static struct epping_context *g_epping_ctx;
|
||||
|
||||
/**
|
||||
* epping_open(): End point ping driver open Function
|
||||
*
|
||||
* This function is called by HDD to open epping module
|
||||
*
|
||||
*
|
||||
* return - 0 for success, negative for failure
|
||||
*/
|
||||
int epping_open(void)
|
||||
{
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: Enter", __func__);
|
||||
|
||||
g_epping_ctx = qdf_mem_malloc(sizeof(*g_epping_ctx));
|
||||
|
||||
if (!g_epping_ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
g_epping_ctx->con_mode = cds_get_conparam();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* epping_disable(): End point ping driver disable Function
|
||||
*
|
||||
* This is the driver disable function - called by HDD to
|
||||
* disable epping module
|
||||
*
|
||||
* return: none
|
||||
*/
|
||||
void epping_disable(void)
|
||||
{
|
||||
epping_context_t *epping_ctx;
|
||||
struct hif_opaque_softc *hif_ctx;
|
||||
HTC_HANDLE htc_handle;
|
||||
|
||||
epping_ctx = g_epping_ctx;
|
||||
if (!epping_ctx) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: error: epping_ctx = NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
|
||||
if (!hif_ctx) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: error: hif_ctx = NULL", __func__);
|
||||
return;
|
||||
}
|
||||
hif_disable_isr(hif_ctx);
|
||||
hif_reset_soc(hif_ctx);
|
||||
|
||||
htc_handle = cds_get_context(QDF_MODULE_ID_HTC);
|
||||
if (!htc_handle) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: error: htc_handle = NULL", __func__);
|
||||
return;
|
||||
}
|
||||
htc_stop(htc_handle);
|
||||
epping_cookie_cleanup(epping_ctx);
|
||||
htc_destroy(htc_handle);
|
||||
|
||||
if (epping_ctx->epping_adapter) {
|
||||
epping_destroy_adapter(epping_ctx->epping_adapter);
|
||||
epping_ctx->epping_adapter = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* epping_close(): End point ping driver close Function
|
||||
*
|
||||
* This is the driver close function - called by HDD to close epping module
|
||||
*
|
||||
* return: none
|
||||
*/
|
||||
void epping_close(void)
|
||||
{
|
||||
epping_context_t *to_free;
|
||||
|
||||
if (!g_epping_ctx) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: error: g_epping_ctx = NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
to_free = g_epping_ctx;
|
||||
g_epping_ctx = NULL;
|
||||
qdf_mem_free(to_free);
|
||||
}
|
||||
|
||||
/**
|
||||
* epping_target_suspend_acknowledge() - process wow ack/nack from fw
|
||||
* @context: htc_init_info->context
|
||||
* @wow_nack: true when wow is rejected
|
||||
* @reason_code : WoW status reason code
|
||||
*/
|
||||
static void epping_target_suspend_acknowledge(void *context, bool wow_nack,
|
||||
uint16_t reson_code)
|
||||
{
|
||||
if (!g_epping_ctx) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: epping_ctx is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
/* EPPING_TODO: do we need wow_nack? */
|
||||
g_epping_ctx->wow_nack = wow_nack;
|
||||
}
|
||||
|
||||
#ifdef WLAN_FEATURE_BMI
|
||||
/**
|
||||
* epping_update_ol_config - API to update ol configuration parameters
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void epping_update_ol_config(void)
|
||||
{
|
||||
struct ol_config_info cfg;
|
||||
struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
|
||||
|
||||
if (!ol_ctx)
|
||||
return;
|
||||
|
||||
cfg.enable_self_recovery = 0;
|
||||
cfg.enable_uart_print = 0;
|
||||
cfg.enable_fw_log = 0;
|
||||
cfg.enable_ramdump_collection = 0;
|
||||
cfg.enable_lpass_support = 0;
|
||||
|
||||
ol_init_ini_config(ol_ctx, &cfg);
|
||||
}
|
||||
|
||||
static
|
||||
QDF_STATUS epping_bmi_download_fw(struct ol_context *ol_ctx)
|
||||
{
|
||||
epping_update_ol_config();
|
||||
|
||||
/* Initialize BMI and Download firmware */
|
||||
if (bmi_download_firmware(ol_ctx)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: BMI failed to download target", __func__);
|
||||
bmi_cleanup(ol_ctx);
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH,
|
||||
"%s: bmi_download_firmware done", __func__);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
#else
|
||||
static
|
||||
QDF_STATUS epping_bmi_download_fw(struct ol_context *ol_ctx)
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* epping_enable(): End point ping driver enable Function
|
||||
*
|
||||
* This is the driver enable function - called by HDD to enable
|
||||
* epping module
|
||||
*
|
||||
* return - 0 : success, negative: error
|
||||
*/
|
||||
int epping_enable(struct device *parent_dev, bool rtnl_held)
|
||||
{
|
||||
int ret = 0;
|
||||
epping_context_t *epping_ctx = NULL;
|
||||
struct cds_context *p_cds_context = NULL;
|
||||
qdf_device_t qdf_ctx;
|
||||
struct htc_init_info htc_info;
|
||||
struct hif_opaque_softc *scn;
|
||||
tSirMacAddr adapter_macAddr;
|
||||
struct ol_context *ol_ctx = NULL;
|
||||
struct hif_target_info *tgt_info;
|
||||
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: Enter", __func__);
|
||||
|
||||
p_cds_context = cds_get_global_context();
|
||||
|
||||
if (!p_cds_context) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: Failed cds_get_global_context", __func__);
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
epping_ctx = g_epping_ctx;
|
||||
if (!epping_ctx) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: Failed to get epping_ctx", __func__);
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
epping_ctx->parent_dev = (void *)parent_dev;
|
||||
epping_get_dummy_mac_addr(adapter_macAddr);
|
||||
|
||||
/* Initialize the timer module */
|
||||
qdf_timer_module_init();
|
||||
|
||||
scn = cds_get_context(QDF_MODULE_ID_HIF);
|
||||
if (!scn) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: scn is null!", __func__);
|
||||
return A_ERROR;
|
||||
}
|
||||
|
||||
tgt_info = hif_get_target_info_handle(scn);
|
||||
|
||||
ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
|
||||
|
||||
if (epping_bmi_download_fw(ol_ctx) != QDF_STATUS_SUCCESS)
|
||||
return A_ERROR;
|
||||
|
||||
/* store target type and target version info in hdd ctx */
|
||||
epping_ctx->target_type = tgt_info->target_type;
|
||||
|
||||
htc_info.pContext = NULL;
|
||||
htc_info.TargetFailure = ol_target_failure;
|
||||
htc_info.TargetSendSuspendComplete = epping_target_suspend_acknowledge;
|
||||
qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
|
||||
|
||||
/* Create HTC */
|
||||
p_cds_context->htc_ctx = htc_create(scn, &htc_info, qdf_ctx,
|
||||
cds_get_conparam());
|
||||
if (!p_cds_context->htc_ctx) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: Failed to Create HTC", __func__);
|
||||
bmi_cleanup(ol_ctx);
|
||||
return A_ERROR;
|
||||
}
|
||||
epping_ctx->HTCHandle =
|
||||
cds_get_context(QDF_MODULE_ID_HTC);
|
||||
if (!epping_ctx->HTCHandle) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: HTCHandle is NULL", __func__);
|
||||
return A_ERROR;
|
||||
}
|
||||
|
||||
if (bmi_done(ol_ctx)) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: Failed to complete BMI phase", __func__);
|
||||
goto error_end;
|
||||
}
|
||||
|
||||
/* start HIF */
|
||||
if (htc_wait_target(epping_ctx->HTCHandle) != QDF_STATUS_SUCCESS) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: htc_wait_target error", __func__);
|
||||
goto error_end;
|
||||
}
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: HTC ready", __func__);
|
||||
|
||||
ret = epping_connect_service(epping_ctx);
|
||||
if (ret != 0) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: htc_wait_targetdone", __func__);
|
||||
goto error_end;
|
||||
}
|
||||
if (htc_start(epping_ctx->HTCHandle) != QDF_STATUS_SUCCESS)
|
||||
goto error_end;
|
||||
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: HTC started", __func__);
|
||||
|
||||
/* init the tx cookie resource */
|
||||
ret = epping_cookie_init(epping_ctx);
|
||||
if (ret < 0) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: cookie init failed", __func__);
|
||||
htc_stop(epping_ctx->HTCHandle);
|
||||
epping_cookie_cleanup(epping_ctx);
|
||||
goto error_end;
|
||||
}
|
||||
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: Exit", __func__);
|
||||
return ret;
|
||||
|
||||
error_end:
|
||||
htc_destroy(p_cds_context->htc_ctx);
|
||||
p_cds_context->htc_ctx = NULL;
|
||||
bmi_cleanup(ol_ctx);
|
||||
return A_ERROR;
|
||||
}
|
||||
|
||||
void epping_enable_adapter(void)
|
||||
{
|
||||
epping_context_t *epping_ctx = g_epping_ctx;
|
||||
tSirMacAddr adapter_macaddr;
|
||||
|
||||
if (!epping_ctx) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL, "epping context is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
epping_get_dummy_mac_addr(adapter_macaddr);
|
||||
epping_ctx->epping_adapter = epping_add_adapter(epping_ctx,
|
||||
adapter_macaddr,
|
||||
QDF_STA_MODE, true);
|
||||
if (!epping_ctx->epping_adapter)
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL, "epping add adapter failed");
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2017, 2019 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.
|
||||
*/
|
||||
|
||||
/*========================================================================
|
||||
|
||||
\file epping_rx.c
|
||||
|
||||
\brief WLAN End Point Ping test tool implementation
|
||||
|
||||
========================================================================*/
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Include Files
|
||||
------------------------------------------------------------------------*/
|
||||
#include <cds_api.h>
|
||||
#include <cds_sched.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <wni_api.h>
|
||||
#include <wlan_ptt_sock_svc.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/ctype.h>
|
||||
#include "epping_main.h"
|
||||
#include "epping_internal.h"
|
||||
#include "epping_test.h"
|
||||
#include <wlan_hdd_napi.h>
|
||||
|
||||
#define AR6000_MAX_RX_BUFFERS 16
|
||||
#define AR6000_BUFFER_SIZE 1664
|
||||
#define AR6000_MIN_HEAD_ROOM 64
|
||||
|
||||
static bool enb_rx_dump;
|
||||
|
||||
#ifdef HIF_SDIO
|
||||
void epping_refill(void *ctx, HTC_ENDPOINT_ID Endpoint)
|
||||
{
|
||||
epping_context_t *pEpping_ctx = (epping_context_t *) ctx;
|
||||
void *osBuf;
|
||||
int RxBuffers;
|
||||
int buffersToRefill;
|
||||
HTC_PACKET *pPacket;
|
||||
HTC_PACKET_QUEUE queue;
|
||||
|
||||
buffersToRefill = (int)AR6000_MAX_RX_BUFFERS -
|
||||
htc_get_num_recv_buffers(pEpping_ctx->HTCHandle, Endpoint);
|
||||
|
||||
if (buffersToRefill <= 0) {
|
||||
/* fast return, nothing to fill */
|
||||
return;
|
||||
}
|
||||
|
||||
INIT_HTC_PACKET_QUEUE(&queue);
|
||||
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_INFO,
|
||||
"%s: providing htc with %d buffers at eid=%d\n",
|
||||
__func__, buffersToRefill, Endpoint);
|
||||
|
||||
for (RxBuffers = 0; RxBuffers < buffersToRefill; RxBuffers++) {
|
||||
osBuf = qdf_nbuf_alloc(NULL, AR6000_BUFFER_SIZE,
|
||||
AR6000_MIN_HEAD_ROOM, 4, false);
|
||||
if (!osBuf) {
|
||||
break;
|
||||
}
|
||||
/* the HTC packet wrapper is at the head of the reserved area
|
||||
* in the skb */
|
||||
pPacket = (HTC_PACKET *) (A_NETBUF_HEAD(osBuf));
|
||||
/* set re-fill info */
|
||||
SET_HTC_PACKET_INFO_RX_REFILL(pPacket, osBuf,
|
||||
qdf_nbuf_data(osBuf),
|
||||
AR6000_BUFFER_SIZE, Endpoint);
|
||||
SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, osBuf);
|
||||
/* add to queue */
|
||||
HTC_PACKET_ENQUEUE(&queue, pPacket);
|
||||
}
|
||||
|
||||
if (!HTC_QUEUE_EMPTY(&queue)) {
|
||||
/* add packets */
|
||||
htc_add_receive_pkt_multiple(pEpping_ctx->HTCHandle, &queue);
|
||||
}
|
||||
}
|
||||
#endif /* HIF_SDIO */
|
||||
|
||||
void epping_rx(void *ctx, HTC_PACKET *pPacket)
|
||||
{
|
||||
epping_context_t *pEpping_ctx = (epping_context_t *) ctx;
|
||||
epping_adapter_t *adapter = pEpping_ctx->epping_adapter;
|
||||
struct net_device *dev = adapter->dev;
|
||||
QDF_STATUS status = pPacket->Status;
|
||||
HTC_ENDPOINT_ID eid = pPacket->Endpoint;
|
||||
struct sk_buff *pktSkb = (struct sk_buff *)pPacket->pPktContext;
|
||||
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_INFO,
|
||||
"%s: adapter = 0x%pK eid=%d, skb=0x%pK, data=0x%pK, len=0x%x status:%d",
|
||||
__func__, adapter, eid, pktSkb, pPacket->pBuffer,
|
||||
pPacket->ActualLength, status);
|
||||
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
if (status != QDF_STATUS_E_CANCELED) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_ERROR, "%s: RX ERR (%d)",
|
||||
__func__, status);
|
||||
}
|
||||
qdf_nbuf_free(pktSkb);
|
||||
return;
|
||||
}
|
||||
|
||||
/* deliver to up layer */
|
||||
if (pktSkb) {
|
||||
if (EPPING_ALIGNMENT_PAD > 0) {
|
||||
A_NETBUF_PULL(pktSkb, EPPING_ALIGNMENT_PAD);
|
||||
}
|
||||
if (enb_rx_dump)
|
||||
epping_hex_dump((void *)qdf_nbuf_data(pktSkb),
|
||||
pktSkb->len, __func__);
|
||||
pktSkb->dev = dev;
|
||||
if ((pktSkb->dev->flags & IFF_UP) == IFF_UP) {
|
||||
pktSkb->protocol = eth_type_trans(pktSkb, pktSkb->dev);
|
||||
++adapter->stats.rx_packets;
|
||||
adapter->stats.rx_bytes += pktSkb->len;
|
||||
qdf_net_buf_debug_release_skb(pktSkb);
|
||||
if (hdd_napi_enabled(HDD_NAPI_ANY))
|
||||
netif_receive_skb(pktSkb);
|
||||
else
|
||||
netif_rx_ni(pktSkb);
|
||||
if ((adapter->stats.rx_packets %
|
||||
EPPING_STATS_LOG_COUNT) == 0) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: total_rx_pkts = %lu",
|
||||
__func__,
|
||||
adapter->stats.rx_packets);
|
||||
}
|
||||
} else {
|
||||
++adapter->stats.rx_dropped;
|
||||
qdf_nbuf_free(pktSkb);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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.
|
||||
*/
|
||||
|
||||
/*========================================================================
|
||||
|
||||
\file epping_tx.c
|
||||
|
||||
\brief WLAN End Point Ping test tool implementation
|
||||
|
||||
========================================================================*/
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Include Files
|
||||
------------------------------------------------------------------------*/
|
||||
#include <cds_api.h>
|
||||
#include <cds_sched.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <wni_api.h>
|
||||
#include <wlan_ptt_sock_svc.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/ctype.h>
|
||||
#include "epping_main.h"
|
||||
#include "epping_internal.h"
|
||||
#include "epping_test.h"
|
||||
|
||||
#define TX_RETRY_TIMEOUT_IN_MS 1
|
||||
|
||||
static bool enb_tx_dump;
|
||||
|
||||
void epping_tx_dup_pkt(epping_adapter_t *adapter,
|
||||
HTC_ENDPOINT_ID eid, qdf_nbuf_t skb)
|
||||
{
|
||||
struct epping_cookie *cookie = NULL;
|
||||
int skb_len, ret;
|
||||
qdf_nbuf_t new_skb;
|
||||
|
||||
cookie = epping_alloc_cookie(adapter->pEpping_ctx);
|
||||
if (!cookie) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: epping_alloc_cookie returns no resource\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
new_skb = qdf_nbuf_copy(skb);
|
||||
if (!new_skb) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: qdf_nbuf_copy returns no resource\n", __func__);
|
||||
epping_free_cookie(adapter->pEpping_ctx, cookie);
|
||||
return;
|
||||
}
|
||||
SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt,
|
||||
cookie, qdf_nbuf_data(skb),
|
||||
qdf_nbuf_len(new_skb), eid, 0);
|
||||
SET_HTC_PACKET_NET_BUF_CONTEXT(&cookie->HtcPkt, new_skb);
|
||||
skb_len = (int)qdf_nbuf_len(new_skb);
|
||||
/* send the packet */
|
||||
ret = htc_send_pkt(adapter->pEpping_ctx->HTCHandle, &cookie->HtcPkt);
|
||||
if (ret != QDF_STATUS_SUCCESS) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: htc_send_pkt failed, ret = %d\n", __func__, ret);
|
||||
epping_free_cookie(adapter->pEpping_ctx, cookie);
|
||||
qdf_nbuf_free(new_skb);
|
||||
return;
|
||||
}
|
||||
adapter->stats.tx_bytes += skb_len;
|
||||
++adapter->stats.tx_packets;
|
||||
if (((adapter->stats.tx_packets +
|
||||
adapter->stats.tx_dropped) % EPPING_STATS_LOG_COUNT) == 0 &&
|
||||
(adapter->stats.tx_packets || adapter->stats.tx_dropped)) {
|
||||
epping_log_stats(adapter, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
static int epping_tx_send_int(qdf_nbuf_t skb, epping_adapter_t *adapter)
|
||||
{
|
||||
EPPING_HEADER *eppingHdr = (EPPING_HEADER *) qdf_nbuf_data(skb);
|
||||
HTC_ENDPOINT_ID eid = ENDPOINT_UNUSED;
|
||||
struct epping_cookie *cookie = NULL;
|
||||
uint8_t ac = 0;
|
||||
QDF_STATUS ret = QDF_STATUS_SUCCESS;
|
||||
int skb_len;
|
||||
EPPING_HEADER tmpHdr = *eppingHdr;
|
||||
|
||||
/* allocate resource for this packet */
|
||||
cookie = epping_alloc_cookie(adapter->pEpping_ctx);
|
||||
/* no resource */
|
||||
if (!cookie) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: epping_alloc_cookie returns no resource\n",
|
||||
__func__);
|
||||
return A_ERROR;
|
||||
}
|
||||
|
||||
if (enb_tx_dump)
|
||||
epping_hex_dump((void *)eppingHdr, skb->len, __func__);
|
||||
/*
|
||||
* a quirk of linux, the payload of the frame is 32-bit aligned and thus
|
||||
* the addition of the HTC header will mis-align the start of the HTC
|
||||
* frame, so we add some padding which will be stripped off in the target
|
||||
*/
|
||||
if (EPPING_ALIGNMENT_PAD > 0) {
|
||||
A_NETBUF_PUSH(skb, EPPING_ALIGNMENT_PAD);
|
||||
}
|
||||
/* prepare ep/HTC information */
|
||||
ac = eppingHdr->StreamNo_h;
|
||||
eid = adapter->pEpping_ctx->EppingEndpoint[ac];
|
||||
if (eid < 0 || eid >= EPPING_MAX_NUM_EPIDS) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: invalid eid = %d, ac = %d\n", __func__, eid,
|
||||
ac);
|
||||
return A_ERROR;
|
||||
}
|
||||
if (tmpHdr.Cmd_h == EPPING_CMD_RESET_RECV_CNT ||
|
||||
tmpHdr.Cmd_h == EPPING_CMD_CONT_RX_START) {
|
||||
epping_set_kperf_flag(adapter, eid, tmpHdr.CmdBuffer_t[0]);
|
||||
}
|
||||
SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt,
|
||||
cookie, qdf_nbuf_data(skb), qdf_nbuf_len(skb),
|
||||
eid, 0);
|
||||
SET_HTC_PACKET_NET_BUF_CONTEXT(&cookie->HtcPkt, skb);
|
||||
skb_len = skb->len;
|
||||
/* send the packet */
|
||||
ret = htc_send_pkt(adapter->pEpping_ctx->HTCHandle, &cookie->HtcPkt);
|
||||
epping_log_packet(adapter, &tmpHdr, ret, __func__);
|
||||
if (ret != QDF_STATUS_SUCCESS) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: htc_send_pkt failed, status = %d\n", __func__,
|
||||
ret);
|
||||
epping_free_cookie(adapter->pEpping_ctx, cookie);
|
||||
return A_ERROR;
|
||||
}
|
||||
adapter->stats.tx_bytes += skb_len;
|
||||
++adapter->stats.tx_packets;
|
||||
if (((adapter->stats.tx_packets +
|
||||
adapter->stats.tx_dropped) % EPPING_STATS_LOG_COUNT) == 0 &&
|
||||
(adapter->stats.tx_packets || adapter->stats.tx_dropped)) {
|
||||
epping_log_stats(adapter, __func__);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void epping_tx_timer_expire(epping_adapter_t *adapter)
|
||||
{
|
||||
qdf_nbuf_t nodrop_skb;
|
||||
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_INFO, "%s: queue len: %d\n", __func__,
|
||||
qdf_nbuf_queue_len(&adapter->nodrop_queue));
|
||||
|
||||
if (!qdf_nbuf_queue_len(&adapter->nodrop_queue)) {
|
||||
/* nodrop queue is empty so no need to arm timer */
|
||||
adapter->epping_timer_state = EPPING_TX_TIMER_STOPPED;
|
||||
return;
|
||||
}
|
||||
|
||||
/* try to flush nodrop queue */
|
||||
while ((nodrop_skb = qdf_nbuf_queue_remove(&adapter->nodrop_queue))) {
|
||||
htc_set_nodrop_pkt(adapter->pEpping_ctx->HTCHandle, true);
|
||||
if (epping_tx_send_int(nodrop_skb, adapter)) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: nodrop: %pK xmit fail in timer\n",
|
||||
__func__, nodrop_skb);
|
||||
/* fail to xmit so put the nodrop packet to the nodrop queue */
|
||||
qdf_nbuf_queue_insert_head(&adapter->nodrop_queue,
|
||||
nodrop_skb);
|
||||
break;
|
||||
} else {
|
||||
htc_set_nodrop_pkt(adapter->pEpping_ctx->HTCHandle, false);
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_INFO,
|
||||
"%s: nodrop: %pK xmit ok in timer\n",
|
||||
__func__, nodrop_skb);
|
||||
}
|
||||
}
|
||||
|
||||
/* if nodrop queue is not empty, continue to arm timer */
|
||||
if (nodrop_skb) {
|
||||
qdf_spin_lock_bh(&adapter->data_lock);
|
||||
/* if nodrop queue is not empty, continue to arm timer */
|
||||
if (adapter->epping_timer_state != EPPING_TX_TIMER_RUNNING) {
|
||||
adapter->epping_timer_state = EPPING_TX_TIMER_RUNNING;
|
||||
qdf_timer_mod(&adapter->epping_timer,
|
||||
TX_RETRY_TIMEOUT_IN_MS);
|
||||
}
|
||||
qdf_spin_unlock_bh(&adapter->data_lock);
|
||||
} else {
|
||||
adapter->epping_timer_state = EPPING_TX_TIMER_STOPPED;
|
||||
}
|
||||
}
|
||||
|
||||
int epping_tx_send(qdf_nbuf_t skb, epping_adapter_t *adapter)
|
||||
{
|
||||
qdf_nbuf_t nodrop_skb;
|
||||
EPPING_HEADER *eppingHdr;
|
||||
uint8_t ac = 0;
|
||||
|
||||
eppingHdr = (EPPING_HEADER *) qdf_nbuf_data(skb);
|
||||
|
||||
if (!IS_EPPING_PACKET(eppingHdr)) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: Received non endpoint ping packets\n", __func__);
|
||||
/* no packet to send, cleanup */
|
||||
qdf_nbuf_free(skb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* the stream ID is mapped to an access class */
|
||||
ac = eppingHdr->StreamNo_h;
|
||||
/* hard coded two ep ids */
|
||||
if (ac != 0 && ac != 1) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: ac %d is not mapped to mboxping service\n",
|
||||
__func__, ac);
|
||||
qdf_nbuf_free(skb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* some EPPING packets cannot be dropped no matter what access class
|
||||
* it was sent on. A special care has been taken:
|
||||
* 1. when there is no TX resource, queue the control packets to
|
||||
* a special queue
|
||||
* 2. when there is TX resource, send the queued control packets first
|
||||
* and then other packets
|
||||
* 3. a timer launches to check if there is queued control packets and
|
||||
* flush them
|
||||
*/
|
||||
|
||||
/* check the nodrop queue first */
|
||||
while ((nodrop_skb = qdf_nbuf_queue_remove(&adapter->nodrop_queue))) {
|
||||
htc_set_nodrop_pkt(adapter->pEpping_ctx->HTCHandle, true);
|
||||
if (epping_tx_send_int(nodrop_skb, adapter)) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: nodrop: %pK xmit fail\n", __func__,
|
||||
nodrop_skb);
|
||||
/* fail to xmit so put the nodrop packet to the nodrop queue */
|
||||
qdf_nbuf_queue_insert_head(&adapter->nodrop_queue,
|
||||
nodrop_skb);
|
||||
/* no cookie so free the current skb */
|
||||
goto tx_fail;
|
||||
} else {
|
||||
htc_set_nodrop_pkt(adapter->pEpping_ctx->HTCHandle, false);
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_INFO,
|
||||
"%s: nodrop: %pK xmit ok\n", __func__,
|
||||
nodrop_skb);
|
||||
}
|
||||
}
|
||||
|
||||
/* send the original packet */
|
||||
if (epping_tx_send_int(skb, adapter))
|
||||
goto tx_fail;
|
||||
|
||||
return 0;
|
||||
|
||||
tx_fail:
|
||||
if (!IS_EPING_PACKET_NO_DROP(eppingHdr)) {
|
||||
/* allow to drop the skb so drop it */
|
||||
qdf_nbuf_free(skb);
|
||||
++adapter->stats.tx_dropped;
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: Tx skb %pK dropped, stats.tx_dropped = %ld\n",
|
||||
__func__, skb, adapter->stats.tx_dropped);
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: nodrop: %pK queued\n", __func__, skb);
|
||||
qdf_nbuf_queue_add(&adapter->nodrop_queue, skb);
|
||||
qdf_spin_lock_bh(&adapter->data_lock);
|
||||
if (adapter->epping_timer_state != EPPING_TX_TIMER_RUNNING) {
|
||||
adapter->epping_timer_state = EPPING_TX_TIMER_RUNNING;
|
||||
qdf_timer_mod(&adapter->epping_timer,
|
||||
TX_RETRY_TIMEOUT_IN_MS);
|
||||
}
|
||||
qdf_spin_unlock_bh(&adapter->data_lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HIF_SDIO
|
||||
enum htc_send_full_action epping_tx_queue_full(void *Context,
|
||||
HTC_PACKET *pPacket)
|
||||
{
|
||||
/*
|
||||
* Call netif_stop_queue frequently will impact the mboxping tx t-put.
|
||||
* Return HTC_SEND_FULL_KEEP directly in epping_tx_queue_full to avoid.
|
||||
*/
|
||||
return HTC_SEND_FULL_KEEP;
|
||||
}
|
||||
#endif /* HIF_SDIO */
|
||||
void epping_tx_complete(void *ctx, HTC_PACKET *htc_pkt)
|
||||
{
|
||||
epping_context_t *pEpping_ctx = (epping_context_t *) ctx;
|
||||
epping_adapter_t *adapter = pEpping_ctx->epping_adapter;
|
||||
struct net_device *dev = adapter->dev;
|
||||
QDF_STATUS status;
|
||||
HTC_ENDPOINT_ID eid;
|
||||
qdf_nbuf_t pktSkb;
|
||||
struct epping_cookie *cookie;
|
||||
A_BOOL flushing = false;
|
||||
qdf_nbuf_queue_t skb_queue;
|
||||
|
||||
if (!htc_pkt)
|
||||
return;
|
||||
|
||||
qdf_nbuf_queue_init(&skb_queue);
|
||||
|
||||
qdf_spin_lock_bh(&adapter->data_lock);
|
||||
|
||||
status = htc_pkt->Status;
|
||||
eid = htc_pkt->Endpoint;
|
||||
pktSkb = GET_HTC_PACKET_NET_BUF_CONTEXT(htc_pkt);
|
||||
cookie = htc_pkt->pPktContext;
|
||||
|
||||
if (!pktSkb) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: NULL skb from hc packet", __func__);
|
||||
QDF_BUG(0);
|
||||
} else {
|
||||
if (htc_pkt->pBuffer != qdf_nbuf_data(pktSkb)) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: htc_pkt buffer not equal to skb->data",
|
||||
__func__);
|
||||
QDF_BUG(0);
|
||||
}
|
||||
/* add this to the list, use faster non-lock API */
|
||||
qdf_nbuf_queue_add(&skb_queue, pktSkb);
|
||||
|
||||
if (QDF_IS_STATUS_SUCCESS(status)) {
|
||||
if (htc_pkt->ActualLength !=
|
||||
qdf_nbuf_len(pktSkb)) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: htc_pkt length not equal to skb->len",
|
||||
__func__);
|
||||
QDF_BUG(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_INFO,
|
||||
"%s skb=%pK data=%pK len=0x%x eid=%d ",
|
||||
__func__, pktSkb, htc_pkt->pBuffer,
|
||||
htc_pkt->ActualLength, eid);
|
||||
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
if (status == QDF_STATUS_E_CANCELED) {
|
||||
/* a packet was flushed */
|
||||
flushing = true;
|
||||
}
|
||||
if (status != QDF_STATUS_E_RESOURCES) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_ERROR,
|
||||
"%s() -TX ERROR, status: 0x%x",
|
||||
__func__, status);
|
||||
}
|
||||
} else {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_INFO, "%s: OK\n", __func__);
|
||||
flushing = false;
|
||||
}
|
||||
|
||||
epping_free_cookie(adapter->pEpping_ctx, cookie);
|
||||
qdf_spin_unlock_bh(&adapter->data_lock);
|
||||
|
||||
/* free all skbs in our local list */
|
||||
while (qdf_nbuf_queue_len(&skb_queue)) {
|
||||
/* use non-lock version */
|
||||
pktSkb = qdf_nbuf_queue_remove(&skb_queue);
|
||||
if (!pktSkb)
|
||||
break;
|
||||
qdf_nbuf_tx_free(pktSkb, QDF_NBUF_PKT_ERROR);
|
||||
pEpping_ctx->total_tx_acks++;
|
||||
}
|
||||
|
||||
if (!flushing) {
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
}
|
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. 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.
|
||||
*/
|
||||
|
||||
/*========================================================================
|
||||
|
||||
\file epping_txrx.c
|
||||
|
||||
\brief WLAN End Point Ping test tool implementation
|
||||
|
||||
========================================================================*/
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Include Files
|
||||
------------------------------------------------------------------------*/
|
||||
#include <cds_api.h>
|
||||
#include <cds_sched.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <wni_api.h>
|
||||
#include <wlan_ptt_sock_svc.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <pld_common.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/ctype.h>
|
||||
#include "epping_main.h"
|
||||
#include "epping_internal.h"
|
||||
#include "qdf_net_if.h"
|
||||
|
||||
static int epping_start_adapter(epping_adapter_t *adapter);
|
||||
static void epping_stop_adapter(epping_adapter_t *adapter);
|
||||
|
||||
static void epping_timer_expire(void *data)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *)data;
|
||||
epping_adapter_t *adapter;
|
||||
|
||||
if (!dev) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: netdev = NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
adapter = netdev_priv(dev);
|
||||
if (!adapter) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: adapter = NULL", __func__);
|
||||
return;
|
||||
}
|
||||
adapter->epping_timer_state = EPPING_TX_TIMER_STOPPED;
|
||||
epping_tx_timer_expire(adapter);
|
||||
}
|
||||
|
||||
static int epping_ndev_open(struct net_device *dev)
|
||||
{
|
||||
epping_adapter_t *adapter;
|
||||
int ret = 0;
|
||||
|
||||
adapter = netdev_priv(dev);
|
||||
epping_start_adapter(adapter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int epping_ndev_stop(struct net_device *dev)
|
||||
{
|
||||
epping_adapter_t *adapter;
|
||||
int ret = 0;
|
||||
|
||||
adapter = netdev_priv(dev);
|
||||
if (!adapter) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: EPPING adapter context is Null", __func__);
|
||||
ret = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
epping_stop_adapter(adapter);
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void epping_ndev_uninit(struct net_device *dev)
|
||||
{
|
||||
epping_adapter_t *adapter;
|
||||
|
||||
adapter = netdev_priv(dev);
|
||||
if (!adapter) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: EPPING adapter context is Null", __func__);
|
||||
goto end;
|
||||
}
|
||||
epping_stop_adapter(adapter);
|
||||
end:
|
||||
return;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
|
||||
static void epping_tx_queue_timeout(struct net_device *dev,
|
||||
unsigned int txqueue)
|
||||
#else
|
||||
static void epping_tx_queue_timeout(struct net_device *dev)
|
||||
#endif
|
||||
{
|
||||
epping_adapter_t *adapter;
|
||||
|
||||
adapter = netdev_priv(dev);
|
||||
if (!adapter) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: EPPING adapter context is Null", __func__);
|
||||
goto end;
|
||||
}
|
||||
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: Transmission timeout occurred, adapter->started= %d",
|
||||
__func__, adapter->started);
|
||||
|
||||
/* Getting here implies we disabled the TX queues
|
||||
* for too long. Since this is epping
|
||||
* (not because of disassociation or low resource scenarios),
|
||||
* try to restart the queue
|
||||
*/
|
||||
if (adapter->started)
|
||||
netif_wake_queue(dev);
|
||||
end:
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
static netdev_tx_t epping_hard_start_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
epping_adapter_t *adapter;
|
||||
int ret = 0;
|
||||
|
||||
adapter = netdev_priv(dev);
|
||||
if (!adapter) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: EPPING adapter context is Null", __func__);
|
||||
kfree_skb(skb);
|
||||
ret = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
qdf_net_buf_debug_acquire_skb(skb, __FILE__, __LINE__);
|
||||
ret = epping_tx_send(skb, adapter);
|
||||
end:
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static struct net_device_stats *epping_get_stats(struct net_device *dev)
|
||||
{
|
||||
epping_adapter_t *adapter = netdev_priv(dev);
|
||||
|
||||
if (!adapter) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_ERROR, "%s: adapter = NULL",
|
||||
__func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &adapter->stats;
|
||||
}
|
||||
|
||||
static int epping_ndev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
epping_adapter_t *adapter;
|
||||
int ret = 0;
|
||||
|
||||
adapter = netdev_priv(dev);
|
||||
if (!adapter) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: EPPING adapter context is Null", __func__);
|
||||
ret = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
if (dev != adapter->dev) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: HDD adapter/dev inconsistency", __func__);
|
||||
ret = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((!ifr) || (!ifr->ifr_data)) {
|
||||
ret = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case (SIOCDEVPRIVATE + 1):
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: do not support ioctl %d (SIOCDEVPRIVATE + 1)",
|
||||
__func__, cmd);
|
||||
break;
|
||||
default:
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
|
||||
__func__, cmd);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int epping_set_mac_address(struct net_device *dev, void *addr)
|
||||
{
|
||||
epping_adapter_t *adapter = netdev_priv(dev);
|
||||
struct sockaddr *psta_mac_addr = addr;
|
||||
qdf_mem_copy(&adapter->macAddressCurrent,
|
||||
psta_mac_addr->sa_data, ETH_ALEN);
|
||||
qdf_net_update_net_device_dev_addr(dev, psta_mac_addr->sa_data,
|
||||
ETH_ALEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void epping_stop_adapter(epping_adapter_t *adapter)
|
||||
{
|
||||
qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
|
||||
|
||||
if (!qdf_ctx) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: qdf_ctx is NULL\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (adapter && adapter->started) {
|
||||
EPPING_LOG(LOG1, FL("Disabling queues"));
|
||||
netif_tx_disable(adapter->dev);
|
||||
netif_carrier_off(adapter->dev);
|
||||
adapter->started = false;
|
||||
pld_request_bus_bandwidth(qdf_ctx->dev,
|
||||
PLD_BUS_WIDTH_LOW);
|
||||
}
|
||||
}
|
||||
|
||||
static int epping_start_adapter(epping_adapter_t *adapter)
|
||||
{
|
||||
qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
|
||||
|
||||
if (!qdf_ctx) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: qdf_ctx is NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!adapter) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: adapter= NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!adapter->started) {
|
||||
pld_request_bus_bandwidth(qdf_ctx->dev,
|
||||
PLD_BUS_WIDTH_HIGH);
|
||||
netif_carrier_on(adapter->dev);
|
||||
EPPING_LOG(LOG1, FL("Enabling queues"));
|
||||
netif_tx_start_all_queues(adapter->dev);
|
||||
adapter->started = true;
|
||||
} else {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_WARN,
|
||||
"%s: adapter %pK already started\n", __func__,
|
||||
adapter);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int epping_register_adapter(epping_adapter_t *adapter, bool rtnl_held)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!rtnl_held)
|
||||
ret = register_netdev(adapter->dev);
|
||||
else
|
||||
ret = register_netdevice(adapter->dev);
|
||||
if (ret != 0) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: unable to register device\n",
|
||||
adapter->dev->name);
|
||||
} else {
|
||||
adapter->registered = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void epping_unregister_adapter(epping_adapter_t *adapter)
|
||||
{
|
||||
if (adapter) {
|
||||
epping_stop_adapter(adapter);
|
||||
if (adapter->registered) {
|
||||
unregister_netdev(adapter->dev);
|
||||
adapter->registered = false;
|
||||
}
|
||||
} else {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: adapter = NULL, unable to unregister device\n",
|
||||
__func__);
|
||||
}
|
||||
}
|
||||
|
||||
void epping_destroy_adapter(epping_adapter_t *adapter)
|
||||
{
|
||||
struct net_device *dev = NULL;
|
||||
epping_context_t *pEpping_ctx;
|
||||
|
||||
if (!adapter || !adapter->pEpping_ctx) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: adapter = NULL\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
dev = adapter->dev;
|
||||
pEpping_ctx = adapter->pEpping_ctx;
|
||||
epping_unregister_adapter(adapter);
|
||||
|
||||
qdf_spinlock_destroy(&adapter->data_lock);
|
||||
qdf_timer_free(&adapter->epping_timer);
|
||||
adapter->epping_timer_state = EPPING_TX_TIMER_STOPPED;
|
||||
|
||||
while (qdf_nbuf_queue_len(&adapter->nodrop_queue)) {
|
||||
qdf_nbuf_t tmp_nbuf = NULL;
|
||||
tmp_nbuf = qdf_nbuf_queue_remove(&adapter->nodrop_queue);
|
||||
if (tmp_nbuf)
|
||||
qdf_nbuf_free(tmp_nbuf);
|
||||
}
|
||||
|
||||
free_netdev(dev);
|
||||
if (!pEpping_ctx)
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: pEpping_ctx = NULL\n", __func__);
|
||||
else
|
||||
pEpping_ctx->epping_adapter = NULL;
|
||||
}
|
||||
|
||||
static struct net_device_ops epping_drv_ops = {
|
||||
.ndo_open = epping_ndev_open,
|
||||
.ndo_stop = epping_ndev_stop,
|
||||
.ndo_uninit = epping_ndev_uninit,
|
||||
.ndo_start_xmit = epping_hard_start_xmit,
|
||||
.ndo_tx_timeout = epping_tx_queue_timeout,
|
||||
.ndo_get_stats = epping_get_stats,
|
||||
.ndo_do_ioctl = epping_ndev_ioctl,
|
||||
.ndo_set_mac_address = epping_set_mac_address,
|
||||
.ndo_select_queue = NULL,
|
||||
};
|
||||
|
||||
#define EPPING_TX_QUEUE_MAX_LEN 128 /* need to be power of 2 */
|
||||
|
||||
epping_adapter_t *epping_add_adapter(epping_context_t *pEpping_ctx,
|
||||
tSirMacAddr macAddr,
|
||||
enum QDF_OPMODE device_mode,
|
||||
bool rtnl_held)
|
||||
{
|
||||
struct net_device *dev;
|
||||
epping_adapter_t *adapter;
|
||||
|
||||
dev = alloc_netdev(sizeof(epping_adapter_t), "wifi%d",
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
|
||||
NET_NAME_UNKNOWN,
|
||||
#endif
|
||||
ether_setup);
|
||||
if (!dev) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"%s: Cannot allocate epping_adapter_t\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
adapter = netdev_priv(dev);
|
||||
qdf_mem_zero(adapter, sizeof(*adapter));
|
||||
adapter->dev = dev;
|
||||
adapter->pEpping_ctx = pEpping_ctx;
|
||||
adapter->device_mode = device_mode; /* station, SAP, etc */
|
||||
qdf_net_update_net_device_dev_addr(dev,
|
||||
(void *)macAddr,
|
||||
sizeof(tSirMacAddr));
|
||||
qdf_mem_copy(adapter->macAddressCurrent.bytes,
|
||||
macAddr, sizeof(tSirMacAddr));
|
||||
qdf_spinlock_create(&adapter->data_lock);
|
||||
qdf_nbuf_queue_init(&adapter->nodrop_queue);
|
||||
adapter->epping_timer_state = EPPING_TX_TIMER_STOPPED;
|
||||
qdf_timer_init(epping_get_qdf_ctx(), &adapter->epping_timer,
|
||||
epping_timer_expire, dev, QDF_TIMER_TYPE_SW);
|
||||
dev->type = ARPHRD_IEEE80211;
|
||||
dev->needed_headroom += 24;
|
||||
dev->netdev_ops = &epping_drv_ops;
|
||||
dev->watchdog_timeo = 5 * HZ; /* XXX */
|
||||
dev->tx_queue_len = EPPING_TXBUF - 1; /* 1 for mgmt frame */
|
||||
if (epping_register_adapter(adapter, rtnl_held) == 0) {
|
||||
EPPING_LOG(LOG1, FL("Disabling queues"));
|
||||
netif_tx_disable(dev);
|
||||
netif_carrier_off(dev);
|
||||
return adapter;
|
||||
} else {
|
||||
epping_destroy_adapter(adapter);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int epping_connect_service(epping_context_t *pEpping_ctx)
|
||||
{
|
||||
int status, i;
|
||||
struct htc_service_connect_req connect;
|
||||
struct htc_service_connect_resp response;
|
||||
|
||||
qdf_mem_zero(&connect, sizeof(connect));
|
||||
qdf_mem_zero(&response, sizeof(response));
|
||||
|
||||
/* these fields are the same for all service endpoints */
|
||||
connect.EpCallbacks.pContext = pEpping_ctx;
|
||||
connect.EpCallbacks.EpTxCompleteMultiple = NULL;
|
||||
connect.EpCallbacks.EpRecv = epping_rx;
|
||||
/* epping_tx_complete use Multiple version */
|
||||
connect.EpCallbacks.EpTxComplete = epping_tx_complete;
|
||||
connect.MaxSendQueueDepth = 64;
|
||||
|
||||
#ifdef HIF_SDIO
|
||||
connect.EpCallbacks.EpRecvRefill = epping_refill;
|
||||
connect.EpCallbacks.EpSendFull =
|
||||
epping_tx_queue_full /* ar6000_tx_queue_full */;
|
||||
#elif defined(HIF_USB) || defined(HIF_PCI) || defined(HIF_SNOC) || \
|
||||
defined(HIF_IPCI)
|
||||
connect.EpCallbacks.EpRecvRefill = NULL /* provided by HIF */;
|
||||
connect.EpCallbacks.EpSendFull = NULL /* provided by HIF */;
|
||||
/* disable flow control for hw flow control */
|
||||
connect.ConnectionFlags |= HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL;
|
||||
#endif
|
||||
|
||||
/* connect to service */
|
||||
connect.service_id = WMI_DATA_BE_SVC;
|
||||
status = htc_connect_service(pEpping_ctx->HTCHandle, &connect, &response);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"Failed to connect to Endpoint Ping BE service status:%d\n",
|
||||
status);
|
||||
return status;
|
||||
} else {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"eppingtest BE endpoint:%d\n", response.Endpoint);
|
||||
}
|
||||
pEpping_ctx->EppingEndpoint[0] = response.Endpoint;
|
||||
|
||||
#if defined(HIF_PCI) || defined(HIF_USB) || defined(HIF_SNOC) || \
|
||||
defined(HIF_IPCI)
|
||||
connect.service_id = WMI_DATA_BK_SVC;
|
||||
status = htc_connect_service(pEpping_ctx->HTCHandle, &connect, &response);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"Failed to connect to Endpoint Ping BK service status:%d\n",
|
||||
status);
|
||||
return status;
|
||||
} else {
|
||||
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||
"eppingtest BK endpoint:%d\n", response.Endpoint);
|
||||
}
|
||||
pEpping_ctx->EppingEndpoint[1] = response.Endpoint;
|
||||
/* Since we do not create other two SVC use BK endpoint
|
||||
* for rest ACs (2, 3) */
|
||||
for (i = 2; i < EPPING_MAX_NUM_EPIDS; i++) {
|
||||
pEpping_ctx->EppingEndpoint[i] = response.Endpoint;
|
||||
}
|
||||
#else
|
||||
/* we only use one endpoint for high latenance bus.
|
||||
* Map all AC's EPIDs to the same endpoint ID returned by HTC */
|
||||
for (i = 0; i < EPPING_MAX_NUM_EPIDS; i++) {
|
||||
pEpping_ctx->EppingEndpoint[i] = response.Endpoint;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
4560
qcom/opensource/wlan/qca-wifi-host-cmn/utils/fwlog/dbglog_host.c
Normal file
4560
qcom/opensource/wlan/qca-wifi-host-cmn/utils/fwlog/dbglog_host.c
Normal file
File diff suppressed because it is too large
Load Diff
274
qcom/opensource/wlan/qca-wifi-host-cmn/utils/fwlog/dbglog_host.h
Normal file
274
qcom/opensource/wlan/qca-wifi-host-cmn/utils/fwlog/dbglog_host.h
Normal file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2014-2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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.
|
||||
*/
|
||||
|
||||
#ifndef _DBGLOG_HOST_H_
|
||||
#define _DBGLOG_HOST_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "dbglog_common.h"
|
||||
#include "wmi_unified_param.h"
|
||||
|
||||
#define DIAG_FWID_OFFSET 24
|
||||
#define DIAG_FWID_MASK 0xFF000000 /* Bit 24-31 */
|
||||
|
||||
#define DIAG_TIMESTAMP_OFFSET 0
|
||||
#define DIAG_TIMESTAMP_MASK 0x00FFFFFF /* Bit 0-23 */
|
||||
|
||||
#define DIAG_ID_OFFSET 16
|
||||
#define DIAG_ID_MASK 0xFFFF0000 /* Bit 16-31 */
|
||||
|
||||
#define DIAG_VDEVID_OFFSET 11
|
||||
#define DIAG_VDEVID_MASK 0x0000F800 /* Bit 11-15 */
|
||||
#define DIAG_VDEVID_NUM_MAX 16
|
||||
|
||||
#define DIAG_VDEVLEVEL_OFFSET 8
|
||||
#define DIAG_VDEVLEVEL_MASK 0x00000700 /* Bit 8-10 */
|
||||
|
||||
#define DIAG_PAYLEN_OFFSET 0
|
||||
#define DIAG_PAYLEN_MASK 0x000000FF /* Bit 0-7 */
|
||||
|
||||
#define DIAG_PAYLEN_OFFSET16 0
|
||||
#define DIAG_PAYLEN_MASK16 0x0000FFFF /* Bit 0-16 */
|
||||
|
||||
#define DIAG_GET_TYPE(arg) \
|
||||
((arg & DIAG_FWID_MASK) >> DIAG_FWID_OFFSET)
|
||||
|
||||
#define DIAG_GET_TIME_STAMP(arg) \
|
||||
((arg & DIAG_TIMESTAMP_MASK) >> DIAG_TIMESTAMP_OFFSET)
|
||||
|
||||
#define DIAG_GET_ID(arg) \
|
||||
((arg & DIAG_ID_MASK) >> DIAG_ID_OFFSET)
|
||||
|
||||
#define DIAG_GET_VDEVID(arg) \
|
||||
((arg & DIAG_VDEVID_MASK) >> DIAG_VDEVID_OFFSET)
|
||||
|
||||
#define DIAG_GET_VDEVLEVEL(arg) \
|
||||
((arg & DIAG_VDEVLEVEL_MASK) >> DIAG_VDEVLEVEL_OFFSET)
|
||||
|
||||
#define DIAG_GET_PAYLEN(arg) \
|
||||
((arg & DIAG_PAYLEN_MASK) >> DIAG_PAYLEN_OFFSET)
|
||||
|
||||
#define DIAG_GET_PAYLEN16(arg) \
|
||||
((arg & DIAG_PAYLEN_MASK16) >> DIAG_PAYLEN_OFFSET16)
|
||||
|
||||
#define diag_alert(params...) QDF_TRACE_FATAL(QDF_MODULE_ID_DIAG, params)
|
||||
#define diag_err(params...) QDF_TRACE_ERROR(QDF_MODULE_ID_DIAG, params)
|
||||
#define diag_warn(params...) QDF_TRACE_WARN(QDF_MODULE_ID_DIAG, params)
|
||||
#define diag_info(params...) QDF_TRACE_INFO(QDF_MODULE_ID_DIAG, params)
|
||||
#define diag_debug(params...) QDF_TRACE_DEBUG(QDF_MODULE_ID_DIAG, params)
|
||||
|
||||
#define diag_err_rl(params...) QDF_TRACE_ERROR_RL(QDF_MODULE_ID_DIAG, params)
|
||||
|
||||
#ifdef FEATURE_FW_LOG_PARSING
|
||||
/*
|
||||
* set the dbglog parser type
|
||||
*/int
|
||||
dbglog_parser_type_init(wmi_unified_t wmi_handle, int type);
|
||||
|
||||
/** dbglog_int - Registers a WMI event handle for WMI_DBGMSG_EVENT
|
||||
* @brief wmi_handle - handle to wmi module
|
||||
*/
|
||||
int
|
||||
dbglog_init(wmi_unified_t wmi_handle);
|
||||
|
||||
/** dbglog_deinit - UnRegisters a WMI event handle for WMI_DBGMSG_EVENT
|
||||
* @brief wmi_handle - handle to wmi module
|
||||
*/
|
||||
int
|
||||
dbglog_deinit(wmi_unified_t wmi_handle);
|
||||
|
||||
/** set the size of the report size
|
||||
* @brief wmi_handle - handle to Wmi module
|
||||
* @brief size - Report size
|
||||
*/
|
||||
int
|
||||
dbglog_set_report_size(wmi_unified_t wmi_handle, uint16_t size);
|
||||
|
||||
/** Set the resolution for time stamp
|
||||
* @brief wmi_handle - handle to Wmi module
|
||||
* @ brief tsr - time stamp resolution
|
||||
*/
|
||||
int
|
||||
dbglog_set_timestamp_resolution(wmi_unified_t wmi_handle,
|
||||
uint16_t tsr);
|
||||
|
||||
/** Enable reporting. If it is set to false then Target won't deliver
|
||||
* any debug information
|
||||
*/
|
||||
int
|
||||
dbglog_report_enable(wmi_unified_t wmi_handle, A_BOOL isenable);
|
||||
|
||||
/** Set the log level
|
||||
* @brief DBGLOG_INFO - Information lowest log level
|
||||
* @brief DBGLOG_WARNING
|
||||
* @brief DBGLOG_ERROR - default log level
|
||||
*/
|
||||
int
|
||||
dbglog_set_log_lvl(wmi_unified_t wmi_handle, DBGLOG_LOG_LVL log_lvl);
|
||||
|
||||
/*
|
||||
* set the debug log level for a given module
|
||||
* mod_id_lvl : the format is more user friendly.
|
||||
* module_id = mod_id_lvl/10;
|
||||
* log_level = mod_id_lvl%10;
|
||||
* example : mod_id_lvl is 153. then module id is 15 and log level is 3.
|
||||
* this format allows user to pass a single value
|
||||
* (which is the most convenient way for most of the OSs)
|
||||
* to be passed from user to the driver.
|
||||
*/
|
||||
int
|
||||
dbglog_set_mod_log_lvl(wmi_unified_t wmi_handle, uint32_t mod_id_lvl);
|
||||
|
||||
/*
|
||||
* set the debug log level for wow module
|
||||
* mod_id_lvl : the format is more user friendly.
|
||||
* module_id = mod_id_lvl/10;
|
||||
* log_level = mod_id_lvl%10;
|
||||
* example : mod_id_lvl is 153. then module id is 15 and log level is 3.
|
||||
* this format allows user to pass a single value
|
||||
* (which is the most convenient way for most of the OSs)
|
||||
* to be passed from user to the driver.
|
||||
*/
|
||||
int
|
||||
dbglog_set_mod_wow_log_lvl(wmi_unified_t wmi_handle, uint32_t mod_id_lvl);
|
||||
|
||||
/** Enable/Disable the logging for VAP */
|
||||
int
|
||||
dbglog_vap_log_enable(wmi_unified_t wmi_handle, uint16_t vap_id,
|
||||
A_BOOL isenable);
|
||||
/** Enable/Disable logging for Module */
|
||||
int
|
||||
dbglog_module_log_enable(wmi_unified_t wmi_handle, uint32_t mod_id,
|
||||
A_BOOL isenable);
|
||||
|
||||
/** set vap enablie bitmap */
|
||||
void
|
||||
dbglog_set_vap_enable_bitmap(wmi_unified_t wmi_handle,
|
||||
uint32_t vap_enable_bitmap);
|
||||
|
||||
/** set log level for all the modules specified in the bitmap.
|
||||
* for all other modules with 0 in the bitmap (or) outside the bitmap,
|
||||
* the log level be reset to DBGLOG_ERR.
|
||||
*/
|
||||
void
|
||||
dbglog_set_mod_enable_bitmap(wmi_unified_t wmi_handle,
|
||||
uint32_t log_level,
|
||||
uint32_t *mod_enable_bitmap,
|
||||
uint32_t bitmap_len);
|
||||
|
||||
int
|
||||
dbglog_parse_debug_logs(ol_scn_t scn, u_int8_t *datap,
|
||||
u_int32_t len);
|
||||
|
||||
/**
|
||||
* cnss_diag_activate_service() - API to register CNSS diag cmd handler
|
||||
*
|
||||
* API to register the handler for the NL message received from cnss_diag
|
||||
* application.
|
||||
*
|
||||
* Return: 0
|
||||
*/
|
||||
int cnss_diag_activate_service(void);
|
||||
|
||||
/**
|
||||
* cnss_diag_deactivate_service() - API to deregister CNSS diag cmd handler
|
||||
*
|
||||
* API to deregister the handler for the NL message received from cnss_diag
|
||||
* application.
|
||||
*
|
||||
* Return: 0
|
||||
*/
|
||||
int cnss_diag_deactivate_service(void);
|
||||
|
||||
#else
|
||||
static inline int
|
||||
dbglog_parser_type_init(wmi_unified_t wmi_handle, int type)
|
||||
{
|
||||
return A_OK;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dbglog_init(wmi_unified_t wmi_handle)
|
||||
{
|
||||
return A_OK;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dbglog_deinit(wmi_unified_t wmi_handle)
|
||||
{
|
||||
return A_OK;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dbglog_report_enable(wmi_unified_t wmi_handle, A_BOOL isenable)
|
||||
{
|
||||
return A_OK;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dbglog_set_log_lvl(wmi_unified_t wmi_handle, DBGLOG_LOG_LVL log_lvl)
|
||||
{
|
||||
return A_OK;
|
||||
}
|
||||
|
||||
static inline int cnss_diag_activate_service(void)
|
||||
{
|
||||
return A_OK;
|
||||
}
|
||||
|
||||
static inline int cnss_diag_deactivate_service(void)
|
||||
{
|
||||
return A_OK;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dbglog_module_log_enable(wmi_unified_t wmi_handle, uint32_t mod_id,
|
||||
A_BOOL isenable)
|
||||
{
|
||||
return A_OK;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dbglog_vap_log_enable(wmi_unified_t wmi_handle, uint16_t vap_id,
|
||||
A_BOOL isenable)
|
||||
{
|
||||
return A_OK;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dbglog_set_mod_log_lvl(wmi_unified_t wmi_handle, uint32_t mod_id_lvl)
|
||||
{
|
||||
return A_OK;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dbglog_set_mod_wow_log_lvl(wmi_unified_t wmi_handle, uint32_t mod_id_lvl)
|
||||
{
|
||||
return A_OK;
|
||||
}
|
||||
#endif /* FEATURE_FW_LOG_PARSING */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DBGLOG_HOST_H_ */
|
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 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.
|
||||
*/
|
||||
|
||||
#include "fw_dbglog_api.h"
|
||||
#include "fw_dbglog_priv.h"
|
||||
|
||||
static inline struct dbglog_info *handle2info(
|
||||
struct common_dbglog_handle *dbg_handle)
|
||||
{
|
||||
return (struct dbglog_info *)dbg_handle;
|
||||
}
|
||||
|
||||
void fwdbg_set_log_lvl(struct common_dbglog_handle *dbg_handle, ol_scn_t scn,
|
||||
uint32_t log_lvl)
|
||||
{
|
||||
struct dbglog_info *dbg_info = handle2info(dbg_handle);
|
||||
|
||||
if (dbg_info->ops->dbglog_set_log_lvl)
|
||||
dbg_info->ops->dbglog_set_log_lvl(scn, log_lvl);
|
||||
|
||||
}
|
||||
|
||||
int fwdbg_fw_handler(struct common_dbglog_handle *dbg_handle, ol_scn_t soc,
|
||||
uint8_t *data, uint32_t datalen)
|
||||
{
|
||||
struct dbglog_info *dbg_info = handle2info(dbg_handle);
|
||||
|
||||
if (dbg_info->ops->dbglog_fw_handler)
|
||||
return dbg_info->ops->dbglog_fw_handler(soc, data, datalen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fwdbg_parse_debug_logs(struct common_dbglog_handle *dbg_handle,
|
||||
ol_scn_t soc, uint8_t *datap,
|
||||
uint16_t len, void *context)
|
||||
{
|
||||
struct dbglog_info *dbg_info = handle2info(dbg_handle);
|
||||
|
||||
if (dbg_info->ops->dbglog_parse_debug_logs)
|
||||
return dbg_info->ops->dbglog_parse_debug_logs(soc,
|
||||
datap, len, context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
qdf_export_symbol(fwdbg_parse_debug_logs);
|
||||
|
||||
void fwdbg_ratelimit_set(struct common_dbglog_handle *dbg_handle,
|
||||
uint32_t burst_limit)
|
||||
{
|
||||
struct dbglog_info *dbg_info = handle2info(dbg_handle);
|
||||
|
||||
if (dbg_info->ops->dbglog_ratelimit_set)
|
||||
dbg_info->ops->dbglog_ratelimit_set(burst_limit);
|
||||
|
||||
}
|
||||
|
||||
void fwdbg_vap_log_enable(struct common_dbglog_handle *dbg_handle, ol_scn_t scn,
|
||||
uint16_t vap_id, bool isenable)
|
||||
{
|
||||
struct dbglog_info *dbg_info = handle2info(dbg_handle);
|
||||
|
||||
if (dbg_info->ops->dbglog_vap_log_enable)
|
||||
dbg_info->ops->dbglog_vap_log_enable(scn, vap_id,
|
||||
isenable);
|
||||
|
||||
}
|
||||
|
||||
void fwdbg_set_timestamp_resolution(struct common_dbglog_handle *dbg_handle,
|
||||
ol_scn_t scn, uint16_t tsr)
|
||||
{
|
||||
struct dbglog_info *dbg_info = handle2info(dbg_handle);
|
||||
|
||||
if (dbg_info->ops->dbglog_set_timestamp_resolution)
|
||||
dbg_info->ops->dbglog_set_timestamp_resolution(scn, tsr);
|
||||
|
||||
}
|
||||
|
||||
void fwdbg_reporting_enable(struct common_dbglog_handle *dbg_handle,
|
||||
ol_scn_t scn, bool isenable)
|
||||
{
|
||||
struct dbglog_info *dbg_info = handle2info(dbg_handle);
|
||||
|
||||
if (dbg_info->ops->dbglog_reporting_enable)
|
||||
dbg_info->ops->dbglog_reporting_enable(scn, isenable);
|
||||
|
||||
}
|
||||
|
||||
void fwdbg_module_log_enable(struct common_dbglog_handle *dbg_handle,
|
||||
ol_scn_t scn, uint32_t mod_id, bool isenable)
|
||||
{
|
||||
struct dbglog_info *dbg_info = handle2info(dbg_handle);
|
||||
|
||||
if (dbg_info->ops->dbglog_module_log_enable)
|
||||
dbg_info->ops->dbglog_module_log_enable(scn, mod_id,
|
||||
isenable);
|
||||
|
||||
}
|
||||
|
||||
void fwdbg_init(struct common_dbglog_handle *dbg_handle, void *soc)
|
||||
{
|
||||
struct dbglog_info *dbg_info = handle2info(dbg_handle);
|
||||
|
||||
if (dbg_info->ops->dbglog_init)
|
||||
dbg_info->ops->dbglog_init(soc);
|
||||
|
||||
}
|
||||
|
||||
void fwdbg_free(struct common_dbglog_handle *dbg_handle, void *soc)
|
||||
{
|
||||
struct dbglog_info *dbg_info = handle2info(dbg_handle);
|
||||
|
||||
if (dbg_info->ops->dbglog_free)
|
||||
dbg_info->ops->dbglog_free(soc);
|
||||
|
||||
}
|
||||
|
||||
void fwdbg_set_report_size(struct common_dbglog_handle *dbg_handle,
|
||||
ol_scn_t scn, uint16_t size)
|
||||
{
|
||||
struct dbglog_info *dbg_info = handle2info(dbg_handle);
|
||||
|
||||
if (dbg_info->ops->dbglog_set_report_size)
|
||||
dbg_info->ops->dbglog_set_report_size(scn, size);
|
||||
|
||||
}
|
||||
|
||||
int fwdbg_smartlog_init(struct common_dbglog_handle *dbg_handle, void *icp)
|
||||
{
|
||||
struct dbglog_info *dbg_info = handle2info(dbg_handle);
|
||||
|
||||
if (dbg_info->ops->smartlog_init)
|
||||
return dbg_info->ops->smartlog_init(icp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fwdbg_smartlog_deinit(struct common_dbglog_handle *dbg_handle, void *sc)
|
||||
{
|
||||
struct dbglog_info *dbg_info = handle2info(dbg_handle);
|
||||
|
||||
if (dbg_info->ops->smartlog_deinit)
|
||||
dbg_info->ops->smartlog_deinit(sc);
|
||||
}
|
||||
|
||||
ssize_t fwdbg_smartlog_dump(struct common_dbglog_handle *dbg_handle,
|
||||
struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dbglog_info *dbg_info = handle2info(dbg_handle);
|
||||
|
||||
if (dbg_info->ops->smartlog_dump)
|
||||
return dbg_info->ops->smartlog_dump(dev, attr, buf);
|
||||
|
||||
return 0;
|
||||
}
|
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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.
|
||||
*/
|
||||
|
||||
#ifndef _FW_DBGLOG_API_H_
|
||||
#define _FW_DBGLOG_API_H_
|
||||
|
||||
#include "target_if.h"
|
||||
|
||||
/**
|
||||
* fwdbg_set_log_lvl() - API to set debug log level
|
||||
* @dbg_handle: Debug module handle
|
||||
* @scn: scn handle
|
||||
* @log_lvl: value of log level
|
||||
*
|
||||
* Send wmi configuration command to set debug log level.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void fwdbg_set_log_lvl(struct common_dbglog_handle *dbg_handle, ol_scn_t scn,
|
||||
uint32_t log_lvl);
|
||||
|
||||
/**
|
||||
* fwdbg_fw_handler() - Firmware handler interface
|
||||
* @dbg_handle: Debug module handle
|
||||
* @sc: soc handle
|
||||
* @data: Reference to command data
|
||||
* @datalen: length of data
|
||||
*
|
||||
* Return: 0 success
|
||||
*/
|
||||
int fwdbg_fw_handler(struct common_dbglog_handle *dbg_handle, ol_scn_t sc,
|
||||
uint8_t *data, uint32_t datalen);
|
||||
|
||||
/**
|
||||
* fwdbg_parse_debug_logs() - API to parse firmware debug logs
|
||||
* @dbg_handle: Debug module handle
|
||||
* @soc: soc handle
|
||||
* @datap: Reference to log data
|
||||
* @len: length of data
|
||||
* @context: log context
|
||||
*
|
||||
* API parse firmware debug log messages and prints to console.
|
||||
*
|
||||
* Return: 0 success
|
||||
*/
|
||||
int fwdbg_parse_debug_logs(struct common_dbglog_handle *dbg_handle,
|
||||
ol_scn_t soc, uint8_t *datap,
|
||||
uint16_t len, void *context);
|
||||
|
||||
/**
|
||||
* fwdbg_ratelimit_set() - API to set rate limit
|
||||
* @dbg_handle: Debug module handle
|
||||
* @burst_limit: burst limit
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void fwdbg_ratelimit_set(struct common_dbglog_handle *dbg_handle,
|
||||
uint32_t burst_limit);
|
||||
|
||||
/**
|
||||
* fwdbg_vap_log_enable() - API to Enable/Disable the logging for VAP
|
||||
* @dbg_handle: Debug module handle
|
||||
* @scn: scn handle
|
||||
* @vap_id: VAP id
|
||||
* @isenable: Enable/disable
|
||||
*
|
||||
* API allows to enable or disable debuglogs at VAP level. It encodes wmi
|
||||
* config command based on VAP id and sends wmi command to firmware to
|
||||
* enable/disable debuglog.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void fwdbg_vap_log_enable(struct common_dbglog_handle *dbg_handle, ol_scn_t scn,
|
||||
uint16_t vap_id, bool isenable);
|
||||
|
||||
/**
|
||||
* fwdbg_set_timestamp_resolution - Set the resolution for time stamp
|
||||
* @dbg_handle: Debug module handle
|
||||
* @scn: scn handle
|
||||
* @tsr: time stamp resolution
|
||||
*
|
||||
* Set the resolution for time stamp in debug logs. It encodes wmi
|
||||
* config command to desired timestamp resolution and sends wmi command to
|
||||
* firmware.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void fwdbg_set_timestamp_resolution(struct common_dbglog_handle *dbg_handle,
|
||||
ol_scn_t scn, uint16_t tsr);
|
||||
|
||||
/**
|
||||
* fwdbg_reporting_enable() - Enable reporting.
|
||||
* @dbg_handle: Debug module handle
|
||||
* @scn: scn handle
|
||||
* @isenable: Enable/disable
|
||||
*
|
||||
* API to enable debug information reporting. It encodes wmi config command
|
||||
* to enable reporting. If set to false then Target won't deliver any debug
|
||||
* information.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void fwdbg_reporting_enable(struct common_dbglog_handle *dbg_handle,
|
||||
ol_scn_t scn, bool isenable);
|
||||
|
||||
/**
|
||||
* fwdbg_module_log_enable() - Enable/Disable logging for Module.
|
||||
* @dbg_handle: Debug module handle
|
||||
* @scn: scn handle
|
||||
* @mod_id: Module id
|
||||
* @isenable: Enable/disable
|
||||
*
|
||||
* API allows to enable or disable debuglogs per module. It encodes wmi
|
||||
* config command based on module id and sends wmi command to firmware to
|
||||
* enable/disable debuglog for that module.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void fwdbg_module_log_enable(struct common_dbglog_handle *dbg_handle,
|
||||
ol_scn_t scn, uint32_t mod_id, bool isenable);
|
||||
|
||||
/**
|
||||
* fwdbg_init() - Initialize debuglog.
|
||||
* @dbg_handle: Debug module handle
|
||||
* @soc: soc handle
|
||||
*
|
||||
* It initializes debuglog print function for set of modules and
|
||||
* initializes WMI event handler for debuglog message event.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void fwdbg_init(struct common_dbglog_handle *dbg_handle, void *soc);
|
||||
|
||||
/**
|
||||
* fwdbg_free() - Free debug handler.
|
||||
* @dbg_handle: Debug module handle
|
||||
* @soc: soc handle
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void fwdbg_free(struct common_dbglog_handle *dbg_handle, void *soc);
|
||||
|
||||
/**
|
||||
* fwdbg_set_report_size() - set the size of the report size
|
||||
* @dbg_handle: Debug module handle
|
||||
* @scn: soc handler
|
||||
* @size: Report size
|
||||
*
|
||||
* Set the debug log report size. It encodes wmi config command to
|
||||
* desired report size and sends wmi command to firmware.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void fwdbg_set_report_size(struct common_dbglog_handle *dbg_handle,
|
||||
ol_scn_t scn, uint16_t size);
|
||||
|
||||
/**
|
||||
* fwdbg_smartlog_init() - initialize smart logging feature
|
||||
* @dbg_handle: Debug module handle
|
||||
* @ic: ic handler
|
||||
*
|
||||
* Return: 0 Success
|
||||
*/
|
||||
int fwdbg_smartlog_init(struct common_dbglog_handle *dbg_handle, void *icp);
|
||||
|
||||
/**
|
||||
* fwdbg_smartlog_deinit() - uninitializes smart logging feature
|
||||
* @dbg_handle: Debug module handle
|
||||
* @sc: sc handler
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void fwdbg_smartlog_deinit(struct common_dbglog_handle *dbg_handle, void *sc);
|
||||
|
||||
/**
|
||||
* fwdbg_smartlog_dump() - dumps smart logs
|
||||
* @dev: dev handler
|
||||
* @dbg_handle: Debug module handle
|
||||
* @attr: dev handler attributes
|
||||
* @buf: destination buffer to dump smart logs
|
||||
*
|
||||
* Return: 0 success
|
||||
*/
|
||||
ssize_t fwdbg_smartlog_dump(struct common_dbglog_handle *dbg_handle,
|
||||
struct device *dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
#endif /* _FW_DBGLOG_API_H_ */
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains the API definitions for the Unified Wireless
|
||||
* Module Interface (WMI).
|
||||
*/
|
||||
#ifndef _FW_DBGLOG_PRIV_H_
|
||||
#define _FW_DBGLOG_PRIV_H_
|
||||
|
||||
#include <wmi_unified_api.h>
|
||||
|
||||
struct dbglog_ops {
|
||||
|
||||
void (*dbglog_set_log_lvl)(ol_scn_t scn, uint32_t log_lvl);
|
||||
int (*dbglog_fw_handler)(ol_scn_t soc, uint8_t *data, uint32_t datalen);
|
||||
int (*dbglog_parse_debug_logs)(ol_scn_t scn,
|
||||
u_int8_t *datap, uint16_t len, void *context);
|
||||
void (*dbglog_ratelimit_set)(uint32_t burst_limit);
|
||||
void (*dbglog_vap_log_enable)(ol_scn_t soc, uint16_t vap_id,
|
||||
bool isenable);
|
||||
void (*dbglog_set_timestamp_resolution)(ol_scn_t soc, uint16_t tsr);
|
||||
void (*dbglog_reporting_enable)(ol_scn_t soc, bool isenable);
|
||||
void (*dbglog_module_log_enable)(ol_scn_t scn,
|
||||
uint32_t mod_id, bool isenable);
|
||||
void (*dbglog_init)(void *scn);
|
||||
void (*dbglog_set_report_size)(ol_scn_t scn, uint16_t size);
|
||||
void (*dbglog_free)(void *soc);
|
||||
int (*smartlog_init)(void *icp);
|
||||
void (*smartlog_deinit)(void *sc);
|
||||
ssize_t (*smartlog_dump)(struct device *dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
|
||||
};
|
||||
|
||||
struct dbglog_info {
|
||||
struct dbglog_ops *ops;
|
||||
};
|
||||
#endif /*_FW_DBGLOG_PRIV_H_ */
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,591 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2017, 2019-2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. 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.
|
||||
*/
|
||||
|
||||
#if !defined(__HOST_DIAG_CORE_LOG_H)
|
||||
#define __HOST_DIAG_CORE_LOG_H
|
||||
|
||||
/**=========================================================================
|
||||
|
||||
\file host_diag_core_log.h
|
||||
|
||||
\brief WLAN UTIL host DIAG logs
|
||||
|
||||
Definitions for WLAN UTIL host diag events
|
||||
|
||||
========================================================================*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Include Files
|
||||
------------------------------------------------------------------------*/
|
||||
#include "qdf_types.h"
|
||||
#include "i_host_diag_core_log.h"
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Preprocessor definitions and constants
|
||||
------------------------------------------------------------------------*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Preprocessor definitions and constants
|
||||
------------------------------------------------------------------------*/
|
||||
#define HOST_LOG_MAX_NUM_SSID (21)
|
||||
#define HOST_LOG_MAX_NUM_BSSID (21)
|
||||
#define HOST_LOG_MAX_SSID_SIZE (32)
|
||||
#define HOST_LOG_MAX_BSSID_SIZE (6)
|
||||
#define HOST_LOG_MAX_NUM_CHANNEL (64)
|
||||
#define HOST_LOG_MAX_NUM_HO_CANDIDATE_APS (20)
|
||||
#define HOST_LOG_MAX_WOW_PTRN_SIZE (128)
|
||||
#define HOST_LOG_MAX_WOW_PTRN_MASK_SIZE (16)
|
||||
#define VOS_LOG_PKT_LOG_SIZE (2048)
|
||||
#define HOST_LOG_PKT_LOG_THRESHOLD 40960
|
||||
#define HOST_LOG_MAX_COLD_BOOT_CAL_DATA_SIZE (2048)
|
||||
|
||||
/* Version to be updated whenever format of vos_log_pktlog_info changes */
|
||||
#define VERSION_LOG_WLAN_PKT_LOG_INFO_C 1
|
||||
/* Version to be updated whenever format of host_log_cold_boot_cal_data_type
|
||||
* changes
|
||||
*/
|
||||
#define VERSION_LOG_WLAN_COLD_BOOT_CAL_DATA_C 1
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
This packet contains the scan results of the recent scan operation
|
||||
LOG_WLAN_SCAN_C 0x1496
|
||||
---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
log_hdr_type hdr;
|
||||
uint8_t eventId;
|
||||
uint8_t numSsid;
|
||||
uint8_t ssid[HOST_LOG_MAX_NUM_SSID][HOST_LOG_MAX_SSID_SIZE];
|
||||
uint8_t bssid[HOST_LOG_MAX_NUM_BSSID][HOST_LOG_MAX_BSSID_SIZE];
|
||||
uint8_t totalSsid;
|
||||
uint8_t minChnTime;
|
||||
uint8_t maxChnTime;
|
||||
uint16_t timeBetweenBgScan;
|
||||
uint8_t BSSMode;
|
||||
uint8_t numChannel;
|
||||
uint8_t channels[HOST_LOG_MAX_NUM_CHANNEL];
|
||||
uint16_t status;
|
||||
} host_log_scan_pkt_type;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
This packet contains the information related to IBSS connection setup
|
||||
LOG_WLAN_IBSS_C 0x1497
|
||||
---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
log_hdr_type hdr;
|
||||
uint8_t eventId;
|
||||
uint8_t channelSetting;
|
||||
struct qdf_mac_addr bssid;
|
||||
struct qdf_mac_addr peer_macaddr;
|
||||
uint8_t ssid[HOST_LOG_MAX_SSID_SIZE];
|
||||
uint8_t operatingChannel;
|
||||
uint8_t beaconInterval;
|
||||
uint8_t status;
|
||||
uint32_t op_freq;
|
||||
} host_log_ibss_pkt_type;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
This packet contains the information related to 802.11D
|
||||
LOG_WLAN_80211D_C 0x1498
|
||||
---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
log_hdr_type hdr;
|
||||
uint8_t eventId;
|
||||
uint8_t numChannel;
|
||||
uint8_t Channels[HOST_LOG_MAX_NUM_CHANNEL];
|
||||
uint8_t TxPwr[HOST_LOG_MAX_NUM_CHANNEL];
|
||||
uint8_t countryCode[3];
|
||||
uint8_t supportMultipleDomain;
|
||||
} host_log_802_11d_pkt_type;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
This is a log packet which contains below handoff information:
|
||||
- Current AP + RSSI (if already associated)
|
||||
- Candidate AP + RSSI (before association and when the list is updated)
|
||||
- For each BSSID in candidate list, provide RSSI, QoS and security compatibility
|
||||
LOG_WLAN_HANDOFF_C 0x1499
|
||||
---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
uint8_t ssid[9];
|
||||
uint8_t bssid[HOST_LOG_MAX_BSSID_SIZE];
|
||||
uint8_t channel_id;
|
||||
uint32_t qos_score;
|
||||
uint32_t sec_score;
|
||||
uint32_t rssi_score;
|
||||
uint32_t overall_score;
|
||||
uint32_t tx_per; /* represented as a % */
|
||||
uint32_t rx_per; /* represented as a % */
|
||||
|
||||
} host_log_ho_ap_info;
|
||||
|
||||
typedef struct {
|
||||
log_hdr_type hdr;
|
||||
uint32_t num_aps;
|
||||
host_log_ho_ap_info current_ap_info;
|
||||
host_log_ho_ap_info
|
||||
candidate_ap_info[HOST_LOG_MAX_NUM_HO_CANDIDATE_APS];
|
||||
} host_log_ho_pkt_type;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
This packet contains the information related to the EDCA parameters
|
||||
advertised by the AP
|
||||
LOG_WLAN_QOS_EDCA_C 0x149A
|
||||
---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
log_hdr_type hdr;
|
||||
uint8_t aci_be;
|
||||
uint8_t cw_be;
|
||||
uint16_t txoplimit_be;
|
||||
uint8_t aci_bk;
|
||||
uint8_t cw_bk;
|
||||
uint16_t txoplimit_bk;
|
||||
uint8_t aci_vi;
|
||||
uint8_t cw_vi;
|
||||
uint16_t txoplimit_vi;
|
||||
uint8_t aci_vo;
|
||||
uint8_t cw_vo;
|
||||
uint16_t txoplimit_vo;
|
||||
} host_log_qos_edca_pkt_type;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
This packet contains the total number of beacon received value
|
||||
LOG_WLAN_BEACON_UPDATE_C 0x149B
|
||||
---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
log_hdr_type hdr;
|
||||
uint32_t bcn_rx_cnt;
|
||||
} host_log_beacon_update_pkt_type;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
This packet contains the information related to a WoW pattern value when set
|
||||
LOG_WLAN_POWERSAVE_WOW_ADD_PTRN_C 0x149C
|
||||
---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
log_hdr_type hdr;
|
||||
uint8_t pattern_id;
|
||||
uint8_t pattern_byte_offset;
|
||||
uint8_t pattern_size;
|
||||
uint8_t pattern[HOST_LOG_MAX_WOW_PTRN_SIZE];
|
||||
uint8_t pattern_mask_size;
|
||||
uint8_t pattern_mask[HOST_LOG_MAX_WOW_PTRN_MASK_SIZE];
|
||||
} host_log_powersave_wow_add_ptrn_pkt_type;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
This packet contains the Tspec info negotiated with the AP for the
|
||||
specific AC
|
||||
LOG_WLAN_QOS_TSPEC_C 0x14A2
|
||||
---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
log_hdr_type hdr;
|
||||
uint8_t tsinfo[3];
|
||||
uint16_t nominal_msdu_size;
|
||||
uint16_t maximum_msdu_size;
|
||||
uint32_t min_service_interval;
|
||||
uint32_t max_service_interval;
|
||||
uint32_t inactivity_interval;
|
||||
uint32_t suspension_interval;
|
||||
uint32_t svc_start_time;
|
||||
uint32_t min_data_rate;
|
||||
uint32_t mean_data_rate;
|
||||
uint32_t peak_data_rate;
|
||||
uint32_t max_burst_size;
|
||||
uint32_t delay_bound;
|
||||
uint32_t min_phy_rate;
|
||||
uint16_t surplus_bw_allowance;
|
||||
uint16_t medium_time;
|
||||
} host_log_qos_tspec_pkt_type;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
This packet contains data information when stall detected
|
||||
LOG_TRSP_DATA_STALL_C 0x1801
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
typedef struct {
|
||||
char channelName[4];
|
||||
uint32_t numDesc;
|
||||
uint32_t numFreeDesc;
|
||||
uint32_t numRsvdDesc;
|
||||
uint32_t headDescOrder;
|
||||
uint32_t tailDescOrder;
|
||||
uint32_t ctrlRegVal;
|
||||
uint32_t statRegVal;
|
||||
uint32_t numValDesc;
|
||||
uint32_t numInvalDesc;
|
||||
} host_log_data_stall_channel_type;
|
||||
|
||||
typedef struct {
|
||||
log_hdr_type hdr;
|
||||
uint32_t PowerState;
|
||||
uint32_t numFreeBd;
|
||||
host_log_data_stall_channel_type dxeChannelInfo[4];
|
||||
} host_log_data_stall_type;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
This packet contains the rssi value from BSS descriptor
|
||||
LOG_WLAN_RSSI_UPDATE_C 0x1354
|
||||
---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
log_hdr_type hdr;
|
||||
int8_t rssi;
|
||||
} host_log_rssi_pkt_type;
|
||||
|
||||
/**
|
||||
* struct host_log_pktlog_info - Packet log info
|
||||
* @log_hdr: Log header
|
||||
* @version: Version
|
||||
* @seq_no: Sequence number
|
||||
* @buf_len: Length of the buffer that follows
|
||||
* @buf: Buffer containing the packet log info
|
||||
*
|
||||
* Structure containing the packet log information
|
||||
* LOG_WLAN_PKT_LOG_INFO_C 0x18E0
|
||||
*/
|
||||
struct host_log_pktlog_info {
|
||||
log_hdr_type log_hdr;
|
||||
uint32_t version;
|
||||
uint32_t seq_no;
|
||||
uint32_t buf_len;
|
||||
uint8_t buf[];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct host_log_cold_boot_cal_data_type - Cold boot cal log info
|
||||
* @hdr: Log header
|
||||
* @version: version
|
||||
* @flags: Flag to indicate if more data follows
|
||||
* @cb_cal_data_len: Length of the cal data
|
||||
* @cb_cal_data: Cold boot cal data
|
||||
*
|
||||
* Structure containing the cold boot calibration data
|
||||
* log information
|
||||
* LOG_WLAN_COLD_BOOT_CAL_DATA_C 0x1A18
|
||||
*/
|
||||
struct host_log_cold_boot_cal_data_type {
|
||||
log_hdr_type hdr;
|
||||
uint32_t version;
|
||||
uint32_t flags;
|
||||
uint32_t cb_cal_data_len;
|
||||
uint8_t cb_cal_data[HOST_LOG_MAX_COLD_BOOT_CAL_DATA_SIZE];
|
||||
};
|
||||
|
||||
#define WLAN_MAX_ROAM_CANDIDATE_AP 9
|
||||
#define WLAN_MAX_ROAM_SCAN_CHAN 38
|
||||
#define WLAN_MAX_SSID_SIZE 32
|
||||
|
||||
/**
|
||||
* struct host_log_wlan_mgmt_tx_rx_info - To capture TX/RX mgmt frames' payload
|
||||
* @hdr: Log header
|
||||
* @version: Version number of the payload
|
||||
* @vdev_id: Vdev id
|
||||
* @is_tx: 1 - TX frame, 0 - RX frame
|
||||
* @mgmt_type: type of frames, value: enum wifi_frm_type
|
||||
* @mgmt_subtype: subtype of mgmt frame, value: enum mgmt_frm_subtype
|
||||
* @mgmt_frame_seq_num: Frame sequence number in 802.11 header
|
||||
* @operating_freq: operating frequency of AP
|
||||
* @ssid_len: length of SSID, max 32 bytes long as per standard
|
||||
* @ssid: SSID of connected AP
|
||||
* @self_mac_addr: mac address of self interface
|
||||
* @bssid: BSSID for which frame is received
|
||||
* @mac_failure_reason: Internal driver failure reason
|
||||
* @mgmt_status_code: 802.11 management frame response status code from
|
||||
* section 9.4.1.9 IEEE 802.11 - 2016
|
||||
* @auth_algo: Authentication algorithm number
|
||||
* @auth_transaction_num: Authentication transaction sequence number
|
||||
* @is_retry: Is retry frame
|
||||
* @rssi: RSSI for the received frame
|
||||
* @origin: 1- Sent by host. 2- sent by firmware
|
||||
*/
|
||||
struct host_log_wlan_mgmt_tx_rx_info {
|
||||
log_hdr_type hdr;
|
||||
uint8_t version;
|
||||
uint8_t vdev_id;
|
||||
bool is_tx;
|
||||
uint8_t mgmt_type;
|
||||
uint8_t mgmt_subtype;
|
||||
uint16_t mgmt_frame_seq_num;
|
||||
uint8_t operating_freq;
|
||||
uint8_t ssid_len;
|
||||
char ssid[WLAN_MAX_SSID_SIZE];
|
||||
uint8_t self_mac_addr[QDF_MAC_ADDR_SIZE];
|
||||
uint8_t bssid[QDF_MAC_ADDR_SIZE];
|
||||
uint16_t mac_failure_reason;
|
||||
uint16_t mgmt_status_code;
|
||||
uint8_t auth_algo;
|
||||
uint8_t auth_transaction_num;
|
||||
uint8_t is_retry;
|
||||
uint32_t rssi;
|
||||
uint8_t origin;
|
||||
} qdf_packed;
|
||||
|
||||
/**
|
||||
* struct wlan_roam_btm_trigger_data - BTM roam trigger related information
|
||||
* @btm_request_mode: BTM request mode - solicited/unsolicited
|
||||
* @disassoc_timer: Number of TBTT before AP disassociates the STA in ms
|
||||
* @validity_interval: Preferred candidate list validity interval in ms
|
||||
* @candidate_list_count: Number of candidates in BTM request.
|
||||
* @btm_resp_status: Status code of the BTM response.
|
||||
*/
|
||||
struct wlan_roam_btm_trigger_data {
|
||||
uint8_t btm_request_mode;
|
||||
uint32_t disassoc_timer;
|
||||
uint32_t validity_interval;
|
||||
uint16_t candidate_list_count;
|
||||
uint16_t btm_resp_status;
|
||||
} qdf_packed;
|
||||
|
||||
/**
|
||||
* struct wlan_roam_cu_trigger_data - BSS Load roam trigger parameters
|
||||
* @cu_load: Connected AP CU load percentage
|
||||
*/
|
||||
struct wlan_roam_cu_trigger_data {
|
||||
uint16_t cu_load;
|
||||
} qdf_packed;
|
||||
|
||||
/**
|
||||
* struct wlan_roam_rssi_trigger_data - RSSI roam trigger related
|
||||
* parameters
|
||||
* @threshold: RSSI threshold value in dBm for LOW rssi roam trigger
|
||||
*/
|
||||
struct wlan_roam_rssi_trigger_data {
|
||||
uint32_t threshold;
|
||||
} qdf_packed;
|
||||
|
||||
/**
|
||||
* struct wlan_roam_deauth_trigger_data - Deauth roaming trigger related
|
||||
* parameters
|
||||
* @type: 1- Deauthentication 2- Disassociation
|
||||
* @reason: Status code of the Deauth/Disassoc received
|
||||
*/
|
||||
struct wlan_roam_deauth_trigger_data {
|
||||
uint8_t type;
|
||||
uint32_t reason;
|
||||
} qdf_packed;
|
||||
|
||||
/**
|
||||
* struct host_log_wlan_roam_trigger_info - Roam trigger
|
||||
* related info
|
||||
* @hdr: Log header
|
||||
* @version: Version number of the payload
|
||||
* @vdev_id: Vdev id
|
||||
* @trigger_reason: Roaming trigger reason
|
||||
* @trigger_sub_reason: Roaming trigger sub reason
|
||||
* @current_rssi: Current connected AP RSSI
|
||||
* @timestamp: Host driver timestamp in msecs
|
||||
* @btm_trig_data: BTM trigger related data
|
||||
* @cu_load_data: CU load trigger related data
|
||||
* @rssi_trig_data: RSSI roam trigger related data
|
||||
* @deauth_trig_data: Deauth Roam trigger related data
|
||||
*/
|
||||
struct host_log_wlan_roam_trigger_info {
|
||||
log_hdr_type hdr;
|
||||
uint8_t version;
|
||||
uint8_t vdev_id;
|
||||
uint32_t trigger_reason;
|
||||
uint32_t trigger_sub_reason;
|
||||
uint32_t current_rssi;
|
||||
uint32_t timestamp;
|
||||
union {
|
||||
struct wlan_roam_btm_trigger_data btm_trig_data;
|
||||
struct wlan_roam_cu_trigger_data cu_load_data;
|
||||
struct wlan_roam_rssi_trigger_data rssi_trig_data;
|
||||
struct wlan_roam_deauth_trigger_data deauth_trig_data;
|
||||
};
|
||||
} qdf_packed;
|
||||
|
||||
/**
|
||||
* struct host_log_wlan_roam_candidate_info - Roam scan candidate APs related
|
||||
* info
|
||||
* @version: Payload structure version
|
||||
* @timestamp: Host timestamp in millisecs
|
||||
* @type: 0 - Candidate AP; 1 - Current connected AP.
|
||||
* @bssid: AP bssid.
|
||||
* @freq: Channel frquency
|
||||
* @cu_load: Channel utilization load of the AP.
|
||||
* @cu_score: Channel Utilization score.
|
||||
* @rssi: Candidate AP rssi
|
||||
* @rssi_score: AP RSSI score
|
||||
* @total_score: Total score of the candidate AP.
|
||||
* @etp: Estimated throughput value of the AP in Mbps
|
||||
*/
|
||||
struct host_log_wlan_roam_candidate_info {
|
||||
uint8_t version;
|
||||
uint32_t timestamp;
|
||||
uint8_t type;
|
||||
uint8_t bssid[QDF_MAC_ADDR_SIZE];
|
||||
uint16_t freq;
|
||||
uint32_t cu_load;
|
||||
uint32_t cu_score;
|
||||
uint32_t rssi;
|
||||
uint32_t rssi_score;
|
||||
uint32_t total_score;
|
||||
uint32_t etp;
|
||||
} qdf_packed;
|
||||
|
||||
/**
|
||||
* struct host_log_wlan_roam_scan_data - Roam scan event details
|
||||
* @hdr: Log header
|
||||
* @version: Version number of the diag log payload
|
||||
* @vdev_id: Vdev ID
|
||||
* @type: 0 - Partial roam scan; 1 - Full roam scan
|
||||
* @num_ap: Number of candidate APs.
|
||||
* @num_chan: Number of channels.
|
||||
* @timestamp: Time of day in milliseconds at which scan was triggered
|
||||
* @trigger_reason: Roam scan trigger reason
|
||||
* @next_rssi_threshold: Next roam can trigger rssi threshold
|
||||
* @chan_freq: List of frequencies scanned as part of roam scan
|
||||
* @ap: List of candidate AP info
|
||||
*/
|
||||
struct host_log_wlan_roam_scan_data {
|
||||
log_hdr_type hdr;
|
||||
uint8_t version;
|
||||
uint8_t vdev_id;
|
||||
uint16_t type;
|
||||
uint8_t num_ap;
|
||||
uint8_t num_chan;
|
||||
uint32_t timestamp;
|
||||
uint32_t trigger_reason;
|
||||
uint32_t next_rssi_threshold;
|
||||
uint16_t chan_freq[WLAN_MAX_ROAM_SCAN_CHAN];
|
||||
struct host_log_wlan_roam_candidate_info ap[WLAN_MAX_ROAM_CANDIDATE_AP];
|
||||
} qdf_packed;
|
||||
|
||||
/**
|
||||
* struct host_log_wlan_roam_result_info - Roam result related info.
|
||||
* @hdr: Log header
|
||||
* @version: Payload structure version
|
||||
* @vdev_id: Vdev Id
|
||||
* @status: 0 - Roaming is success ; 1 - Roaming failed
|
||||
* @timestamp: Host timestamp in millisecs
|
||||
* @fail_reason: One of WMI_ROAM_FAIL_REASON_ID
|
||||
*/
|
||||
struct host_log_wlan_roam_result_info {
|
||||
log_hdr_type hdr;
|
||||
uint8_t version;
|
||||
uint8_t vdev_id;
|
||||
bool status;
|
||||
uint32_t timestamp;
|
||||
uint32_t fail_reason;
|
||||
} qdf_packed;
|
||||
|
||||
/**
|
||||
* struct wlan_rrm_beacon_report - RRM beacon report related
|
||||
* parameters
|
||||
* @req_bssid: beacon report requestor BSSID
|
||||
* @req_ssid: Requested SSID for beacon report
|
||||
* @is_wildcard_bssid: Is the BSSID FF:FF:FF:FF:FF:FF
|
||||
* @req_reg_class: Regulatory class mentioned in the request
|
||||
* @req_measurement_mode: Measurement mode. Active/Passive/Beacon report Table
|
||||
* @req_measurement_duration: Measurement duration requested.
|
||||
* @num_reports_in_frame: Number of BSS scanned
|
||||
* @is_last_frame_in_req: True if this frame is the last frame sent for the
|
||||
* request
|
||||
*/
|
||||
struct wlan_rrm_beacon_report {
|
||||
uint8_t req_bssid[QDF_MAC_ADDR_SIZE];
|
||||
uint8_t req_ssid[WLAN_MAX_SSID_SIZE];
|
||||
bool is_wildcard_bssid;
|
||||
uint8_t req_reg_class;
|
||||
uint16_t req_measurement_mode;
|
||||
uint16_t req_measurement_duration;
|
||||
uint8_t num_reports_in_frame;
|
||||
bool is_last_frame_in_req;
|
||||
} qdf_packed;
|
||||
|
||||
/**
|
||||
* struct host_log_wlan_rrm_tx_rx_info - RRM frame related details
|
||||
* @hdr: Log header
|
||||
* @version: Version of the payload structure
|
||||
* @vdev_id: Vdev id
|
||||
* @origin: Sent by host or firmware
|
||||
* @is_tx: Is Tx frame or RX frame
|
||||
* @roam_result: Roaming result
|
||||
* @timestamp: Time of the day in milliseconds
|
||||
* @mgmt_frame_seq_num: Frame sequence number
|
||||
* @received_chan_freq: Frame received channel frequency
|
||||
* @action_category: Action frame category
|
||||
* @rrm_action_code: Radio measurement/Noise measurement
|
||||
* @radio_measurement_type: Neighbor report/Beacon report
|
||||
* @bssid: BSSID field in frame
|
||||
* @req_num_freq: Number of frequencies provided in request
|
||||
* @req_freq: Frequencies requested
|
||||
* @fail_reason_code: response TX failure status code
|
||||
* @rssi: Rx frame rssi
|
||||
* @bcn_rpt: Beacon report related parameters
|
||||
*/
|
||||
struct host_log_wlan_rrm_tx_rx_info {
|
||||
log_hdr_type hdr;
|
||||
uint8_t version;
|
||||
uint8_t vdev_id;
|
||||
uint8_t origin;
|
||||
bool is_tx;
|
||||
bool roam_result;
|
||||
uint32_t timestamp;
|
||||
uint16_t mgmt_frame_seq_num;
|
||||
uint16_t received_chan_freq;
|
||||
uint8_t action_category;
|
||||
uint8_t rrm_action_code;
|
||||
uint8_t radio_measurement_type;
|
||||
uint8_t bssid[QDF_MAC_ADDR_SIZE];
|
||||
uint8_t req_num_freq;
|
||||
uint16_t req_freq[WLAN_MAX_ROAM_SCAN_CHAN];
|
||||
uint8_t fail_reason_code;
|
||||
uint32_t rssi;
|
||||
struct wlan_rrm_beacon_report bcn_rpt;
|
||||
} qdf_packed;
|
||||
|
||||
/**
|
||||
* struct host_event_proto_pkt_info - DP protocol pkt info
|
||||
* @hdr: Log header
|
||||
* @version: version
|
||||
* @type: data pkt type
|
||||
* @subtype: data pkt subtype
|
||||
* @dir: tx or rx
|
||||
* @sa: source MAC address
|
||||
* @da: destination MAC address
|
||||
* @msdu_id: MSDU id
|
||||
* @status: status
|
||||
*
|
||||
* Structure containing the protocol data pkt info
|
||||
*
|
||||
* LOG_WLAN_DP_PROTO_PKT_INFO_C 0x1A1E
|
||||
*/
|
||||
struct host_event_proto_pkt_info {
|
||||
log_hdr_type hdr;
|
||||
uint32_t version;
|
||||
uint8_t type;
|
||||
uint8_t subtype;
|
||||
uint8_t dir;
|
||||
uint8_t sa[QDF_MAC_ADDR_SIZE];
|
||||
uint8_t da[QDF_MAC_ADDR_SIZE];
|
||||
uint16_t msdu_id;
|
||||
uint8_t status;
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
Function declarations and documentation
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __HOST_DIAG_CORE_LOG_H */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2021 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.
|
||||
*/
|
||||
|
||||
/*============================================================================
|
||||
FILE: host_diag_log.c
|
||||
|
||||
OVERVIEW: This source file contains definitions for WLAN UTIL diag APIs
|
||||
|
||||
DEPENDENCIES:
|
||||
============================================================================*/
|
||||
|
||||
#include "qdf_types.h"
|
||||
#include "i_host_diag_core_log.h"
|
||||
#include "host_diag_core_event.h"
|
||||
#include "wlan_nlink_common.h"
|
||||
#include "cds_sched.h"
|
||||
#include "wlan_ptt_sock_svc.h"
|
||||
#include "wlan_nlink_srv.h"
|
||||
#include "cds_api.h"
|
||||
#include "wlan_ps_wow_diag.h"
|
||||
#include "qdf_str.h"
|
||||
|
||||
#define PTT_MSG_DIAG_CMDS_TYPE (0x5050)
|
||||
|
||||
#define DIAG_TYPE_LOGS (1)
|
||||
#define DIAG_TYPE_EVENTS (2)
|
||||
|
||||
#define DIAG_SWAP16(A) ((((uint16_t)(A) & 0xff00) >> 8) | (((uint16_t)(A) & 0x00ff) << 8))
|
||||
|
||||
typedef struct event_report_s {
|
||||
uint32_t diag_type;
|
||||
uint16_t event_id;
|
||||
uint16_t length;
|
||||
} event_report_t;
|
||||
|
||||
/**---------------------------------------------------------------------------
|
||||
|
||||
\brief host_diag_log_set_code() -
|
||||
|
||||
This function sets the logging code in the given log record.
|
||||
|
||||
\param - ptr - Pointer to the log header type.
|
||||
- code - log code.
|
||||
\return - None
|
||||
|
||||
--------------------------------------------------------------------------*/
|
||||
|
||||
void host_diag_log_set_code(void *ptr, uint16_t code)
|
||||
{
|
||||
if (ptr) {
|
||||
/* All log packets are required to start with 'log_header_type' */
|
||||
((log_hdr_type *) ptr)->code = code;
|
||||
}
|
||||
}
|
||||
|
||||
/**---------------------------------------------------------------------------
|
||||
|
||||
\brief host_diag_log_set_length() -
|
||||
|
||||
This function sets the length field in the given log record.
|
||||
|
||||
\param - ptr - Pointer to the log header type.
|
||||
- length - log length.
|
||||
|
||||
\return - None
|
||||
|
||||
--------------------------------------------------------------------------*/
|
||||
|
||||
void host_diag_log_set_length(void *ptr, uint16_t length)
|
||||
{
|
||||
if (ptr) {
|
||||
/* All log packets are required to start with 'log_header_type' */
|
||||
((log_hdr_type *) ptr)->len = (uint16_t) length;
|
||||
}
|
||||
}
|
||||
|
||||
/**---------------------------------------------------------------------------
|
||||
|
||||
\brief host_diag_log_submit() -
|
||||
|
||||
This function sends the log data to the ptt socket app only if it is registered with the driver.
|
||||
|
||||
\param - ptr - Pointer to the log header type.
|
||||
|
||||
\return - None
|
||||
|
||||
--------------------------------------------------------------------------*/
|
||||
|
||||
void host_diag_log_submit(void *plog_hdr_ptr)
|
||||
{
|
||||
log_hdr_type *pHdr = (log_hdr_type *) plog_hdr_ptr;
|
||||
tAniHdr *wmsg = NULL;
|
||||
uint8_t *pBuf;
|
||||
uint16_t data_len;
|
||||
uint16_t total_len;
|
||||
|
||||
if (cds_is_load_or_unload_in_progress())
|
||||
return;
|
||||
|
||||
if (nl_srv_is_initialized() != 0)
|
||||
return;
|
||||
|
||||
if (cds_is_multicast_logging()) {
|
||||
data_len = pHdr->len;
|
||||
|
||||
total_len = sizeof(tAniHdr) + sizeof(uint32_t) + data_len;
|
||||
|
||||
pBuf = (uint8_t *) qdf_mem_malloc(total_len);
|
||||
|
||||
if (!pBuf)
|
||||
return;
|
||||
|
||||
wmsg = (tAniHdr *) pBuf;
|
||||
wmsg->type = PTT_MSG_DIAG_CMDS_TYPE;
|
||||
wmsg->length = total_len;
|
||||
wmsg->length = DIAG_SWAP16(wmsg->length);
|
||||
pBuf += sizeof(tAniHdr);
|
||||
|
||||
/* Diag Type events or log */
|
||||
*(uint32_t *) pBuf = DIAG_TYPE_LOGS;
|
||||
pBuf += sizeof(uint32_t);
|
||||
|
||||
memcpy(pBuf, pHdr, data_len);
|
||||
ptt_sock_send_msg_to_app (wmsg, 0, ANI_NL_MSG_PUMAC,
|
||||
INVALID_PID);
|
||||
qdf_mem_free((void *)wmsg);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* host_diag_log_wlock() - This function is used to send wake lock diag events
|
||||
* @reason: Reason why the wakelock was taken or released
|
||||
* @wake_lock_name: Function in which the wakelock was taken or released
|
||||
* @timeout: Timeout value in case of timed wakelocks
|
||||
* @status: Status field indicating whether the wake lock was taken/released
|
||||
*
|
||||
* This function is used to send wake lock diag events to user space
|
||||
*
|
||||
* Return: None
|
||||
*
|
||||
*/
|
||||
void host_diag_log_wlock(uint32_t reason, const char *wake_lock_name,
|
||||
uint32_t timeout, uint32_t status)
|
||||
{
|
||||
WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event,
|
||||
struct host_event_wlan_wake_lock);
|
||||
|
||||
if ((nl_srv_is_initialized() != 0) ||
|
||||
(cds_is_wakelock_enabled() == false))
|
||||
return;
|
||||
|
||||
wlan_diag_event.status = status;
|
||||
wlan_diag_event.reason = reason;
|
||||
wlan_diag_event.timeout = timeout;
|
||||
wlan_diag_event.name_len = strlen(wake_lock_name);
|
||||
strlcpy(&wlan_diag_event.name[0],
|
||||
wake_lock_name,
|
||||
wlan_diag_event.name_len+1);
|
||||
|
||||
WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_WAKE_LOCK);
|
||||
}
|
||||
|
||||
/**---------------------------------------------------------------------------
|
||||
|
||||
\brief host_diag_event_report_payload() -
|
||||
|
||||
This function sends the event data to the ptt socket app only if it is
|
||||
registered with the driver.
|
||||
|
||||
\param - ptr - Pointer to the log header type.
|
||||
|
||||
\return - None
|
||||
|
||||
--------------------------------------------------------------------------*/
|
||||
|
||||
void host_diag_event_report_payload(uint16_t event_Id, uint16_t length,
|
||||
void *pPayload)
|
||||
{
|
||||
tAniHdr *wmsg = NULL;
|
||||
uint8_t *pBuf;
|
||||
event_report_t *pEvent_report;
|
||||
uint16_t total_len;
|
||||
int ret;
|
||||
|
||||
if (cds_is_load_or_unload_in_progress())
|
||||
return;
|
||||
|
||||
if (nl_srv_is_initialized() != 0)
|
||||
return;
|
||||
|
||||
if (cds_is_multicast_logging()) {
|
||||
total_len = sizeof(tAniHdr) + sizeof(event_report_t) + length;
|
||||
|
||||
pBuf = (uint8_t *) qdf_mem_malloc(total_len);
|
||||
|
||||
if (!pBuf)
|
||||
return;
|
||||
|
||||
wmsg = (tAniHdr *) pBuf;
|
||||
wmsg->type = PTT_MSG_DIAG_CMDS_TYPE;
|
||||
wmsg->length = total_len;
|
||||
wmsg->length = DIAG_SWAP16(wmsg->length);
|
||||
pBuf += sizeof(tAniHdr);
|
||||
|
||||
pEvent_report = (event_report_t *) pBuf;
|
||||
pEvent_report->diag_type = DIAG_TYPE_EVENTS;
|
||||
pEvent_report->event_id = event_Id;
|
||||
pEvent_report->length = length;
|
||||
|
||||
pBuf += sizeof(event_report_t);
|
||||
|
||||
memcpy(pBuf, pPayload, length);
|
||||
|
||||
ret = ptt_sock_send_msg_to_app
|
||||
(wmsg, 0, ANI_NL_MSG_PUMAC, INVALID_PID);
|
||||
if ((ret < 0) && (ret != -ESRCH)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"Ptt Socket error sending message to the app!!");
|
||||
qdf_mem_free((void *)wmsg);
|
||||
return;
|
||||
}
|
||||
|
||||
qdf_mem_free((void *)wmsg);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* host_log_low_resource_failure() - This function is used to send low
|
||||
* resource failure event
|
||||
* @event_sub_type: Reason why the failure was observed
|
||||
*
|
||||
* This function is used to send low resource failure events to user space
|
||||
*
|
||||
* Return: None
|
||||
*
|
||||
*/
|
||||
void host_log_low_resource_failure(uint8_t event_sub_type)
|
||||
{
|
||||
WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event,
|
||||
struct host_event_wlan_low_resource_failure);
|
||||
|
||||
wlan_diag_event.event_sub_type = event_sub_type;
|
||||
|
||||
WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event,
|
||||
EVENT_WLAN_LOW_RESOURCE_FAILURE);
|
||||
}
|
||||
|
||||
void host_log_rsn_info(uint8_t *ucast_cipher, uint8_t *mcast_cipher,
|
||||
uint8_t *akm_suite, uint8_t *group_mgmt)
|
||||
{
|
||||
WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event,
|
||||
struct event_wlan_csr_rsn_info);
|
||||
|
||||
qdf_mem_copy(wlan_diag_event.ucast_cipher, ucast_cipher,
|
||||
RSN_OUI_SIZE);
|
||||
qdf_mem_copy(wlan_diag_event.mcast_cipher, mcast_cipher,
|
||||
RSN_OUI_SIZE);
|
||||
qdf_mem_copy(wlan_diag_event.akm_suite, akm_suite,
|
||||
RSN_OUI_SIZE);
|
||||
qdf_mem_copy(wlan_diag_event.group_mgmt, group_mgmt,
|
||||
RSN_OUI_SIZE);
|
||||
|
||||
WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event,
|
||||
EVENT_WLAN_RSN_INFO);
|
||||
}
|
||||
|
||||
void
|
||||
host_log_wlan_auth_info(uint16_t auth_algo_num, uint16_t auth_tx_seq_num,
|
||||
uint16_t auth_status_code)
|
||||
{
|
||||
WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event,
|
||||
struct event_wlan_lim_auth_info);
|
||||
|
||||
wlan_diag_event.auth_algo_num = auth_algo_num;
|
||||
wlan_diag_event.auth_transaction_seq_num = auth_tx_seq_num;
|
||||
wlan_diag_event.auth_status_code = auth_status_code;
|
||||
|
||||
WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event,
|
||||
EVENT_WLAN_AUTH_INFO);
|
||||
}
|
||||
|
||||
#ifdef FEATURE_WLAN_DIAG_SUPPORT
|
||||
/**
|
||||
* qdf_wow_wakeup_host_event()- send wow wakeup event
|
||||
* @wow_wakeup_cause: WOW wakeup reason code
|
||||
*
|
||||
* This function sends wow wakeup reason code diag event
|
||||
*
|
||||
* Return: void.
|
||||
*/
|
||||
void qdf_wow_wakeup_host_event(uint8_t wow_wakeup_cause)
|
||||
{
|
||||
WLAN_HOST_DIAG_EVENT_DEF(wowRequest,
|
||||
host_event_wlan_powersave_wow_payload_type);
|
||||
qdf_mem_zero(&wowRequest, sizeof(wowRequest));
|
||||
|
||||
wowRequest.event_subtype = WLAN_WOW_WAKEUP;
|
||||
wowRequest.wow_wakeup_cause = wow_wakeup_cause;
|
||||
WLAN_HOST_DIAG_EVENT_REPORT(&wowRequest,
|
||||
EVENT_WLAN_POWERSAVE_WOW);
|
||||
}
|
||||
|
||||
void host_log_acs_req_event(uint8_t *intf, const uint8_t *hw_mode, uint16_t bw,
|
||||
uint8_t ht, uint8_t vht, uint16_t chan_start,
|
||||
uint16_t chan_end)
|
||||
{
|
||||
WLAN_HOST_DIAG_EVENT_DEF(acs_req, struct host_event_wlan_acs_req);
|
||||
|
||||
qdf_str_lcopy(acs_req.intf, intf, HOST_EVENT_INTF_STR_LEN);
|
||||
qdf_str_lcopy(acs_req.hw_mode, hw_mode, HOST_EVENT_HW_MODE_STR_LEN);
|
||||
acs_req.bw = bw;
|
||||
acs_req.ht = ht;
|
||||
acs_req.vht = vht;
|
||||
acs_req.chan_start = chan_start;
|
||||
acs_req.chan_end = chan_end;
|
||||
|
||||
WLAN_HOST_DIAG_EVENT_REPORT(&acs_req, EVENT_WLAN_ACS_REQ);
|
||||
}
|
||||
|
||||
void host_log_acs_scan_start(uint32_t scan_id, uint8_t vdev_id)
|
||||
{
|
||||
WLAN_HOST_DIAG_EVENT_DEF(acs_scan_start,
|
||||
struct host_event_wlan_acs_scan_start);
|
||||
|
||||
acs_scan_start.scan_id = scan_id;
|
||||
acs_scan_start.vdev_id = vdev_id;
|
||||
|
||||
WLAN_HOST_DIAG_EVENT_REPORT(&acs_scan_start,
|
||||
EVENT_WLAN_ACS_SCAN_START);
|
||||
}
|
||||
|
||||
void host_log_acs_scan_done(const uint8_t *status,
|
||||
uint8_t vdev_id, uint32_t scan_id)
|
||||
{
|
||||
WLAN_HOST_DIAG_EVENT_DEF(acs_scan_done,
|
||||
struct host_event_wlan_acs_scan_done);
|
||||
|
||||
qdf_str_lcopy(acs_scan_done.status, status, HOST_EVENT_STATUS_STR_LEN);
|
||||
acs_scan_done.vdev_id = vdev_id;
|
||||
acs_scan_done.scan_id = scan_id;
|
||||
|
||||
WLAN_HOST_DIAG_EVENT_REPORT(&acs_scan_done, EVENT_WLAN_ACS_SCAN_DONE);
|
||||
}
|
||||
|
||||
void host_log_acs_chan_spect_weight(uint16_t chan, uint16_t weight,
|
||||
int32_t rssi, uint16_t bss_count)
|
||||
{
|
||||
WLAN_HOST_DIAG_EVENT_DEF(
|
||||
acs_chan_spect_weight,
|
||||
struct host_event_wlan_acs_chan_spectral_weight);
|
||||
|
||||
acs_chan_spect_weight.chan = chan;
|
||||
acs_chan_spect_weight.weight = weight;
|
||||
acs_chan_spect_weight.rssi = rssi;
|
||||
acs_chan_spect_weight.bss_count = bss_count;
|
||||
|
||||
WLAN_HOST_DIAG_EVENT_REPORT(&acs_chan_spect_weight,
|
||||
EVENT_WLAN_ACS_CHANNEL_SPECTRAL_WEIGHT);
|
||||
}
|
||||
|
||||
void host_log_acs_best_chan(uint16_t chan, uint16_t weight)
|
||||
{
|
||||
WLAN_HOST_DIAG_EVENT_DEF(acs_best_chan,
|
||||
struct host_event_wlan_acs_best_chan);
|
||||
|
||||
acs_best_chan.chan = chan;
|
||||
acs_best_chan.weight = weight;
|
||||
|
||||
WLAN_HOST_DIAG_EVENT_REPORT(&acs_best_chan,
|
||||
EVENT_WLAN_ACS_BEST_CHANNEL);
|
||||
}
|
||||
|
||||
void host_log_device_status(uint16_t status_code)
|
||||
{
|
||||
WLAN_HOST_DIAG_EVENT_DEF(driver_status,
|
||||
host_event_wlan_bringup_status_payload_type);
|
||||
|
||||
driver_status.wlan_status = status_code;
|
||||
|
||||
/* driver version not used yet, fill properly if need later */
|
||||
qdf_mem_zero(driver_status.driver_version,
|
||||
sizeof(driver_status.driver_version));
|
||||
|
||||
WLAN_HOST_DIAG_EVENT_REPORT(&driver_status,
|
||||
EVENT_WLAN_BRINGUP_STATUS);
|
||||
}
|
||||
|
||||
#endif
|
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2019, 2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. 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.
|
||||
*/
|
||||
|
||||
#if !defined(__I_HOST_DIAG_CORE_EVENT_H)
|
||||
#define __I_HOST_DIAG_CORE_EVENT_H
|
||||
|
||||
/**=========================================================================
|
||||
|
||||
\file i_host_diag_core_event.h
|
||||
|
||||
\brief Android specific definitions for WLAN UTIL DIAG events
|
||||
|
||||
========================================================================*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Include Files
|
||||
------------------------------------------------------------------------*/
|
||||
#include <qdf_types.h>
|
||||
#ifdef FEATURE_WLAN_DIAG_SUPPORT
|
||||
#include <host_diag_event_defs.h>
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Preprocessor definitions and constants
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef FEATURE_WLAN_DIAG_SUPPORT
|
||||
|
||||
void host_diag_event_report_payload(uint16_t event_Id, uint16_t length,
|
||||
void *pPayload);
|
||||
/*---------------------------------------------------------------------------
|
||||
Allocate an event payload holder
|
||||
---------------------------------------------------------------------------*/
|
||||
#define WLAN_HOST_DIAG_EVENT_DEF(payload_name, payload_type) \
|
||||
payload_type(payload_name)
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Report the event
|
||||
---------------------------------------------------------------------------*/
|
||||
#define WLAN_HOST_DIAG_EVENT_REPORT(payload_ptr, ev_id) \
|
||||
do { \
|
||||
host_diag_event_report_payload(ev_id, \
|
||||
sizeof(*(payload_ptr)), \
|
||||
(void *)(payload_ptr)); \
|
||||
} while (0)
|
||||
|
||||
#else /* FEATURE_WLAN_DIAG_SUPPORT */
|
||||
|
||||
#define WLAN_HOST_DIAG_EVENT_DEF(payload_name, payload_type)
|
||||
#define WLAN_HOST_DIAG_EVENT_REPORT(payload_ptr, ev_id)
|
||||
|
||||
#endif /* FEATURE_WLAN_DIAG_SUPPORT */
|
||||
|
||||
/**
|
||||
* enum auth_timeout_type - authentication timeout type
|
||||
* @AUTH_FAILURE_TIMEOUT: auth failure timeout
|
||||
* @AUTH_RESPONSE_TIMEOUT: auth response timeout
|
||||
*/
|
||||
enum auth_timeout_type {
|
||||
AUTH_FAILURE_TIMEOUT,
|
||||
AUTH_RESPONSE_TIMEOUT,
|
||||
};
|
||||
|
||||
#ifdef CONNECTIVITY_DIAG_EVENT
|
||||
/**
|
||||
* enum diag_roam_reason - Represents the reason codes for roaming.
|
||||
* @DIAG_ROAM_REASON_UNKNOWN: Any reason that do not classify under the below
|
||||
* reasons.
|
||||
* @DIAG_ROAM_REASON_PER: Roam triggered when packet error rates(PER) breached
|
||||
* the configured threshold.
|
||||
* @DIAG_ROAM_REASON_BEACON_MISS: Roam triggered due to the continuous
|
||||
* configured beacon misses from the then connected AP.
|
||||
* @DIAG_ROAM_REASON_POOR_RSSI: Roam triggered due to the poor RSSI reported
|
||||
* by the connected AP.
|
||||
* @DIAG_ROAM_REASON_BETTER_RSSI: Roam triggered for finding a BSSID with a
|
||||
* better RSSI than the connected BSSID. Here the RSSI of the current BSSID is
|
||||
* not poor.
|
||||
* @DIAG_ROAM_REASON_CONGESTION: Roam triggered considering the connected
|
||||
* channel or environment being very noisy / congested.
|
||||
* @DIAG_ROAM_REASON_USER_TRIGGER: Roam triggered due to an explicit request
|
||||
* from the user (user space).
|
||||
* @DIAG_ROAM_REASON_BTM: Roam triggered due to BTM request frame received from
|
||||
* connected AP.
|
||||
* @DIAG_ROAM_REASON_BSS_LOAD: Roam triggered due to the channel utilization
|
||||
* breaching out the configured threshold.
|
||||
* @DIAG_ROAM_REASON_WTC: Roam triggered due to Wireless to Cellular BSS
|
||||
* transition request.
|
||||
* @DIAG_ROAM_REASON_IDLE: Roam triggered when device is suspended,
|
||||
* there is no data activity with the AP and the current rssi falls below a
|
||||
* certain threshold.
|
||||
* @DIAG_ROAM_REASON_DISCONNECTION: Roam triggered due to
|
||||
* deauthentication or disassociation frames received from the connected AP.
|
||||
* @DIAG_ROAM_REASON_PERIODIC_TIMER: Roam triggered as part of the periodic
|
||||
* scan that happens when there is no candidate AP found during the poor
|
||||
* RSSI scan trigger.
|
||||
* @DIAG_ROAM_REASON_BACKGROUND_SCAN: Roam triggered based on the scan
|
||||
* results obtained from an external scan (not aimed at roaming).
|
||||
* @DIAG_ROAM_REASON_BT_ACTIVITY: Roam triggered due to bluetooth
|
||||
* connection is established when the station is connected in 2.4 Ghz band.
|
||||
*/
|
||||
enum diag_roam_reason {
|
||||
DIAG_ROAM_REASON_UNKNOWN,
|
||||
DIAG_ROAM_REASON_PER,
|
||||
DIAG_ROAM_REASON_BEACON_MISS,
|
||||
DIAG_ROAM_REASON_POOR_RSSI,
|
||||
DIAG_ROAM_REASON_BETTER_RSSI,
|
||||
DIAG_ROAM_REASON_CONGESTION,
|
||||
DIAG_ROAM_REASON_USER_TRIGGER,
|
||||
DIAG_ROAM_REASON_BTM,
|
||||
DIAG_ROAM_REASON_BSS_LOAD,
|
||||
DIAG_ROAM_REASON_WTC,
|
||||
DIAG_ROAM_REASON_IDLE,
|
||||
DIAG_ROAM_REASON_DISCONNECTION,
|
||||
DIAG_ROAM_REASON_PERIODIC_TIMER,
|
||||
DIAG_ROAM_REASON_BACKGROUND_SCAN,
|
||||
DIAG_ROAM_REASON_BT_ACTIVITY
|
||||
};
|
||||
|
||||
/**
|
||||
* enum diag_roam_sub_reason - Used by attribute
|
||||
* @DIAG_ROAM_SUB_REASON_UNKNOWN: Roam sub-reason unknown/unspecified
|
||||
* @DIAG_ROAM_SUB_REASON_PERIODIC_TIMER: Roam scan triggered due to periodic
|
||||
* timer expiry
|
||||
* @DIAG_ROAM_SUB_REASON_INACTIVITY_TIMER_LOW_RSSI: Roam scan trigger due
|
||||
* to no candidate found during LOW RSSI trigger.
|
||||
* @DIAG_ROAM_SUB_REASON_BTM_DI_TIMER: Roam scan triggered due to BTM Disassoc
|
||||
* Imminent timeout
|
||||
* @DIAG_ROAM_SUB_REASON_FULL_SCAN: Roam scan triggered due to partial scan
|
||||
* failure
|
||||
* @DIAG_ROAM_SUB_REASON_LOW_RSSI_PERIODIC: Roam trigger due to
|
||||
* emergency like deauth/disassoc.
|
||||
* @DIAG_ROAM_SUB_REASON_CU_PERIODIC: Roam trigger due to
|
||||
* BSS transition management request.
|
||||
* @DIAG_ROAM_SUB_REASON_PERIODIC_TIMER_AFTER_INACTIVITY_LOW_RSSI:
|
||||
* Roam scan triggered due to Low RSSI periodic timer
|
||||
* @DIAG_ROAM_SUB_REASON_PERIODIC_TIMER_AFTER_INACTIVITY_CU:
|
||||
* Roam trigger due to periodic timer after no candidate found during CU
|
||||
* inactivity timer scan.
|
||||
* @DIAG_ROAM_SUB_REASON_INACTIVITY_TIMER_CU: Roam trigger due to no candidate
|
||||
* found in high CU roam trigger.
|
||||
*/
|
||||
|
||||
enum diag_roam_sub_reason {
|
||||
DIAG_ROAM_SUB_REASON_UNKNOWN = 0,
|
||||
DIAG_ROAM_SUB_REASON_PERIODIC_TIMER = 1,
|
||||
DIAG_ROAM_SUB_REASON_INACTIVITY_TIMER_LOW_RSSI = 2,
|
||||
DIAG_ROAM_SUB_REASON_BTM_DI_TIMER = 3,
|
||||
DIAG_ROAM_SUB_REASON_FULL_SCAN = 4,
|
||||
DIAG_ROAM_SUB_REASON_LOW_RSSI_PERIODIC = 5,
|
||||
DIAG_ROAM_SUB_REASON_CU_PERIODIC = 6,
|
||||
DIAG_ROAM_SUB_REASON_PERIODIC_TIMER_AFTER_INACTIVITY_LOW_RSSI = 7,
|
||||
DIAG_ROAM_SUB_REASON_PERIODIC_TIMER_AFTER_INACTIVITY_CU = 8,
|
||||
DIAG_ROAM_SUB_REASON_INACTIVITY_TIMER_CU = 9,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
Function declarations and documentation
|
||||
------------------------------------------------------------------------*/
|
||||
#ifdef FEATURE_WLAN_DIAG_SUPPORT
|
||||
void host_diag_log_wlock(uint32_t reason, const char *wake_lock_name,
|
||||
uint32_t timeout, uint32_t status);
|
||||
#else
|
||||
static inline void host_diag_log_wlock(uint32_t reason,
|
||||
const char *wake_lock_name,
|
||||
uint32_t timeout, uint32_t status)
|
||||
{
|
||||
|
||||
}
|
||||
#endif /* FEATURE_WLAN_DIAG_SUPPORT */
|
||||
|
||||
#ifdef FEATURE_WLAN_DIAG_SUPPORT
|
||||
void host_log_low_resource_failure(uint8_t event_sub_type);
|
||||
#else
|
||||
static inline void host_log_low_resource_failure(uint8_t event_sub_type)
|
||||
{
|
||||
|
||||
}
|
||||
#endif /* FEATURE_WLAN_DIAG_SUPPORT */
|
||||
|
||||
#ifdef FEATURE_WLAN_DIAG_SUPPORT
|
||||
/**
|
||||
* host_log_rsn_info() - This function is used to send
|
||||
* requested rsn info in assoc request
|
||||
* @ucast_cipher: Unicast ciphers used in assoc request
|
||||
* @mcast_cipher: Group ciphers used in assoc request
|
||||
* @auth_suite: Gives information about akm suites used in assoc request
|
||||
* @gp_mgmt_cipher: Requested group mgmt cipher suite
|
||||
*
|
||||
* This function is used to send RSN info used in assoc req to user space
|
||||
*
|
||||
* Return: None
|
||||
*
|
||||
*/
|
||||
void host_log_rsn_info(uint8_t *ucast_cipher, uint8_t *mcast_cipher,
|
||||
uint8_t *auth_suite, uint8_t *gp_mgmt_cipher);
|
||||
|
||||
#else
|
||||
static inline void host_log_rsn_info(uint8_t *ucast_cipher,
|
||||
uint8_t *mcast_cipher,
|
||||
uint8_t *auth_suite,
|
||||
uint8_t *gp_mgmt_cipher)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif /* FEATURE_WLAN_DIAG_SUPPORT */
|
||||
|
||||
#ifdef FEATURE_WLAN_DIAG_SUPPORT
|
||||
/**
|
||||
* host_log_wlan_auth_info() - This function is used to send
|
||||
* algo num, seq num and status code for auth request
|
||||
* @auth_algo_num: Gives information about algo num used in auth request
|
||||
* @auth_tx_seq_num: seq num of auth request
|
||||
* @auth_status_code: status code of auth request
|
||||
*
|
||||
* This function is used to send send algo num, seq num and status code
|
||||
* for auth request
|
||||
*
|
||||
* Return: None
|
||||
*
|
||||
*/
|
||||
void
|
||||
host_log_wlan_auth_info(uint16_t auth_algo_num, uint16_t auth_tx_seq_num,
|
||||
uint16_t auth_status_code);
|
||||
|
||||
#else
|
||||
static inline void
|
||||
host_log_wlan_auth_info(uint16_t auth_algo_num, uint16_t auth_tx_seq_num,
|
||||
uint16_t auth_status_code)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* FEATURE_WLAN_DIAG_SUPPORT */
|
||||
|
||||
#ifdef FEATURE_WLAN_DIAG_SUPPORT
|
||||
void qdf_wow_wakeup_host_event(uint8_t wow_wakeup_cause);
|
||||
|
||||
/**
|
||||
* host_log_acs_req_event() - ACS request event indication
|
||||
* @intf: network interface name for WLAN
|
||||
* @hw_mode: hw mode configured by hostapd
|
||||
* @bw: channel bandwidth (MHz)
|
||||
* @ht: a flag indicating whether HT phy mode is enabled
|
||||
* @vht: a flag indicating whether VHT phy mode is enabled
|
||||
* @chan_start: starting channel number for ACS scan
|
||||
* @chan_end: ending channel number for ACS scan
|
||||
*
|
||||
* Indicates the diag event for ACS request with payload related
|
||||
* to parameters populated by hostapd
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void host_log_acs_req_event(uint8_t *intf, const uint8_t *hw_mode,
|
||||
uint16_t bw, uint8_t ht, uint8_t vht,
|
||||
uint16_t chan_start, uint16_t chan_end);
|
||||
|
||||
/**
|
||||
* host_log_acs_scan_start() - ACS scan start event indication
|
||||
* @scan_id: scan request ID
|
||||
* @vdev_id: vdev/session ID
|
||||
*
|
||||
* Indicates the diag event for ACS scan start request
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void host_log_acs_scan_start(uint32_t scan_id, uint8_t vdev_id);
|
||||
|
||||
/**
|
||||
* host_log_acs_scan_done() - ACS scan done event indication
|
||||
* @status: indicating whether ACS scan is successful
|
||||
* @vdev_id: vdev/session ID
|
||||
* @scan_id: scan request ID
|
||||
*
|
||||
* Indicates the diag event for ACS scan done
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void host_log_acs_scan_done(const uint8_t *status, uint8_t vdev_id,
|
||||
uint32_t scan_id);
|
||||
|
||||
/**
|
||||
* host_log_acs_chan_spect_weight() - ACS channel spectral weight indication
|
||||
* weight event indication
|
||||
* @chan: channel number
|
||||
* @weight: channel weight
|
||||
* @rssi: RSSI value obtained after scanning
|
||||
* @bss_count: number of BSS detected on this channel
|
||||
*
|
||||
* Indicates a diag event for ACS channel weight evaluation result
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void host_log_acs_chan_spect_weight(uint16_t chan, uint16_t weight,
|
||||
int32_t rssi, uint16_t bss_count);
|
||||
|
||||
/**
|
||||
* host_log_acs_best_chan() - ACS best channel event indication
|
||||
* @chan: channel number
|
||||
* @weight: channel weight
|
||||
*
|
||||
* Indicates the best channel has been selected after ACS
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void host_log_acs_best_chan(uint16_t chan, uint16_t weight);
|
||||
|
||||
/**
|
||||
* host_log_device_status() - device status indication
|
||||
* @status_code: status code from enum wlan_bringup_status
|
||||
*
|
||||
* Indicates device status
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void host_log_device_status(uint16_t status_code);
|
||||
|
||||
#else
|
||||
static inline void qdf_wow_wakeup_host_event(uint8_t wow_wakeup_cause)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void host_log_acs_req_event(uint8_t *intf, const uint8_t *hw_mode,
|
||||
uint16_t bw, uint8_t ht, uint8_t vht,
|
||||
uint16_t chan_start,
|
||||
uint16_t chan_end)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void host_log_acs_scan_start(uint32_t scan_id, uint8_t vdev_id)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void host_log_acs_scan_done(const uint8_t *status,
|
||||
uint8_t vdev_id, uint32_t scan_id)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void host_log_acs_chan_spect_weight(uint16_t chan,
|
||||
uint16_t weight, int32_t rssi,
|
||||
uint16_t bss_count)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void host_log_acs_best_chan(uint16_t chan, uint32_t weight)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void host_log_device_status(uint16_t status_code)
|
||||
{
|
||||
}
|
||||
#endif /* FEATURE_WLAN_DIAG_SUPPORT */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __I_HOST_DIAG_CORE_EVENT_H */
|
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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.
|
||||
*/
|
||||
|
||||
#if !defined(__I_HOST_DIAG_CORE_LOG_H)
|
||||
#define __I_HOST_DIAG_CORE_LOG_H
|
||||
|
||||
#include <log_codes.h>
|
||||
|
||||
/**=========================================================================
|
||||
|
||||
\file i_host_diag_core_event.h
|
||||
|
||||
\brief android-specific definitions for WLAN UTIL DIAG logs
|
||||
|
||||
========================================================================*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Include Files
|
||||
------------------------------------------------------------------------*/
|
||||
#include <qdf_types.h>
|
||||
#include <qdf_mem.h>
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Preprocessor definitions and constants
|
||||
------------------------------------------------------------------------*/
|
||||
/* FIXME To be removed when DIAG support is added. This definition should be */
|
||||
/* picked from log.h file above. */
|
||||
typedef struct {
|
||||
/* Specifies the length, in bytes of the entry, including this header. */
|
||||
uint16_t len;
|
||||
|
||||
/* Specifies the log code for the entry */
|
||||
uint16_t code;
|
||||
|
||||
/*Time Stamp lo */
|
||||
uint32_t ts_lo;
|
||||
|
||||
/*Time Stamp hi */
|
||||
uint32_t ts_hi;
|
||||
} __packed log_hdr_type;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef FEATURE_WLAN_DIAG_SUPPORT
|
||||
void host_diag_log_set_code(void *ptr, uint16_t code);
|
||||
void host_diag_log_set_length(void *ptr, uint16_t length);
|
||||
void host_diag_log_set_timestamp(void *plog_hdr_ptr);
|
||||
void host_diag_log_submit(void *plog_hdr_ptr);
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Allocate an event payload holder
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define WLAN_HOST_DIAG_LOG_ALLOC(payload_ptr, payload_type, log_code) \
|
||||
do { \
|
||||
payload_ptr = (payload_type *)qdf_mem_malloc(sizeof(payload_type)); \
|
||||
if (payload_ptr) { \
|
||||
host_diag_log_set_code(payload_ptr, log_code); \
|
||||
host_diag_log_set_length(payload_ptr, sizeof(payload_type)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Report the event
|
||||
---------------------------------------------------------------------------*/
|
||||
#define WLAN_HOST_DIAG_LOG_REPORT(payload_ptr) \
|
||||
do { \
|
||||
if (payload_ptr) { \
|
||||
host_diag_log_submit(payload_ptr); \
|
||||
qdf_mem_free(payload_ptr); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Free the payload
|
||||
---------------------------------------------------------------------------*/
|
||||
#define WLAN_HOST_DIAG_LOG_FREE(payload_ptr) \
|
||||
do { \
|
||||
if (payload_ptr) { \
|
||||
qdf_mem_free(payload_ptr); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else /* FEATURE_WLAN_DIAG_SUPPORT */
|
||||
|
||||
#define WLAN_HOST_DIAG_LOG_ALLOC(payload_ptr, payload_type, log_code)
|
||||
#define WLAN_HOST_DIAG_LOG_REPORT(payload_ptr)
|
||||
#define WLAN_HOST_DIAG_LOG_FREE(payload_ptr)
|
||||
|
||||
static inline void host_diag_log_set_code(void *ptr, uint16_t code)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void host_diag_log_set_length(void *ptr, uint16_t length)
|
||||
{
|
||||
}
|
||||
#endif /* FEATURE_WLAN_DIAG_SUPPORT */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
Function declarations and documentation
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __I_HOST_DIAG_CORE_LOG_H */
|
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022,2024 Qualcomm Innovation Center, Inc. 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.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* wlan_logging_sock_svc.h
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef WLAN_LOGGING_SOCK_SVC_H
|
||||
#define WLAN_LOGGING_SOCK_SVC_H
|
||||
|
||||
#include <wlan_nlink_srv.h>
|
||||
#include <qdf_status.h>
|
||||
#include <qdf_trace.h>
|
||||
#include <wlan_nlink_common.h>
|
||||
|
||||
int wlan_logging_sock_init_svc(void);
|
||||
int wlan_logging_sock_deinit_svc(void);
|
||||
int wlan_log_to_user(QDF_TRACE_LEVEL log_level, char *to_be_sent, int length);
|
||||
|
||||
/**
|
||||
* wlan_logging_set_flush_timer() - Sets the time period for log flush timer
|
||||
* @milliseconds: Time period in milliseconds
|
||||
*
|
||||
* This function sets the time period interval during which the log buffers
|
||||
* will be flushed out to user space. Setting this interval can set an
|
||||
* approximate maximum delay after which any message logged through QDF_TRACE
|
||||
* will appear at user-space
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
int wlan_logging_set_flush_timer(uint32_t milliseconds);
|
||||
|
||||
/**
|
||||
* wlan_logging_notifier_init() - registers to panic notifier chain
|
||||
* @dump_at_kernel_enable: qdf logging at kernel level enabled
|
||||
*
|
||||
* This function registers an handler to panic notifier chain if
|
||||
* qdf logging at kernel level is disabled.
|
||||
*
|
||||
* Return: 0 on success
|
||||
*/
|
||||
int wlan_logging_notifier_init(bool dump_at_kernel_enable);
|
||||
|
||||
/**
|
||||
* wlan_logging_notifier_deinit() - unregisters to panic notifier chain
|
||||
* @dump_at_kernel_enable: qdf logging at kernel level enabled
|
||||
*
|
||||
* This function unregisters an handler to panic notifier chain if
|
||||
* qdf logging at kernel level is disabled.
|
||||
*
|
||||
* Return: 0 on success
|
||||
*/
|
||||
int wlan_logging_notifier_deinit(bool dump_at_kernel_enable);
|
||||
|
||||
#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
|
||||
/**
|
||||
* wlan_logging_wait_for_flush_log_completion() - Wait for flush log completion
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS wlan_logging_wait_for_flush_log_completion(void);
|
||||
|
||||
void wlan_logging_set_per_pkt_stats(void);
|
||||
|
||||
/**
|
||||
* wlan_logging_set_connectivity_log() - INterrupt the gwlan_logging thread
|
||||
* to send the connectivity logs
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void wlan_logging_set_connectivity_log(void);
|
||||
void wlan_logging_set_fw_flush_complete(void);
|
||||
void wlan_flush_host_logs_for_fatal(void);
|
||||
void wlan_logging_set_active(bool active);
|
||||
void wlan_set_console_log_levels(uint32_t console_log_levels);
|
||||
#else
|
||||
static inline QDF_STATUS wlan_logging_wait_for_flush_log_completion(void)
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
static inline void wlan_flush_host_logs_for_fatal(void) {}
|
||||
static inline void wlan_logging_set_per_pkt_stats(void) {}
|
||||
static inline void wlan_logging_set_fw_flush_complete(void) {}
|
||||
static inline void wlan_logging_set_active(bool active) {}
|
||||
static inline void wlan_set_console_log_levels(uint32_t console_log_levels) {}
|
||||
#endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */
|
||||
|
||||
#if defined(WLAN_LOGGING_SOCK_SVC_ENABLE) && \
|
||||
defined(CONNECTIVITY_PKTLOG)
|
||||
/**
|
||||
* wlan_deregister_txrx_packetdump() - tx/rx packet dump
|
||||
* deregistration
|
||||
* @pdev_id: id of the datapath pdev handle
|
||||
*
|
||||
* This function is used to deregister tx/rx packet dump callbacks
|
||||
* with ol, pe and htt layers
|
||||
*
|
||||
* Return: None
|
||||
*
|
||||
*/
|
||||
void wlan_deregister_txrx_packetdump(uint8_t pdev_id);
|
||||
|
||||
/**
|
||||
* wlan_register_txrx_packetdump() - tx/rx packet dump
|
||||
* registration
|
||||
* @pdev_id: id of the datapath pdev handle
|
||||
*
|
||||
* This function is used to register tx/rx packet dump callbacks
|
||||
* with ol, pe and htt layers
|
||||
*
|
||||
* Return: None
|
||||
*
|
||||
*/
|
||||
void wlan_register_txrx_packetdump(uint8_t pdev_id);
|
||||
#else
|
||||
static inline void wlan_deregister_txrx_packetdump(uint8_t pdev_id) {}
|
||||
static inline void wlan_register_txrx_packetdump(uint8_t pdev_id) {}
|
||||
#endif
|
||||
|
||||
#if defined(WLAN_LOGGING_SOCK_SVC_ENABLE) && defined(FEATURE_WLAN_DIAG_SUPPORT)
|
||||
void wlan_report_log_completion(uint32_t is_fatal,
|
||||
uint32_t indicator,
|
||||
uint32_t reason_code,
|
||||
uint8_t ring_id);
|
||||
#else
|
||||
static inline void wlan_report_log_completion(uint32_t is_fatal,
|
||||
uint32_t indicator,
|
||||
uint32_t reason_code,
|
||||
uint8_t ring_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* FEATURE_WLAN_DIAG_SUPPORT */
|
||||
|
||||
#if defined(WLAN_LOGGING_SOCK_SVC_ENABLE) && \
|
||||
defined(CONNECTIVITY_PKTLOG)
|
||||
void wlan_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump, void *data);
|
||||
#else
|
||||
static inline
|
||||
void wlan_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump, void *data)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* enum tx_status - tx status
|
||||
* @tx_status_ok: successfully sent + acked
|
||||
* @tx_status_discard: discard - not sent (congestion control)
|
||||
* @tx_status_no_ack: no_ack - sent, but no ack
|
||||
* @tx_status_download_fail: download_fail -
|
||||
* the host could not deliver the tx frame to the target
|
||||
* @tx_status_peer_del: peer_del - tx completion for
|
||||
* already deleted peer used for HL case
|
||||
*
|
||||
* This enum has tx status types
|
||||
*/
|
||||
enum tx_status {
|
||||
tx_status_ok,
|
||||
tx_status_discard,
|
||||
tx_status_no_ack,
|
||||
tx_status_download_fail,
|
||||
tx_status_peer_del,
|
||||
};
|
||||
|
||||
#ifdef WLAN_CHIPSET_STATS
|
||||
void wlan_set_chipset_stats_bit(void);
|
||||
#else
|
||||
static inline void wlan_set_chipset_stats_bit(void)
|
||||
{
|
||||
}
|
||||
#endif /* WLAN_CHIPSET_STATS */
|
||||
#endif /* WLAN_LOGGING_SOCK_SVC_H */
|
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, 2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. 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: Roaming debug log operations declarations
|
||||
*/
|
||||
#ifndef _WLAN_ROAM_DEBUG_H_
|
||||
#define _WLAN_ROAM_DEBUG_H_
|
||||
|
||||
#define roam_debug(args ...) \
|
||||
QDF_TRACE_DEBUG_NO_FL(QDF_MODULE_ID_ROAM_DEBUG, ## args)
|
||||
#define roam_info(args ...) \
|
||||
QDF_TRACE_INFO_NO_FL(QDF_MODULE_ID_ROAM_DEBUG, ## args)
|
||||
|
||||
#define wlan_rec_conn_info(vdev_id, op, mac_addr, arg1, arg2) \
|
||||
wlan_rec_debug_log(REC_CONN, vdev_id, op, 0, mac_addr, 0, arg1,\
|
||||
arg2)
|
||||
|
||||
#ifndef WLAN_ROAM_DEBUG_MAX_REC
|
||||
#define WLAN_ROAM_DEBUG_MAX_REC 128
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
REC_ROAM,
|
||||
REC_CONN,
|
||||
REC_MAX,
|
||||
} wlan_rec_type;
|
||||
|
||||
/**
|
||||
* @DEBUG_PEER_CREATE_SEND: sent peer_create command to firmware
|
||||
* @DEBUG_PEER_CREATE_RESP: received peer create response
|
||||
* @DEBUG_PEER_DELETE_SEND: sent peer delete command to firmware
|
||||
* @DEBUG_PEER_DELETE_RESP: received peer delete response
|
||||
* @DEBUG_PEER_MAP_EVENT: received peer map event
|
||||
* @DEBUG_PEER_UNMAP_EVENT: received peer unmap event
|
||||
* @DEBUG_PEER_UNREF_DELETE: peer reference is decremented
|
||||
* @DEBUG_DELETING_PEER_OBJ: peer object is deleted
|
||||
* @DEBUG_ROAM_SYNCH_IND: received roam offload sync indication
|
||||
* @DEBUG_ROAM_SYNCH_CNF: sent roam offload sync confirmation
|
||||
* @DEBUG_ROAM_SYNCH_FAIL: received roam sync failure indication
|
||||
* @DEBUG_ROAM_EVENT: received roam event
|
||||
* @DEBUG_BUS_SUSPEND: host going into suspend mode
|
||||
* @DEBUG_BUS_RESUME: host operation resumed
|
||||
* @DEBUG_CONN_CONNECTING: trace connecting to bssid
|
||||
* @DEBUG_CONN_ASSOCIATION: trace association completion
|
||||
* @DEBUG_CONN_CONNECT_RESULT: trace connect result to os
|
||||
* @DEBUG_CONN_ROAMING: trace station roaming propagtion
|
||||
* @DEBUG_CONN_ROAMED: trace roamed to bssid
|
||||
* @DEBUG_CONN_ROAMED_IND: trace roam indication
|
||||
* @DEBUG_CONN_DISCONNECT: trace station disconnect
|
||||
* @DEBUG_CONN_DISCONNECT_HANDLER: trace disconnect handler
|
||||
* @DEBUG_CONN_DISCONNECT_IND: trace disconnect indication
|
||||
* @DEBUG_CONN_RSO: trace RSO state changing
|
||||
*/
|
||||
enum peer_debug_op {
|
||||
DEBUG_PEER_CREATE_SEND = 0,
|
||||
DEBUG_PEER_CREATE_RESP,
|
||||
DEBUG_PEER_DELETE_SEND,
|
||||
DEBUG_PEER_DELETE_RESP,
|
||||
DEBUG_PEER_MAP_EVENT,
|
||||
DEBUG_PEER_UNMAP_EVENT,
|
||||
DEBUG_PEER_UNREF_DELETE,
|
||||
DEBUG_DELETING_PEER_OBJ,
|
||||
DEBUG_ROAM_SYNCH_IND,
|
||||
DEBUG_ROAM_SYNCH_CNF,
|
||||
DEBUG_ROAM_SYNCH_FAIL,
|
||||
DEBUG_ROAM_EVENT,
|
||||
DEBUG_WOW_ROAM_EVENT,
|
||||
DEBUG_BUS_SUSPEND,
|
||||
DEBUG_BUS_RESUME,
|
||||
DEBUG_WOW_REASON,
|
||||
DEBUG_CONN_CONNECTING,
|
||||
DEBUG_CONN_ASSOCIATION,
|
||||
DEBUG_CONN_CONNECT_RESULT,
|
||||
DEBUG_CONN_ROAMING,
|
||||
DEBUG_CONN_ROAMED,
|
||||
DEBUG_CONN_ROAMED_IND,
|
||||
DEBUG_CONN_DISCONNECT,
|
||||
DEBUG_CONN_DISCONNECT_HANDLER,
|
||||
DEBUG_CONN_DISCONNECT_IND,
|
||||
DEBUG_CONN_RSO,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wlan_roam_debug_rec - roam debug information record definition
|
||||
* @time: timestamp when record was added
|
||||
* @operation: identifier for operation, command, event, etc.
|
||||
* @vdev_id: vdev identifier
|
||||
* @peer_id: peer_id. Range 0 - 255, 0xffff is invalid peer_id.
|
||||
* @mac_addr: mac address of peer
|
||||
* @peer_obj: pointer to peer object
|
||||
* @arg1: Optional argument #1
|
||||
* @arg2: Opttional argument #2
|
||||
*/
|
||||
struct wlan_roam_debug_rec {
|
||||
uint64_t time;
|
||||
enum peer_debug_op operation;
|
||||
uint8_t vdev_id;
|
||||
uint16_t peer_id;
|
||||
struct qdf_mac_addr mac_addr;
|
||||
void *peer_obj;
|
||||
uint32_t arg1;
|
||||
uint32_t arg2;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wlan_roam_debug_info - Buffer to store the wma debug records
|
||||
* @index: index of the most recent entry in the circular buffer
|
||||
* @num_max_rec: maximum records stored in the records array
|
||||
* @rec: array to store wma debug records, used in circular fashion
|
||||
*/
|
||||
struct wlan_roam_debug_info {
|
||||
qdf_atomic_t index;
|
||||
uint32_t num_max_rec;
|
||||
void (*rec_print)(struct wlan_roam_debug_rec *dbg_rec,
|
||||
uint32_t idx, uint32_t delta,
|
||||
bool to_kernel);
|
||||
struct wlan_roam_debug_rec rec[WLAN_ROAM_DEBUG_MAX_REC];
|
||||
};
|
||||
|
||||
#define DEBUG_INVALID_PEER_ID 0xffff
|
||||
#define DEBUG_INVALID_VDEV_ID 0xff
|
||||
|
||||
#ifdef FEATURE_ROAM_DEBUG
|
||||
/**
|
||||
* wlan_roam_debug_log() - Add a debug log entry to wlan roam debug records
|
||||
* @vdev_id: vdev identifier
|
||||
* @op: operation identifier
|
||||
* @peer_id: peer id
|
||||
* @mac_addr: mac address of peer, can be NULL
|
||||
* @peer_obj: peer object address, can be NULL
|
||||
* @arg1: extra argument #1
|
||||
* @arg2: extra argument #2
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void wlan_roam_debug_log(uint8_t vdev_id, uint8_t op,
|
||||
uint16_t peer_id, void *mac_addr,
|
||||
void *peer_obj, uint32_t arg1, uint32_t arg2);
|
||||
/**
|
||||
* wlan_rec_debug_log() - Add a debug log entry to wlan debug records
|
||||
* @rec_type: record type
|
||||
* @vdev_id: vdev identifier
|
||||
* @op: operation identifier
|
||||
* @peer_id: peer id
|
||||
* @mac_addr: mac address of peer, can be NULL
|
||||
* @peer_obj: peer object address, can be NULL
|
||||
* @arg1: extra argument #1
|
||||
* @arg2: extra argument #2
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void wlan_rec_debug_log(wlan_rec_type rec_type, uint8_t vdev_id, uint8_t op,
|
||||
uint16_t peer_id, const void *mac_addr,
|
||||
void *peer_obj, uint32_t arg1, uint32_t arg2);
|
||||
|
||||
/**
|
||||
* wlan_roam_debug_dump_table() - Print the roam debug log records
|
||||
* print all the valid debug records in the order of timestamp
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void wlan_roam_debug_dump_table(void);
|
||||
|
||||
/**
|
||||
* wlan_rec_debug_dump_table() - Print the wlan roam debug log records
|
||||
* @rec_type: recorad type
|
||||
* @count: count of records to print
|
||||
* @to_kernel: print to kernel or not
|
||||
*
|
||||
* print all the valid debug records in the order of timestamp
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void wlan_rec_debug_dump_table(wlan_rec_type rec_type, uint32_t count,
|
||||
bool to_kernel);
|
||||
|
||||
#ifdef WLAN_LOGGING_BUFFERS_DYNAMICALLY
|
||||
/**
|
||||
* wlan_roam_debug_init() - Allocate log buffer dynamically
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void wlan_roam_debug_init(void);
|
||||
/**
|
||||
* wlan_roam_debug_deinit() - Free log buffer allocated dynamically
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void wlan_roam_debug_deinit(void);
|
||||
#else /* WLAN_LOGGING_BUFFERS_DYNAMICALLY */
|
||||
static inline void wlan_roam_debug_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wlan_roam_debug_deinit(void)
|
||||
{
|
||||
}
|
||||
#endif /* WLAN_LOGGING_BUFFERS_DYNAMICALLY */
|
||||
|
||||
#else /* FEATURE_ROAM_DEBUG */
|
||||
static inline void
|
||||
wlan_roam_debug_log(uint8_t vdev_id, uint8_t op,
|
||||
uint16_t peer_id, void *mac_addr,
|
||||
void *peer_obj, uint32_t arg1, uint32_t arg2)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wlan_rec_debug_log(
|
||||
wlan_rec_type rec_type, uint8_t vdev_id, uint8_t op,
|
||||
uint16_t peer_id, const void *mac_addr,
|
||||
void *peer_obj, uint32_t arg1, uint32_t arg2)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wlan_roam_debug_dump_table(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wlan_rec_debug_dump_table(wlan_rec_type rec_type,
|
||||
uint32_t count,
|
||||
bool to_kernel)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wlan_roam_debug_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void wlan_roam_debug_deinit(void)
|
||||
{
|
||||
}
|
||||
#endif /* FEATURE_ROAM_DEBUG */
|
||||
|
||||
#endif /* _WLAN_ROAM_DEBUG_H_ */
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, 2020-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. 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: Roaming debug log operations routines and global data
|
||||
*/
|
||||
|
||||
#include <qdf_types.h>
|
||||
#include <qdf_atomic.h>
|
||||
#include <qdf_mem.h>
|
||||
#include <qdf_time.h>
|
||||
#include <qdf_trace.h>
|
||||
#include <qdf_module.h>
|
||||
#include <wlan_cmn.h>
|
||||
#include "wlan_roam_debug.h"
|
||||
|
||||
#ifdef FEATURE_ROAM_DEBUG
|
||||
static void wlan_roam_rec_print(struct wlan_roam_debug_rec *dbg_rec,
|
||||
uint32_t idx, uint32_t delta,
|
||||
bool to_kernel);
|
||||
|
||||
static void wlan_conn_rec_print(struct wlan_roam_debug_rec *dbg_rec,
|
||||
uint32_t idx, uint32_t delta,
|
||||
bool to_kernel);
|
||||
|
||||
#ifdef WLAN_LOGGING_BUFFERS_DYNAMICALLY
|
||||
static struct wlan_roam_debug_info *global_wlan_roam_debug_table;
|
||||
|
||||
/**
|
||||
* wlan_roam_debug_init() - Allocate log buffer dynamically
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void wlan_roam_debug_init(void)
|
||||
{
|
||||
uint8_t i;
|
||||
global_wlan_roam_debug_table = qdf_mem_valloc(
|
||||
sizeof(struct wlan_roam_debug_info) * REC_MAX);
|
||||
|
||||
QDF_BUG(global_wlan_roam_debug_table);
|
||||
|
||||
if (global_wlan_roam_debug_table) {
|
||||
for (i = 0; i < REC_MAX; i++) {
|
||||
qdf_atomic_init(&global_wlan_roam_debug_table[i].index);
|
||||
global_wlan_roam_debug_table[i].num_max_rec =
|
||||
WLAN_ROAM_DEBUG_MAX_REC;
|
||||
if (i == REC_ROAM)
|
||||
global_wlan_roam_debug_table[i].rec_print =
|
||||
wlan_roam_rec_print;
|
||||
else
|
||||
global_wlan_roam_debug_table[i].rec_print =
|
||||
wlan_conn_rec_print;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qdf_export_symbol(wlan_roam_debug_init);
|
||||
|
||||
static inline struct wlan_roam_debug_info *wlan_roam_debug_get_table(
|
||||
wlan_rec_type type)
|
||||
{
|
||||
if (type >= REC_MAX)
|
||||
return NULL;
|
||||
return &global_wlan_roam_debug_table[type];
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_roam_debug_deinit() - Free log buffer allocated dynamically
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void wlan_roam_debug_deinit(void)
|
||||
{
|
||||
qdf_mem_vfree(global_wlan_roam_debug_table);
|
||||
global_wlan_roam_debug_table = NULL;
|
||||
}
|
||||
|
||||
qdf_export_symbol(wlan_roam_debug_deinit);
|
||||
#else /* WLAN_LOGGING_BUFFERS_DYNAMICALLY */
|
||||
/*
|
||||
* wlan roam debug log is stored in this global structure. It can be accessed
|
||||
* without requiring any psoc or vdev context. It will be accessible in
|
||||
* the crash dump without having to dereference complex stack traces.
|
||||
*/
|
||||
static struct wlan_roam_debug_info global_wlan_roam_debug_table[REC_MAX] = {
|
||||
[REC_ROAM] = {{ 0 },
|
||||
.num_max_rec = WLAN_ROAM_DEBUG_MAX_REC,
|
||||
.rec_print = wlan_roam_rec_print},
|
||||
[REC_CONN] = {{ 0 },
|
||||
.num_max_rec = WLAN_ROAM_DEBUG_MAX_REC,
|
||||
.rec_print = wlan_conn_rec_print},
|
||||
};
|
||||
|
||||
static inline struct wlan_roam_debug_info *wlan_roam_debug_get_table(
|
||||
wlan_rec_type type)
|
||||
{
|
||||
if (type >= REC_MAX)
|
||||
return NULL;
|
||||
return &global_wlan_roam_debug_table[type];
|
||||
}
|
||||
#endif /* WLAN_LOGGING_BUFFERS_DYNAMICALLY */
|
||||
|
||||
/**
|
||||
* wlan_roam_next_debug_log_index() - atomically increment and wrap around index
|
||||
* @index: address of index to increment
|
||||
* @size: wrap around this value
|
||||
*
|
||||
* Return: new value of index
|
||||
*/
|
||||
static int wlan_roam_next_debug_log_index(qdf_atomic_t *index, int size)
|
||||
{
|
||||
int i = qdf_atomic_inc_return(index);
|
||||
|
||||
if (i == WLAN_ROAM_DEBUG_MAX_REC)
|
||||
qdf_atomic_sub(WLAN_ROAM_DEBUG_MAX_REC, index);
|
||||
while (i >= size)
|
||||
i -= WLAN_ROAM_DEBUG_MAX_REC;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_roam_debug_log() - Add a debug log entry to wlan roam debug records
|
||||
* @vdev_id: vdev identifier
|
||||
* @op: operation identifier
|
||||
* @peer_id: peer id
|
||||
* @mac_addr: mac address of peer, can be NULL
|
||||
* @peer_obj: peer object address, can be NULL
|
||||
* @arg1: extra argument #1
|
||||
* @arg2: extra argument #2
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void wlan_roam_debug_log(uint8_t vdev_id, uint8_t op,
|
||||
uint16_t peer_id, void *mac_addr,
|
||||
void *peer_obj, uint32_t arg1, uint32_t arg2)
|
||||
{
|
||||
wlan_rec_debug_log(REC_ROAM, vdev_id, op, peer_id, mac_addr,
|
||||
peer_obj, arg1, arg2);
|
||||
}
|
||||
|
||||
qdf_export_symbol(wlan_roam_debug_log);
|
||||
|
||||
void wlan_rec_debug_log(wlan_rec_type rec_type, uint8_t vdev_id, uint8_t op,
|
||||
uint16_t peer_id, const void *mac_addr,
|
||||
void *peer_obj, uint32_t arg1, uint32_t arg2)
|
||||
{
|
||||
uint32_t i;
|
||||
struct wlan_roam_debug_info *dbg_tbl;
|
||||
struct wlan_roam_debug_rec *rec;
|
||||
|
||||
dbg_tbl = wlan_roam_debug_get_table(rec_type);
|
||||
if (!dbg_tbl)
|
||||
return;
|
||||
|
||||
i = wlan_roam_next_debug_log_index(
|
||||
&dbg_tbl->index,
|
||||
WLAN_ROAM_DEBUG_MAX_REC);
|
||||
rec = &dbg_tbl->rec[i];
|
||||
rec->time = qdf_get_log_timestamp();
|
||||
rec->operation = op;
|
||||
rec->vdev_id = vdev_id;
|
||||
rec->peer_id = peer_id;
|
||||
if (mac_addr)
|
||||
qdf_mem_copy(rec->mac_addr.bytes, mac_addr,
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
else
|
||||
qdf_mem_zero(rec->mac_addr.bytes,
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
rec->peer_obj = peer_obj;
|
||||
rec->arg1 = arg1;
|
||||
rec->arg2 = arg2;
|
||||
}
|
||||
|
||||
qdf_export_symbol(wlan_rec_debug_log);
|
||||
|
||||
/**
|
||||
* wlan_roam_debug_string() - convert operation value to printable string
|
||||
* @op: operation identifier
|
||||
*
|
||||
* Return: printable string for the operation
|
||||
*/
|
||||
static char *wlan_roam_debug_string(uint32_t op)
|
||||
{
|
||||
switch (op) {
|
||||
case DEBUG_PEER_CREATE_SEND:
|
||||
return "peer create send";
|
||||
case DEBUG_PEER_CREATE_RESP:
|
||||
return "peer create resp_event";
|
||||
case DEBUG_PEER_DELETE_SEND:
|
||||
return "peer delete send";
|
||||
case DEBUG_PEER_DELETE_RESP:
|
||||
return "peer delete resp_event";
|
||||
case DEBUG_PEER_MAP_EVENT:
|
||||
return "peer map event";
|
||||
case DEBUG_PEER_UNMAP_EVENT:
|
||||
return "peer unmap event";
|
||||
case DEBUG_PEER_UNREF_DELETE:
|
||||
return "peer unref delete";
|
||||
case DEBUG_DELETING_PEER_OBJ:
|
||||
return "peer obj deleted";
|
||||
case DEBUG_ROAM_SYNCH_IND:
|
||||
return "roam synch ind event";
|
||||
case DEBUG_ROAM_SYNCH_CNF:
|
||||
return "roam sync conf sent";
|
||||
case DEBUG_ROAM_SYNCH_FAIL:
|
||||
return "roam sync fail event";
|
||||
case DEBUG_ROAM_EVENT:
|
||||
return "roam event";
|
||||
case DEBUG_WOW_ROAM_EVENT:
|
||||
return "wow wakeup roam event";
|
||||
case DEBUG_BUS_SUSPEND:
|
||||
return "host suspend";
|
||||
case DEBUG_BUS_RESUME:
|
||||
return "host wakeup";
|
||||
case DEBUG_WOW_REASON:
|
||||
return "wow wakeup reason";
|
||||
case DEBUG_CONN_CONNECTING:
|
||||
return "conn";
|
||||
case DEBUG_CONN_ASSOCIATION:
|
||||
return "assoc";
|
||||
case DEBUG_CONN_CONNECT_RESULT:
|
||||
return "cnrlt";
|
||||
case DEBUG_CONN_ROAMING:
|
||||
return "roaming";
|
||||
case DEBUG_CONN_ROAMED:
|
||||
return "roamed";
|
||||
case DEBUG_CONN_ROAMED_IND:
|
||||
return "rmind";
|
||||
case DEBUG_CONN_DISCONNECT:
|
||||
return "disc";
|
||||
case DEBUG_CONN_DISCONNECT_HANDLER:
|
||||
return "dishdr";
|
||||
case DEBUG_CONN_DISCONNECT_IND:
|
||||
return "disind";
|
||||
case DEBUG_CONN_RSO:
|
||||
return "rso";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void wlan_roam_rec_print(struct wlan_roam_debug_rec *dbg_rec,
|
||||
uint32_t idx, uint32_t delta,
|
||||
bool to_kernel)
|
||||
{
|
||||
roam_debug("index = %5d timestamp = 0x%016llx delta ms = %-12u",
|
||||
idx, dbg_rec->time, delta);
|
||||
roam_debug("info = %-24s vdev_id = %-3d mac addr = "QDF_MAC_ADDR_FMT,
|
||||
wlan_roam_debug_string(dbg_rec->operation),
|
||||
(int8_t)dbg_rec->vdev_id,
|
||||
QDF_MAC_ADDR_REF(dbg_rec->mac_addr.bytes));
|
||||
roam_debug("peer obj = 0x%pK peer_id = %-4d", dbg_rec->peer_obj,
|
||||
(int8_t)dbg_rec->peer_id);
|
||||
roam_debug("arg1 = 0x%-8x arg2 = 0x%-8x", dbg_rec->arg1,
|
||||
dbg_rec->arg2);
|
||||
}
|
||||
|
||||
void wlan_conn_rec_print(struct wlan_roam_debug_rec *dbg_rec,
|
||||
uint32_t idx, uint32_t delta,
|
||||
bool to_kernel)
|
||||
{
|
||||
if (to_kernel) {
|
||||
roam_info("i %d ti 0x%08llx ms %u vdv %d %s a1 0x%x a2 0x%x "QDF_MAC_ADDR_FMT,
|
||||
idx, dbg_rec->time, delta, (int8_t)dbg_rec->vdev_id,
|
||||
wlan_roam_debug_string(dbg_rec->operation),
|
||||
dbg_rec->arg1, dbg_rec->arg2,
|
||||
QDF_MAC_ADDR_REF(dbg_rec->mac_addr.bytes));
|
||||
} else {
|
||||
roam_debug("i %d ti 0x%08llx ms %u vdv %d %s a1 0x%x a2 0x%x "QDF_MAC_ADDR_FMT,
|
||||
idx, dbg_rec->time, delta, (int8_t)dbg_rec->vdev_id,
|
||||
wlan_roam_debug_string(dbg_rec->operation),
|
||||
dbg_rec->arg1, dbg_rec->arg2,
|
||||
QDF_MAC_ADDR_REF(dbg_rec->mac_addr.bytes));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_rec_debug_dump_table() - Print the wlan roam debug log records
|
||||
* print all the valid debug records in the order of timestamp
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void wlan_rec_debug_dump_table(wlan_rec_type rec_type, uint32_t count,
|
||||
bool to_kernel)
|
||||
{
|
||||
uint32_t i;
|
||||
int32_t current_index;
|
||||
struct wlan_roam_debug_info *dbg_tbl;
|
||||
struct wlan_roam_debug_rec *dbg_rec;
|
||||
uint64_t startt = 0;
|
||||
uint32_t delta;
|
||||
|
||||
#define DEBUG_CLOCK_TICKS_PER_MSEC 19200
|
||||
if (count > WLAN_ROAM_DEBUG_MAX_REC)
|
||||
count = WLAN_ROAM_DEBUG_MAX_REC;
|
||||
dbg_tbl = wlan_roam_debug_get_table(rec_type);
|
||||
if (!dbg_tbl)
|
||||
return;
|
||||
|
||||
current_index = qdf_atomic_read(&dbg_tbl->index);
|
||||
if (current_index < 0) {
|
||||
roam_debug("No records to dump");
|
||||
return;
|
||||
}
|
||||
roam_debug("dump %d rec type %d idx %d", count, rec_type,
|
||||
current_index);
|
||||
|
||||
i = (current_index + WLAN_ROAM_DEBUG_MAX_REC - count) %
|
||||
WLAN_ROAM_DEBUG_MAX_REC;
|
||||
do {
|
||||
/* wrap around */
|
||||
i = (i + 1) % WLAN_ROAM_DEBUG_MAX_REC;
|
||||
dbg_rec = &dbg_tbl->rec[i];
|
||||
/* skip unused entry */
|
||||
if (dbg_rec->time == 0)
|
||||
continue;
|
||||
if (count == 0)
|
||||
break;
|
||||
count--;
|
||||
|
||||
if (startt == 0)
|
||||
startt = dbg_rec->time;
|
||||
/*
|
||||
* Divide by 19200 == right shift 8 bits, then divide by 75
|
||||
* 32 bit computation keeps both 32 and 64 bit compilers happy.
|
||||
* The value will roll over after approx. 33554 seconds.
|
||||
*/
|
||||
delta = (uint32_t) (((dbg_rec->time - startt) >> 8) &
|
||||
0xffffffff);
|
||||
delta = delta / (DEBUG_CLOCK_TICKS_PER_MSEC >> 8);
|
||||
|
||||
if (dbg_tbl->rec_print)
|
||||
dbg_tbl->rec_print(dbg_rec, i, delta, to_kernel);
|
||||
} while (i != current_index);
|
||||
}
|
||||
|
||||
qdf_export_symbol(wlan_rec_debug_dump_table);
|
||||
|
||||
/**
|
||||
* wlan_roam_debug_dump_table() - Print the wlan roam debug log records
|
||||
* print all the valid debug records in the order of timestamp
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void wlan_roam_debug_dump_table(void)
|
||||
{
|
||||
wlan_rec_debug_dump_table(REC_ROAM, WLAN_ROAM_DEBUG_MAX_REC, false);
|
||||
}
|
||||
qdf_export_symbol(wlan_roam_debug_dump_table);
|
||||
|
||||
#endif /* FEATURE_ROAM_DEBUG */
|
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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.
|
||||
*/
|
||||
|
||||
/*===========================================================================
|
||||
\file wlan_nlink_common.h
|
||||
|
||||
Exports and types for the Netlink Service interface. This header file contains
|
||||
message types and definitions that is shared between the user space service
|
||||
(e.g. logging service) and WLAN kernel module.
|
||||
|
||||
===========================================================================*/
|
||||
|
||||
#ifndef WLAN_NLINK_COMMON_H__
|
||||
#define WLAN_NLINK_COMMON_H__
|
||||
|
||||
#include <linux/netlink.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/if.h>
|
||||
#else
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* External Functions
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Preprocessor Definitions and Constants
|
||||
*-------------------------------------------------------------------------*/
|
||||
#define WLAN_NL_MAX_PAYLOAD 5120 /* maximum size for netlink message */
|
||||
#define WLAN_NLINK_PROTO_FAMILY NETLINK_USERSOCK
|
||||
#define WLAN_NLINK_MCAST_GRP_ID 0x01
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Type Declarations
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The following enum defines the target service within WLAN driver for which the
|
||||
* message is intended for. Each service along with its counterpart
|
||||
* in the user space, define a set of messages they recognize.
|
||||
* Each of this message will have an header of type tAniMsgHdr defined below.
|
||||
* Each Netlink message to/from a kernel module will contain only one
|
||||
* message which is preceded by a tAniMsgHdr. The maximum size (in bytes) of
|
||||
* a netlink message is assumed to be MAX_PAYLOAD bytes.
|
||||
*
|
||||
* +------------+-------+----------+----------+
|
||||
* |Netlink hdr | Align |tAniMsgHdr| msg body |
|
||||
* +------------+-------+----------|----------+
|
||||
*/
|
||||
|
||||
/* Message Types */
|
||||
#define WLAN_SVC_FW_CRASHED_IND 0x100
|
||||
#define WLAN_SVC_LTE_COEX_IND 0x101
|
||||
#define WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND 0x102
|
||||
#define WLAN_SVC_DFS_CAC_START_IND 0x103
|
||||
#define WLAN_SVC_DFS_CAC_END_IND 0x104
|
||||
#define WLAN_SVC_DFS_RADAR_DETECT_IND 0x105
|
||||
#define WLAN_SVC_WLAN_STATUS_IND 0x106
|
||||
#define WLAN_SVC_WLAN_VERSION_IND 0x107
|
||||
#define WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND 0x108
|
||||
#define WLAN_SVC_WLAN_TP_IND 0x109
|
||||
#define WLAN_SVC_RPS_ENABLE_IND 0x10A
|
||||
#define WLAN_SVC_WLAN_TP_TX_IND 0x10B
|
||||
#define WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND 0x10C
|
||||
#define WLAN_SVC_WLAN_RADIO_INDEX 0x10D
|
||||
#define WLAN_SVC_FW_SHUTDOWN_IND 0x10E
|
||||
#define WLAN_SVC_CORE_MINFREQ 0x10F
|
||||
#define WLAN_SVC_MAX_SSID_LEN 32
|
||||
#define WLAN_SVC_MAX_BSSID_LEN 6
|
||||
#define WLAN_SVC_MAX_STR_LEN 16
|
||||
#define WLAN_SVC_MAX_NUM_CHAN 128
|
||||
#define WLAN_SVC_COUNTRY_CODE_LEN 3
|
||||
|
||||
#define ANI_NL_MSG_BASE 0x10 /* Some arbitrary base */
|
||||
|
||||
typedef enum eAniNlModuleTypes {
|
||||
ANI_NL_MSG_PUMAC = ANI_NL_MSG_BASE + 0x01, /* PTT Socket App */
|
||||
ANI_NL_MSG_PTT = ANI_NL_MSG_BASE + 0x07, /* Quarky GUI */
|
||||
WLAN_NL_MSG_OEM = ANI_NL_MSG_BASE + 0x09,
|
||||
WLAN_NL_MSG_SVC = ANI_NL_MSG_BASE + 0x0a,
|
||||
WLAN_NL_MSG_CNSS_DIAG = ANI_NL_MSG_BASE + 0x0B, /* Value needs to be 27 */
|
||||
ANI_NL_MSG_LOG,
|
||||
WLAN_NL_MSG_SPECTRAL_SCAN,
|
||||
ANI_NL_MSG_MAX
|
||||
} tAniNlModTypes, tWlanNlModTypes;
|
||||
|
||||
#define WLAN_NL_MSG_BASE ANI_NL_MSG_BASE
|
||||
#define WLAN_NL_MSG_MAX ANI_NL_MSG_MAX
|
||||
|
||||
/* All Netlink messages must contain this header */
|
||||
typedef struct sAniHdr {
|
||||
unsigned short type;
|
||||
unsigned short length;
|
||||
} tAniHdr, tAniMsgHdr;
|
||||
|
||||
typedef struct sAniNlMsg {
|
||||
struct nlmsghdr nlh; /* Netlink Header */
|
||||
int radio; /* unit number of the radio */
|
||||
tAniHdr wmsg; /* Airgo Message Header */
|
||||
} tAniNlHdr;
|
||||
|
||||
struct radio_index_tlv {
|
||||
unsigned short type;
|
||||
unsigned short length;
|
||||
int radio;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct svc_channel_info - Channel information
|
||||
* @chan_id: Channel ID
|
||||
* @reserved0: Reserved for padding and future use
|
||||
* @mhz: Primary 20 MHz channel frequency in MHz
|
||||
* @band_center_freq1: Center frequency 1 in MHz
|
||||
* @band_center_freq2: Center frequency 2 in MHz
|
||||
* @info: Channel info
|
||||
* @reg_info_1: Regulatory information field 1 which contains
|
||||
* MIN power, MAX power, reg power and reg class ID
|
||||
* @reg_info_2: Regulatory information field 2 which contains antennamax
|
||||
*/
|
||||
struct svc_channel_info {
|
||||
uint32_t chan_id;
|
||||
uint32_t reserved0;
|
||||
uint32_t mhz;
|
||||
uint32_t band_center_freq1;
|
||||
uint32_t band_center_freq2;
|
||||
uint32_t info;
|
||||
uint32_t reg_info_1;
|
||||
uint32_t reg_info_2;
|
||||
};
|
||||
|
||||
struct wlan_status_data {
|
||||
uint8_t lpss_support;
|
||||
uint8_t is_on;
|
||||
uint8_t vdev_id;
|
||||
uint8_t is_connected;
|
||||
int8_t rssi;
|
||||
uint8_t ssid_len;
|
||||
uint8_t country_code[WLAN_SVC_COUNTRY_CODE_LEN];
|
||||
uint32_t vdev_mode;
|
||||
uint32_t freq;
|
||||
uint32_t numChannels;
|
||||
uint8_t channel_list[WLAN_SVC_MAX_NUM_CHAN];
|
||||
uint8_t ssid[WLAN_SVC_MAX_SSID_LEN];
|
||||
uint8_t bssid[WLAN_SVC_MAX_BSSID_LEN];
|
||||
struct svc_channel_info channel_info[WLAN_SVC_MAX_NUM_CHAN];
|
||||
};
|
||||
|
||||
struct wlan_version_data {
|
||||
uint32_t chip_id;
|
||||
char chip_name[WLAN_SVC_MAX_STR_LEN];
|
||||
char chip_from[WLAN_SVC_MAX_STR_LEN];
|
||||
char host_version[WLAN_SVC_MAX_STR_LEN];
|
||||
char fw_version[WLAN_SVC_MAX_STR_LEN];
|
||||
};
|
||||
|
||||
struct wlan_dfs_info {
|
||||
uint16_t channel;
|
||||
uint8_t country_code[WLAN_SVC_COUNTRY_CODE_LEN];
|
||||
};
|
||||
|
||||
/*
|
||||
* Maximum number of queues supported by WLAN driver. Setting an upper
|
||||
* limit. Actual number of queues may be smaller than this value.
|
||||
*/
|
||||
#define WLAN_SVC_IFACE_NUM_QUEUES 6
|
||||
|
||||
/**
|
||||
* struct wlan_rps_data - structure to send RPS info to cnss-daemon
|
||||
* @ifname: interface name for which the RPS data belongs to
|
||||
* @num_queues: number of rx queues for which RPS data is being sent
|
||||
* @cpu_map_list: array of cpu maps for different rx queues supported by
|
||||
* the wlan driver
|
||||
*
|
||||
* The structure specifies the format of data exchanged between wlan
|
||||
* driver and cnss-daemon. On receipt of the data, cnss-daemon is expected
|
||||
* to apply the 'cpu_map' for each rx queue belonging to the interface 'ifname'
|
||||
*/
|
||||
struct wlan_rps_data {
|
||||
char ifname[IFNAMSIZ];
|
||||
uint16_t num_queues;
|
||||
uint16_t cpu_map_list[WLAN_SVC_IFACE_NUM_QUEUES];
|
||||
};
|
||||
|
||||
/**
|
||||
* enum wlan_tp_level - indicates wlan throughput level
|
||||
* @WLAN_SVC_TP_NONE: used for initialization
|
||||
* @WLAN_SVC_TP_LOW: used to identify low throughput level
|
||||
* @WLAN_SVC_TP_MEDIUM: used to identify medium throughput level
|
||||
* @WLAN_SVC_TP_HIGH: used to identify high throughput level
|
||||
*
|
||||
* The different throughput levels are determined on the basis of # of tx and
|
||||
* rx packets and other threshold values. For example, if the # of total
|
||||
* packets sent or received by the driver is greater than 500 in the last 100ms
|
||||
* , the driver has a high throughput requirement. The driver may tweak certain
|
||||
* system parameters based on the throughput level.
|
||||
*/
|
||||
enum wlan_tp_level {
|
||||
WLAN_SVC_TP_NONE,
|
||||
WLAN_SVC_TP_LOW,
|
||||
WLAN_SVC_TP_MEDIUM,
|
||||
WLAN_SVC_TP_HIGH,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wlan_core_minfreq - msg to [re]set the min freq of a set of cores
|
||||
* @magic: signature token: 0xBABA
|
||||
* @reserved: unused for now
|
||||
* @coremask: bitmap of cores (16 bits) bit0=CORE0, bit1=CORE1, ...
|
||||
* coremask is ONLY valid for set command
|
||||
* valid values: 0xf0, or 0x0f
|
||||
* @freq: frequency in KH
|
||||
* > 0: "set to the given frequency"
|
||||
* == 0: "free; remove the lock"
|
||||
*
|
||||
* Msg structure passed by the driver to cnss-daemon.
|
||||
*
|
||||
* Semantical Alert:
|
||||
* There can be only one outstanding lock, even for different masks.
|
||||
*/
|
||||
#define WLAN_CORE_MINFREQ_MAGIC 0xBABA
|
||||
struct wlan_core_minfreq {
|
||||
uint16_t magic;
|
||||
uint16_t reserved;
|
||||
uint16_t coremask;
|
||||
uint16_t freq;
|
||||
};
|
||||
|
||||
/* Indication to enable TCP delayed ack in TPUT indication */
|
||||
#define TCP_DEL_ACK_IND (1 << 0)
|
||||
#define TCP_DEL_ACK_IND_MASK 0x1
|
||||
/* Indication to enable TCP advance window scaling in TPUT indication */
|
||||
#define TCP_ADV_WIN_SCL (1 << 1)
|
||||
#define TCP_ADV_WIN_SCL_MASK 0x2
|
||||
|
||||
/* TCP limit output bytes for low and high TPUT */
|
||||
#define TCP_LIMIT_OUTPUT_BYTES_LOW 506072
|
||||
#define TCP_LIMIT_OUTPUT_BYTES_HI 4048579
|
||||
|
||||
/* TCP window scale for low and high TPUT */
|
||||
#define WIN_SCALE_LOW 2
|
||||
#define WIN_SCALE_HI 1
|
||||
|
||||
/* TCP DEL ACK value for low and high TPUT */
|
||||
#define TCP_DEL_ACK_LOW 0
|
||||
#define TCP_DEL_ACK_HI 20
|
||||
|
||||
/**
|
||||
* struct wlan_rx_tp_data - msg to TCP delayed ack and advance window scaling
|
||||
* @level: Throughput level.
|
||||
* @rx_tp_flags: Bit map of flags, for which this indcation will take
|
||||
* effect, bit map for TCP_ADV_WIN_SCL and TCP_DEL_ACK_IND.
|
||||
*/
|
||||
struct wlan_rx_tp_data {
|
||||
enum wlan_tp_level level;
|
||||
uint16_t rx_tp_flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wlan_tx_tp_data - msg to TCP for Tx Dir
|
||||
* @level: Throughput level.
|
||||
* @tcp_limit_output: Tcp limit output flag.
|
||||
*
|
||||
*/
|
||||
struct wlan_tx_tp_data {
|
||||
enum wlan_tp_level level;
|
||||
bool tcp_limit_output;
|
||||
};
|
||||
|
||||
#endif /* WLAN_NLINK_COMMON_H__ */
|
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2017, 2019-2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* wlan_nlink_srv.h
|
||||
*
|
||||
* wlan_nlink_srv is used to RX/TX Netlink messages from user space to kernel
|
||||
* modules and vice versa. Kernel modules must register a message handler for a
|
||||
* message type so that the wlan_nlink_srv can invoke the corresponding msg handler
|
||||
* whenever a Netlink message of a particular type has been received from an
|
||||
* application. In the opposite direction, wlan_nlink_srv provides a mechanism
|
||||
* which kernel modules can use to send Netlink messages to applications.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef WLAN_NLINK_SRV_H
|
||||
#define WLAN_NLINK_SRV_H
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/netlink.h>
|
||||
#include <wlan_nlink_common.h>
|
||||
|
||||
#define INVALID_PID -1
|
||||
#define NLINK_MAX_CALLBACKS (WLAN_NL_MSG_MAX - WLAN_NL_MSG_BASE)
|
||||
|
||||
typedef int (*nl_srv_msg_callback)(struct sk_buff *skb);
|
||||
|
||||
/**
|
||||
* cld80211_oem_send_reply() - API to send cld80211 msg
|
||||
* @skb: Sk buffer
|
||||
* @hdr: nl80211hdr pointer
|
||||
* @nest: pointer of vendor nested attribute
|
||||
* @flags: Flags
|
||||
*
|
||||
* API to send cld80211 msg to applications
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void cld80211_oem_send_reply(struct sk_buff *msg, void *hdr,
|
||||
struct nlattr *nest, int flags);
|
||||
|
||||
/**
|
||||
* nl80211hdr_put() - API to allocate skb for cld80211 msg
|
||||
* @hdr: nl80211hdr pointer
|
||||
* @portid: Port ID
|
||||
* @nest: pointer of vendor nested attribute
|
||||
* @flags: Flags
|
||||
*
|
||||
* API to allocate skb for cld80211 msg
|
||||
*
|
||||
* Return: Pointer to skbuff
|
||||
*/
|
||||
|
||||
struct sk_buff *
|
||||
cld80211_oem_rsp_alloc_skb(uint32_t portid, void **hdr, struct nlattr **nest,
|
||||
int *flags);
|
||||
int nl_srv_init(void *wiphy, int proto);
|
||||
void nl_srv_exit(void);
|
||||
int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler);
|
||||
int nl_srv_unregister(tWlanNlModTypes msg_type,
|
||||
nl_srv_msg_callback msg_handler);
|
||||
|
||||
#ifdef CNSS_GENL
|
||||
int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag,
|
||||
int app_id, int mcgroup_id);
|
||||
int nl_srv_bcast(struct sk_buff *skb, int mcgroup_id, int app_id);
|
||||
|
||||
/**
|
||||
* nl80211hdr_put() - API to fill genlmsg header
|
||||
* @skb: Sk buffer
|
||||
* @portid: Port ID
|
||||
* @seq: Sequence number
|
||||
* @flags: Flags
|
||||
* @cmd: Command id
|
||||
*
|
||||
* API to fill genl message header for broadcast events to user space
|
||||
*
|
||||
* Return: Pointer to user specific header/payload
|
||||
*/
|
||||
void *nl80211hdr_put(struct sk_buff *skb, uint32_t portid,
|
||||
uint32_t seq, int flags, uint8_t cmd);
|
||||
#else
|
||||
int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag);
|
||||
int nl_srv_bcast(struct sk_buff *skb);
|
||||
#endif
|
||||
|
||||
int nl_srv_is_initialized(void);
|
||||
void nl_srv_ucast_oem(struct sk_buff *skb, int dst_pid, int flag);
|
||||
|
||||
#endif
|
@@ -0,0 +1,846 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* wlan_nlink_srv.c
|
||||
*
|
||||
* This file contains the definitions specific to the wlan_nlink_srv
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/sock.h>
|
||||
#include <wlan_nlink_srv.h>
|
||||
#include <qdf_trace.h>
|
||||
#include <qdf_module.h>
|
||||
|
||||
#define WLAN_CLD80211_MAX_SIZE (SKB_WITH_OVERHEAD(8192UL) - NLMSG_HDRLEN)
|
||||
|
||||
#if defined(CONFIG_CNSS_LOGGER)
|
||||
|
||||
#include <net/cnss_logger.h>
|
||||
|
||||
static int radio_idx = -EINVAL;
|
||||
static void *wiphy_ptr;
|
||||
static bool logger_initialized;
|
||||
|
||||
/**
|
||||
* nl_srv_init() - wrapper function to register to cnss_logger
|
||||
* @wiphy: the pointer to the wiphy structure
|
||||
* @proto: the host log netlink protocol
|
||||
*
|
||||
* The netlink socket is no longer initialized in the driver itself, instead
|
||||
* will be initialized in the cnss_logger module, the driver should register
|
||||
* itself to cnss_logger module to get the radio_index for all the netlink
|
||||
* operation. (cfg80211 vendor command is using different netlink socket).
|
||||
*
|
||||
* The cnss_logger_device_register() use to register the driver with the
|
||||
* wiphy structure and the module name (debug purpose) and then return the
|
||||
* radio_index depending on the availability.
|
||||
*
|
||||
* Return: radio index for success and -EINVAL for failure
|
||||
*/
|
||||
int nl_srv_init(void *wiphy, int proto)
|
||||
{
|
||||
if (logger_initialized)
|
||||
goto initialized;
|
||||
|
||||
wiphy_ptr = wiphy;
|
||||
radio_idx = cnss_logger_device_register(wiphy, THIS_MODULE->name);
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: radio_index: %d, wiphy_ptr: %pK",
|
||||
__func__, radio_idx, wiphy_ptr);
|
||||
|
||||
if (radio_idx >= 0)
|
||||
logger_initialized = true;
|
||||
|
||||
initialized:
|
||||
return radio_idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_exit() - wrapper function to unregister from cnss_logger
|
||||
*
|
||||
* The cnss_logger_device_unregister() use to unregister the driver with
|
||||
* the radio_index assigned and wiphy structure from cnss_logger.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void nl_srv_exit(void)
|
||||
{
|
||||
if (logger_initialized) {
|
||||
cnss_logger_device_unregister(radio_idx, wiphy_ptr);
|
||||
radio_idx = -EINVAL;
|
||||
wiphy_ptr = NULL;
|
||||
logger_initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_ucast() - wrapper function to do unicast tx through cnss_logger
|
||||
* @skb: the socket buffer to send
|
||||
* @dst_pid: the port id
|
||||
* @flag: the blocking or nonblocking flag
|
||||
*
|
||||
* The nl_srv_is_initialized() is used to do sanity check if the netlink
|
||||
* service is ready, e.g if the radio_index is assigned properly, if not
|
||||
* the driver should take the responsibility to free the skb.
|
||||
*
|
||||
* The cnss_logger_nl_ucast() use the same parameters to send the socket
|
||||
* buffers.
|
||||
*
|
||||
* Return: the error of the transmission status
|
||||
*/
|
||||
int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
|
||||
/* sender's pid */
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
|
||||
NETLINK_CB(skb).pid = 0;
|
||||
#else
|
||||
NETLINK_CB(skb).portid = 0;
|
||||
#endif
|
||||
/* not multicast */
|
||||
NETLINK_CB(skb).dst_group = 0;
|
||||
|
||||
if (nl_srv_is_initialized() == 0) {
|
||||
err = cnss_logger_nl_ucast(skb, dst_pid, flag);
|
||||
if (err < 0)
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"NLINK: netlink_unicast to pid[%d] failed, ret[%d]",
|
||||
dst_pid, err);
|
||||
} else {
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_bcast() - wrapper function to do broadcast tx through cnss_logger
|
||||
* @skb: the socket buffer to send
|
||||
*
|
||||
* The cnss_logger_nl_bcast() is used to transmit the socket buffer.
|
||||
*
|
||||
* Return: status of transmission
|
||||
*/
|
||||
int nl_srv_bcast(struct sk_buff *skb)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
int flags = GFP_KERNEL;
|
||||
|
||||
if (in_interrupt() || irqs_disabled() || in_atomic())
|
||||
flags = GFP_ATOMIC;
|
||||
|
||||
/* sender's pid */
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
|
||||
NETLINK_CB(skb).pid = 0;
|
||||
#else
|
||||
NETLINK_CB(skb).portid = 0;
|
||||
#endif
|
||||
/* destination group */
|
||||
NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID;
|
||||
|
||||
if (nl_srv_is_initialized() == 0) {
|
||||
err = cnss_logger_nl_bcast(skb, WLAN_NLINK_MCAST_GRP_ID, flags);
|
||||
if ((err < 0) && (err != -ESRCH)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"NLINK: netlink_broadcast failed err = %d",
|
||||
err);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
else
|
||||
dev_kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
qdf_export_symbol(nl_srv_bcast);
|
||||
|
||||
/**
|
||||
* nl_srv_unregister() - wrapper function to unregister event to cnss_logger
|
||||
* @msg_type: the message to unregister
|
||||
* @msg_handler: the message handler
|
||||
*
|
||||
* The cnss_logger_event_unregister() is used to unregister the message and
|
||||
* message handler.
|
||||
*
|
||||
* Return: 0 if successfully unregister, otherwise proper error code
|
||||
*/
|
||||
int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (nl_srv_is_initialized() != 0)
|
||||
return ret;
|
||||
|
||||
if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
|
||||
msg_handler) {
|
||||
ret = cnss_logger_event_unregister(radio_idx, msg_type,
|
||||
msg_handler);
|
||||
} else {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"NLINK: nl_srv_unregister failed for msg_type %d",
|
||||
msg_type);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_register() - wrapper function to register event to cnss_logger
|
||||
* @msg_type: the message to register
|
||||
* @msg_handler: the message handler
|
||||
*
|
||||
* The cnss_logger_event_register() is used to register the message and
|
||||
* message handler.
|
||||
*
|
||||
* Return: 0 if successfully register, otherwise proper error code
|
||||
*/
|
||||
int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (nl_srv_is_initialized() != 0)
|
||||
return ret;
|
||||
|
||||
if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
|
||||
msg_handler) {
|
||||
ret = cnss_logger_event_register(radio_idx, msg_type,
|
||||
msg_handler);
|
||||
} else {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"NLINK: nl_srv_register failed for msg_type %d",
|
||||
msg_type);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_is_initialized() - check if netlink service is initialized
|
||||
*
|
||||
* Return: 0 if it is initialized, otherwise error code
|
||||
*/
|
||||
inline int nl_srv_is_initialized(void)
|
||||
{
|
||||
if (logger_initialized)
|
||||
return 0;
|
||||
else
|
||||
return -EPERM;
|
||||
}
|
||||
qdf_export_symbol(nl_srv_is_initialized);
|
||||
|
||||
/*
|
||||
* If MULTI_IF_NAME is not defined, then this is the primary instance of the
|
||||
* driver and the diagnostics netlink socket will be available. If
|
||||
* MULTI_IF_NAME is defined then this is not the primary instance of the driver
|
||||
* and the diagnostics netlink socket will not be available since this
|
||||
* diagnostics netlink socket can only be exposed by one instance of the driver.
|
||||
*/
|
||||
#elif defined(CNSS_GENL)
|
||||
#include <qdf_mem.h>
|
||||
#include <wlan_nlink_common.h>
|
||||
#include <net/genetlink.h>
|
||||
#ifdef CONFIG_CNSS_OUT_OF_TREE
|
||||
#include "cnss_nl.h"
|
||||
#else
|
||||
#include <net/cnss_nl.h>
|
||||
#endif
|
||||
|
||||
void cld80211_oem_send_reply(struct sk_buff *msg, void *hdr,
|
||||
struct nlattr *nest, int flags)
|
||||
{
|
||||
struct genl_family *cld80211_fam = cld80211_get_genl_family();
|
||||
|
||||
nla_nest_end(msg, nest);
|
||||
genlmsg_end(msg, hdr);
|
||||
|
||||
genlmsg_multicast_netns(cld80211_fam, &init_net, msg, 0,
|
||||
CLD80211_MCGRP_OEM_MSGS, flags);
|
||||
}
|
||||
|
||||
struct sk_buff *
|
||||
cld80211_oem_rsp_alloc_skb(uint32_t portid, void **hdr, struct nlattr **nest,
|
||||
int *flags)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
|
||||
if (in_interrupt() || irqs_disabled() || in_atomic())
|
||||
*flags = GFP_ATOMIC;
|
||||
|
||||
msg = nlmsg_new(WLAN_CLD80211_MAX_SIZE, *flags);
|
||||
if (!msg) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"nlmsg malloc fails");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*hdr = nl80211hdr_put(msg, portid, 0, *flags, WLAN_NL_MSG_OEM);
|
||||
if (*hdr == NULL) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"nl80211 hdr put failed");
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
*nest = nla_nest_start(msg, CLD80211_ATTR_VENDOR_DATA);
|
||||
if (*nest == NULL) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"nla_nest_start failed");
|
||||
goto nla_put_failure;
|
||||
}
|
||||
return msg;
|
||||
nla_put_failure:
|
||||
genlmsg_cancel(msg, *hdr);
|
||||
nlmsg_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* For CNSS_GENL netlink sockets will be initialized by CNSS Kernel Module */
|
||||
int nl_srv_init(void *wiphy, int proto)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nl_srv_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
int nl_srv_is_initialized(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Not implemented by CNSS kernel module */
|
||||
int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *nl80211hdr_put(struct sk_buff *skb, uint32_t portid,
|
||||
uint32_t seq, int flags, uint8_t cmd)
|
||||
{
|
||||
struct genl_family *cld80211_fam = cld80211_get_genl_family();
|
||||
|
||||
return genlmsg_put(skb, portid, seq, cld80211_fam, flags, cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* cld80211_fill_data() - API to fill payload to nl message
|
||||
* @msg: Sk buffer
|
||||
* @portid: Port ID
|
||||
* @seq: Sequence number
|
||||
* @flags: Flags
|
||||
* @cmd: Command ID
|
||||
* @buf: data buffer/payload to be filled
|
||||
* @len: length of the payload ie. @buf
|
||||
*
|
||||
* API to fill the payload/data of the nl message to be sent
|
||||
*
|
||||
* Return: zero on success
|
||||
*/
|
||||
static int cld80211_fill_data(struct sk_buff *msg, uint32_t portid,
|
||||
uint32_t seq, int flags, uint8_t cmd,
|
||||
uint8_t *buf, int len)
|
||||
{
|
||||
void *hdr;
|
||||
struct nlattr *nest;
|
||||
|
||||
hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
|
||||
if (!hdr) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"nl80211 hdr put failed");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
nest = nla_nest_start(msg, CLD80211_ATTR_VENDOR_DATA);
|
||||
if (!nest) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"nla_nest_start failed");
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
if (nla_put(msg, CLD80211_ATTR_DATA, len, buf)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"nla_put failed");
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
nla_nest_end(msg, nest);
|
||||
genlmsg_end(msg, hdr);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/**
|
||||
* send_msg_to_cld80211() - API to send message to user space Application
|
||||
* @mcgroup_id: Multicast group ID
|
||||
* @pid: Port ID
|
||||
* @app_id: Application ID
|
||||
* @buf: Data/payload buffer to be sent
|
||||
* @len: Length of the data ie. @buf
|
||||
*
|
||||
* API to send the nl message to user space application.
|
||||
*
|
||||
* Return: zero on success
|
||||
*/
|
||||
static int send_msg_to_cld80211(int mcgroup_id, int pid, int app_id,
|
||||
uint8_t *buf, int len)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
struct genl_family *cld80211_fam = cld80211_get_genl_family();
|
||||
int status;
|
||||
int flags = GFP_KERNEL;
|
||||
|
||||
if (in_interrupt() || irqs_disabled() || in_atomic())
|
||||
flags = GFP_ATOMIC;
|
||||
|
||||
if (len > NLMSG_DEFAULT_SIZE) {
|
||||
if (len > WLAN_CLD80211_MAX_SIZE) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"buf size:%d if more than max size: %d",
|
||||
len, (int) WLAN_CLD80211_MAX_SIZE);
|
||||
return -ENOMEM;
|
||||
}
|
||||
msg = nlmsg_new(WLAN_CLD80211_MAX_SIZE, flags);
|
||||
} else {
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, flags);
|
||||
}
|
||||
if (!msg) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"nlmsg malloc fails");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
status = cld80211_fill_data(msg, pid, 0, 0, app_id, buf, len);
|
||||
if (status) {
|
||||
nlmsg_free(msg);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
genlmsg_multicast_netns(cld80211_fam, &init_net, msg, 0,
|
||||
mcgroup_id, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_bcast() - wrapper function to do broadcast events to user space apps
|
||||
* @skb: the socket buffer to send
|
||||
* @mcgroup_id: multicast group id
|
||||
* @app_id: application id
|
||||
*
|
||||
* This function is common wrapper to send broadcast events to different
|
||||
* user space applications.
|
||||
*
|
||||
* return: none
|
||||
*/
|
||||
int nl_srv_bcast(struct sk_buff *skb, int mcgroup_id, int app_id)
|
||||
{
|
||||
struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
|
||||
void *msg = NLMSG_DATA(nlh);
|
||||
uint32_t msg_len = nlmsg_len(nlh);
|
||||
int status;
|
||||
|
||||
status = send_msg_to_cld80211(mcgroup_id, 0, app_id, msg, msg_len);
|
||||
if (status) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"send msg to cld80211 fails for app id %d", app_id);
|
||||
dev_kfree_skb(skb);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
qdf_export_symbol(nl_srv_bcast);
|
||||
|
||||
/**
|
||||
* nl_srv_ucast() - wrapper function to do unicast events to user space apps
|
||||
* @skb: the socket buffer to send
|
||||
* @dst_pid: destination process IF
|
||||
* @flag: flags
|
||||
* @app_id: application id
|
||||
* @mcgroup_id: Multicast group ID
|
||||
*
|
||||
* This function is common wrapper to send unicast events to different
|
||||
* user space applications. This internally used broadcast API with multicast
|
||||
* group mcgrp_id. This wrapper serves as a common API in both
|
||||
* new generic netlink infra and legacy implementation.
|
||||
*
|
||||
* return: zero on success, error code otherwise
|
||||
*/
|
||||
int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag,
|
||||
int app_id, int mcgroup_id)
|
||||
{
|
||||
struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
|
||||
void *msg = NLMSG_DATA(nlh);
|
||||
uint32_t msg_len = nlmsg_len(nlh);
|
||||
int status;
|
||||
|
||||
status = send_msg_to_cld80211(mcgroup_id, dst_pid, app_id,
|
||||
msg, msg_len);
|
||||
if (status) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"send msg to cld80211 fails for app id %d", app_id);
|
||||
dev_kfree_skb(skb);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif !defined(MULTI_IF_NAME) || defined(MULTI_IF_LOG)
|
||||
|
||||
/* Global variables */
|
||||
static DEFINE_MUTEX(nl_srv_sem);
|
||||
static struct sock *nl_srv_sock;
|
||||
static nl_srv_msg_callback nl_srv_msg_handler[NLINK_MAX_CALLBACKS];
|
||||
|
||||
/* Forward declaration */
|
||||
static void nl_srv_rcv(struct sk_buff *sk);
|
||||
static void nl_srv_rcv_skb(struct sk_buff *skb);
|
||||
static void nl_srv_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh);
|
||||
|
||||
/*
|
||||
* Initialize the netlink service.
|
||||
* Netlink service is usable after this.
|
||||
*/
|
||||
int nl_srv_init(void *wiphy, int proto)
|
||||
{
|
||||
int retcode = 0;
|
||||
struct netlink_kernel_cfg cfg = {
|
||||
.groups = WLAN_NLINK_MCAST_GRP_ID,
|
||||
.input = nl_srv_rcv
|
||||
};
|
||||
|
||||
nl_srv_sock = netlink_kernel_create(&init_net, proto,
|
||||
&cfg);
|
||||
|
||||
if (nl_srv_sock) {
|
||||
memset(nl_srv_msg_handler, 0, sizeof(nl_srv_msg_handler));
|
||||
} else {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"NLINK: netlink_kernel_create failed");
|
||||
retcode = -ECONNREFUSED;
|
||||
}
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deinit the netlink service.
|
||||
* Netlink service is unusable after this.
|
||||
*/
|
||||
void nl_srv_exit(void)
|
||||
{
|
||||
if (nl_srv_is_initialized() == 0)
|
||||
netlink_kernel_release(nl_srv_sock);
|
||||
|
||||
nl_srv_sock = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a message handler for a specified module.
|
||||
* Each module (e.g. WLAN_NL_MSG_BTC )will register a
|
||||
* handler to handle messages addressed to it.
|
||||
*/
|
||||
int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
|
||||
{
|
||||
int retcode = 0;
|
||||
|
||||
if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
|
||||
msg_handler) {
|
||||
nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] = msg_handler;
|
||||
} else {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"NLINK: nl_srv_register failed for msg_type %d",
|
||||
msg_type);
|
||||
retcode = -EINVAL;
|
||||
}
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
qdf_export_symbol(nl_srv_register);
|
||||
|
||||
/*
|
||||
* Unregister the message handler for a specified module.
|
||||
*/
|
||||
int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
|
||||
{
|
||||
int retcode = 0;
|
||||
|
||||
if ((msg_type >= WLAN_NL_MSG_BASE) && (msg_type < WLAN_NL_MSG_MAX) &&
|
||||
(nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] == msg_handler)) {
|
||||
nl_srv_msg_handler[msg_type - WLAN_NL_MSG_BASE] = NULL;
|
||||
} else {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"NLINK: nl_srv_unregister failed for msg_type %d",
|
||||
msg_type);
|
||||
retcode = -EINVAL;
|
||||
}
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unicast the message to the process in user space identfied
|
||||
* by the dst-pid
|
||||
*/
|
||||
int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
|
||||
NETLINK_CB(skb).portid = 0; /* sender's pid */
|
||||
NETLINK_CB(skb).dst_group = 0; /* not multicast */
|
||||
|
||||
if (nl_srv_sock) {
|
||||
err = netlink_unicast(nl_srv_sock, skb, dst_pid, flag);
|
||||
if (err < 0)
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"NLINK: netlink_unicast to pid[%d] failed, ret[%d]",
|
||||
dst_pid, err);
|
||||
} else {
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Broadcast the message. Broadcast will return an error if
|
||||
* there are no listeners
|
||||
*/
|
||||
int nl_srv_bcast(struct sk_buff *skb)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
int flags = GFP_KERNEL;
|
||||
|
||||
if (in_interrupt() || irqs_disabled() || in_atomic())
|
||||
flags = GFP_ATOMIC;
|
||||
|
||||
NETLINK_CB(skb).portid = 0; /* sender's pid */
|
||||
NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID; /* destination group */
|
||||
|
||||
if (nl_srv_sock) {
|
||||
err = netlink_broadcast(nl_srv_sock, skb, 0,
|
||||
WLAN_NLINK_MCAST_GRP_ID, flags);
|
||||
if ((err < 0) && (err != -ESRCH)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"NLINK: netlink_broadcast failed err = %d",
|
||||
err);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
} else
|
||||
dev_kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
qdf_export_symbol(nl_srv_bcast);
|
||||
|
||||
/*
|
||||
* Processes the Netlink socket input queue.
|
||||
* Dequeue skb's from the socket input queue and process
|
||||
* all the netlink messages in that skb, before moving
|
||||
* to the next skb.
|
||||
*/
|
||||
static void nl_srv_rcv(struct sk_buff *sk)
|
||||
{
|
||||
mutex_lock(&nl_srv_sem);
|
||||
nl_srv_rcv_skb(sk);
|
||||
mutex_unlock(&nl_srv_sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Each skb could contain multiple Netlink messages. Process all the
|
||||
* messages in one skb and discard malformed skb's silently.
|
||||
*/
|
||||
static void nl_srv_rcv_skb(struct sk_buff *skb)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
|
||||
while (skb->len >= NLMSG_SPACE(0)) {
|
||||
u32 rlen;
|
||||
|
||||
nlh = (struct nlmsghdr *)skb->data;
|
||||
|
||||
if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||
"NLINK: Invalid "
|
||||
"Netlink message: skb[%pK], len[%d], nlhdr[%pK], nlmsg_len[%d]",
|
||||
skb, skb->len, nlh, nlh->nlmsg_len);
|
||||
return;
|
||||
}
|
||||
|
||||
rlen = NLMSG_ALIGN(nlh->nlmsg_len);
|
||||
if (rlen > skb->len)
|
||||
rlen = skb->len;
|
||||
nl_srv_rcv_msg(skb, nlh);
|
||||
skb_pull(skb, rlen);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a netlink message.
|
||||
* Each netlink message will have a message of type tAniMsgHdr inside.
|
||||
*/
|
||||
static void nl_srv_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
{
|
||||
int type;
|
||||
|
||||
/* Only requests are handled by kernel now */
|
||||
if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) {
|
||||
QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_HDD,
|
||||
"NLINK: Received Invalid NL Req type [%x]",
|
||||
nlh->nlmsg_flags);
|
||||
return;
|
||||
}
|
||||
|
||||
type = nlh->nlmsg_type;
|
||||
|
||||
/* Unknown message */
|
||||
if (type < WLAN_NL_MSG_BASE || type >= WLAN_NL_MSG_MAX) {
|
||||
QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_HDD,
|
||||
"NLINK: Received Invalid NL Msg type [%x]",
|
||||
type);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* All the messages must at least carry the tAniMsgHdr
|
||||
* Drop any message with invalid length
|
||||
*/
|
||||
if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(tAniMsgHdr))) {
|
||||
QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_HDD,
|
||||
"NLINK: Received NL Msg with invalid len[%x]",
|
||||
nlh->nlmsg_len);
|
||||
return;
|
||||
}
|
||||
|
||||
/* turn type into dispatch table offset */
|
||||
type -= WLAN_NL_MSG_BASE;
|
||||
|
||||
/* dispatch to handler */
|
||||
if (nl_srv_msg_handler[type]) {
|
||||
(nl_srv_msg_handler[type])(skb);
|
||||
} else {
|
||||
QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_HDD,
|
||||
"NLINK: No handler for msg [0x%X]", type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_is_initialized() - This function is used check if the netlink
|
||||
* service is initialized
|
||||
*
|
||||
* This function is used check if the netlink service is initialized
|
||||
*
|
||||
* Return: Return -EPERM if the service is not initialized
|
||||
*
|
||||
*/
|
||||
int nl_srv_is_initialized(void)
|
||||
{
|
||||
if (nl_srv_sock)
|
||||
return 0;
|
||||
|
||||
return -EPERM;
|
||||
}
|
||||
qdf_export_symbol(nl_srv_is_initialized);
|
||||
|
||||
#else
|
||||
|
||||
int nl_srv_init(void *wiphy, int proto)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nl_srv_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag)
|
||||
{
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_srv_bcast(struct sk_buff *skb)
|
||||
{
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
qdf_export_symbol(nl_srv_bcast);
|
||||
|
||||
int nl_srv_is_initialized(void)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
qdf_export_symbol(nl_srv_is_initialized);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* nl_srv_ucast_oem() - Wrapper function to send ucast msgs to OEM
|
||||
* @skb: sk buffer pointer
|
||||
* @dst_pid: Destination PID
|
||||
* @flag: flags
|
||||
*
|
||||
* Sends the ucast message to OEM with generic nl socket if CNSS_GENL
|
||||
* is enabled. Else, use the legacy netlink socket to send.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
#ifdef CNSS_GENL
|
||||
void nl_srv_ucast_oem(struct sk_buff *skb, int dst_pid, int flag)
|
||||
{
|
||||
nl_srv_ucast(skb, dst_pid, flag, WLAN_NL_MSG_OEM,
|
||||
CLD80211_MCGRP_OEM_MSGS);
|
||||
}
|
||||
#else
|
||||
void nl_srv_ucast_oem(struct sk_buff *skb, int dst_pid, int flag)
|
||||
{
|
||||
nl_srv_ucast(skb, dst_pid, flag);
|
||||
}
|
||||
|
||||
qdf_export_symbol(nl_srv_ucast_oem);
|
||||
#endif
|
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014, 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef _PKTLOG_
|
||||
#define _PKTLOG_
|
||||
#ifndef REMOVE_PKT_LOG
|
||||
|
||||
/**
|
||||
* @typedef ol_pktlog_dev_handle
|
||||
* @brief opaque handle for pktlog device object
|
||||
*/
|
||||
struct ol_pktlog_dev_t;
|
||||
typedef struct ol_pktlog_dev_t *ol_pktlog_dev_handle;
|
||||
#endif /* #ifndef REMOVE_PKT_LOG */
|
||||
#endif /* _PKTLOG_ */
|
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. 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.
|
||||
*/
|
||||
|
||||
#ifndef _PKTLOG_AC_H_
|
||||
#define _PKTLOG_AC_H_
|
||||
|
||||
#include "hif.h"
|
||||
#if defined(CONNECTIVITY_PKTLOG) || !defined(REMOVE_PKT_LOG)
|
||||
#include "ol_if_athvar.h"
|
||||
#include "osdep.h"
|
||||
#include <wmi_unified.h>
|
||||
#include <wmi_unified_api.h>
|
||||
#include <wdi_event_api.h>
|
||||
#include <ol_defines.h>
|
||||
#include <pktlog_ac_api.h>
|
||||
#include <pktlog_ac_fmt.h>
|
||||
|
||||
#define NO_REG_FUNCS 4
|
||||
|
||||
/* Locking interface for pktlog */
|
||||
#define PKTLOG_LOCK_INIT(_pl_info) qdf_spinlock_create(&(_pl_info)->log_lock)
|
||||
#define PKTLOG_LOCK_DESTROY(_pl_info) \
|
||||
qdf_spinlock_destroy(&(_pl_info)->log_lock)
|
||||
#define PKTLOG_LOCK(_pl_info) qdf_spin_lock_bh(&(_pl_info)->log_lock)
|
||||
#define PKTLOG_UNLOCK(_pl_info) qdf_spin_unlock_bh(&(_pl_info)->log_lock)
|
||||
|
||||
#define PKTLOG_MODE_SYSTEM 1
|
||||
#define PKTLOG_MODE_ADAPTER 2
|
||||
|
||||
/*
|
||||
* The proc entry starts with magic number and version field which will be
|
||||
* used by post processing scripts. These fields are not needed by applications
|
||||
* that do not use these scripts. This is skipped using the offset value.
|
||||
*/
|
||||
#define PKTLOG_READ_OFFSET 8
|
||||
|
||||
/* forward declaration for cdp_pdev */
|
||||
struct cdp_pdev;
|
||||
|
||||
/* Opaque softc */
|
||||
struct ol_ath_generic_softc_t;
|
||||
typedef struct ol_ath_generic_softc_t *ol_ath_generic_softc_handle;
|
||||
extern void pktlog_disable_adapter_logging(struct hif_opaque_softc *scn);
|
||||
extern int pktlog_alloc_buf(struct hif_opaque_softc *scn);
|
||||
extern void pktlog_release_buf(struct hif_opaque_softc *scn);
|
||||
|
||||
ssize_t pktlog_read_proc_entry(char *buf, size_t nbytes, loff_t *ppos,
|
||||
struct ath_pktlog_info *pl_info, bool *read_complete);
|
||||
|
||||
/**
|
||||
* wdi_pktlog_unsubscribe() - Unsubscribe pktlog callbacks
|
||||
* @pdev_id: pdev id
|
||||
* @log_state: Pktlog registration
|
||||
*
|
||||
* Return: zero on success, non-zero on failure
|
||||
*/
|
||||
A_STATUS wdi_pktlog_unsubscribe(uint8_t pdev_id, uint32_t log_state);
|
||||
|
||||
struct ol_pl_arch_dep_funcs {
|
||||
void (*pktlog_init)(struct hif_opaque_softc *scn);
|
||||
int (*pktlog_enable)(struct hif_opaque_softc *scn, int32_t log_state,
|
||||
bool ini, uint8_t user,
|
||||
uint32_t is_iwpriv_command);
|
||||
int (*pktlog_setsize)(struct hif_opaque_softc *scn, int32_t log_state);
|
||||
int (*pktlog_disable)(struct hif_opaque_softc *scn);
|
||||
};
|
||||
|
||||
struct ol_pl_os_dep_funcs {
|
||||
int (*pktlog_attach)(struct hif_opaque_softc *scn);
|
||||
void (*pktlog_detach)(struct hif_opaque_softc *scn);
|
||||
|
||||
};
|
||||
|
||||
struct ath_pktlog_wmi_params {
|
||||
WMI_PKTLOG_EVENT pktlog_event;
|
||||
WMI_CMD_ID cmd_id;
|
||||
bool ini_triggered;
|
||||
uint8_t user_triggered;
|
||||
};
|
||||
|
||||
extern struct ol_pl_arch_dep_funcs ol_pl_funcs;
|
||||
extern struct ol_pl_os_dep_funcs *g_ol_pl_os_dep_funcs;
|
||||
|
||||
/* Pktlog handler to save the state of the pktlogs */
|
||||
struct pktlog_dev_t {
|
||||
struct ol_pl_arch_dep_funcs *pl_funcs;
|
||||
struct ath_pktlog_info *pl_info;
|
||||
ol_ath_generic_softc_handle scn;
|
||||
uint8_t pdev_id;
|
||||
char *name;
|
||||
bool tgt_pktlog_alloced;
|
||||
bool is_pktlog_cb_subscribed;
|
||||
bool mt_pktlog_enabled;
|
||||
uint32_t htc_err_cnt;
|
||||
uint8_t htc_endpoint;
|
||||
void *htc_pdev;
|
||||
bool vendor_cmd_send;
|
||||
uint8_t callback_type;
|
||||
uint32_t invalid_packets;
|
||||
};
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0))
|
||||
#define PKTLOG_SYSCTL_SIZE 10
|
||||
#else
|
||||
#define PKTLOG_SYSCTL_SIZE 14
|
||||
#endif
|
||||
|
||||
#define PKTLOG_MAX_SEND_QUEUE_DEPTH 64
|
||||
|
||||
/*
|
||||
* Linux specific pktlog state information
|
||||
*/
|
||||
struct ath_pktlog_info_lnx {
|
||||
struct ath_pktlog_info info;
|
||||
struct ctl_table sysctls[PKTLOG_SYSCTL_SIZE];
|
||||
struct proc_dir_entry *proc_entry;
|
||||
struct ctl_table_header *sysctl_header;
|
||||
};
|
||||
|
||||
#define PL_INFO_LNX(_pl_info) ((struct ath_pktlog_info_lnx *)(_pl_info))
|
||||
|
||||
/*
|
||||
* WDI related data and functions
|
||||
* Callback function to the WDI events
|
||||
*/
|
||||
void pktlog_callback(void *pdev, enum WDI_EVENT event, void *log_data,
|
||||
u_int16_t peer_id, uint32_t status);
|
||||
|
||||
void pktlog_init(struct hif_opaque_softc *scn);
|
||||
int pktlog_enable(struct hif_opaque_softc *scn, int32_t log_state,
|
||||
bool, uint8_t, uint32_t);
|
||||
int __pktlog_enable(struct hif_opaque_softc *scn, int32_t log_state,
|
||||
bool ini_triggered, uint8_t user_triggered,
|
||||
uint32_t is_iwpriv_command);
|
||||
int pktlog_setsize(struct hif_opaque_softc *scn, int32_t log_state);
|
||||
int pktlog_clearbuff(struct hif_opaque_softc *scn, bool clear_buff);
|
||||
int pktlog_disable(struct hif_opaque_softc *scn);
|
||||
int pktlogmod_init(void *context);
|
||||
void pktlogmod_exit(void *context);
|
||||
int pktlog_htc_attach(void);
|
||||
|
||||
/**
|
||||
* pktlog_process_fw_msg() - process packetlog message
|
||||
* @pdev_id: physical device instance id
|
||||
* @msg_word: message buffer
|
||||
* @msg_len: message length
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void pktlog_process_fw_msg(uint8_t pdev_id, uint32_t *msg_word,
|
||||
uint32_t msg_len);
|
||||
void lit_pktlog_callback(void *context, enum WDI_EVENT event, void *log_data,
|
||||
u_int16_t peer_id, uint32_t status);
|
||||
|
||||
#define ol_pktlog_attach(_scn) \
|
||||
do { \
|
||||
if (g_ol_pl_os_dep_funcs) { \
|
||||
g_ol_pl_os_dep_funcs->pktlog_attach(_scn); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ol_pktlog_detach(_scn) \
|
||||
do { \
|
||||
if (g_ol_pl_os_dep_funcs) { \
|
||||
g_ol_pl_os_dep_funcs->pktlog_detach(_scn); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else /* REMOVE_PKT_LOG */
|
||||
#define ol_pktlog_attach(_scn) ({ (void)_scn; })
|
||||
#define ol_pktlog_detach(_scn) ({ (void)_scn; })
|
||||
static inline void pktlog_init(struct hif_opaque_softc *scn)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int pktlog_enable(struct hif_opaque_softc *scn, int32_t log_state,
|
||||
bool ini, uint8_t user,
|
||||
uint32_t is_iwpriv_command)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int __pktlog_enable(struct hif_opaque_softc *scn, int32_t log_state,
|
||||
bool ini_triggered, uint8_t user_triggered,
|
||||
uint32_t is_iwpriv_command)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int pktlog_setsize(struct hif_opaque_softc *scn,
|
||||
int32_t log_state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int pktlog_clearbuff(struct hif_opaque_softc *scn,
|
||||
bool clear_buff)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int pktlog_disable(struct hif_opaque_softc *scn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int pktlog_htc_attach(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void pktlog_process_fw_msg(uint8_t pdev_id, uint32_t *msg_word,
|
||||
uint32_t msg_len)
|
||||
{ }
|
||||
#endif /* REMOVE_PKT_LOG */
|
||||
#endif /* _PKTLOG_AC_H_ */
|
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2014, 2016-2018, 2020 The Linux Foundation.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The file is used to define structures that are shared between
|
||||
* kernel space and user space pktlog application.
|
||||
*/
|
||||
|
||||
#ifndef _PKTLOG_AC_API_
|
||||
#define _PKTLOG_AC_API_
|
||||
#if defined(CONNECTIVITY_PKTLOG) || !defined(REMOVE_PKT_LOG)
|
||||
|
||||
struct hif_opaque_softc;
|
||||
/**
|
||||
* typedef hif_opaque_softc_handle - opaque handle for hif_opaque_softc
|
||||
*/
|
||||
typedef struct hif_opaque_softc * hif_opaque_softc_handle;
|
||||
|
||||
enum pktlog_callback_regtype {
|
||||
PKTLOG_DEFAULT_CALLBACK_REGISTRATION,
|
||||
PKTLOG_LITE_CALLBACK_REGISTRATION
|
||||
};
|
||||
|
||||
struct net_device;
|
||||
/**
|
||||
* typedef net_device_handle - opaque handle to linux net device object
|
||||
*/
|
||||
typedef struct net_device * net_device_handle;
|
||||
|
||||
struct pktlog_dev_t;
|
||||
|
||||
void pktlog_sethandle(struct pktlog_dev_t **pl_handle,
|
||||
hif_opaque_softc_handle scn);
|
||||
void pktlog_set_pdev_id(struct pktlog_dev_t *pl_dev, uint8_t pdev_id);
|
||||
|
||||
void *get_txrx_context(void);
|
||||
|
||||
struct pktlog_dev_t *get_pktlog_handle(void);
|
||||
void pktlog_set_callback_regtype(enum pktlog_callback_regtype callback_type);
|
||||
|
||||
/* Packet log state information */
|
||||
#ifndef _PKTLOG_INFO
|
||||
#define _PKTLOG_INFO
|
||||
|
||||
/**
|
||||
* enum ath_pktlog_state - pktlog status
|
||||
* @PKTLOG_OPR_IN_PROGRESS : pktlog command in progress
|
||||
* @PKTLOG_OPR_IN_PROGRESS_READ_START: pktlog read is issued
|
||||
* @PKTLOG_OPR_IN_PROGRESS_READ_START_PKTLOG_DISABLED:
|
||||
* as part of pktlog read, pktlog is disabled
|
||||
* @PKTLOG_OPR_IN_PROGRESS_READ_COMPLETE:
|
||||
* as part of read, till pktlog read is complete
|
||||
* @PKTLOG_OPR_IN_PROGRESS_CLEARBUFF_COMPLETE:
|
||||
* as part of read, pktlog clear buffer is done
|
||||
* @PKTLOG_OPR_NOT_IN_PROGRESS: no pktlog command in progress
|
||||
*/
|
||||
enum ath_pktlog_state {
|
||||
PKTLOG_OPR_IN_PROGRESS = 0,
|
||||
PKTLOG_OPR_IN_PROGRESS_READ_START,
|
||||
PKTLOG_OPR_IN_PROGRESS_READ_START_PKTLOG_DISABLED,
|
||||
PKTLOG_OPR_IN_PROGRESS_READ_COMPLETE,
|
||||
PKTLOG_OPR_IN_PROGRESS_CLEARBUFF_COMPLETE,
|
||||
PKTLOG_OPR_NOT_IN_PROGRESS
|
||||
};
|
||||
|
||||
struct ath_pktlog_info {
|
||||
struct ath_pktlog_buf *buf;
|
||||
uint32_t log_state;
|
||||
uint32_t saved_state;
|
||||
uint32_t options;
|
||||
/* Initial saved state: It will save the log state in pktlog
|
||||
* open and used in pktlog release after
|
||||
* pktlog read is complete.
|
||||
*/
|
||||
uint32_t init_saved_state;
|
||||
enum ath_pktlog_state curr_pkt_state;
|
||||
|
||||
/* Size of buffer in bytes */
|
||||
int32_t buf_size;
|
||||
qdf_spinlock_t log_lock;
|
||||
struct mutex pktlog_mutex;
|
||||
|
||||
/* Threshold of TCP SACK packets for triggered stop */
|
||||
int sack_thr;
|
||||
|
||||
/* # of tail packets to log after triggered stop */
|
||||
int tail_length;
|
||||
|
||||
/* throuput threshold in bytes for triggered stop */
|
||||
uint32_t thruput_thresh;
|
||||
|
||||
/* (aggregated or single) packet size in bytes */
|
||||
uint32_t pktlen;
|
||||
|
||||
/* a temporary variable for counting TX throughput only */
|
||||
/* PER threshold for triggered stop, 10 for 10%, range [1, 99] */
|
||||
uint32_t per_thresh;
|
||||
|
||||
/* Phyerr threshold for triggered stop */
|
||||
uint32_t phyerr_thresh;
|
||||
|
||||
/* time period for counting trigger parameters, in millisecond */
|
||||
uint32_t trigger_interval;
|
||||
uint32_t start_time_thruput;
|
||||
uint32_t start_time_per;
|
||||
};
|
||||
#endif /* _PKTLOG_INFO */
|
||||
#else /* REMOVE_PKT_LOG */
|
||||
typedef void *pktlog_dev_handle;
|
||||
#define pktlog_set_pdev_id(pl_dev, pdev_id) \
|
||||
do { \
|
||||
(void)pl_dev; \
|
||||
(void)pdev_id; \
|
||||
} while (0)
|
||||
|
||||
#define pktlog_sethandle(pl_handle, scn) \
|
||||
do { \
|
||||
(void)pl_handle; \
|
||||
(void)scn; \
|
||||
} while (0)
|
||||
|
||||
#define ol_pl_set_name(dev) \
|
||||
do { \
|
||||
(void)scn; \
|
||||
(void)dev; \
|
||||
} while (0)
|
||||
|
||||
#endif /* REMOVE_PKT_LOG */
|
||||
#endif /* _PKTLOG_AC_API_ */
|
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2012-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.
|
||||
*/
|
||||
|
||||
#ifndef _PKTLOG_AC_I_
|
||||
#define _PKTLOG_AC_I_
|
||||
|
||||
#ifndef REMOVE_PKT_LOG
|
||||
|
||||
#include <ol_txrx_internal.h>
|
||||
#include <pktlog_ac.h>
|
||||
|
||||
|
||||
#define PKTLOG_TAG "ATH_PKTLOG"
|
||||
#define PKTLOG_DEFAULT_BUFSIZE (10 * 1024 * 1024) /* 10MB */
|
||||
#define PKTLOG_DEFAULT_SACK_THR 3
|
||||
#define PKTLOG_DEFAULT_TAIL_LENGTH 100
|
||||
#define PKTLOG_DEFAULT_THRUPUT_THRESH (64 * 1024)
|
||||
#define PKTLOG_DEFAULT_PER_THRESH 30
|
||||
#define PKTLOG_DEFAULT_PHYERR_THRESH 300
|
||||
#define PKTLOG_DEFAULT_TRIGGER_INTERVAL 500
|
||||
|
||||
/* Max Pktlog buffer size received from fw/hw */
|
||||
#define MAX_PKTLOG_RECV_BUF_SIZE 2048
|
||||
|
||||
struct ath_pktlog_arg {
|
||||
struct ath_pktlog_info *pl_info;
|
||||
uint32_t flags;
|
||||
uint16_t missed_cnt;
|
||||
#ifdef HELIUMPLUS
|
||||
uint8_t log_type;
|
||||
uint8_t macId;
|
||||
#else
|
||||
uint16_t log_type;
|
||||
#endif
|
||||
size_t log_size;
|
||||
uint16_t timestamp;
|
||||
#ifdef PKTLOG_HAS_SPECIFIC_DATA
|
||||
uint32_t type_specific_data;
|
||||
#endif
|
||||
char *buf;
|
||||
};
|
||||
|
||||
void pktlog_getbuf_intsafe(struct ath_pktlog_arg *plarg);
|
||||
char *pktlog_getbuf(struct pktlog_dev_t *pl_dev,
|
||||
struct ath_pktlog_info *pl_info,
|
||||
size_t log_size, struct ath_pktlog_hdr *pl_hdr);
|
||||
|
||||
#ifdef PKTLOG_HAS_SPECIFIC_DATA
|
||||
/**
|
||||
* pktlog_hdr_set_specific_data() - set type specific data
|
||||
* @log_hdr: pktlog header
|
||||
* @type_specific_data: type specific data
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void
|
||||
pktlog_hdr_set_specific_data(struct ath_pktlog_hdr *log_hdr,
|
||||
uint32_t type_specific_data);
|
||||
|
||||
/**
|
||||
* pktlog_hdr_get_specific_data() - get type specific data
|
||||
* @log_hdr: pktlog header
|
||||
* @type_specific_data: type specific data
|
||||
*
|
||||
* Return: pktlog subtype
|
||||
*/
|
||||
uint32_t
|
||||
pktlog_hdr_get_specific_data(struct ath_pktlog_hdr *log_hdr);
|
||||
|
||||
/**
|
||||
* pktlog_arg_set_specific_data() - set type specific data
|
||||
* @log_hdr: pktlog arg
|
||||
* @type_specific_data: type specific data
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void
|
||||
pktlog_arg_set_specific_data(struct ath_pktlog_arg *plarg,
|
||||
uint32_t type_specific_data);
|
||||
|
||||
/**
|
||||
* pktlog_arg_get_specific_data() - set type specific data
|
||||
* @log_hdr: pktlog arg
|
||||
* @type_specific_data: type specific data
|
||||
*
|
||||
* Return: pktlog subtype
|
||||
*/
|
||||
uint32_t
|
||||
pktlog_arg_get_specific_data(struct ath_pktlog_arg *plarg);
|
||||
#else
|
||||
static inline void
|
||||
pktlog_hdr_set_specific_data(struct ath_pktlog_hdr *log_hdr,
|
||||
uint32_t type_specific_data)
|
||||
{
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
pktlog_hdr_get_specific_data(struct ath_pktlog_hdr *log_hdr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
pktlog_arg_set_specific_data(struct ath_pktlog_arg *plarg,
|
||||
uint32_t type_specific_data)
|
||||
{
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
pktlog_arg_get_specific_data(struct ath_pktlog_arg *plarg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* PKTLOG_HAS_SPECIFIC_DATA */
|
||||
#endif /* REMOVE_PKT_LOG */
|
||||
#endif
|
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* Copyright (c) 2013-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.
|
||||
*/
|
||||
|
||||
#include "ol_txrx_types.h"
|
||||
#include "ol_htt_tx_api.h"
|
||||
#include "ol_tx_desc.h"
|
||||
#include "qdf_mem.h"
|
||||
#include "htt.h"
|
||||
#include "htt_internal.h"
|
||||
#include "pktlog_ac_i.h"
|
||||
#include "wma_api.h"
|
||||
#include "wlan_logging_sock_svc.h"
|
||||
|
||||
#define TX_DESC_ID_LOW_MASK 0xffff
|
||||
#define TX_DESC_ID_LOW_SHIFT 0
|
||||
#define TX_DESC_ID_HIGH_MASK 0xffff0000
|
||||
#define TX_DESC_ID_HIGH_SHIFT 16
|
||||
|
||||
#ifndef REMOVE_PKT_LOG
|
||||
/**
|
||||
* process_tx_info() - process tx pktlog buffers
|
||||
* @txrx_pdev: ol pdev handle
|
||||
* @data: pktlog buffer
|
||||
*
|
||||
* Return: 0 - success/non-zero - failure
|
||||
*/
|
||||
A_STATUS process_tx_info(struct cdp_pdev *txrx_pdev, void *data);
|
||||
|
||||
/**
|
||||
* process_rx_info_remote() - process rx pktlog buffers
|
||||
* @txrx_pdev: ol pdev handle
|
||||
* @data: pktlog buffer
|
||||
*
|
||||
* Return: 0 - success/non-zero - failure
|
||||
*/
|
||||
A_STATUS process_rx_info_remote(void *pdev, void *data);
|
||||
|
||||
/**
|
||||
* process_rx_info() - process rx pktlog buffers
|
||||
* @txrx_pdev: ol pdev handle
|
||||
* @data: pktlog buffer
|
||||
*
|
||||
* Return: 0 - success/non-zero - failure
|
||||
*/
|
||||
A_STATUS process_rx_info(void *pdev, void *data);
|
||||
|
||||
/**
|
||||
* process_rate_find() - process rate event pktlog buffers
|
||||
* @txrx_pdev: ol pdev handle
|
||||
* @data: pktlog buffer
|
||||
*
|
||||
* Return: 0 - success/non-zero - failure
|
||||
*/
|
||||
A_STATUS process_rate_find(void *pdev, void *data);
|
||||
|
||||
/**
|
||||
* process_rate_update() - process rate event pktlog buffers
|
||||
* @txrx_pdev: ol pdev handle
|
||||
* @data: pktlog buffer
|
||||
*
|
||||
* Return: 0 - success/non-zero - failure
|
||||
*/
|
||||
A_STATUS process_rate_update(void *pdev, void *data);
|
||||
|
||||
/**
|
||||
* process_sw_event() - process sw event pktlog buffers
|
||||
* @txrx_pdev: ol pdev handle
|
||||
* @data: pktlog buffer
|
||||
*
|
||||
* Return: 0 - success/non-zero - failure
|
||||
*/
|
||||
A_STATUS process_sw_event(void *pdev, void *data);
|
||||
#else
|
||||
static inline
|
||||
A_STATUS process_tx_info(struct cdp_pdev *txrx_pdev, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
A_STATUS process_rx_info_remote(void *pdev, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
A_STATUS process_rx_info(void *pdev, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
A_STATUS process_rate_find(void *pdev, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
A_STATUS process_rate_update(void *pdev, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
A_STATUS process_sw_event(void *pdev, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* REMOVE_PKT_LOG */
|
||||
|
||||
/**
|
||||
* process_offload_pktlog_wifi3() - Process full pktlog events
|
||||
* pdev: abstract pdev handle
|
||||
* data: pktlog buffer
|
||||
*
|
||||
* Return: zero on success, non-zero on failure
|
||||
*/
|
||||
static inline A_STATUS
|
||||
process_offload_pktlog_wifi3(struct cdp_pdev *pdev, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* process_rx_desc_remote_wifi3() - Process pktlog buffers received
|
||||
* from monitor status ring
|
||||
* @pdev: pdev handle
|
||||
* @data: pktlog buffer pointer
|
||||
*
|
||||
* Return: 0 - success/non-zero - failure
|
||||
*/
|
||||
static inline int
|
||||
process_rx_desc_remote_wifi3(void *pdev, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* process_pktlog_lite_wifi3() - Process pktlog buffers received
|
||||
* from monitor status ring
|
||||
* @pdev: pdev handle
|
||||
* @data: pktlog buffer pointer
|
||||
*
|
||||
* Return: 0 - success/non-zero - failure
|
||||
*/
|
||||
static inline int
|
||||
process_pktlog_lite_wifi3(void *context, void *log_data,
|
||||
uint16_t log_type)
|
||||
{
|
||||
return 0;
|
||||
}
|
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* Copyright (c) 2013-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.
|
||||
*/
|
||||
|
||||
#include "pktlog_ac_i.h"
|
||||
#include "wlan_logging_sock_svc.h"
|
||||
|
||||
#ifndef REMOVE_PKT_LOG
|
||||
/**
|
||||
* process_offload_pktlog_wifi3() - Process full pktlog events
|
||||
* pdev: abstract pdev handle
|
||||
* data: pktlog buffer
|
||||
*
|
||||
* Return: zero on success, non-zero on failure
|
||||
*/
|
||||
A_STATUS
|
||||
process_offload_pktlog_wifi3(struct cdp_pdev *pdev, void *data);
|
||||
|
||||
/**
|
||||
* process_rx_desc_remote_wifi3() - Process pktlog buffers received
|
||||
* from monitor status ring
|
||||
* @pdev: pdev handle
|
||||
* @data: pktlog buffer pointer
|
||||
*
|
||||
* Return: 0 - success/non-zero - failure
|
||||
*/
|
||||
int process_rx_desc_remote_wifi3(void *pdev, void *data);
|
||||
|
||||
/**
|
||||
* process_pktlog_lite_wifi3() - Process pktlog buffers received
|
||||
* from monitor status ring
|
||||
* @pdev: pdev handle
|
||||
* @data: pktlog buffer pointer
|
||||
*
|
||||
* Return: 0 - success/non-zero - failure
|
||||
*/
|
||||
int process_pktlog_lite_wifi3(void *context, void *log_data,
|
||||
uint16_t log_type);
|
||||
#else
|
||||
static inline A_STATUS
|
||||
process_offload_pktlog_wifi3(struct cdp_pdev *pdev, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int process_rx_desc_remote_wifi3(void *pdev, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
process_pktlog_lite_wifi3(void *context, void *log_data,
|
||||
uint16_t log_type)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* REMOVE_PKT_LOG */
|
||||
|
||||
/**
|
||||
* process_tx_info() - process tx pktlog buffers
|
||||
* @txrx_pdev: ol pdev handle
|
||||
* @data: pktlog buffer
|
||||
*
|
||||
* Return: 0 - success/non-zero - failure
|
||||
*/
|
||||
static inline
|
||||
A_STATUS process_tx_info(struct cdp_pdev *txrx_pdev, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* process_rx_info_remote() - process rx pktlog buffers
|
||||
* @txrx_pdev: ol pdev handle
|
||||
* @data: pktlog buffer
|
||||
*
|
||||
* Return: 0 - success/non-zero - failure
|
||||
*/
|
||||
static inline
|
||||
A_STATUS process_rx_info_remote(void *pdev, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* process_rx_remote() - process rx pktlog buffers
|
||||
* @txrx_pdev: ol pdev handle
|
||||
* @data: pktlog buffer
|
||||
*
|
||||
* Return: 0 - success/non-zero - failure
|
||||
*/
|
||||
static inline
|
||||
A_STATUS process_rx_info(void *pdev, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* process_rate_find() - process rate event pktlog buffers
|
||||
* @txrx_pdev: ol pdev handle
|
||||
* @data: pktlog buffer
|
||||
*
|
||||
* Return: 0 - success/non-zero - failure
|
||||
*/
|
||||
static inline
|
||||
A_STATUS process_rate_find(void *pdev, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* process_rate_update() - process rate event pktlog buffers
|
||||
* @txrx_pdev: ol pdev handle
|
||||
* @data: pktlog buffer
|
||||
*
|
||||
* Return: 0 - success/non-zero - failure
|
||||
*/
|
||||
static inline
|
||||
A_STATUS process_rate_update(void *pdev, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* process_sw_event() - process sw event pktlog buffers
|
||||
* @txrx_pdev: ol pdev handle
|
||||
* @data: pktlog buffer
|
||||
*
|
||||
* Return: 0 - success/non-zero - failure
|
||||
*/
|
||||
static inline
|
||||
A_STATUS process_sw_event(void *pdev, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
1192
qcom/opensource/wlan/qca-wifi-host-cmn/utils/pktlog/linux_ac.c
Normal file
1192
qcom/opensource/wlan/qca-wifi-host-cmn/utils/pktlog/linux_ac.c
Normal file
File diff suppressed because it is too large
Load Diff
1181
qcom/opensource/wlan/qca-wifi-host-cmn/utils/pktlog/pktlog_ac.c
Normal file
1181
qcom/opensource/wlan/qca-wifi-host-cmn/utils/pktlog/pktlog_ac.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (c) 2013-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.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef REMOVE_PKT_LOG
|
||||
#include "ol_txrx_types.h"
|
||||
#include "ol_htt_tx_api.h"
|
||||
#include "ol_tx_desc.h"
|
||||
#include "qdf_mem.h"
|
||||
#include "htt.h"
|
||||
#include "htt_internal.h"
|
||||
#include "pktlog_ac_i.h"
|
||||
#include "wma_api.h"
|
||||
#include "wlan_logging_sock_svc.h"
|
||||
|
||||
#ifdef PKTLOG_HAS_SPECIFIC_DATA
|
||||
void
|
||||
pktlog_hdr_set_specific_data(struct ath_pktlog_hdr *log_hdr,
|
||||
uint32_t type_specific_data)
|
||||
{
|
||||
log_hdr->type_specific_data = type_specific_data;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
pktlog_hdr_get_specific_data(struct ath_pktlog_hdr *log_hdr)
|
||||
{
|
||||
return log_hdr->type_specific_data;
|
||||
}
|
||||
|
||||
void
|
||||
pktlog_arg_set_specific_data(struct ath_pktlog_arg *plarg,
|
||||
uint32_t type_specific_data)
|
||||
{
|
||||
plarg->type_specific_data = type_specific_data;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
pktlog_arg_get_specific_data(struct ath_pktlog_arg *plarg)
|
||||
{
|
||||
return plarg->type_specific_data;
|
||||
}
|
||||
#endif /* PKTLOG_HAS_SPECIFIC_DATA */
|
||||
|
||||
void pktlog_getbuf_intsafe(struct ath_pktlog_arg *plarg)
|
||||
{
|
||||
struct ath_pktlog_buf *log_buf;
|
||||
int32_t buf_size;
|
||||
struct ath_pktlog_hdr *log_hdr;
|
||||
int32_t cur_wr_offset;
|
||||
char *log_ptr;
|
||||
struct ath_pktlog_info *pl_info;
|
||||
uint16_t log_type;
|
||||
size_t log_size;
|
||||
uint32_t flags;
|
||||
#ifdef HELIUMPLUS
|
||||
uint8_t mac_id;
|
||||
#endif
|
||||
|
||||
if (!plarg) {
|
||||
qdf_info("Invalid parg");
|
||||
return;
|
||||
}
|
||||
|
||||
pl_info = plarg->pl_info;
|
||||
#ifdef HELIUMPLUS
|
||||
mac_id = plarg->macId;
|
||||
log_type = plarg->log_type;
|
||||
#else
|
||||
log_type = plarg->log_type;
|
||||
#endif
|
||||
log_size = plarg->log_size;
|
||||
log_buf = pl_info->buf;
|
||||
flags = plarg->flags;
|
||||
|
||||
if (!log_buf) {
|
||||
qdf_info("Invalid log_buf");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
buf_size = pl_info->buf_size;
|
||||
cur_wr_offset = log_buf->wr_offset;
|
||||
/* Move read offset to the next entry if there is a buffer overlap */
|
||||
if (log_buf->rd_offset >= 0) {
|
||||
if ((cur_wr_offset <= log_buf->rd_offset)
|
||||
&& (cur_wr_offset + sizeof(struct ath_pktlog_hdr)) >
|
||||
log_buf->rd_offset) {
|
||||
PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf,
|
||||
buf_size);
|
||||
}
|
||||
} else {
|
||||
log_buf->rd_offset = cur_wr_offset;
|
||||
}
|
||||
|
||||
log_hdr = (struct ath_pktlog_hdr *)(log_buf->log_data + cur_wr_offset);
|
||||
|
||||
log_hdr->flags = flags;
|
||||
#ifdef HELIUMPLUS
|
||||
log_hdr->macId = mac_id;
|
||||
log_hdr->log_type = log_type;
|
||||
#else
|
||||
log_hdr->log_type = log_type;
|
||||
#endif
|
||||
log_hdr->size = (uint16_t) log_size;
|
||||
log_hdr->missed_cnt = plarg->missed_cnt;
|
||||
log_hdr->timestamp = plarg->timestamp;
|
||||
pktlog_hdr_set_specific_data(log_hdr,
|
||||
pktlog_arg_get_specific_data(plarg));
|
||||
cur_wr_offset += sizeof(*log_hdr);
|
||||
|
||||
if ((buf_size - cur_wr_offset) < log_size) {
|
||||
while ((cur_wr_offset <= log_buf->rd_offset)
|
||||
&& (log_buf->rd_offset < buf_size)) {
|
||||
PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf,
|
||||
buf_size);
|
||||
}
|
||||
cur_wr_offset = 0;
|
||||
}
|
||||
|
||||
while ((cur_wr_offset <= log_buf->rd_offset)
|
||||
&& (cur_wr_offset + log_size) > log_buf->rd_offset) {
|
||||
PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, buf_size);
|
||||
}
|
||||
|
||||
log_ptr = &(log_buf->log_data[cur_wr_offset]);
|
||||
cur_wr_offset += log_hdr->size;
|
||||
|
||||
log_buf->wr_offset = ((buf_size - cur_wr_offset) >=
|
||||
sizeof(struct ath_pktlog_hdr)) ? cur_wr_offset :
|
||||
0;
|
||||
|
||||
plarg->buf = log_ptr;
|
||||
}
|
||||
|
||||
char *pktlog_getbuf(struct pktlog_dev_t *pl_dev,
|
||||
struct ath_pktlog_info *pl_info,
|
||||
size_t log_size, struct ath_pktlog_hdr *pl_hdr)
|
||||
{
|
||||
struct ath_pktlog_arg plarg = { 0, };
|
||||
uint8_t flags = 0;
|
||||
|
||||
plarg.pl_info = pl_info;
|
||||
#ifdef HELIUMPLUS
|
||||
plarg.macId = pl_hdr->macId;
|
||||
plarg.log_type = pl_hdr->log_type;
|
||||
#else
|
||||
plarg.log_type = pl_hdr->log_type;
|
||||
#endif
|
||||
plarg.log_size = log_size;
|
||||
plarg.flags = pl_hdr->flags;
|
||||
plarg.missed_cnt = pl_hdr->missed_cnt;
|
||||
plarg.timestamp = pl_hdr->timestamp;
|
||||
pktlog_arg_set_specific_data(&plarg,
|
||||
pktlog_hdr_get_specific_data(pl_hdr));
|
||||
|
||||
if (flags & PHFLAGS_INTERRUPT_CONTEXT) {
|
||||
/*
|
||||
* We are already in interrupt context, no need to make it
|
||||
* intsafe. call the function directly.
|
||||
*/
|
||||
pktlog_getbuf_intsafe(&plarg);
|
||||
} else {
|
||||
PKTLOG_LOCK(pl_info);
|
||||
pktlog_getbuf_intsafe(&plarg);
|
||||
PKTLOG_UNLOCK(pl_info);
|
||||
}
|
||||
|
||||
return plarg.buf;
|
||||
}
|
||||
#endif /*REMOVE_PKT_LOG */
|
1196
qcom/opensource/wlan/qca-wifi-host-cmn/utils/pktlog/pktlog_wifi2.c
Normal file
1196
qcom/opensource/wlan/qca-wifi-host-cmn/utils/pktlog/pktlog_wifi2.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* Copyright (c) 2013-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.
|
||||
*/
|
||||
|
||||
/* WIFI3 - Refers to platforms - 6290/6390/6490 */
|
||||
#include "pktlog_wifi3.h"
|
||||
|
||||
#ifndef REMOVE_PKT_LOG
|
||||
A_STATUS
|
||||
process_offload_pktlog_wifi3(struct cdp_pdev *pdev, void *data)
|
||||
{
|
||||
struct pktlog_dev_t *pl_dev = get_pktlog_handle();
|
||||
struct ath_pktlog_info *pl_info;
|
||||
struct ath_pktlog_hdr pl_hdr;
|
||||
uint32_t *pl_tgt_hdr;
|
||||
void *txdesc_hdr_ctl = NULL;
|
||||
size_t log_size = 0;
|
||||
|
||||
if (!pl_dev) {
|
||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||
"Invalid context in %s\n", __func__);
|
||||
return A_ERROR;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||
"Invalid data in %s\n", __func__);
|
||||
return A_ERROR;
|
||||
}
|
||||
|
||||
pl_tgt_hdr = (uint32_t *)data;
|
||||
|
||||
pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) &
|
||||
ATH_PKTLOG_HDR_FLAGS_MASK) >>
|
||||
ATH_PKTLOG_HDR_FLAGS_SHIFT;
|
||||
pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) &
|
||||
ATH_PKTLOG_HDR_MISSED_CNT_MASK) >>
|
||||
ATH_PKTLOG_HDR_MISSED_CNT_SHIFT;
|
||||
pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) &
|
||||
ATH_PKTLOG_HDR_LOG_TYPE_MASK) >>
|
||||
ATH_PKTLOG_HDR_LOG_TYPE_SHIFT;
|
||||
pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) &
|
||||
ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT;
|
||||
pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET);
|
||||
|
||||
pktlog_hdr_set_specific_data(&pl_hdr,
|
||||
*(pl_tgt_hdr +
|
||||
ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET));
|
||||
if (pl_hdr.size > MAX_PKTLOG_RECV_BUF_SIZE) {
|
||||
pl_dev->invalid_packets++;
|
||||
return A_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Must include to process different types
|
||||
* TX_CTL, TX_STATUS, TX_MSDU_ID, TX_FRM_HDR
|
||||
*/
|
||||
pl_info = pl_dev->pl_info;
|
||||
log_size = pl_hdr.size;
|
||||
txdesc_hdr_ctl =
|
||||
(void *)pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr);
|
||||
if (!txdesc_hdr_ctl) {
|
||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||
"Failed to allocate pktlog descriptor");
|
||||
return A_NO_MEMORY;
|
||||
}
|
||||
qdf_assert(txdesc_hdr_ctl);
|
||||
qdf_assert(pl_hdr->size < PKTLOG_MAX_TX_WORDS * sizeof(u_int32_t));
|
||||
qdf_mem_copy(txdesc_hdr_ctl,
|
||||
((void *)data + sizeof(struct ath_pktlog_hdr)),
|
||||
pl_hdr.size);
|
||||
cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, txdesc_hdr_ctl);
|
||||
|
||||
return A_OK;
|
||||
}
|
||||
|
||||
int process_rx_desc_remote_wifi3(void *pdev, void *data)
|
||||
{
|
||||
struct pktlog_dev_t *pl_dev = get_pktlog_handle();
|
||||
struct ath_pktlog_hdr pl_hdr;
|
||||
struct ath_pktlog_rx_info rxstat_log;
|
||||
size_t log_size;
|
||||
struct ath_pktlog_info *pl_info;
|
||||
qdf_nbuf_t log_nbuf = (qdf_nbuf_t)data;
|
||||
|
||||
if (!pl_dev) {
|
||||
qdf_err("Pktlog handle is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pl_info = pl_dev->pl_info;
|
||||
qdf_mem_zero(&pl_hdr, sizeof(pl_hdr));
|
||||
pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S);
|
||||
pl_hdr.missed_cnt = 0;
|
||||
pl_hdr.log_type = PKTLOG_TYPE_RX_STATBUF;
|
||||
pl_hdr.size = qdf_nbuf_len(log_nbuf);
|
||||
pl_hdr.timestamp = 0;
|
||||
log_size = pl_hdr.size;
|
||||
rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info,
|
||||
log_size, &pl_hdr);
|
||||
|
||||
if (!rxstat_log.rx_desc) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG,
|
||||
"%s: Rx descriptor is NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qdf_mem_copy(rxstat_log.rx_desc, qdf_nbuf_data(log_nbuf), pl_hdr.size);
|
||||
cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
|
||||
rxstat_log.rx_desc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
process_pktlog_lite_wifi3(void *context, void *log_data,
|
||||
uint16_t log_type)
|
||||
{
|
||||
struct pktlog_dev_t *pl_dev = get_pktlog_handle();
|
||||
struct ath_pktlog_info *pl_info;
|
||||
struct ath_pktlog_hdr pl_hdr;
|
||||
struct ath_pktlog_rx_info rxstat_log;
|
||||
size_t log_size;
|
||||
qdf_nbuf_t log_nbuf = (qdf_nbuf_t)log_data;
|
||||
|
||||
if (!pl_dev) {
|
||||
qdf_err("Pktlog handle is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pl_info = pl_dev->pl_info;
|
||||
qdf_mem_zero(&pl_hdr, sizeof(pl_hdr));
|
||||
pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S);
|
||||
pl_hdr.missed_cnt = 0;
|
||||
pl_hdr.log_type = log_type;
|
||||
pl_hdr.size = qdf_nbuf_len(log_nbuf);
|
||||
pl_hdr.timestamp = 0;
|
||||
log_size = pl_hdr.size;
|
||||
rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info,
|
||||
log_size, &pl_hdr);
|
||||
if (!rxstat_log.rx_desc) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG,
|
||||
"%s: Rx descriptor is NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qdf_mem_copy(rxstat_log.rx_desc, qdf_nbuf_data(log_nbuf), pl_hdr.size);
|
||||
|
||||
cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc);
|
||||
return 0;
|
||||
}
|
||||
#endif /* REMOVE_PKT_LOG */
|
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2018,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.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* wlan_ptt_sock_svc.c
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef PTT_SOCK_SVC_H
|
||||
#define PTT_SOCK_SVC_H
|
||||
#include <wlan_nlink_srv.h>
|
||||
#include <qdf_types.h>
|
||||
#include <qdf_status.h>
|
||||
#include <qdf_trace.h>
|
||||
|
||||
/*
|
||||
* Quarky Message Format:
|
||||
* The following is the messaging protocol between Quarky and PTT Socket App.
|
||||
* The totalMsgLen is the length from Radio till msgBody. The value of Radio
|
||||
* is always defaulted to 0. The MsgLen is the length from msgId till msgBody.
|
||||
* The length of the msgBody varies with respect to the MsgId. Buffer space
|
||||
* for MsgBody is already allocated in the received buffer. So in case of READ
|
||||
* we just need to populate the values in the received message and send it
|
||||
* back
|
||||
* +------------+-------+-------+--------+-------+---------+
|
||||
* |TotalMsgLen | Radio | MsgId | MsgLen |Status |MsgBody |
|
||||
* +------------+-------+-------|--------+-------+---------+
|
||||
* <------4----><--4---><---2--><---2---><---4--><--------->
|
||||
*/
|
||||
/* PTT Socket App Message Ids */
|
||||
#define PTT_MSG_READ_REGISTER 0x3040
|
||||
#define PTT_MSG_WRITE_REGISTER 0x3041
|
||||
#define PTT_MSG_READ_MEMORY 0x3044
|
||||
#define PTT_MSG_WRITE_MEMORY 0x3045
|
||||
#define PTT_MSG_LOG_DUMP_DBG 0x32A1
|
||||
#define PTT_MSG_FTM_CMDS_TYPE 0x4040
|
||||
#define ANI_DRIVER_MSG_START 0x0001
|
||||
#define ANI_MSG_APP_REG_REQ (ANI_DRIVER_MSG_START + 0)
|
||||
#define ANI_MSG_APP_REG_RSP (ANI_DRIVER_MSG_START + 1)
|
||||
#define ANI_MSG_OEM_DATA_REQ (ANI_DRIVER_MSG_START + 2)
|
||||
#define ANI_MSG_OEM_DATA_RSP (ANI_DRIVER_MSG_START + 3)
|
||||
#define ANI_MSG_CHANNEL_INFO_REQ (ANI_DRIVER_MSG_START + 4)
|
||||
#define ANI_MSG_CHANNEL_INFO_RSP (ANI_DRIVER_MSG_START + 5)
|
||||
#define ANI_MSG_OEM_ERROR (ANI_DRIVER_MSG_START + 6)
|
||||
#define ANI_MSG_PEER_STATUS_IND (ANI_DRIVER_MSG_START + 7)
|
||||
#define ANI_MSG_SET_OEM_CAP_REQ (ANI_DRIVER_MSG_START + 8)
|
||||
#define ANI_MSG_SET_OEM_CAP_RSP (ANI_DRIVER_MSG_START + 9)
|
||||
#define ANI_MSG_GET_OEM_CAP_REQ (ANI_DRIVER_MSG_START + 10)
|
||||
#define ANI_MSG_GET_OEM_CAP_RSP (ANI_DRIVER_MSG_START + 11)
|
||||
|
||||
#define ANI_MAX_RADIOS 3
|
||||
#define ANI_NL_MSG_OK 0
|
||||
#define ANI_NL_MSG_ERROR -1
|
||||
#define ANI_NL_MSG_OVERHEAD (NLMSG_SPACE(tAniHdr + 4))
|
||||
/*
|
||||
* Packet Format for READ_REGISTER & WRITE_REGISTER:
|
||||
* TotalMsgLen : 4 bytes [value=20 bytes]
|
||||
* Radio : 4 bytes
|
||||
* MsgId : 2 bytes
|
||||
* MsgLen : 2 bytes
|
||||
* Status : 4 bytes
|
||||
* Address : 4 bytes
|
||||
* Payload : 4 bytes
|
||||
*/
|
||||
/*
|
||||
* Packet Format for READ_MEMORY & WRITE_MEMORY :
|
||||
* TotalMsgLen : 4 bytes [value= 20+LEN_PAYLOAD bytes]
|
||||
* Radio : 4 bytes
|
||||
* MsgId : 2 bytes
|
||||
* MsgLen : 2 bytes
|
||||
* Status : 4 bytes
|
||||
* Address : 4 bytes
|
||||
* Length : 4 bytes [LEN_PAYLOAD]
|
||||
* Payload : LEN_PAYLOAD bytes
|
||||
*/
|
||||
#if defined(PTT_SOCK_SVC_ENABLE) && defined(CNSS_GENL)
|
||||
/**
|
||||
* ptt_sock_activate_svc() - API to register PTT/PUMAC command handlers
|
||||
*
|
||||
* API to register the handler for PTT/PUMAC NL messages.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void ptt_sock_activate_svc(void);
|
||||
|
||||
/**
|
||||
* ptt_sock_deactivate_svc() - API to deregister PTT/PUMAC command handlers
|
||||
*
|
||||
* API to deregister the handler for PTT/PUMAC NL messages.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void ptt_sock_deactivate_svc(void);
|
||||
|
||||
#else
|
||||
static inline void ptt_sock_activate_svc(void)
|
||||
{
|
||||
}
|
||||
static inline void ptt_sock_deactivate_svc(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
int ptt_sock_send_msg_to_app(tAniHdr *wmsg, int radio, int src_mod, int pid);
|
||||
/*
|
||||
* Format of message exchanged between the PTT Socket App in userspace and the
|
||||
* WLAN Driver, in either direction. Each msg will begin with this header and
|
||||
* will followed by the Quarky message
|
||||
*/
|
||||
struct sAniAppRegReq {
|
||||
tAniNlModTypes type; /* module id */
|
||||
int pid; /* process id */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sptt_app_reg_req - PTT register request structure
|
||||
* @radio: Radio ID
|
||||
* @wmsg: ANI header
|
||||
*
|
||||
* payload structure received as nl data from PTT app/user space
|
||||
*/
|
||||
struct sptt_app_reg_req {
|
||||
int radio;
|
||||
tAniHdr wmsg;
|
||||
};
|
||||
|
||||
struct sAniNlAppRegRsp {
|
||||
tAniHdr wniHdr; /* Generic WNI msg header */
|
||||
struct sAniAppRegReq regReq; /* The original request msg */
|
||||
int ret; /* Return code */
|
||||
};
|
||||
#endif
|
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. 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.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* wlan_ptt_sock_svc.c
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifdef PTT_SOCK_SVC_ENABLE
|
||||
#include <wlan_nlink_srv.h>
|
||||
#include <qdf_types.h>
|
||||
#include <qdf_status.h>
|
||||
#include <qdf_trace.h>
|
||||
#include <wlan_nlink_common.h>
|
||||
#include <wlan_ptt_sock_svc.h>
|
||||
#include <qdf_types.h>
|
||||
#include <qdf_trace.h>
|
||||
|
||||
#ifdef CNSS_GENL
|
||||
#ifdef CONFIG_CNSS_OUT_OF_TREE
|
||||
#include "cnss_nl.h"
|
||||
#else
|
||||
#include <net/cnss_nl.h>
|
||||
#endif
|
||||
#include <wlan_cfg80211.h>
|
||||
#endif
|
||||
|
||||
#define PTT_SOCK_DEBUG
|
||||
#ifdef PTT_SOCK_DEBUG
|
||||
#define PTT_TRACE(level, args ...) QDF_TRACE(QDF_MODULE_ID_QDF, level, ## args)
|
||||
#else
|
||||
#define PTT_TRACE(level, args ...)
|
||||
#endif
|
||||
|
||||
#ifdef PTT_SOCK_DEBUG_VERBOSE
|
||||
/* Utility function to perform a hex dump */
|
||||
static void ptt_sock_dump_buf(const unsigned char *pbuf, int cnt)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
if ((i % 16) == 0)
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO,
|
||||
"\n%pK:", pbuf);
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, " %02X",
|
||||
*pbuf);
|
||||
pbuf++;
|
||||
}
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* nl_srv_ucast_ptt() - Wrapper function to send ucast msgs to PTT
|
||||
* @skb: sk buffer pointer
|
||||
* @dst_pid: Destination PID
|
||||
* @flag: flags
|
||||
*
|
||||
* Sends the ucast message to PTT with generic nl socket if CNSS_GENL
|
||||
* is enabled. Else, use the legacy netlink socket to send.
|
||||
*
|
||||
* Return: zero on success, error code otherwise
|
||||
*/
|
||||
static int nl_srv_ucast_ptt(struct sk_buff *skb, int dst_pid, int flag)
|
||||
{
|
||||
#ifdef CNSS_GENL
|
||||
return nl_srv_ucast(skb, dst_pid, flag, ANI_NL_MSG_PUMAC,
|
||||
CLD80211_MCGRP_DIAG_EVENTS);
|
||||
#else
|
||||
return nl_srv_ucast(skb, dst_pid, flag);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_bcast_ptt() - Wrapper function to send bcast msgs to DIAG mcast group
|
||||
* @skb: sk buffer pointer
|
||||
*
|
||||
* Sends the bcast message to DIAG multicast group with generic nl socket
|
||||
* if CNSS_GENL is enabled. Else, use the legacy netlink socket to send.
|
||||
*
|
||||
* Return: zero on success, error code otherwise
|
||||
*/
|
||||
static int nl_srv_bcast_ptt(struct sk_buff *skb)
|
||||
{
|
||||
#ifdef CNSS_GENL
|
||||
return nl_srv_bcast(skb, CLD80211_MCGRP_DIAG_EVENTS, ANI_NL_MSG_PUMAC);
|
||||
#else
|
||||
return nl_srv_bcast(skb);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* ptt_sock_send_msg_to_app() - Send nl message to user space
|
||||
* wmsg: Message header
|
||||
* radio: Unit number of the radio
|
||||
* src_mod: Message type
|
||||
* pid: Process ID to which message will be unicast. Message
|
||||
* will be broadcast when PID is INVALID_PID
|
||||
*
|
||||
* Utility function to send a netlink message to an application in user space
|
||||
*
|
||||
* Return: 0 on success and negative value on failure
|
||||
*/
|
||||
int ptt_sock_send_msg_to_app(tAniHdr *wmsg, int radio, int src_mod, int pid)
|
||||
{
|
||||
int err = -1;
|
||||
int payload_len;
|
||||
int tot_msg_len;
|
||||
tAniNlHdr *wnl;
|
||||
struct sk_buff *skb;
|
||||
struct nlmsghdr *nlh;
|
||||
int wmsg_length = be16_to_cpu(wmsg->length);
|
||||
static int nlmsg_seq;
|
||||
|
||||
if (radio < 0 || radio > ANI_MAX_RADIOS) {
|
||||
PTT_TRACE(QDF_TRACE_LEVEL_ERROR, "%s: invalid radio id [%d]\n",
|
||||
__func__, radio);
|
||||
return -EINVAL;
|
||||
}
|
||||
payload_len = wmsg_length + sizeof(wnl->radio) + sizeof(*wmsg);
|
||||
tot_msg_len = NLMSG_SPACE(payload_len);
|
||||
skb = dev_alloc_skb(tot_msg_len);
|
||||
if (!skb) {
|
||||
PTT_TRACE(QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: dev_alloc_skb() failed for msg size[%d]\n",
|
||||
__func__, tot_msg_len);
|
||||
return -ENOMEM;
|
||||
}
|
||||
nlh =
|
||||
nlmsg_put(skb, pid, nlmsg_seq++, src_mod, payload_len,
|
||||
NLM_F_REQUEST);
|
||||
if (!nlh) {
|
||||
PTT_TRACE(QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: nlmsg_put() failed for msg size[%d]\n", __func__,
|
||||
tot_msg_len);
|
||||
kfree_skb(skb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
wnl = (tAniNlHdr *) nlh;
|
||||
wnl->radio = radio;
|
||||
|
||||
/* Offset of data buffer from nlmsg_hdr + sizeof(int) radio */
|
||||
memcpy(nlmsg_data(nlh) + sizeof(wnl->radio), wmsg, wmsg_length);
|
||||
#ifdef PTT_SOCK_DEBUG_VERBOSE
|
||||
ptt_sock_dump_buf((const unsigned char *)skb->data, skb->len);
|
||||
#endif
|
||||
|
||||
if (pid != INVALID_PID)
|
||||
err = nl_srv_ucast_ptt(skb, pid, MSG_DONTWAIT);
|
||||
else
|
||||
err = nl_srv_bcast_ptt(skb);
|
||||
|
||||
if ((err < 0) && (err != -ESRCH))
|
||||
PTT_TRACE(QDF_TRACE_LEVEL_INFO,
|
||||
"%s:Failed sending Msg Type [0x%X] to pid[%d]\n",
|
||||
__func__, be16_to_cpu(wmsg->type), pid);
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CNSS_GENL
|
||||
/**
|
||||
* ptt_cmd_handler() - Handler function for PTT commands
|
||||
* @data: Data to be parsed
|
||||
* @data_len: Length of the data received
|
||||
* @ctx: Registered context reference
|
||||
* @pid: Process id of the user space application
|
||||
*
|
||||
* This function handles the command from PTT user space application
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void ptt_cmd_handler(const void *data, int data_len, void *ctx, int pid)
|
||||
{
|
||||
uint16_t length;
|
||||
struct sptt_app_reg_req *payload;
|
||||
struct nlattr *tb[CLD80211_ATTR_MAX + 1];
|
||||
|
||||
/*
|
||||
* audit note: it is ok to pass a NULL policy here since a
|
||||
* length check on the data is added later already
|
||||
*/
|
||||
if (wlan_cfg80211_nla_parse(tb, CLD80211_ATTR_MAX,
|
||||
data, data_len, NULL)) {
|
||||
PTT_TRACE(QDF_TRACE_LEVEL_ERROR, "Invalid ATTR");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tb[CLD80211_ATTR_DATA]) {
|
||||
PTT_TRACE(QDF_TRACE_LEVEL_ERROR, "attr ATTR_DATA failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (nla_len(tb[CLD80211_ATTR_DATA]) < sizeof(struct sptt_app_reg_req)) {
|
||||
PTT_TRACE(QDF_TRACE_LEVEL_ERROR, "%s:attr length check fails\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
payload = (struct sptt_app_reg_req *)(nla_data(tb[CLD80211_ATTR_DATA]));
|
||||
length = be16_to_cpu(payload->wmsg.length);
|
||||
if ((USHRT_MAX - length) < (sizeof(payload->radio) + sizeof(tAniHdr))) {
|
||||
PTT_TRACE(QDF_TRACE_LEVEL_ERROR,
|
||||
"u16 overflow length %d %zu %zu",
|
||||
length,
|
||||
sizeof(payload->radio),
|
||||
sizeof(tAniHdr));
|
||||
return;
|
||||
}
|
||||
|
||||
if (nla_len(tb[CLD80211_ATTR_DATA]) < (length +
|
||||
sizeof(payload->radio) +
|
||||
sizeof(tAniHdr))) {
|
||||
PTT_TRACE(QDF_TRACE_LEVEL_ERROR, "ATTR_DATA len check failed");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (payload->wmsg.type) {
|
||||
case ANI_MSG_APP_REG_REQ:
|
||||
ptt_sock_send_msg_to_app(&payload->wmsg, payload->radio,
|
||||
ANI_NL_MSG_PUMAC, pid);
|
||||
break;
|
||||
default:
|
||||
PTT_TRACE(QDF_TRACE_LEVEL_ERROR, "Unknown msg type %d",
|
||||
payload->wmsg.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ptt_sock_activate_svc(void)
|
||||
{
|
||||
register_cld_cmd_cb(ANI_NL_MSG_PUMAC, ptt_cmd_handler, NULL);
|
||||
register_cld_cmd_cb(ANI_NL_MSG_PTT, ptt_cmd_handler, NULL);
|
||||
}
|
||||
|
||||
void ptt_sock_deactivate_svc(void)
|
||||
{
|
||||
deregister_cld_cmd_cb(ANI_NL_MSG_PTT);
|
||||
deregister_cld_cmd_cb(ANI_NL_MSG_PUMAC);
|
||||
}
|
||||
#endif
|
||||
#endif /* PTT_SOCK_SVC_ENABLE */
|
115
qcom/opensource/wlan/qca-wifi-host-cmn/utils/qld/inc/qld_api.h
Normal file
115
qcom/opensource/wlan/qca-wifi-host-cmn/utils/qld/inc/qld_api.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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: qld_api.h
|
||||
* QLD: This file provides public exposed functions
|
||||
*/
|
||||
|
||||
#ifndef _QLD_API_H_
|
||||
#define _QLD_API_H_
|
||||
|
||||
#define QLD_MAX_NAME 48
|
||||
|
||||
/**
|
||||
* struct qld_entry - Individual entry in qld_event
|
||||
* @addr: Start address of object to dump
|
||||
* @size: Size of memory dump
|
||||
* @name: Name of memory dump
|
||||
*/
|
||||
struct qld_entry {
|
||||
uint64_t addr;
|
||||
size_t size;
|
||||
char name[QLD_MAX_NAME];
|
||||
};
|
||||
|
||||
/**
|
||||
* typedef qld_iter_func - qld callback function
|
||||
* @req: opaque pointer
|
||||
* @qld_entry: qld_entry
|
||||
*
|
||||
* Return: 0 - OK -EINVAL - On failure
|
||||
*/
|
||||
typedef int (*qld_iter_func)(void *req, struct qld_entry *entry);
|
||||
|
||||
/**
|
||||
* qld_iterate_list() - qld list iteration routine
|
||||
* @gen_table: callback function to generate table
|
||||
* @req: opaque request
|
||||
*
|
||||
* Return: 0 - OK -EINVAL - On failure
|
||||
*/
|
||||
int qld_iterate_list(qld_iter_func gen_table, void *req);
|
||||
|
||||
/**
|
||||
* qld_register() - Register qld for the given address
|
||||
* @addr: starting address the dump
|
||||
* @size: size of memory to dump
|
||||
* @name: name identifier of dump
|
||||
*
|
||||
* Return: 0 - OK -EINVAL -ENOMEM - On failure
|
||||
*/
|
||||
int qld_register(void *addr, size_t size, char *name);
|
||||
|
||||
/**
|
||||
* qld_unregister() - Un-register qld for the given address
|
||||
* @addr: starting address the dump
|
||||
*
|
||||
* Return: 0 - OK -EINVAL - On failure
|
||||
*/
|
||||
int qld_unregister(void *addr);
|
||||
|
||||
/**
|
||||
* qld_list_init() - Initialize qld list
|
||||
* @max_list: maximum size list supports
|
||||
*
|
||||
* Return: 0 - OK -EINVAL -ENOMEM - On failure
|
||||
*/
|
||||
int qld_list_init(uint32_t max_list);
|
||||
|
||||
/**
|
||||
* qld_list_delete() - empty qld list
|
||||
*
|
||||
* Return: 0 - OK -EINVAL - On failure
|
||||
*/
|
||||
int qld_list_delete(void);
|
||||
|
||||
/**
|
||||
* qld_list_deinit() - De-initialize qld list
|
||||
*
|
||||
* Return: 0 - OK -EINVAL - On failure
|
||||
*/
|
||||
int qld_list_deinit(void);
|
||||
|
||||
/**
|
||||
* qld_get_list_count () - get size of qld list
|
||||
* @list_count: list_count to set
|
||||
*
|
||||
* Return: 0 - OK -EINVAL - On failure
|
||||
*/
|
||||
int qld_get_list_count(uint32_t *list_count);
|
||||
|
||||
/**
|
||||
* is_qld_enable() - check if qld feature is set
|
||||
*
|
||||
* Return: true on success, false on failure
|
||||
*/
|
||||
bool is_qld_enable(void);
|
||||
|
||||
#endif /* _QLD_API_H_ */
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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: qld_priv.h
|
||||
* QLD: This file provides Private functions for qld
|
||||
*/
|
||||
|
||||
#ifndef _QLD_PRIV_H_
|
||||
#define _QLD_PRIV_H_
|
||||
|
||||
#include <qdf_lock.h>
|
||||
#include <qdf_list.h>
|
||||
#include <qld_api.h>
|
||||
|
||||
#define qld_alert(format, args...) \
|
||||
QDF_TRACE_FATAL(QDF_MODULE_ID_QLD, format, ## args)
|
||||
|
||||
#define qld_err(format, args...) \
|
||||
QDF_TRACE_ERROR(QDF_MODULE_ID_QLD, format, ## args)
|
||||
|
||||
#define qld_warn(format, args...) \
|
||||
QDF_TRACE_WARN(QDF_MODULE_ID_QLD, format, ## args)
|
||||
|
||||
#define qld_info(format, args...) \
|
||||
QDF_TRACE_INFO(QDF_MODULE_ID_QLD, format, ## args)
|
||||
|
||||
#define qld_debug(format, args...) \
|
||||
QDF_TRACE_DEBUG(QDF_MODULE_ID_QLD, format, ## args)
|
||||
|
||||
/**
|
||||
* struct qld_list_handle - Top level qld structure
|
||||
* @qld_lock: Spinlock for structure
|
||||
* @qld_list: linked list for linking
|
||||
* @qld_max_list: maximum list size
|
||||
*/
|
||||
struct qld_list_handle {
|
||||
qdf_spinlock_t qld_lock;
|
||||
qdf_list_t qld_list;
|
||||
uint32_t qld_max_list;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct qld_node - qld node
|
||||
* @node: single node of linked list
|
||||
* @entry: single qld_entry in list
|
||||
*/
|
||||
struct qld_node {
|
||||
qdf_list_node_t node;
|
||||
struct qld_entry entry;
|
||||
};
|
||||
|
||||
#endif /*_QLD_PRIV_H_*/
|
207
qcom/opensource/wlan/qca-wifi-host-cmn/utils/qld/src/qld.c
Normal file
207
qcom/opensource/wlan/qca-wifi-host-cmn/utils/qld/src/qld.c
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) 2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. 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: qld
|
||||
* QLD: main file of QCA Live Dump (QLD)
|
||||
*/
|
||||
|
||||
#include "qld_priv.h"
|
||||
#include "qld_api.h"
|
||||
#include "qdf_module.h"
|
||||
|
||||
/* Handle for qld structure */
|
||||
static struct qld_list_handle *qld_handle;
|
||||
|
||||
bool is_qld_enable(void)
|
||||
{
|
||||
if (!qld_handle)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
qdf_export_symbol(is_qld_enable);
|
||||
|
||||
int qld_list_init(uint32_t max_list)
|
||||
{
|
||||
if (!max_list)
|
||||
return -EINVAL;
|
||||
|
||||
qld_handle = qdf_mem_malloc(sizeof(*qld_handle));
|
||||
|
||||
if (!qld_handle)
|
||||
return -ENOMEM;
|
||||
|
||||
qdf_spinlock_create(&qld_handle->qld_lock);
|
||||
qld_handle->qld_max_list = max_list;
|
||||
qdf_list_create(&qld_handle->qld_list, qld_handle->qld_max_list);
|
||||
qld_debug("LIST init with max size of %u", qld_handle->qld_max_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
qdf_export_symbol(qld_list_init);
|
||||
|
||||
int qld_list_deinit(void)
|
||||
{
|
||||
if (!qld_handle) {
|
||||
qld_err("Handle NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Delete the list */
|
||||
qld_list_delete();
|
||||
qdf_list_destroy(&qld_handle->qld_list);
|
||||
qdf_spinlock_destroy(&qld_handle->qld_lock);
|
||||
qdf_mem_free(qld_handle);
|
||||
qld_handle = NULL;
|
||||
qld_debug("LIST De-initialized");
|
||||
return 0;
|
||||
}
|
||||
|
||||
qdf_export_symbol(qld_list_deinit);
|
||||
|
||||
int qld_list_delete(void)
|
||||
{
|
||||
struct qld_node *qld;
|
||||
qdf_list_node_t *node = NULL;
|
||||
qdf_list_t *list;
|
||||
|
||||
if (!qld_handle) {
|
||||
qld_err("Handle NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
list = &qld_handle->qld_list;
|
||||
qdf_spinlock_acquire(&qld_handle->qld_lock);
|
||||
/* Check and remove the elements of list */
|
||||
while (qdf_list_remove_front(list, &node) == QDF_STATUS_SUCCESS) {
|
||||
qld = qdf_container_of(node, struct qld_node, node);
|
||||
qdf_mem_free(qld);
|
||||
}
|
||||
qdf_spinlock_release(&qld_handle->qld_lock);
|
||||
qld_debug("LIST Emptied");
|
||||
return 0;
|
||||
}
|
||||
|
||||
qdf_export_symbol(qld_list_delete);
|
||||
|
||||
int qld_register(void *addr, size_t size, char *name)
|
||||
{
|
||||
struct qld_node *qld;
|
||||
uint32_t list_count = 0;
|
||||
|
||||
if (!qld_handle || !addr) {
|
||||
qld_debug("Handle or address is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((qld_get_list_count(&list_count) != 0)) {
|
||||
qdf_err("QLD: Invalid list count");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (list_count >= qld_handle->qld_max_list) {
|
||||
qld_err("List full,reg failed.Increase list size");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Check if data is already registered */
|
||||
qdf_spinlock_acquire(&qld_handle->qld_lock);
|
||||
qdf_list_for_each(&qld_handle->qld_list, qld, node) {
|
||||
if (qld->entry.addr == (uintptr_t)addr) {
|
||||
qld_err("%s already registered", qld->entry.name);
|
||||
qdf_spinlock_release(&qld_handle->qld_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
qdf_spinlock_release(&qld_handle->qld_lock);
|
||||
qld = qdf_mem_malloc(sizeof(*qld));
|
||||
if (!qld)
|
||||
return -ENOMEM;
|
||||
|
||||
qld_debug("Insert addr=%pK size=%zu name=%s", (void *)addr, size, name);
|
||||
qdf_spinlock_acquire(&qld_handle->qld_lock);
|
||||
qld->entry.addr = (uintptr_t)addr;
|
||||
qld->entry.size = size;
|
||||
qdf_snprintf(qld->entry.name, sizeof(qld->entry.name), "%s", name);
|
||||
qdf_list_insert_front(&qld_handle->qld_list, &qld->node);
|
||||
qdf_spinlock_release(&qld_handle->qld_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
qdf_export_symbol(qld_register);
|
||||
|
||||
int qld_unregister(void *addr)
|
||||
{
|
||||
struct qld_node *qld = NULL;
|
||||
struct qld_node *cur_entry;
|
||||
|
||||
if (!qld_handle || !addr) {
|
||||
qld_err("Handle or address is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
qdf_spinlock_acquire(&qld_handle->qld_lock);
|
||||
qdf_list_for_each(&qld_handle->qld_list, cur_entry, node) {
|
||||
if (cur_entry->entry.addr == (uintptr_t)addr) {
|
||||
qld = cur_entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (qld) {
|
||||
qdf_list_remove_node(&qld_handle->qld_list, &qld->node);
|
||||
qld_debug("Delete name=%s, size=%zu", qld->entry.name,
|
||||
qld->entry.size);
|
||||
qdf_mem_free(qld);
|
||||
}
|
||||
qdf_spinlock_release(&qld_handle->qld_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
qdf_export_symbol(qld_unregister);
|
||||
|
||||
int qld_iterate_list(qld_iter_func gen_table, void *qld_req)
|
||||
{
|
||||
struct qld_node *qld = NULL;
|
||||
|
||||
if (!qld_handle)
|
||||
return -EINVAL;
|
||||
|
||||
if (!qld_req || !gen_table) {
|
||||
qld_err("req buffer or func is NULL %s", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
qdf_spinlock_acquire(&qld_handle->qld_lock);
|
||||
qdf_list_for_each(&qld_handle->qld_list, qld, node) {
|
||||
(gen_table)(qld_req, &qld->entry);
|
||||
}
|
||||
qdf_spinlock_release(&qld_handle->qld_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
qdf_export_symbol(qld_iterate_list);
|
||||
|
||||
int qld_get_list_count(uint32_t *list_count)
|
||||
{
|
||||
if (!qld_handle) {
|
||||
qld_err("Handle NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
*list_count = qld_handle->qld_list.count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
qdf_export_symbol(qld_get_list_count);
|
592
qcom/opensource/wlan/qca-wifi-host-cmn/utils/sys/queue.h
Normal file
592
qcom/opensource/wlan/qca-wifi-host-cmn/utils/sys/queue.h
Normal file
@@ -0,0 +1,592 @@
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||
* $FreeBSD: src/sys/sys/queue.h,v 1.58 2004/04/07 04:19:49 imp Exp $
|
||||
*/
|
||||
|
||||
#ifndef _QUEUE_H_
|
||||
#define _QUEUE_H_
|
||||
|
||||
/*
|
||||
* This file defines four types of data structures: singly-linked lists,
|
||||
* singly-linked tail queues, lists and tail queues.
|
||||
*
|
||||
* A singly-linked list is headed by a single forward pointer. The elements
|
||||
* are singly linked for minimum space and pointer manipulation overhead at
|
||||
* the expense of O(n) removal for arbitrary elements. New elements can be
|
||||
* added to the list after an existing element or at the head of the list.
|
||||
* Elements being removed from the head of the list should use the explicit
|
||||
* macro for this purpose for optimum efficiency. A singly-linked list may
|
||||
* only be traversed in the forward direction. Singly-linked lists are ideal
|
||||
* for applications with large datasets and few or no removals or for
|
||||
* implementing a LIFO queue.
|
||||
*
|
||||
* A singly-linked tail queue is headed by a pair of pointers, one to the
|
||||
* head of the list and the other to the tail of the list. The elements are
|
||||
* singly linked for minimum space and pointer manipulation overhead at the
|
||||
* expense of O(n) removal for arbitrary elements. New elements can be added
|
||||
* to the list after an existing element, at the head of the list, or at the
|
||||
* end of the list. Elements being removed from the head of the tail queue
|
||||
* should use the explicit macro for this purpose for optimum efficiency.
|
||||
* A singly-linked tail queue may only be traversed in the forward direction.
|
||||
* Singly-linked tail queues are ideal for applications with large datasets
|
||||
* and few or no removals or for implementing a FIFO queue.
|
||||
*
|
||||
* A list is headed by a single forward pointer (or an array of forward
|
||||
* pointers for a hash table header). The elements are doubly linked
|
||||
* so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before
|
||||
* or after an existing element or at the head of the list. A list
|
||||
* may only be traversed in the forward direction.
|
||||
*
|
||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or
|
||||
* after an existing element, at the head of the list, or at the end of
|
||||
* the list. A tail queue may be traversed in either direction.
|
||||
*
|
||||
* For details on the use of these macros, see the queue(3) manual page.
|
||||
*
|
||||
*
|
||||
* SLIST LIST STAILQ TAILQ
|
||||
* _HEAD + + + +
|
||||
* _HEAD_INITIALIZER + + + +
|
||||
* _ENTRY + + + +
|
||||
* _INIT + + + +
|
||||
* _EMPTY + + + +
|
||||
* _FIRST + + + +
|
||||
* _NEXT + + + +
|
||||
* _PREV - - - +
|
||||
* _LAST - - + +
|
||||
* _FOREACH + + + +
|
||||
* _FOREACH_SAFE + + + +
|
||||
* _FOREACH_REVERSE - - - +
|
||||
* _FOREACH_REVERSE_SAFE - - - +
|
||||
* _INSERT_HEAD + + + +
|
||||
* _INSERT_BEFORE - + - +
|
||||
* _INSERT_AFTER + + + +
|
||||
* _INSERT_TAIL - - + +
|
||||
* _CONCAT - - + +
|
||||
* _REMOVE_HEAD + - + -
|
||||
* _REMOVE + + + +
|
||||
*
|
||||
*/
|
||||
#define QUEUE_MACRO_DEBUG 0
|
||||
#if QUEUE_MACRO_DEBUG
|
||||
/*
|
||||
* Store the last 2 places the queue element or head was altered
|
||||
*/
|
||||
struct qm_trace {
|
||||
char *lastfile;
|
||||
int lastline;
|
||||
char *prevfile;
|
||||
int prevline;
|
||||
};
|
||||
|
||||
#define TRACEBUF struct qm_trace trace;
|
||||
#define TRASHIT(x) do {(x) = (void *)NULL; } while (0)
|
||||
|
||||
#define QMD_TRACE_HEAD(head) do { \
|
||||
(head)->trace.prevline = (head)->trace.lastline; \
|
||||
(head)->trace.prevfile = (head)->trace.lastfile; \
|
||||
(head)->trace.lastline = __LINE__; \
|
||||
(head)->trace.lastfile = __FILE__; \
|
||||
} while (0)
|
||||
|
||||
#define QMD_TRACE_ELEM(elem) do { \
|
||||
(elem)->trace.prevline = (elem)->trace.lastline; \
|
||||
(elem)->trace.prevfile = (elem)->trace.lastfile; \
|
||||
(elem)->trace.lastline = __LINE__; \
|
||||
(elem)->trace.lastfile = __FILE__; \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define QMD_TRACE_ELEM(elem)
|
||||
#define QMD_TRACE_HEAD(head)
|
||||
#define TRACEBUF
|
||||
#define TRASHIT(x) do {(x) = (void *)0; } while (0)
|
||||
#endif /* QUEUE_MACRO_DEBUG */
|
||||
|
||||
#ifdef ATHR_RNWF
|
||||
/*
|
||||
* NDIS contains a defn for SLIST_ENTRY and SINGLE_LIST_ENTRY
|
||||
*/
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Singly-linked List declarations.
|
||||
*/
|
||||
#define SLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *slh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define SLIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define SING_LIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sle_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked List functions.
|
||||
*/
|
||||
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
|
||||
|
||||
#define SLIST_FIRST(head) ((head)->slh_first)
|
||||
|
||||
#define SLIST_FOREACH(var, head, field) \
|
||||
for ((var) = SLIST_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = SLIST_NEXT((var), field))
|
||||
|
||||
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = SLIST_FIRST((head)); \
|
||||
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
|
||||
for ((varp) = &SLIST_FIRST((head)); \
|
||||
((var) = *(varp)) != NULL; \
|
||||
(varp) = &SLIST_NEXT((var), field))
|
||||
|
||||
#define SLIST_INIT(head) do { \
|
||||
SLIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
||||
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
|
||||
SLIST_NEXT((slistelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_HEAD(head, elm, field) do { \
|
||||
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
|
||||
SLIST_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||
|
||||
#define SLIST_REMOVE(head, elm, type, field) do { \
|
||||
if (SLIST_FIRST((head)) == (elm)) { \
|
||||
SLIST_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = SLIST_FIRST((head)); \
|
||||
while (SLIST_NEXT(curelm, field) != (elm)) \
|
||||
curelm = SLIST_NEXT(curelm, field); \
|
||||
SLIST_NEXT(curelm, field) = \
|
||||
SLIST_NEXT(SLIST_NEXT(curelm, field), field);\
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE_HEAD(head, field) do { \
|
||||
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), \
|
||||
field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue declarations.
|
||||
*/
|
||||
#define STAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *stqh_first; \
|
||||
struct type **stqh_last; \
|
||||
}
|
||||
|
||||
#define STAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).stqh_first }
|
||||
|
||||
#define STAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *stqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue functions.
|
||||
*/
|
||||
#define STAILQ_CONCAT(head1, head2) do { \
|
||||
if (!STAILQ_EMPTY((head2))) { \
|
||||
*(head1)->stqh_last = (head2)->stqh_first; \
|
||||
(head1)->stqh_last = (head2)->stqh_last; \
|
||||
STAILQ_INIT((head2)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
|
||||
|
||||
#define STAILQ_FIRST(head) ((head)->stqh_first)
|
||||
|
||||
#define STAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = STAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = STAILQ_NEXT((var), field))
|
||||
|
||||
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = STAILQ_FIRST((head)); \
|
||||
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define STAILQ_INIT(head) do { \
|
||||
STAILQ_FIRST((head)) = NULL; \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
|
||||
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), \
|
||||
field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
STAILQ_NEXT((tqelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == \
|
||||
NULL) \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
STAILQ_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
STAILQ_NEXT((elm), field) = NULL; \
|
||||
*(head)->stqh_last = (elm); \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_LAST(head, type, field) \
|
||||
(STAILQ_EMPTY((head)) ? \
|
||||
NULL : \
|
||||
((struct type *) \
|
||||
((char *)((head)->stqh_last) - __offsetof(struct type, field))))
|
||||
|
||||
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
|
||||
|
||||
#define STAILQ_REMOVE(head, elm, type, field) do { \
|
||||
if (STAILQ_FIRST((head)) == (elm)) { \
|
||||
STAILQ_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = STAILQ_FIRST((head)); \
|
||||
while (STAILQ_NEXT(curelm, field) != (elm)) \
|
||||
curelm = STAILQ_NEXT(curelm, field); \
|
||||
if ((STAILQ_NEXT(curelm, field) = \
|
||||
STAILQ_NEXT(STAILQ_NEXT(curelm, field), \
|
||||
field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_NEXT((curelm),\
|
||||
field); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
|
||||
if (STAILQ_NEXT(elm, field)) { \
|
||||
if ((STAILQ_NEXT(elm, field) = \
|
||||
STAILQ_NEXT(STAILQ_NEXT(elm, field), \
|
||||
field)) == NULL) \
|
||||
(head)->stqh_last = \
|
||||
&STAILQ_NEXT((elm), field); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD(head, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = \
|
||||
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == \
|
||||
NULL)\
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = \
|
||||
STAILQ_NEXT((elm), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* List declarations.
|
||||
*/
|
||||
#define ATH_LIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *lh_first; \
|
||||
}
|
||||
|
||||
#ifndef LIST_HEAD
|
||||
#define LIST_HEAD ATH_LIST_HEAD
|
||||
#endif
|
||||
|
||||
#define LIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define LIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *le_next; \
|
||||
struct type **le_prev; \
|
||||
}
|
||||
|
||||
/*
|
||||
* List functions.
|
||||
*/
|
||||
|
||||
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
|
||||
|
||||
#define LIST_FIRST(head) ((head)->lh_first)
|
||||
|
||||
#define LIST_FOREACH(var, head, field) \
|
||||
for ((var) = LIST_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = LIST_NEXT((var), field))
|
||||
|
||||
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = LIST_FIRST((head)); \
|
||||
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define LIST_INIT(head) do { \
|
||||
LIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
|
||||
if ((LIST_NEXT((elm), field) = \
|
||||
LIST_NEXT((listelm), field)) != NULL) \
|
||||
LIST_NEXT((listelm), field)->field.le_prev = \
|
||||
&LIST_NEXT((elm), field); \
|
||||
LIST_NEXT((listelm), field) = (elm); \
|
||||
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||
LIST_NEXT((elm), field) = (listelm); \
|
||||
*(listelm)->field.le_prev = (elm); \
|
||||
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
|
||||
LIST_FIRST((head))->field.le_prev = \
|
||||
&LIST_NEXT((elm), field); \
|
||||
LIST_FIRST((head)) = (elm); \
|
||||
(elm)->field.le_prev = &LIST_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||
|
||||
#define LIST_REMOVE(elm, field) do { \
|
||||
if (LIST_NEXT((elm), field) != NULL) \
|
||||
LIST_NEXT((elm), field)->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Tail queue declarations.
|
||||
*/
|
||||
#ifndef TRACE_TX_LEAK
|
||||
#define TRACE_TX_LEAK 0
|
||||
#endif
|
||||
|
||||
#if TRACE_TX_LEAK
|
||||
#define HEADNAME char headname[64];
|
||||
#define COPY_HEADNAME(head) OS_MEMCPY((head)->headname, #head, sizeof(#head))
|
||||
#else
|
||||
#define HEADNAME
|
||||
#define COPY_HEADNAME(head)
|
||||
#endif
|
||||
|
||||
#define TAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *tqh_first; \
|
||||
struct type **tqh_last; \
|
||||
HEADNAME \
|
||||
TRACEBUF \
|
||||
}
|
||||
|
||||
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).tqh_first }
|
||||
|
||||
#define TAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *tqe_next; \
|
||||
struct type **tqe_prev; \
|
||||
TRACEBUF \
|
||||
}
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
|
||||
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
|
||||
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
|
||||
#define TAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = TAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = TAILQ_NEXT((var), field))
|
||||
|
||||
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = TAILQ_FIRST((head)); \
|
||||
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
||||
for ((var) = TAILQ_LAST((head), headname); \
|
||||
(var); \
|
||||
(var) = TAILQ_PREV((var), headname, field))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
|
||||
for ((var) = TAILQ_LAST((head), headname); \
|
||||
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define TAILQ_INIT(head) do { \
|
||||
TAILQ_FIRST((head)) = NULL; \
|
||||
(head)->tqh_last = &TAILQ_FIRST((head)); \
|
||||
COPY_HEADNAME(head); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), \
|
||||
field)) != NULL) \
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||
&TAILQ_NEXT((elm), field); \
|
||||
else { \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
} \
|
||||
TAILQ_NEXT((listelm), field) = (elm); \
|
||||
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
QMD_TRACE_ELEM(&listelm->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||
TAILQ_NEXT((elm), field) = (listelm); \
|
||||
*(listelm)->field.tqe_prev = (elm); \
|
||||
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
QMD_TRACE_ELEM(&listelm->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)\
|
||||
TAILQ_FIRST((head))->field.tqe_prev = \
|
||||
&TAILQ_NEXT((elm), field); \
|
||||
else \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
TAILQ_FIRST((head)) = (elm); \
|
||||
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
TAILQ_NEXT((elm), field) = NULL; \
|
||||
(elm)->field.tqe_prev = (head)->tqh_last; \
|
||||
*(head)->tqh_last = (elm); \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_LAST(head, headname) \
|
||||
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
||||
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
|
||||
#define TAILQ_PREV(elm, headname, field) \
|
||||
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
||||
|
||||
#define TAILQ_REMOVE(head, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field)) != NULL) \
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||
(elm)->field.tqe_prev; \
|
||||
else { \
|
||||
(head)->tqh_last = (elm)->field.tqe_prev; \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
} \
|
||||
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
|
||||
TRASHIT((elm)->field.tqe_next); \
|
||||
TRASHIT((elm)->field.tqe_prev); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_CONCAT(head1, head2, field) do { \
|
||||
if (!TAILQ_EMPTY(head2)) { \
|
||||
*(head1)->tqh_last = (head2)->tqh_first; \
|
||||
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;\
|
||||
(head1)->tqh_last = (head2)->tqh_last; \
|
||||
TAILQ_INIT((head2)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
/*
|
||||
* XXX insque() and remque() are an old way of handling certain queues.
|
||||
* They bogusly assumes that all queue heads look alike.
|
||||
*/
|
||||
|
||||
struct quehead {
|
||||
struct quehead *qh_link;
|
||||
struct quehead *qh_rlink;
|
||||
};
|
||||
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
|
||||
|
||||
static inline void insque(void *a, void *b)
|
||||
{
|
||||
struct quehead *element = (struct quehead *)a,
|
||||
*head = (struct quehead *)b;
|
||||
|
||||
element->qh_link = head->qh_link;
|
||||
element->qh_rlink = head;
|
||||
head->qh_link = element;
|
||||
element->qh_link->qh_rlink = element;
|
||||
}
|
||||
|
||||
static inline void remque(void *a)
|
||||
{
|
||||
struct quehead *element = (struct quehead *)a;
|
||||
|
||||
element->qh_link->qh_rlink = element->qh_rlink;
|
||||
element->qh_rlink->qh_link = element->qh_link;
|
||||
element->qh_rlink = 0;
|
||||
}
|
||||
|
||||
#else /* !(__GNUC__ || __INTEL_COMPILER) */
|
||||
|
||||
void insque(void *a, void *b);
|
||||
void remque(void *a);
|
||||
|
||||
#endif /* __GNUC__ || __INTEL_COMPILER */
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* _QUEUE_H_ */
|
Reference in New Issue
Block a user