qcacmn: Add core\utils directory and files to qcacmn
As a part of UMAC convergence, move the core\utils logging to qcacmn. CRs-Fixed: 1109855 Change-Id: I499a392f74f3e52e99df4d03e4a27bce6cf5be7c
This commit is contained in:

committed by
qcabuildsw

parent
6195152790
commit
60644c29e6
199
utils/epping/inc/epping_internal.h
Normal file
199
utils/epping/inc/epping_internal.h
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EPPING_INTERNAL_H
|
||||||
|
#define EPPING_INTERNAL_H
|
||||||
|
/**===========================================================================
|
||||||
|
|
||||||
|
\file epping_internal.h
|
||||||
|
|
||||||
|
\brief Linux epping internal head file
|
||||||
|
|
||||||
|
==========================================================================*/
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
Include files
|
||||||
|
-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
#include <linux/semaphore.h>
|
||||||
|
#if defined(WLAN_OPEN_SOURCE) && 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)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
#ifdef HIF_PCI
|
||||||
|
#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;
|
||||||
|
#ifdef HIF_PCI
|
||||||
|
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 tQDF_ADAPTER_MODE 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 *pAdapter,
|
||||||
|
EPPING_HEADER *eppingHdr, int ret, const char *str);
|
||||||
|
void epping_log_stats(epping_adapter_t *pAdapter, const char *str);
|
||||||
|
void epping_set_kperf_flag(epping_adapter_t *pAdapter,
|
||||||
|
HTC_ENDPOINT_ID eid, A_UINT8 kperf_flag);
|
||||||
|
|
||||||
|
/* epping_tx signatures */
|
||||||
|
void epping_tx_timer_expire(epping_adapter_t *pAdapter);
|
||||||
|
void epping_tx_complete_multiple(void *ctx, HTC_PACKET_QUEUE *pPacketQueue);
|
||||||
|
int epping_tx_send(qdf_nbuf_t skb, epping_adapter_t *pAdapter);
|
||||||
|
|
||||||
|
#ifdef HIF_SDIO
|
||||||
|
HTC_SEND_FULL_ACTION epping_tx_queue_full(void *Context, HTC_PACKET *pPacket);
|
||||||
|
#endif
|
||||||
|
void epping_tx_dup_pkt(epping_adapter_t *pAdapter,
|
||||||
|
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 tQDF_ADAPTER_MODE device_mode);
|
||||||
|
void epping_destroy_adapter(epping_adapter_t *pAdapter);
|
||||||
|
int epping_connect_service(epping_context_t *pEpping_ctx);
|
||||||
|
#ifdef HIF_PCI
|
||||||
|
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 */
|
||||||
|
#endif /* end #ifndef EPPING_INTERNAL_H */
|
49
utils/epping/inc/epping_main.h
Normal file
49
utils/epping/inc/epping_main.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
int epping_open(void);
|
||||||
|
void epping_close(void);
|
||||||
|
void epping_disable(void);
|
||||||
|
int epping_enable(struct device *parent_dev);
|
||||||
|
#endif /* end #ifndef EPPING_MAIN_H */
|
210
utils/epping/src/epping_helper.c
Normal file
210
utils/epping/src/epping_helper.c
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*========================================================================
|
||||||
|
|
||||||
|
\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)
|
||||||
|
{
|
||||||
|
A_UINT32 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] == NULL) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: no mem for cookie (idx = %d)", __func__,
|
||||||
|
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 != NULL) {
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
char *buf = (char *)data;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printk("%s: E, %s\n", __func__, str);
|
||||||
|
for (i = 0; (i + 7) < buf_len; i += 8) {
|
||||||
|
printk("%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||||
|
buf[i],
|
||||||
|
buf[i + 1],
|
||||||
|
buf[i + 2],
|
||||||
|
buf[i + 3],
|
||||||
|
buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dump the bytes in the last line */
|
||||||
|
for (; i < buf_len; i++) {
|
||||||
|
printk("%02x ", buf[i]);
|
||||||
|
}
|
||||||
|
printk("\n%s: X %s\n", __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 *pAdapter,
|
||||||
|
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,
|
||||||
|
pAdapter->stats.tx_packets,
|
||||||
|
pAdapter->stats.tx_dropped,
|
||||||
|
pAdapter->stats.tx_bytes,
|
||||||
|
pAdapter->stats.rx_packets,
|
||||||
|
pAdapter->stats.rx_dropped,
|
||||||
|
pAdapter->stats.rx_bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void epping_log_stats(epping_adapter_t *pAdapter, 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,
|
||||||
|
pAdapter->stats.tx_packets,
|
||||||
|
pAdapter->stats.tx_dropped,
|
||||||
|
pAdapter->stats.tx_bytes,
|
||||||
|
pAdapter->stats.rx_packets,
|
||||||
|
pAdapter->stats.rx_dropped,
|
||||||
|
pAdapter->stats.rx_bytes,
|
||||||
|
pAdapter->pEpping_ctx->total_tx_acks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void epping_set_kperf_flag(epping_adapter_t *pAdapter,
|
||||||
|
HTC_ENDPOINT_ID eid, A_UINT8 kperf_flag)
|
||||||
|
{
|
||||||
|
pAdapter->pEpping_ctx->kperf_num_rx_recv[eid] = 0;
|
||||||
|
pAdapter->pEpping_ctx->kperf_num_tx_acks[eid] = 0;
|
||||||
|
}
|
354
utils/epping/src/epping_main.c
Normal file
354
utils/epping/src/epping_main.c
Normal file
@@ -0,0 +1,354 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*========================================================================
|
||||||
|
|
||||||
|
\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 "cds_concurrency.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
|
||||||
|
|
||||||
|
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 == NULL) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"%s: cannot alloc epping context", __func__);
|
||||||
|
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 *pEpping_ctx;
|
||||||
|
struct hif_opaque_softc *hif_ctx;
|
||||||
|
HTC_HANDLE htc_handle;
|
||||||
|
|
||||||
|
pEpping_ctx = g_epping_ctx;
|
||||||
|
if (pEpping_ctx == NULL) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: error: pEpping_ctx = NULL", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pEpping_ctx->epping_adapter) {
|
||||||
|
epping_destroy_adapter(pEpping_ctx->epping_adapter);
|
||||||
|
pEpping_ctx->epping_adapter = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
|
||||||
|
if (hif_ctx == NULL) {
|
||||||
|
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 == NULL) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: error: htc_handle = NULL", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
htc_stop(htc_handle);
|
||||||
|
epping_cookie_cleanup(pEpping_ctx);
|
||||||
|
htc_destroy(htc_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 == NULL) {
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
static void epping_target_suspend_acknowledge(void *context, bool wow_nack)
|
||||||
|
{
|
||||||
|
if (NULL == 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
epping_context_t *pEpping_ctx = NULL;
|
||||||
|
cds_context_type *p_cds_context = NULL;
|
||||||
|
qdf_device_t qdf_ctx;
|
||||||
|
HTC_INIT_INFO htcInfo;
|
||||||
|
struct hif_opaque_softc *scn;
|
||||||
|
tSirMacAddr adapter_macAddr;
|
||||||
|
struct hif_target_info *tgt_info;
|
||||||
|
struct ol_context *ol_ctx;
|
||||||
|
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: Enter", __func__);
|
||||||
|
|
||||||
|
p_cds_context = cds_get_global_context();
|
||||||
|
|
||||||
|
if (p_cds_context == NULL) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: Failed cds_get_global_context", __func__);
|
||||||
|
ret = -1;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
pEpping_ctx = g_epping_ctx;
|
||||||
|
if (pEpping_ctx == NULL) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: Failed to get pEpping_ctx", __func__);
|
||||||
|
ret = -1;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
pEpping_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);
|
||||||
|
|
||||||
|
/* store target type and target version info in hdd ctx */
|
||||||
|
pEpping_ctx->target_type = tgt_info->target_type;
|
||||||
|
|
||||||
|
ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
|
||||||
|
if (!ol_ctx) {
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: ol_ctx is NULL", __func__);
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
epping_update_ol_config();
|
||||||
|
#ifndef FEATURE_BMI_2
|
||||||
|
/* 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 A_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH,
|
||||||
|
"%s: bmi_download_firmware done", __func__);
|
||||||
|
|
||||||
|
htcInfo.pContext = ol_ctx;
|
||||||
|
htcInfo.TargetFailure = ol_target_failure;
|
||||||
|
htcInfo.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, &htcInfo, 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;
|
||||||
|
}
|
||||||
|
pEpping_ctx->HTCHandle =
|
||||||
|
cds_get_context(QDF_MODULE_ID_HTC);
|
||||||
|
if (pEpping_ctx->HTCHandle == NULL) {
|
||||||
|
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(pEpping_ctx->HTCHandle) != A_OK) {
|
||||||
|
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(pEpping_ctx);
|
||||||
|
if (ret != 0) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: htc_wait_targetdone", __func__);
|
||||||
|
goto error_end;
|
||||||
|
}
|
||||||
|
if (htc_start(pEpping_ctx->HTCHandle) != A_OK) {
|
||||||
|
goto error_end;
|
||||||
|
}
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_INFO_HIGH, "%s: HTC started", __func__);
|
||||||
|
|
||||||
|
/* init the tx cookie resource */
|
||||||
|
ret = epping_cookie_init(pEpping_ctx);
|
||||||
|
if (ret == 0) {
|
||||||
|
pEpping_ctx->epping_adapter = epping_add_adapter(pEpping_ctx,
|
||||||
|
adapter_macAddr,
|
||||||
|
QDF_STA_MODE);
|
||||||
|
}
|
||||||
|
if (ret < 0 || pEpping_ctx->epping_adapter == NULL) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: epping_add_adaptererror error", __func__);
|
||||||
|
htc_stop(pEpping_ctx->HTCHandle);
|
||||||
|
epping_cookie_cleanup(pEpping_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;
|
||||||
|
}
|
162
utils/epping/src/epping_rx.c
Normal file
162
utils/epping/src/epping_rx.c
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*========================================================================
|
||||||
|
|
||||||
|
\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 (NULL == 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 *pAdapter = pEpping_ctx->epping_adapter;
|
||||||
|
struct net_device *dev = pAdapter->dev;
|
||||||
|
A_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: pAdapter = 0x%p eid=%d, skb=0x%p, data=0x%p, len=0x%x status:%d",
|
||||||
|
__func__, pAdapter, eid, pktSkb, pPacket->pBuffer,
|
||||||
|
pPacket->ActualLength, status);
|
||||||
|
|
||||||
|
if (status != A_OK) {
|
||||||
|
if (status != A_ECANCELED) {
|
||||||
|
printk("%s: RX ERR (%d)\n", __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);
|
||||||
|
++pAdapter->stats.rx_packets;
|
||||||
|
pAdapter->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 ((pAdapter->stats.rx_packets %
|
||||||
|
EPPING_STATS_LOG_COUNT) == 0) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: total_rx_pkts = %lu",
|
||||||
|
__func__,
|
||||||
|
pAdapter->stats.rx_packets);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
++pAdapter->stats.rx_dropped;
|
||||||
|
qdf_nbuf_free(pktSkb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
405
utils/epping/src/epping_tx.c
Normal file
405
utils/epping/src/epping_tx.c
Normal file
@@ -0,0 +1,405 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*========================================================================
|
||||||
|
|
||||||
|
\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 *pAdapter,
|
||||||
|
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(pAdapter->pEpping_ctx);
|
||||||
|
if (cookie == NULL) {
|
||||||
|
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(pAdapter->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(pAdapter->pEpping_ctx->HTCHandle, &cookie->HtcPkt);
|
||||||
|
if (ret != A_OK) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: htc_send_pkt failed, ret = %d\n", __func__, ret);
|
||||||
|
epping_free_cookie(pAdapter->pEpping_ctx, cookie);
|
||||||
|
qdf_nbuf_free(new_skb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pAdapter->stats.tx_bytes += skb_len;
|
||||||
|
++pAdapter->stats.tx_packets;
|
||||||
|
if (((pAdapter->stats.tx_packets +
|
||||||
|
pAdapter->stats.tx_dropped) % EPPING_STATS_LOG_COUNT) == 0 &&
|
||||||
|
(pAdapter->stats.tx_packets || pAdapter->stats.tx_dropped)) {
|
||||||
|
epping_log_stats(pAdapter, __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int epping_tx_send_int(qdf_nbuf_t skb, epping_adapter_t *pAdapter)
|
||||||
|
{
|
||||||
|
EPPING_HEADER *eppingHdr = (EPPING_HEADER *) qdf_nbuf_data(skb);
|
||||||
|
HTC_ENDPOINT_ID eid = ENDPOINT_UNUSED;
|
||||||
|
struct epping_cookie *cookie = NULL;
|
||||||
|
A_UINT8 ac = 0;
|
||||||
|
A_STATUS ret = A_OK;
|
||||||
|
int skb_len;
|
||||||
|
EPPING_HEADER tmpHdr = *eppingHdr;
|
||||||
|
|
||||||
|
/* allocate resource for this packet */
|
||||||
|
cookie = epping_alloc_cookie(pAdapter->pEpping_ctx);
|
||||||
|
/* no resource */
|
||||||
|
if (cookie == NULL) {
|
||||||
|
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 = pAdapter->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(pAdapter, 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(pAdapter->pEpping_ctx->HTCHandle, &cookie->HtcPkt);
|
||||||
|
epping_log_packet(pAdapter, &tmpHdr, ret, __func__);
|
||||||
|
if (ret != A_OK) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: htc_send_pkt failed, status = %d\n", __func__,
|
||||||
|
ret);
|
||||||
|
epping_free_cookie(pAdapter->pEpping_ctx, cookie);
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
pAdapter->stats.tx_bytes += skb_len;
|
||||||
|
++pAdapter->stats.tx_packets;
|
||||||
|
if (((pAdapter->stats.tx_packets +
|
||||||
|
pAdapter->stats.tx_dropped) % EPPING_STATS_LOG_COUNT) == 0 &&
|
||||||
|
(pAdapter->stats.tx_packets || pAdapter->stats.tx_dropped)) {
|
||||||
|
epping_log_stats(pAdapter, __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void epping_tx_timer_expire(epping_adapter_t *pAdapter)
|
||||||
|
{
|
||||||
|
qdf_nbuf_t nodrop_skb;
|
||||||
|
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_INFO, "%s: queue len: %d\n", __func__,
|
||||||
|
qdf_nbuf_queue_len(&pAdapter->nodrop_queue));
|
||||||
|
|
||||||
|
if (!qdf_nbuf_queue_len(&pAdapter->nodrop_queue)) {
|
||||||
|
/* nodrop queue is empty so no need to arm timer */
|
||||||
|
pAdapter->epping_timer_state = EPPING_TX_TIMER_STOPPED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try to flush nodrop queue */
|
||||||
|
while ((nodrop_skb = qdf_nbuf_queue_remove(&pAdapter->nodrop_queue))) {
|
||||||
|
htc_set_nodrop_pkt(pAdapter->pEpping_ctx->HTCHandle, true);
|
||||||
|
if (epping_tx_send_int(nodrop_skb, pAdapter)) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: nodrop: %p 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(&pAdapter->nodrop_queue,
|
||||||
|
nodrop_skb);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
htc_set_nodrop_pkt(pAdapter->pEpping_ctx->HTCHandle, false);
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_INFO,
|
||||||
|
"%s: nodrop: %p 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(&pAdapter->data_lock);
|
||||||
|
/* if nodrop queue is not empty, continue to arm timer */
|
||||||
|
if (pAdapter->epping_timer_state != EPPING_TX_TIMER_RUNNING) {
|
||||||
|
pAdapter->epping_timer_state = EPPING_TX_TIMER_RUNNING;
|
||||||
|
qdf_timer_mod(&pAdapter->epping_timer,
|
||||||
|
TX_RETRY_TIMEOUT_IN_MS);
|
||||||
|
}
|
||||||
|
qdf_spin_unlock_bh(&pAdapter->data_lock);
|
||||||
|
} else {
|
||||||
|
pAdapter->epping_timer_state = EPPING_TX_TIMER_STOPPED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int epping_tx_send(qdf_nbuf_t skb, epping_adapter_t *pAdapter)
|
||||||
|
{
|
||||||
|
qdf_nbuf_t nodrop_skb;
|
||||||
|
EPPING_HEADER *eppingHdr;
|
||||||
|
A_UINT8 ac = 0;
|
||||||
|
|
||||||
|
eppingHdr = (EPPING_HEADER *) qdf_nbuf_data(skb);
|
||||||
|
|
||||||
|
if (!IS_EPPING_PACKET(eppingHdr)) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: Recived 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(&pAdapter->nodrop_queue))) {
|
||||||
|
htc_set_nodrop_pkt(pAdapter->pEpping_ctx->HTCHandle, true);
|
||||||
|
if (epping_tx_send_int(nodrop_skb, pAdapter)) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: nodrop: %p xmit fail\n", __func__,
|
||||||
|
nodrop_skb);
|
||||||
|
/* fail to xmit so put the nodrop packet to the nodrop queue */
|
||||||
|
qdf_nbuf_queue_insert_head(&pAdapter->nodrop_queue,
|
||||||
|
nodrop_skb);
|
||||||
|
/* no cookie so free the current skb */
|
||||||
|
goto tx_fail;
|
||||||
|
} else {
|
||||||
|
htc_set_nodrop_pkt(pAdapter->pEpping_ctx->HTCHandle, false);
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_INFO,
|
||||||
|
"%s: nodrop: %p xmit ok\n", __func__,
|
||||||
|
nodrop_skb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send the original packet */
|
||||||
|
if (epping_tx_send_int(skb, pAdapter))
|
||||||
|
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);
|
||||||
|
++pAdapter->stats.tx_dropped;
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: Tx skb %p dropped, stats.tx_dropped = %ld\n",
|
||||||
|
__func__, skb, pAdapter->stats.tx_dropped);
|
||||||
|
return -ENOMEM;
|
||||||
|
} else {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: nodrop: %p queued\n", __func__, skb);
|
||||||
|
qdf_nbuf_queue_add(&pAdapter->nodrop_queue, skb);
|
||||||
|
qdf_spin_lock_bh(&pAdapter->data_lock);
|
||||||
|
if (pAdapter->epping_timer_state != EPPING_TX_TIMER_RUNNING) {
|
||||||
|
pAdapter->epping_timer_state = EPPING_TX_TIMER_RUNNING;
|
||||||
|
qdf_timer_mod(&pAdapter->epping_timer,
|
||||||
|
TX_RETRY_TIMEOUT_IN_MS);
|
||||||
|
}
|
||||||
|
qdf_spin_unlock_bh(&pAdapter->data_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HIF_SDIO
|
||||||
|
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_multiple(void *ctx, HTC_PACKET_QUEUE *pPacketQueue)
|
||||||
|
{
|
||||||
|
epping_context_t *pEpping_ctx = (epping_context_t *) ctx;
|
||||||
|
epping_adapter_t *pAdapter = pEpping_ctx->epping_adapter;
|
||||||
|
struct net_device *dev = pAdapter->dev;
|
||||||
|
A_STATUS status;
|
||||||
|
HTC_ENDPOINT_ID eid;
|
||||||
|
qdf_nbuf_t pktSkb;
|
||||||
|
struct epping_cookie *cookie;
|
||||||
|
A_BOOL flushing = false;
|
||||||
|
qdf_nbuf_queue_t skb_queue;
|
||||||
|
HTC_PACKET *htc_pkt;
|
||||||
|
|
||||||
|
qdf_nbuf_queue_init(&skb_queue);
|
||||||
|
|
||||||
|
qdf_spin_lock_bh(&pAdapter->data_lock);
|
||||||
|
|
||||||
|
while (!HTC_QUEUE_EMPTY(pPacketQueue)) {
|
||||||
|
htc_pkt = htc_packet_dequeue(pPacketQueue);
|
||||||
|
if (htc_pkt == NULL)
|
||||||
|
break;
|
||||||
|
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 (A_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=%p data=%p len=0x%x eid=%d ",
|
||||||
|
__func__, pktSkb, htc_pkt->pBuffer,
|
||||||
|
htc_pkt->ActualLength, eid);
|
||||||
|
|
||||||
|
if (A_FAILED(status)) {
|
||||||
|
if (status == A_ECANCELED) {
|
||||||
|
/* a packet was flushed */
|
||||||
|
flushing = true;
|
||||||
|
}
|
||||||
|
if (status != A_NO_RESOURCE) {
|
||||||
|
printk("%s() -TX ERROR, status: 0x%x\n",
|
||||||
|
__func__, status);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_INFO, "%s: OK\n", __func__);
|
||||||
|
flushing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
epping_free_cookie(pAdapter->pEpping_ctx, cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
qdf_spin_unlock_bh(&pAdapter->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 == NULL)
|
||||||
|
break;
|
||||||
|
qdf_nbuf_tx_free(pktSkb, QDF_NBUF_PKT_ERROR);
|
||||||
|
pEpping_ctx->total_tx_acks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flushing) {
|
||||||
|
netif_wake_queue(dev);
|
||||||
|
}
|
||||||
|
}
|
470
utils/epping/src/epping_txrx.c
Normal file
470
utils/epping/src/epping_txrx.c
Normal file
@@ -0,0 +1,470 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*========================================================================
|
||||||
|
|
||||||
|
\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"
|
||||||
|
|
||||||
|
static int epping_start_adapter(epping_adapter_t *pAdapter);
|
||||||
|
static void epping_stop_adapter(epping_adapter_t *pAdapter);
|
||||||
|
|
||||||
|
static void epping_timer_expire(void *data)
|
||||||
|
{
|
||||||
|
struct net_device *dev = (struct net_device *)data;
|
||||||
|
epping_adapter_t *pAdapter;
|
||||||
|
|
||||||
|
if (dev == NULL) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: netdev = NULL", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pAdapter = netdev_priv(dev);
|
||||||
|
if (pAdapter == NULL) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: adapter = NULL", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pAdapter->epping_timer_state = EPPING_TX_TIMER_STOPPED;
|
||||||
|
epping_tx_timer_expire(pAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int epping_ndev_open(struct net_device *dev)
|
||||||
|
{
|
||||||
|
epping_adapter_t *pAdapter;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
pAdapter = netdev_priv(dev);
|
||||||
|
epping_start_adapter(pAdapter);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int epping_ndev_stop(struct net_device *dev)
|
||||||
|
{
|
||||||
|
epping_adapter_t *pAdapter;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
pAdapter = netdev_priv(dev);
|
||||||
|
if (NULL == pAdapter) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: EPPING adapter context is Null", __func__);
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
epping_stop_adapter(pAdapter);
|
||||||
|
end:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void epping_ndev_uninit(struct net_device *dev)
|
||||||
|
{
|
||||||
|
epping_adapter_t *pAdapter;
|
||||||
|
|
||||||
|
pAdapter = netdev_priv(dev);
|
||||||
|
if (NULL == pAdapter) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: EPPING adapter context is Null", __func__);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
epping_stop_adapter(pAdapter);
|
||||||
|
end:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void epping_tx_queue_timeout(struct net_device *dev)
|
||||||
|
{
|
||||||
|
epping_adapter_t *pAdapter;
|
||||||
|
|
||||||
|
pAdapter = netdev_priv(dev);
|
||||||
|
if (NULL == pAdapter) {
|
||||||
|
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, pAdapter->started= %d",
|
||||||
|
__func__, pAdapter->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 (pAdapter->started)
|
||||||
|
netif_wake_queue(dev);
|
||||||
|
end:
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int epping_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
|
{
|
||||||
|
epping_adapter_t *pAdapter;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
pAdapter = netdev_priv(dev);
|
||||||
|
if (NULL == pAdapter) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: EPPING adapter context is Null", __func__);
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = epping_tx_send(skb, pAdapter);
|
||||||
|
end:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct net_device_stats *epping_get_stats(struct net_device *dev)
|
||||||
|
{
|
||||||
|
epping_adapter_t *pAdapter = netdev_priv(dev);
|
||||||
|
|
||||||
|
if (NULL == pAdapter) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_ERROR, "%s: pAdapter = NULL",
|
||||||
|
__func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pAdapter->stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int epping_ndev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||||
|
{
|
||||||
|
epping_adapter_t *pAdapter;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
pAdapter = netdev_priv(dev);
|
||||||
|
if (NULL == pAdapter) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: EPPING adapter context is Null", __func__);
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (dev != pAdapter->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 *pAdapter = netdev_priv(dev);
|
||||||
|
struct sockaddr *psta_mac_addr = addr;
|
||||||
|
qdf_mem_copy(&pAdapter->macAddressCurrent,
|
||||||
|
psta_mac_addr->sa_data, ETH_ALEN);
|
||||||
|
qdf_mem_copy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void epping_stop_adapter(epping_adapter_t *pAdapter)
|
||||||
|
{
|
||||||
|
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 (pAdapter && pAdapter->started) {
|
||||||
|
EPPING_LOG(LOG1, FL("Disabling queues"));
|
||||||
|
netif_tx_disable(pAdapter->dev);
|
||||||
|
netif_carrier_off(pAdapter->dev);
|
||||||
|
pAdapter->started = false;
|
||||||
|
pld_request_bus_bandwidth(qdf_ctx->dev,
|
||||||
|
PLD_BUS_WIDTH_LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int epping_start_adapter(epping_adapter_t *pAdapter)
|
||||||
|
{
|
||||||
|
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 (!pAdapter) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: pAdapter= NULL\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (!pAdapter->started) {
|
||||||
|
pld_request_bus_bandwidth(qdf_ctx->dev,
|
||||||
|
PLD_BUS_WIDTH_HIGH);
|
||||||
|
netif_carrier_on(pAdapter->dev);
|
||||||
|
EPPING_LOG(LOG1, FL("Enabling queues"));
|
||||||
|
netif_tx_start_all_queues(pAdapter->dev);
|
||||||
|
pAdapter->started = true;
|
||||||
|
} else {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_WARN,
|
||||||
|
"%s: pAdapter %p already started\n", __func__,
|
||||||
|
pAdapter);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int epping_register_adapter(epping_adapter_t *pAdapter)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = register_netdev(pAdapter->dev);
|
||||||
|
if (ret != 0) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: unable to register device\n",
|
||||||
|
pAdapter->dev->name);
|
||||||
|
} else {
|
||||||
|
pAdapter->registered = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void epping_unregister_adapter(epping_adapter_t *pAdapter)
|
||||||
|
{
|
||||||
|
if (pAdapter) {
|
||||||
|
epping_stop_adapter(pAdapter);
|
||||||
|
if (pAdapter->registered) {
|
||||||
|
unregister_netdev(pAdapter->dev);
|
||||||
|
pAdapter->registered = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: pAdapter = NULL, unable to unregister device\n",
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void epping_destroy_adapter(epping_adapter_t *pAdapter)
|
||||||
|
{
|
||||||
|
struct net_device *dev = NULL;
|
||||||
|
epping_context_t *pEpping_ctx;
|
||||||
|
|
||||||
|
if (!pAdapter || !pAdapter->pEpping_ctx) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: pAdapter = NULL\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev = pAdapter->dev;
|
||||||
|
pEpping_ctx = pAdapter->pEpping_ctx;
|
||||||
|
epping_unregister_adapter(pAdapter);
|
||||||
|
|
||||||
|
qdf_spinlock_destroy(&pAdapter->data_lock);
|
||||||
|
qdf_timer_free(&pAdapter->epping_timer);
|
||||||
|
pAdapter->epping_timer_state = EPPING_TX_TIMER_STOPPED;
|
||||||
|
|
||||||
|
while (qdf_nbuf_queue_len(&pAdapter->nodrop_queue)) {
|
||||||
|
qdf_nbuf_t tmp_nbuf = NULL;
|
||||||
|
tmp_nbuf = qdf_nbuf_queue_remove(&pAdapter->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 tQDF_ADAPTER_MODE device_mode)
|
||||||
|
{
|
||||||
|
struct net_device *dev;
|
||||||
|
epping_adapter_t *pAdapter;
|
||||||
|
|
||||||
|
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 == NULL) {
|
||||||
|
EPPING_LOG(QDF_TRACE_LEVEL_FATAL,
|
||||||
|
"%s: Cannot allocate epping_adapter_t\n", __func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pAdapter = netdev_priv(dev);
|
||||||
|
qdf_mem_zero(pAdapter, sizeof(*pAdapter));
|
||||||
|
pAdapter->dev = dev;
|
||||||
|
pAdapter->pEpping_ctx = pEpping_ctx;
|
||||||
|
pAdapter->device_mode = device_mode; /* station, SAP, etc */
|
||||||
|
qdf_mem_copy(dev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
|
||||||
|
qdf_mem_copy(pAdapter->macAddressCurrent.bytes,
|
||||||
|
macAddr, sizeof(tSirMacAddr));
|
||||||
|
qdf_spinlock_create(&pAdapter->data_lock);
|
||||||
|
qdf_nbuf_queue_init(&pAdapter->nodrop_queue);
|
||||||
|
pAdapter->epping_timer_state = EPPING_TX_TIMER_STOPPED;
|
||||||
|
qdf_timer_init(epping_get_qdf_ctx(), &pAdapter->epping_timer,
|
||||||
|
epping_timer_expire, dev, QDF_TIMER_TYPE_SW);
|
||||||
|
dev->type = ARPHRD_IEEE80211;
|
||||||
|
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(pAdapter) == 0) {
|
||||||
|
EPPING_LOG(LOG1, FL("Disabling queues"));
|
||||||
|
netif_tx_disable(dev);
|
||||||
|
netif_carrier_off(dev);
|
||||||
|
return pAdapter;
|
||||||
|
} else {
|
||||||
|
epping_destroy_adapter(pAdapter);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int epping_connect_service(epping_context_t *pEpping_ctx)
|
||||||
|
{
|
||||||
|
int status, i;
|
||||||
|
HTC_SERVICE_CONNECT_REQ connect;
|
||||||
|
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 = epping_tx_complete_multiple;
|
||||||
|
connect.EpCallbacks.EpRecv = epping_rx;
|
||||||
|
/* epping_tx_complete use Multiple version */
|
||||||
|
connect.EpCallbacks.EpTxComplete = NULL;
|
||||||
|
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)
|
||||||
|
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 (status != EOK) {
|
||||||
|
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)
|
||||||
|
connect.service_id = WMI_DATA_BK_SVC;
|
||||||
|
status = htc_connect_service(pEpping_ctx->HTCHandle, &connect, &response);
|
||||||
|
if (status != EOK) {
|
||||||
|
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;
|
||||||
|
}
|
4394
utils/fwlog/dbglog_host.c
Normal file
4394
utils/fwlog/dbglog_host.c
Normal file
File diff suppressed because it is too large
Load Diff
174
utils/fwlog/dbglog_host.h
Normal file
174
utils/fwlog/dbglog_host.h
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011, 2014-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DBGLOG_HOST_H_
|
||||||
|
#define _DBGLOG_HOST_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "dbglog_common.h"
|
||||||
|
#include "ol_defines.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)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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, A_UINT16 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,
|
||||||
|
A_UINT16 tsr);
|
||||||
|
|
||||||
|
/** Enable reporting. If it is set to false then Traget wont 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, enum 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 sinlge 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, A_UINT32 mod_id_lvl);
|
||||||
|
|
||||||
|
/** Enable/Disable the logging for VAP */
|
||||||
|
int
|
||||||
|
dbglog_vap_log_enable(wmi_unified_t wmi_handle, A_UINT16 vap_id,
|
||||||
|
A_BOOL isenable);
|
||||||
|
/** Enable/Disable logging for Module */
|
||||||
|
int
|
||||||
|
dbglog_module_log_enable(wmi_unified_t wmi_handle, A_UINT32 mod_id,
|
||||||
|
A_BOOL isenable);
|
||||||
|
|
||||||
|
/** set vap enablie bitmap */
|
||||||
|
void
|
||||||
|
dbglog_set_vap_enable_bitmap(wmi_unified_t wmi_handle,
|
||||||
|
A_UINT32 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,
|
||||||
|
A_UINT32 log_level,
|
||||||
|
A_UINT32 *mod_enable_bitmap,
|
||||||
|
A_UINT32 bitmap_len);
|
||||||
|
|
||||||
|
int
|
||||||
|
dbglog_parse_debug_logs(ol_scn_t scn, u_int8_t *datap,
|
||||||
|
u_int32_t len);
|
||||||
|
|
||||||
|
|
||||||
|
/** Register the cnss_diag activate with the wlan driver */
|
||||||
|
int cnss_diag_activate_service(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _DBGLOG_HOST_H_ */
|
453
utils/host_diag_log/inc/host_diag_core_event.h
Normal file
453
utils/host_diag_log/inc/host_diag_core_event.h
Normal file
@@ -0,0 +1,453 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(__HOST_DIAG_CORE_EVENT_H)
|
||||||
|
#define __HOST_DIAG_CORE_EVENT_H
|
||||||
|
|
||||||
|
/**=========================================================================
|
||||||
|
|
||||||
|
\file host_diag_core_event.h
|
||||||
|
|
||||||
|
\brief WLAN UTIL host DIAG Events
|
||||||
|
|
||||||
|
Definitions for DIAG Events
|
||||||
|
|
||||||
|
========================================================================*/
|
||||||
|
|
||||||
|
/* $Header$ */
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------
|
||||||
|
Include Files
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
#include "qdf_types.h"
|
||||||
|
#include "i_host_diag_core_event.h"
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------
|
||||||
|
Preprocessor definitions and constants
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#define WAKE_LOCK_NAME_LEN 80
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_SECURITY
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t eventId;
|
||||||
|
uint8_t authMode;
|
||||||
|
uint8_t encryptionModeUnicast;
|
||||||
|
uint8_t encryptionModeMulticast;
|
||||||
|
uint8_t pmkIDMatch;
|
||||||
|
uint8_t bssid[6];
|
||||||
|
uint8_t keyId;
|
||||||
|
uint8_t status;
|
||||||
|
} host_event_wlan_security_payload_type;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_STATUS_V2
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t eventId;
|
||||||
|
uint8_t ssid[32];
|
||||||
|
uint8_t bssType;
|
||||||
|
uint8_t rssi;
|
||||||
|
uint8_t channel;
|
||||||
|
uint8_t qosCapability;
|
||||||
|
uint8_t authType;
|
||||||
|
uint8_t encryptionType;
|
||||||
|
uint8_t reason;
|
||||||
|
uint8_t reasonDisconnect;
|
||||||
|
} host_event_wlan_status_payload_type;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_HANDOFF
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t eventId;
|
||||||
|
uint8_t currentApBssid[6];
|
||||||
|
uint8_t currentApRssi;
|
||||||
|
uint8_t candidateApBssid[6];
|
||||||
|
uint8_t candidateApRssi;
|
||||||
|
} host_event_wlan_handoff_payload_type;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_VCC
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t eventId;
|
||||||
|
uint8_t rssi;
|
||||||
|
uint8_t txPer;
|
||||||
|
uint8_t rxPer;
|
||||||
|
int linkQuality;
|
||||||
|
} host_event_wlan_vcc_payload_type;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_QOS
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t eventId;
|
||||||
|
uint8_t reasonCode;
|
||||||
|
} host_event_wlan_qos_payload_type;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_PE
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
char bssid[6];
|
||||||
|
uint16_t event_type;
|
||||||
|
uint16_t sme_state;
|
||||||
|
uint16_t mlm_state;
|
||||||
|
uint16_t status;
|
||||||
|
uint16_t reason_code;
|
||||||
|
} host_event_wlan_pe_payload_type;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_ADD_BLOCK_ACK_SUCCESS
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
char ucBaPeerMac[6];
|
||||||
|
uint8_t ucBaTid;
|
||||||
|
uint8_t ucBaBufferSize;
|
||||||
|
uint16_t usBaSSN;
|
||||||
|
uint8_t fInitiator;
|
||||||
|
} host_event_wlan_add_block_ack_success_payload_type;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_ADD_BLOCK_ACK_FAILED
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
char ucBaPeerMac[6];
|
||||||
|
uint8_t ucBaTid;
|
||||||
|
uint8_t ucReasonCode;
|
||||||
|
uint8_t fInitiator;
|
||||||
|
} host_event_wlan_add_block_ack_failed_payload_type;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_DELETE_BLOCK_ACK_SUCCESS
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
char ucBaPeerMac[6];
|
||||||
|
uint8_t ucBaTid;
|
||||||
|
uint8_t ucDeleteReasonCode;
|
||||||
|
} host_event_wlan_add_block_ack_deleted_payload_type;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_DELETE_BLOCK_ACK_FAILED
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
char ucBaPeerMac[6];
|
||||||
|
uint8_t ucBaTid;
|
||||||
|
uint8_t ucDeleteReasonCode;
|
||||||
|
uint8_t ucFailReasonCode;
|
||||||
|
} host_event_wlan_add_block_ack_delete_failed_payload_type;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_BSS_PROTECTION
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t event_type;
|
||||||
|
uint8_t prot_type;
|
||||||
|
} host_event_wlan_bss_prot_payload_type;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_BRINGUP_STATUS
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
uint16_t wlanStatus;
|
||||||
|
char driverVersion[10];
|
||||||
|
} host_event_wlan_bringup_status_payload_type;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_POWERSAVE_WOW
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t event_subtype;
|
||||||
|
uint8_t wow_type;
|
||||||
|
uint8_t wow_magic_pattern[6];
|
||||||
|
uint8_t wow_del_ptrn_id;
|
||||||
|
uint8_t wow_wakeup_cause;
|
||||||
|
uint8_t wow_wakeup_cause_pbm_ptrn_id;
|
||||||
|
} host_event_wlan_powersave_wow_payload_type;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_BTC
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t eventId;
|
||||||
|
uint8_t btAddr[6];
|
||||||
|
uint16_t connHandle;
|
||||||
|
uint8_t connStatus;
|
||||||
|
uint8_t linkType;
|
||||||
|
uint8_t scoInterval;
|
||||||
|
uint8_t scoWindow;
|
||||||
|
uint8_t retransWindow;
|
||||||
|
uint8_t mode;
|
||||||
|
} host_event_wlan_btc_type;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_EAPOL
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* struct host_event_wlan_eapol - Structure holding the eapol information
|
||||||
|
* @event_sub_type: 0-Transmitted, 1-Received
|
||||||
|
* @eapol_packet_type: 0 - EAP Start, 1 - EAPOL Start, 2 - EAPOL Logoff
|
||||||
|
3 - EAPOL Key, 4 - EAPOL Encapsulated Alert
|
||||||
|
* @eapol_key_info: This field from the driver is in big endian format.
|
||||||
|
* So, the masks .0x8013. can be used to extract the
|
||||||
|
* message type. After masking, the values corresponding
|
||||||
|
* to messages 1/2/3/4 are given below:
|
||||||
|
* Msg. 1 0x8000
|
||||||
|
* Msg. 2 0x0001
|
||||||
|
* Msg. 3 0x8013
|
||||||
|
* Msg. 4 0x0003
|
||||||
|
* @eapol_rate: Rate at which the frame is received
|
||||||
|
* @dest_addr: Destination address
|
||||||
|
* @src_addr: Source address
|
||||||
|
*
|
||||||
|
* This structure contains the EAPOL information related to logging
|
||||||
|
*/
|
||||||
|
struct host_event_wlan_eapol {
|
||||||
|
uint8_t event_sub_type;
|
||||||
|
uint8_t eapol_packet_type;
|
||||||
|
uint16_t eapol_key_info;
|
||||||
|
uint16_t eapol_rate;
|
||||||
|
uint8_t dest_addr[6];
|
||||||
|
uint8_t src_addr[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_LOW_RESOURCE_FAILURE
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* struct host_event_wlan_low_resource_failure - Structure holding the
|
||||||
|
* low resource failure information
|
||||||
|
* @event_sub_type: Gives further information about reason for
|
||||||
|
* low resource condition
|
||||||
|
*
|
||||||
|
* This structure will hold the low resource failure information
|
||||||
|
*/
|
||||||
|
struct host_event_wlan_low_resource_failure {
|
||||||
|
uint8_t event_sub_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum resource_failure_type - Reason for low resource failure condition
|
||||||
|
* @WIFI_EVENT_MEMORY_FAILURE: Memory failure
|
||||||
|
*
|
||||||
|
* This enum has the reason codes why the low resource situation is observed
|
||||||
|
*/
|
||||||
|
enum resource_failure_type {
|
||||||
|
WIFI_EVENT_MEMORY_FAILURE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_WAKE_LOCK
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* struct host_event_wlan_wake_lock - Structure holding the wakelock information
|
||||||
|
* @status: Whether the wakelock is taken/released
|
||||||
|
* @reason: Reason for taking this wakelock
|
||||||
|
* @timeout: Timeout value in case of timed wakelocks
|
||||||
|
* @name_len: Length of the name of the wakelock that will follow
|
||||||
|
* @name: Name of the wakelock
|
||||||
|
*
|
||||||
|
* This structure will hold the wakelock information
|
||||||
|
*/
|
||||||
|
struct host_event_wlan_wake_lock {
|
||||||
|
uint32_t status;
|
||||||
|
uint32_t reason;
|
||||||
|
uint32_t timeout;
|
||||||
|
uint32_t name_len;
|
||||||
|
char name[WAKE_LOCK_NAME_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Event ID: EVENT_WLAN_LOG_COMPLETE
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* struct host_event_wlan_log_complete - Holds log completion details
|
||||||
|
* @is_fatal: Indicates if the event is fatal or not
|
||||||
|
* @indicator: Source of the bug report - Framework/Host/Firmware
|
||||||
|
* @reason_code: Reason for triggering bug report
|
||||||
|
* @reserved: Reserved field
|
||||||
|
*
|
||||||
|
* This structure holds the log completion related information
|
||||||
|
*/
|
||||||
|
struct host_event_wlan_log_complete {
|
||||||
|
uint32_t is_fatal;
|
||||||
|
uint32_t indicator;
|
||||||
|
uint32_t reason_code;
|
||||||
|
uint32_t reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct host_event_tdls_teardown - tdls teardown diag event
|
||||||
|
* @reason: reason for tear down
|
||||||
|
* @peer_mac: peer mac
|
||||||
|
*
|
||||||
|
* This structure contains tdls teardown diag event info
|
||||||
|
*/
|
||||||
|
struct host_event_tdls_teardown {
|
||||||
|
uint32_t reason;
|
||||||
|
uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct host_event_tdls_enable_link - tdls enable link event
|
||||||
|
* @peer_mac: peer mac
|
||||||
|
* @is_off_chan_supported: if off channel supported
|
||||||
|
* @is_off_chan_configured: if off channel configured
|
||||||
|
* @is_off_chan_established: if off channel established
|
||||||
|
*
|
||||||
|
* This structure contain tdls enable link diag event info
|
||||||
|
*/
|
||||||
|
struct host_event_tdls_enable_link {
|
||||||
|
uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
|
||||||
|
uint8_t is_off_chan_supported;
|
||||||
|
uint8_t is_off_chan_configured;
|
||||||
|
uint8_t is_off_chan_established;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct host_event_suspend - suspend/resume state
|
||||||
|
* @state: suspend/resume state
|
||||||
|
*
|
||||||
|
* This structure contains suspend resume diag event info
|
||||||
|
*/
|
||||||
|
struct host_event_suspend {
|
||||||
|
uint8_t state;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct host_event_offload_req - offload state
|
||||||
|
* @offload_type: offload type
|
||||||
|
* @state: enabled or disabled state
|
||||||
|
*
|
||||||
|
* This structure contains offload diag event info
|
||||||
|
*/
|
||||||
|
struct host_event_offload_req {
|
||||||
|
uint8_t offload_type;
|
||||||
|
uint8_t state;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct host_event_tdls_scan_rejected - scan
|
||||||
|
* rejected due to tdls
|
||||||
|
* @status: rejected status
|
||||||
|
*
|
||||||
|
* This structure contains scan rejected due to
|
||||||
|
* tdls event info
|
||||||
|
*/
|
||||||
|
struct host_event_tdls_scan_rejected {
|
||||||
|
uint8_t status;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct host_event_tdls_tx_rx_mgmt - for TX RX management frame
|
||||||
|
* @event_id: event ID
|
||||||
|
* @tx_rx: tx or rx
|
||||||
|
* @type: type of frame
|
||||||
|
* @action_sub_type: action frame type
|
||||||
|
* @peer_mac: peer mac
|
||||||
|
*
|
||||||
|
* This structure contains tdls TX RX management frame info
|
||||||
|
*/
|
||||||
|
struct host_event_tdls_tx_rx_mgmt {
|
||||||
|
uint8_t event_id;
|
||||||
|
uint8_t tx_rx;
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t action_sub_type;
|
||||||
|
uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Function declarations and documenation
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* enum wifi_connectivity_events - Enum containing EAPOL sub type
|
||||||
|
* @WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED: EAPOL transmitted
|
||||||
|
* @WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED: EAPOL received
|
||||||
|
*
|
||||||
|
* This enum contains the EAPOL subtype
|
||||||
|
*/
|
||||||
|
enum wifi_connectivity_events {
|
||||||
|
WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED,
|
||||||
|
WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum wake_lock_reason - Reason for taking/releasing wakelock
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT: Driver initialization
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT: Driver re-initialization
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_DRIVER_EXIT: Driver shutdown
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_SCAN: Scan request/response handling
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_EXT_SCAN: Extended scan request/response handling
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_RESUME_WLAN: Driver resume
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_ROC: Remain on channel request/response handling
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_AUTO_SUSPEND: Auto suspend related handling
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_IPA: IPA related handling
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_ADD_STA: Addition of STA
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_HOLD_RX: Wakelocks taken for receive
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_SAP: SoftAP related wakelocks
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_WOW: WoW feature related
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_PNO: PNO feature related
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_DEL_STA: Deletion of a station
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_DFS: DFS related wakelocks
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP: Firmware response
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_MISC: Miscellaneous wakelocks
|
||||||
|
* @WIFI_POWER_EVENT_WAKELOCK_DHCP: DHCP negotiation under way
|
||||||
|
*
|
||||||
|
* Indicates the reason for which the wakelock was taken/released
|
||||||
|
*/
|
||||||
|
enum wake_lock_reason {
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_DRIVER_EXIT,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_SCAN,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_EXT_SCAN,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_RESUME_WLAN,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_ROC,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_AUTO_SUSPEND,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_IPA,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_ADD_STA,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_HOLD_RX,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_SAP,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_WOW,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_PNO,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_DEL_STA,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_DFS,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_MISC,
|
||||||
|
WIFI_POWER_EVENT_WAKELOCK_DHCP,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* __HOST_DIAG_CORE_EVENT_H */
|
278
utils/host_diag_log/inc/host_diag_core_log.h
Normal file
278
utils/host_diag_log/inc/host_diag_core_log.h
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
/* Version to be updated whenever format of vos_log_pktlog_info changes */
|
||||||
|
#define VERSION_LOG_WLAN_PKT_LOG_INFO_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;
|
||||||
|
} 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 patern 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
|
||||||
|
* @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[];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Function declarations and documenation
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* __HOST_DIAG_CORE_LOG_H */
|
129
utils/host_diag_log/inc/host_diag_event_defs.h
Normal file
129
utils/host_diag_log/inc/host_diag_event_defs.h
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EVENT_DEFS_H
|
||||||
|
#define EVENT_DEFS_H
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
EVENT_DROP_ID = 0,
|
||||||
|
|
||||||
|
/* Events between 0x1 to 0x674 are not used */
|
||||||
|
|
||||||
|
EVENT_WLAN_SECURITY = 0x675, /* 13 byte payload */
|
||||||
|
EVENT_WLAN_STATUS, /* 15 byte payload */
|
||||||
|
|
||||||
|
/* Events 0x677 and 0x678 are not used */
|
||||||
|
|
||||||
|
EVENT_WLAN_QOS = 0x679, /* 2 byte payload */
|
||||||
|
EVENT_WLAN_PE, /* 16 byte payload */
|
||||||
|
|
||||||
|
/* Events between 0x67b to 0x67f are not used */
|
||||||
|
|
||||||
|
EVENT_WLAN_BRINGUP_STATUS = 0x680, /* 12 byte payload */
|
||||||
|
EVENT_WLAN_POWERSAVE_GENERIC, /* 16 byte payload */
|
||||||
|
EVENT_WLAN_POWERSAVE_WOW, /* 11 byte payload */
|
||||||
|
|
||||||
|
/* Events between 0x683 to 0x690 are not used */
|
||||||
|
|
||||||
|
EVENT_WLAN_BTC = 0x691, /* 15 byte payload */
|
||||||
|
EVENT_WLAN_EAPOL = 0xA8D,/* 18 bytes payload */
|
||||||
|
EVENT_WLAN_WAKE_LOCK = 0xAA2, /* 96 bytes payload */
|
||||||
|
EVENT_WLAN_BEACON_RECEIVED = 0xAA6, /* FW event: 2726 */
|
||||||
|
EVENT_WLAN_LOG_COMPLETE = 0xAA7, /* 16 bytes payload */
|
||||||
|
EVENT_WLAN_STATUS_V2 = 0xAB3,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* <diag_event>
|
||||||
|
* EVENT_WLAN_TDLS_TEARDOWN
|
||||||
|
* @ reason: reason for tear down.
|
||||||
|
* @peer_mac: Peer mac address
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This event is sent when TDLS tear down happens.
|
||||||
|
*
|
||||||
|
* Supported Feature: TDLS
|
||||||
|
*
|
||||||
|
* </diag_event>
|
||||||
|
*/
|
||||||
|
EVENT_WLAN_TDLS_TEARDOWN = 0xAB5,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* <diag_event>
|
||||||
|
* EVENT_WLAN_TDLS_ENABLE_LINK
|
||||||
|
* @peer_mac: peer mac
|
||||||
|
* @is_off_chan_supported: If peer supports off channel
|
||||||
|
* @is_off_chan_configured: If off channel is configured
|
||||||
|
* @is_off_chan_established: If off channel is established
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This event is sent when TDLS enable link happens.
|
||||||
|
*
|
||||||
|
* Supported Feature: TDLS
|
||||||
|
*
|
||||||
|
* </diag_event>
|
||||||
|
*/
|
||||||
|
EVENT_WLAN_TDLS_ENABLE_LINK = 0XAB6,
|
||||||
|
EVENT_WLAN_SUSPEND_RESUME = 0xAB7,
|
||||||
|
EVENT_WLAN_OFFLOAD_REQ = 0xAB8,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* <diag_event>
|
||||||
|
* EVENT_TDLS_SCAN_BLOCK
|
||||||
|
* @status: rejected status
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This event is sent when scan is rejected due to TDLS.
|
||||||
|
*
|
||||||
|
* Supported Feature: TDLS
|
||||||
|
*
|
||||||
|
* </diag_event>
|
||||||
|
*/
|
||||||
|
EVENT_TDLS_SCAN_BLOCK = 0xAB9,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* <diag_event>
|
||||||
|
* EVENT_WLAN_TDLS_TX_RX_MGMT
|
||||||
|
* @event_id: event id
|
||||||
|
* @tx_rx: tx or rx
|
||||||
|
* @type: type of frame
|
||||||
|
* @action_sub_type: action frame type
|
||||||
|
* @peer_mac: peer mac
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This event is sent when TDLS mgmt rx tx happens.
|
||||||
|
*
|
||||||
|
* Supported Feature: TDLS
|
||||||
|
*
|
||||||
|
* </diag_event>
|
||||||
|
*/
|
||||||
|
EVENT_WLAN_TDLS_TX_RX_MGMT = 0xABA,
|
||||||
|
EVENT_WLAN_LOW_RESOURCE_FAILURE = 0xABB,
|
||||||
|
|
||||||
|
EVENT_MAX_ID = 0x0FFF
|
||||||
|
} event_id_enum_type;
|
||||||
|
|
||||||
|
#endif /* EVENT_DEFS_H */
|
2075
utils/host_diag_log/inc/log_codes.h
Normal file
2075
utils/host_diag_log/inc/log_codes.h
Normal file
File diff suppressed because it is too large
Load Diff
306
utils/host_diag_log/src/host_diag_log.c
Normal file
306
utils/host_diag_log/src/host_diag_log.c
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*============================================================================
|
||||||
|
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"
|
||||||
|
|
||||||
|
#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()) {
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO,
|
||||||
|
"%s: Unloading/Loading in Progress. Ignore!!!",
|
||||||
|
__func__);
|
||||||
|
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) {
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"qdf_mem_malloc failed");
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (cds_is_load_or_unload_in_progress()) {
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO,
|
||||||
|
"%s: Unloading/Loading in Progress. Ignore!!!",
|
||||||
|
__func__);
|
||||||
|
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) {
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"qdf_mem_malloc failed");
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (ptt_sock_send_msg_to_app
|
||||||
|
(wmsg, 0, ANI_NL_MSG_PUMAC, INVALID_PID) < 0) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
#endif
|
129
utils/host_diag_log/src/i_host_diag_core_event.h
Normal file
129
utils/host_diag_log/src/i_host_diag_core_event.h
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Function declarations and documenation
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
#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
|
||||||
|
void qdf_wow_wakeup_host_event(uint8_t wow_wakeup_cause);
|
||||||
|
#else
|
||||||
|
static inline void qdf_wow_wakeup_host_event(uint8_t wow_wakeup_cause)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* FEATURE_WLAN_DIAG_SUPPORT */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* __I_HOST_DIAG_CORE_EVENT_H */
|
129
utils/host_diag_log/src/i_host_diag_core_log.h
Normal file
129
utils/host_diag_log/src/i_host_diag_core_log.h
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(__I_HOST_DIAG_CORE_LOG_H)
|
||||||
|
#define __I_HOST_DIAG_CORE_LOG_H
|
||||||
|
|
||||||
|
#ifdef FEATURE_WLAN_DIAG_SUPPORT
|
||||||
|
#include <log_codes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**=========================================================================
|
||||||
|
|
||||||
|
\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 definiton 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)
|
||||||
|
|
||||||
|
#endif /* FEATURE_WLAN_DIAG_SUPPORT */
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Function declarations and documenation
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* __I_HOST_DIAG_CORE_LOG_H */
|
82
utils/logging/inc/wlan_logging_sock_svc.h
Normal file
82
utils/logging/inc/wlan_logging_sock_svc.h
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* 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_logging_sock_activate_svc(int log_fe_to_console, int num_buf);
|
||||||
|
int wlan_logging_sock_deactivate_svc(void);
|
||||||
|
int wlan_log_to_user(QDF_TRACE_LEVEL log_level, char *to_be_sent, int length);
|
||||||
|
|
||||||
|
#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
|
||||||
|
void wlan_logging_set_per_pkt_stats(void);
|
||||||
|
void wlan_logging_set_fw_flush_complete(void);
|
||||||
|
void wlan_flush_host_logs_for_fatal(void);
|
||||||
|
#else
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */
|
||||||
|
|
||||||
|
#ifdef FEATURE_WLAN_DIAG_SUPPORT
|
||||||
|
void wlan_report_log_completion(uint32_t is_fatal,
|
||||||
|
uint32_t indicator,
|
||||||
|
uint32_t reason_code);
|
||||||
|
#else
|
||||||
|
static inline void wlan_report_log_completion(uint32_t is_fatal,
|
||||||
|
uint32_t indicator,
|
||||||
|
uint32_t reason_code)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* FEATURE_WLAN_DIAG_SUPPORT */
|
||||||
|
|
||||||
|
void wlan_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump, void *data);
|
||||||
|
|
||||||
|
void wlan_deregister_txrx_packetdump(void);
|
||||||
|
void wlan_register_txrx_packetdump(void);
|
||||||
|
|
||||||
|
#endif /* WLAN_LOGGING_SOCK_SVC_H */
|
1503
utils/logging/src/wlan_logging_sock_svc.c
Normal file
1503
utils/logging/src/wlan_logging_sock_svc.c
Normal file
File diff suppressed because it is too large
Load Diff
200
utils/nlink/inc/wlan_nlink_common.h
Normal file
200
utils/nlink/inc/wlan_nlink_common.h
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*===========================================================================
|
||||||
|
\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>
|
||||||
|
#include <linux/if.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
* External Functions
|
||||||
|
*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
* Preprocessor Definitions and Constants
|
||||||
|
*-------------------------------------------------------------------------*/
|
||||||
|
#define WLAN_NL_MAX_PAYLOAD 256 /* 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 maximun 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_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,
|
||||||
|
WLAN_NL_MSG_CNSS_DIAG = ANI_NL_MSG_BASE + 0x0B, /* Value needs to be 27 */
|
||||||
|
ANI_NL_MSG_LOG,
|
||||||
|
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 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 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];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maximim 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,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* WLAN_NLINK_COMMON_H__ */
|
60
utils/nlink/inc/wlan_nlink_srv.h
Normal file
60
utils/nlink/inc/wlan_nlink_srv.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
int nl_srv_init(void *wiphy);
|
||||||
|
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);
|
||||||
|
int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag);
|
||||||
|
int nl_srv_bcast(struct sk_buff *skb);
|
||||||
|
int nl_srv_is_initialized(void);
|
||||||
|
#endif
|
539
utils/nlink/src/wlan_nlink_srv.c
Normal file
539
utils/nlink/src/wlan_nlink_srv.c
Normal file
@@ -0,0 +1,539 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* wlan_nlink_srv.c
|
||||||
|
*
|
||||||
|
* This file contains the definitions specific to the wlan_nlink_srv
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* 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 diagnotics netlink socket will not be available since this
|
||||||
|
* diagnostics netlink socket can only be exposed by one instance of the driver.
|
||||||
|
*/
|
||||||
|
#ifndef MULTI_IF_NAME
|
||||||
|
|
||||||
|
#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>
|
||||||
|
|
||||||
|
#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
|
||||||
|
*
|
||||||
|
* 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 availibility.
|
||||||
|
*
|
||||||
|
* Return: radio index for success and -EINVAL for failure
|
||||||
|
*/
|
||||||
|
int nl_srv_init(void *wiphy)
|
||||||
|
{
|
||||||
|
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: %p",
|
||||||
|
__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);
|
||||||
|
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);
|
||||||
|
else
|
||||||
|
dev_kfree_skb(skb);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 != NULL) {
|
||||||
|
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 != NULL) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
|
||||||
|
/* 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 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, WLAN_NLINK_PROTO_FAMILY,
|
||||||
|
&cfg);
|
||||||
|
|
||||||
|
if (nl_srv_sock != NULL) {
|
||||||
|
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 != NULL) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 = 0;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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 = 0;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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[%p], len[%d], nlhdr[%p], 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(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||||
|
"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(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||||
|
"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(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||||
|
"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] != NULL) {
|
||||||
|
(nl_srv_msg_handler[type])(skb);
|
||||||
|
} else {
|
||||||
|
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
|
||||||
|
"NLINK: No handler for Netlink 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;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#else /* ifndef MULTI_IF_NAME */
|
||||||
|
|
||||||
|
#include <wlan_nlink_srv.h>
|
||||||
|
|
||||||
|
int nl_srv_init(void *wiphy)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nl_srv_bcast(struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nl_srv_is_initialized(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
39
utils/pktlog/include/pktlog.h
Normal file
39
utils/pktlog/include/pktlog.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014, 2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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_ */
|
186
utils/pktlog/include/pktlog_ac.h
Normal file
186
utils/pktlog/include/pktlog_ac.h
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PKTLOG_AC_H_
|
||||||
|
#define _PKTLOG_AC_H_
|
||||||
|
#ifndef REMOVE_PKT_LOG
|
||||||
|
|
||||||
|
#include "ol_if_athvar.h"
|
||||||
|
#include <pktlog_ac_api.h>
|
||||||
|
#include <pktlog_ac_fmt.h>
|
||||||
|
#include "osdep.h"
|
||||||
|
#include <wmi_unified.h>
|
||||||
|
#include <wmi_unified_api.h>
|
||||||
|
#include <wdi_event_api.h>
|
||||||
|
#include "hif.h"
|
||||||
|
|
||||||
|
#define NO_REG_FUNCS 4
|
||||||
|
|
||||||
|
/* Locking interface for pktlog */
|
||||||
|
#define PKTLOG_LOCK_INIT(_pl_info) spin_lock_init(&(_pl_info)->log_lock)
|
||||||
|
#define PKTLOG_LOCK_DESTROY(_pl_info)
|
||||||
|
#define PKTLOG_LOCK(_pl_info) spin_lock(&(_pl_info)->log_lock)
|
||||||
|
#define PKTLOG_UNLOCK(_pl_info) spin_unlock(&(_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
|
||||||
|
|
||||||
|
/* 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(ol_txrx_pdev_handle pdev_txrx_handle);
|
||||||
|
|
||||||
|
ssize_t pktlog_read_proc_entry(char *buf, size_t nbytes, loff_t *ppos,
|
||||||
|
struct ath_pktlog_info *pl_info, bool *read_complete);
|
||||||
|
int pktlog_send_per_pkt_stats_to_user(void);
|
||||||
|
A_STATUS
|
||||||
|
wdi_pktlog_unsubscribe(struct ol_txrx_pdev_t *txrx_pdev, 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 ol_txrx_pdev_t *handle);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
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 ol_pktlog_dev_t {
|
||||||
|
struct ol_pl_arch_dep_funcs *pl_funcs;
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
ol_ath_generic_softc_handle scn;
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PKTLOG_SYSCTL_SIZE 14
|
||||||
|
#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))
|
||||||
|
|
||||||
|
extern struct ol_pktlog_dev_t ol_pl_dev;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WDI related data and functions
|
||||||
|
* Callback function to the WDI events
|
||||||
|
*/
|
||||||
|
void pktlog_callback(void *pdev, enum WDI_EVENT event, void *log_data);
|
||||||
|
|
||||||
|
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_setsize(struct hif_opaque_softc *scn, int32_t log_state);
|
||||||
|
int pktlog_disable(struct hif_opaque_softc *scn);
|
||||||
|
int pktlogmod_init(void *context);
|
||||||
|
void pktlogmod_exit(struct ol_txrx_pdev_t *handle);
|
||||||
|
int pktlog_htc_attach(void);
|
||||||
|
void pktlog_process_fw_msg(uint32_t *msg_word);
|
||||||
|
|
||||||
|
#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 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 int pktlog_setsize(struct hif_opaque_softc *scn, int32_t log_state)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static 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(uint32_t *msg_word)
|
||||||
|
{ }
|
||||||
|
#endif /* REMOVE_PKT_LOG */
|
||||||
|
#endif /* _PKTLOG_AC_H_ */
|
114
utils/pktlog/include/pktlog_ac_api.h
Normal file
114
utils/pktlog/include/pktlog_ac_api.h
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012-2014, 2016-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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_
|
||||||
|
#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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef hif_opaque_softc_handle
|
||||||
|
* @brief opaque handle for hif_opaque_softc
|
||||||
|
*/
|
||||||
|
struct hif_opaque_softc;
|
||||||
|
typedef struct hif_opaque_softc *hif_opaque_softc_handle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef net_device_handle
|
||||||
|
* @brief opaque handle linux phy device object
|
||||||
|
*/
|
||||||
|
struct net_device;
|
||||||
|
typedef struct net_device *net_device_handle;
|
||||||
|
|
||||||
|
void ol_pl_sethandle(ol_pktlog_dev_handle *pl_handle,
|
||||||
|
hif_opaque_softc_handle scn);
|
||||||
|
|
||||||
|
/* Packet log state information */
|
||||||
|
#ifndef _PKTLOG_INFO
|
||||||
|
#define _PKTLOG_INFO
|
||||||
|
struct ath_pktlog_info {
|
||||||
|
struct ath_pktlog_buf *buf;
|
||||||
|
uint32_t log_state;
|
||||||
|
uint32_t saved_state;
|
||||||
|
uint32_t options;
|
||||||
|
|
||||||
|
/* Size of buffer in bytes */
|
||||||
|
int32_t buf_size;
|
||||||
|
spinlock_t log_lock;
|
||||||
|
|
||||||
|
/* 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 milisecond */
|
||||||
|
uint32_t trigger_interval;
|
||||||
|
uint32_t start_time_thruput;
|
||||||
|
uint32_t start_time_per;
|
||||||
|
};
|
||||||
|
#endif /* _PKTLOG_INFO */
|
||||||
|
#else /* REMOVE_PKT_LOG */
|
||||||
|
typedef void *ol_pktlog_dev_handle;
|
||||||
|
#define ol_pl_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_ */
|
78
utils/pktlog/include/pktlog_ac_i.h
Normal file
78
utils/pktlog/include/pktlog_ac_i.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PKTLOG_AC_I_
|
||||||
|
#define _PKTLOG_AC_I_
|
||||||
|
#ifndef REMOVE_PKT_LOG
|
||||||
|
|
||||||
|
#include <ol_txrx_internal.h>
|
||||||
|
#include <pktlog_ac.h>
|
||||||
|
|
||||||
|
#ifdef FEATURE_PKTLOG
|
||||||
|
#define PKTLOG_DEFAULT_BUFSIZE (10 * 1024 * 1024) /* 10MB */
|
||||||
|
#else
|
||||||
|
#define PKTLOG_DEFAULT_BUFSIZE (1 * 1024 * 1024) /* 1MB */
|
||||||
|
#endif
|
||||||
|
#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
|
||||||
|
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 HELIUMPLUS
|
||||||
|
uint32_t type_specific_data;
|
||||||
|
#endif
|
||||||
|
char *buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
void pktlog_getbuf_intsafe(struct ath_pktlog_arg *plarg);
|
||||||
|
char *pktlog_getbuf(struct ol_pktlog_dev_t *pl_dev,
|
||||||
|
struct ath_pktlog_info *pl_info,
|
||||||
|
size_t log_size, struct ath_pktlog_hdr *pl_hdr);
|
||||||
|
|
||||||
|
A_STATUS process_tx_info(struct ol_txrx_pdev_t *pdev, void *data);
|
||||||
|
A_STATUS process_rx_info(void *pdev, void *data);
|
||||||
|
A_STATUS process_rx_info_remote(void *pdev, void *data);
|
||||||
|
A_STATUS process_rate_find(void *pdev, void *data);
|
||||||
|
A_STATUS process_rate_update(void *pdev, void *data);
|
||||||
|
A_STATUS process_sw_event(void *pdev, void *data);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* REMOVE_PKT_LOG */
|
||||||
|
#endif
|
931
utils/pktlog/linux_ac.c
Normal file
931
utils/pktlog/linux_ac.c
Normal file
@@ -0,0 +1,931 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef REMOVE_PKT_LOG
|
||||||
|
#ifndef EXPORT_SYMTAB
|
||||||
|
#define EXPORT_SYMTAB
|
||||||
|
#endif
|
||||||
|
#ifndef __KERNEL__
|
||||||
|
#define __KERNEL__
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Linux specific implementation of Pktlogs for 802.11ac
|
||||||
|
*/
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/proc_fs.h>
|
||||||
|
#include <pktlog_ac_i.h>
|
||||||
|
#include <pktlog_ac_fmt.h>
|
||||||
|
#include <pktlog_ac.h>
|
||||||
|
#include "i_host_diag_core_log.h"
|
||||||
|
#include "host_diag_core_log.h"
|
||||||
|
#include "ani_global.h"
|
||||||
|
|
||||||
|
#define PKTLOG_TAG "ATH_PKTLOG"
|
||||||
|
#define PKTLOG_DEVNAME_SIZE 32
|
||||||
|
#define MAX_WLANDEV 1
|
||||||
|
|
||||||
|
#ifdef MULTI_IF_NAME
|
||||||
|
#define PKTLOG_PROC_DIR "ath_pktlog" MULTI_IF_NAME
|
||||||
|
#else
|
||||||
|
#define PKTLOG_PROC_DIR "ath_pktlog"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Permissions for creating proc entries */
|
||||||
|
#define PKTLOG_PROC_PERM 0444
|
||||||
|
#define PKTLOG_PROCSYS_DIR_PERM 0555
|
||||||
|
#define PKTLOG_PROCSYS_PERM 0644
|
||||||
|
|
||||||
|
#ifndef __MOD_INC_USE_COUNT
|
||||||
|
#define PKTLOG_MOD_INC_USE_COUNT do { \
|
||||||
|
if (!try_module_get(THIS_MODULE)) { \
|
||||||
|
printk(KERN_WARNING "try_module_get failed\n"); \
|
||||||
|
} } while (0)
|
||||||
|
|
||||||
|
#define PKTLOG_MOD_DEC_USE_COUNT module_put(THIS_MODULE)
|
||||||
|
#else
|
||||||
|
#define PKTLOG_MOD_INC_USE_COUNT MOD_INC_USE_COUNT
|
||||||
|
#define PKTLOG_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct ath_pktlog_info *g_pktlog_info;
|
||||||
|
|
||||||
|
static struct proc_dir_entry *g_pktlog_pde;
|
||||||
|
|
||||||
|
static int pktlog_attach(struct hif_opaque_softc *sc);
|
||||||
|
static void pktlog_detach(struct ol_txrx_pdev_t *handle);
|
||||||
|
static int pktlog_open(struct inode *i, struct file *f);
|
||||||
|
static int pktlog_release(struct inode *i, struct file *f);
|
||||||
|
static int pktlog_mmap(struct file *f, struct vm_area_struct *vma);
|
||||||
|
static ssize_t pktlog_read(struct file *file, char *buf, size_t nbytes,
|
||||||
|
loff_t *ppos);
|
||||||
|
|
||||||
|
static struct file_operations pktlog_fops = {
|
||||||
|
open: pktlog_open,
|
||||||
|
release:pktlog_release,
|
||||||
|
mmap : pktlog_mmap,
|
||||||
|
read : pktlog_read,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Linux implementation of helper functions
|
||||||
|
*/
|
||||||
|
static struct ol_pktlog_dev_t *cds_get_pl_handle(void)
|
||||||
|
{
|
||||||
|
ol_txrx_pdev_handle pdev_txrx_handle;
|
||||||
|
pdev_txrx_handle = cds_get_context(QDF_MODULE_ID_TXRX);
|
||||||
|
if (!pdev_txrx_handle) {
|
||||||
|
QDF_ASSERT(0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return pdev_txrx_handle->pl_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ol_pktlog_dev_t *ol_get_pl_handle(
|
||||||
|
ol_txrx_pdev_handle pdev_txrx_handle)
|
||||||
|
{
|
||||||
|
if (!pdev_txrx_handle)
|
||||||
|
return NULL;
|
||||||
|
return pdev_txrx_handle->pl_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pktlog_disable_adapter_logging(struct hif_opaque_softc *scn)
|
||||||
|
{
|
||||||
|
struct ol_pktlog_dev_t *pl_dev = cds_get_pl_handle();
|
||||||
|
if (pl_dev)
|
||||||
|
pl_dev->pl_info->log_state = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pktlog_alloc_buf(struct hif_opaque_softc *scn)
|
||||||
|
{
|
||||||
|
uint32_t page_cnt;
|
||||||
|
unsigned long vaddr;
|
||||||
|
struct page *vpg;
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
ol_txrx_pdev_handle pdev_txrx_handle;
|
||||||
|
pdev_txrx_handle = cds_get_context(QDF_MODULE_ID_TXRX);
|
||||||
|
|
||||||
|
if (!pdev_txrx_handle || !pdev_txrx_handle->pl_dev) {
|
||||||
|
printk(PKTLOG_TAG
|
||||||
|
"%s: Unable to allocate buffer "
|
||||||
|
"scn or scn->pdev_txrx_handle->pl_dev is null\n",
|
||||||
|
__func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_info = pdev_txrx_handle->pl_dev->pl_info;
|
||||||
|
|
||||||
|
page_cnt = (sizeof(*(pl_info->buf)) + pl_info->buf_size) / PAGE_SIZE;
|
||||||
|
|
||||||
|
pl_info->buf = vmalloc((page_cnt + 2) * PAGE_SIZE);
|
||||||
|
if (pl_info->buf == NULL) {
|
||||||
|
printk(PKTLOG_TAG
|
||||||
|
"%s: Unable to allocate buffer "
|
||||||
|
"(%d pages)\n", __func__, page_cnt);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_info->buf = (struct ath_pktlog_buf *)
|
||||||
|
(((unsigned long)(pl_info->buf) + PAGE_SIZE - 1)
|
||||||
|
& PAGE_MASK);
|
||||||
|
|
||||||
|
for (vaddr = (unsigned long)(pl_info->buf);
|
||||||
|
vaddr < ((unsigned long)(pl_info->buf) + (page_cnt * PAGE_SIZE));
|
||||||
|
vaddr += PAGE_SIZE) {
|
||||||
|
vpg = vmalloc_to_page((const void *)vaddr);
|
||||||
|
SetPageReserved(vpg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pktlog_release_buf(ol_txrx_pdev_handle pdev_txrx_handle)
|
||||||
|
{
|
||||||
|
unsigned long page_cnt;
|
||||||
|
unsigned long vaddr;
|
||||||
|
struct page *vpg;
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
|
||||||
|
if (!pdev_txrx_handle || !pdev_txrx_handle->pl_dev) {
|
||||||
|
printk(PKTLOG_TAG
|
||||||
|
"%s: Unable to allocate buffer"
|
||||||
|
"scn or scn->pdev_txrx_handle->pl_dev is null\n",
|
||||||
|
__func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_info = pdev_txrx_handle->pl_dev->pl_info;
|
||||||
|
|
||||||
|
page_cnt = ((sizeof(*(pl_info->buf)) + pl_info->buf_size) /
|
||||||
|
PAGE_SIZE) + 1;
|
||||||
|
|
||||||
|
for (vaddr = (unsigned long)(pl_info->buf);
|
||||||
|
vaddr < (unsigned long)(pl_info->buf) + (page_cnt * PAGE_SIZE);
|
||||||
|
vaddr += PAGE_SIZE) {
|
||||||
|
vpg = vmalloc_to_page((const void *)vaddr);
|
||||||
|
ClearPageReserved(vpg);
|
||||||
|
}
|
||||||
|
|
||||||
|
vfree(pl_info->buf);
|
||||||
|
pl_info->buf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pktlog_cleanup(struct ath_pktlog_info *pl_info)
|
||||||
|
{
|
||||||
|
pl_info->log_state = 0;
|
||||||
|
PKTLOG_LOCK_DESTROY(pl_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sysctl procfs handler to enable pktlog */
|
||||||
|
static int
|
||||||
|
qdf_sysctl_decl(ath_sysctl_pktlog_enable, ctl, write, filp, buffer, lenp, ppos)
|
||||||
|
{
|
||||||
|
int ret, enable;
|
||||||
|
ol_ath_generic_softc_handle scn;
|
||||||
|
struct ol_pktlog_dev_t *pl_dev;
|
||||||
|
|
||||||
|
scn = (ol_ath_generic_softc_handle) ctl->extra1;
|
||||||
|
|
||||||
|
if (!scn) {
|
||||||
|
printk("%s: Invalid scn context\n", __func__);
|
||||||
|
ASSERT(0);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_dev = cds_get_pl_handle();
|
||||||
|
|
||||||
|
if (!pl_dev) {
|
||||||
|
printk("%s: Invalid pktlog context\n", __func__);
|
||||||
|
ASSERT(0);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctl->data = &enable;
|
||||||
|
ctl->maxlen = sizeof(enable);
|
||||||
|
|
||||||
|
if (write) {
|
||||||
|
ret = QDF_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
|
||||||
|
lenp, ppos);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = pl_dev->pl_funcs->pktlog_enable(
|
||||||
|
(struct hif_opaque_softc *)scn, enable,
|
||||||
|
cds_is_packet_log_enabled(), 0, 1);
|
||||||
|
else
|
||||||
|
printk(PKTLOG_TAG "%s:proc_dointvec failed\n",
|
||||||
|
__func__);
|
||||||
|
} else {
|
||||||
|
ret = QDF_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
|
||||||
|
lenp, ppos);
|
||||||
|
if (ret)
|
||||||
|
printk(PKTLOG_TAG "%s:proc_dointvec failed\n",
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctl->data = NULL;
|
||||||
|
ctl->maxlen = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_pktlog_bufsize(struct ol_pktlog_dev_t *pl_dev)
|
||||||
|
{
|
||||||
|
return pl_dev->pl_info->buf_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sysctl procfs handler to set/get pktlog size */
|
||||||
|
static int
|
||||||
|
qdf_sysctl_decl(ath_sysctl_pktlog_size, ctl, write, filp, buffer, lenp, ppos)
|
||||||
|
{
|
||||||
|
int ret, size;
|
||||||
|
ol_ath_generic_softc_handle scn;
|
||||||
|
struct ol_pktlog_dev_t *pl_dev;
|
||||||
|
|
||||||
|
scn = (ol_ath_generic_softc_handle) ctl->extra1;
|
||||||
|
|
||||||
|
if (!scn) {
|
||||||
|
printk("%s: Invalid scn context\n", __func__);
|
||||||
|
ASSERT(0);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_dev = cds_get_pl_handle();
|
||||||
|
|
||||||
|
if (!pl_dev) {
|
||||||
|
printk("%s: Invalid pktlog handle\n", __func__);
|
||||||
|
ASSERT(0);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctl->data = &size;
|
||||||
|
ctl->maxlen = sizeof(size);
|
||||||
|
|
||||||
|
if (write) {
|
||||||
|
ret = QDF_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
|
||||||
|
lenp, ppos);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = pl_dev->pl_funcs->pktlog_setsize(
|
||||||
|
(struct hif_opaque_softc *)scn, size);
|
||||||
|
} else {
|
||||||
|
size = get_pktlog_bufsize(pl_dev);
|
||||||
|
ret = QDF_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
|
||||||
|
lenp, ppos);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctl->data = NULL;
|
||||||
|
ctl->maxlen = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Register sysctl table */
|
||||||
|
static int pktlog_sysctl_register(struct hif_opaque_softc *scn)
|
||||||
|
{
|
||||||
|
struct ol_pktlog_dev_t *pl_dev = cds_get_pl_handle();
|
||||||
|
struct ath_pktlog_info_lnx *pl_info_lnx;
|
||||||
|
char *proc_name;
|
||||||
|
|
||||||
|
if (pl_dev) {
|
||||||
|
pl_info_lnx = PL_INFO_LNX(pl_dev->pl_info);
|
||||||
|
proc_name = pl_dev->name;
|
||||||
|
} else {
|
||||||
|
pl_info_lnx = PL_INFO_LNX(g_pktlog_info);
|
||||||
|
proc_name = PKTLOG_PROC_SYSTEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the sysctl table for creating the following sysctl entries:
|
||||||
|
* /proc/sys/PKTLOG_PROC_DIR/<adapter>/enable for enabling/disabling
|
||||||
|
* pktlog
|
||||||
|
* /proc/sys/PKTLOG_PROC_DIR/<adapter>/size for changing the buffer size
|
||||||
|
*/
|
||||||
|
memset(pl_info_lnx->sysctls, 0, sizeof(pl_info_lnx->sysctls));
|
||||||
|
pl_info_lnx->sysctls[0].procname = PKTLOG_PROC_DIR;
|
||||||
|
pl_info_lnx->sysctls[0].mode = PKTLOG_PROCSYS_DIR_PERM;
|
||||||
|
pl_info_lnx->sysctls[0].child = &pl_info_lnx->sysctls[2];
|
||||||
|
|
||||||
|
/* [1] is NULL terminator */
|
||||||
|
pl_info_lnx->sysctls[2].procname = proc_name;
|
||||||
|
pl_info_lnx->sysctls[2].mode = PKTLOG_PROCSYS_DIR_PERM;
|
||||||
|
pl_info_lnx->sysctls[2].child = &pl_info_lnx->sysctls[4];
|
||||||
|
|
||||||
|
/* [3] is NULL terminator */
|
||||||
|
pl_info_lnx->sysctls[4].procname = "enable";
|
||||||
|
pl_info_lnx->sysctls[4].mode = PKTLOG_PROCSYS_PERM;
|
||||||
|
pl_info_lnx->sysctls[4].proc_handler = ath_sysctl_pktlog_enable;
|
||||||
|
pl_info_lnx->sysctls[4].extra1 = scn;
|
||||||
|
|
||||||
|
pl_info_lnx->sysctls[5].procname = "size";
|
||||||
|
pl_info_lnx->sysctls[5].mode = PKTLOG_PROCSYS_PERM;
|
||||||
|
pl_info_lnx->sysctls[5].proc_handler = ath_sysctl_pktlog_size;
|
||||||
|
pl_info_lnx->sysctls[5].extra1 = scn;
|
||||||
|
|
||||||
|
pl_info_lnx->sysctls[6].procname = "options";
|
||||||
|
pl_info_lnx->sysctls[6].mode = PKTLOG_PROCSYS_PERM;
|
||||||
|
pl_info_lnx->sysctls[6].proc_handler = proc_dointvec;
|
||||||
|
pl_info_lnx->sysctls[6].data = &pl_info_lnx->info.options;
|
||||||
|
pl_info_lnx->sysctls[6].maxlen = sizeof(pl_info_lnx->info.options);
|
||||||
|
|
||||||
|
pl_info_lnx->sysctls[7].procname = "sack_thr";
|
||||||
|
pl_info_lnx->sysctls[7].mode = PKTLOG_PROCSYS_PERM;
|
||||||
|
pl_info_lnx->sysctls[7].proc_handler = proc_dointvec;
|
||||||
|
pl_info_lnx->sysctls[7].data = &pl_info_lnx->info.sack_thr;
|
||||||
|
pl_info_lnx->sysctls[7].maxlen = sizeof(pl_info_lnx->info.sack_thr);
|
||||||
|
|
||||||
|
pl_info_lnx->sysctls[8].procname = "tail_length";
|
||||||
|
pl_info_lnx->sysctls[8].mode = PKTLOG_PROCSYS_PERM;
|
||||||
|
pl_info_lnx->sysctls[8].proc_handler = proc_dointvec;
|
||||||
|
pl_info_lnx->sysctls[8].data = &pl_info_lnx->info.tail_length;
|
||||||
|
pl_info_lnx->sysctls[8].maxlen = sizeof(pl_info_lnx->info.tail_length);
|
||||||
|
|
||||||
|
pl_info_lnx->sysctls[9].procname = "thruput_thresh";
|
||||||
|
pl_info_lnx->sysctls[9].mode = PKTLOG_PROCSYS_PERM;
|
||||||
|
pl_info_lnx->sysctls[9].proc_handler = proc_dointvec;
|
||||||
|
pl_info_lnx->sysctls[9].data = &pl_info_lnx->info.thruput_thresh;
|
||||||
|
pl_info_lnx->sysctls[9].maxlen =
|
||||||
|
sizeof(pl_info_lnx->info.thruput_thresh);
|
||||||
|
|
||||||
|
pl_info_lnx->sysctls[10].procname = "phyerr_thresh";
|
||||||
|
pl_info_lnx->sysctls[10].mode = PKTLOG_PROCSYS_PERM;
|
||||||
|
pl_info_lnx->sysctls[10].proc_handler = proc_dointvec;
|
||||||
|
pl_info_lnx->sysctls[10].data = &pl_info_lnx->info.phyerr_thresh;
|
||||||
|
pl_info_lnx->sysctls[10].maxlen =
|
||||||
|
sizeof(pl_info_lnx->info.phyerr_thresh);
|
||||||
|
|
||||||
|
pl_info_lnx->sysctls[11].procname = "per_thresh";
|
||||||
|
pl_info_lnx->sysctls[11].mode = PKTLOG_PROCSYS_PERM;
|
||||||
|
pl_info_lnx->sysctls[11].proc_handler = proc_dointvec;
|
||||||
|
pl_info_lnx->sysctls[11].data = &pl_info_lnx->info.per_thresh;
|
||||||
|
pl_info_lnx->sysctls[11].maxlen = sizeof(pl_info_lnx->info.per_thresh);
|
||||||
|
|
||||||
|
pl_info_lnx->sysctls[12].procname = "trigger_interval";
|
||||||
|
pl_info_lnx->sysctls[12].mode = PKTLOG_PROCSYS_PERM;
|
||||||
|
pl_info_lnx->sysctls[12].proc_handler = proc_dointvec;
|
||||||
|
pl_info_lnx->sysctls[12].data = &pl_info_lnx->info.trigger_interval;
|
||||||
|
pl_info_lnx->sysctls[12].maxlen =
|
||||||
|
sizeof(pl_info_lnx->info.trigger_interval);
|
||||||
|
/* [13] is NULL terminator */
|
||||||
|
|
||||||
|
/* and register everything */
|
||||||
|
/* register_sysctl_table changed from 2.6.21 onwards */
|
||||||
|
pl_info_lnx->sysctl_header =
|
||||||
|
register_sysctl_table(pl_info_lnx->sysctls);
|
||||||
|
|
||||||
|
if (!pl_info_lnx->sysctl_header) {
|
||||||
|
printk("%s: failed to register sysctls!\n", proc_name);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize logging for system or adapter
|
||||||
|
* Parameter scn should be NULL for system wide logging
|
||||||
|
*/
|
||||||
|
static int pktlog_attach(struct hif_opaque_softc *scn)
|
||||||
|
{
|
||||||
|
struct ol_pktlog_dev_t *pl_dev;
|
||||||
|
struct ath_pktlog_info_lnx *pl_info_lnx;
|
||||||
|
char *proc_name;
|
||||||
|
struct proc_dir_entry *proc_entry;
|
||||||
|
|
||||||
|
pl_dev = cds_get_pl_handle();
|
||||||
|
|
||||||
|
if (pl_dev != NULL) {
|
||||||
|
pl_info_lnx = kmalloc(sizeof(*pl_info_lnx), GFP_KERNEL);
|
||||||
|
if (pl_info_lnx == NULL) {
|
||||||
|
printk(PKTLOG_TAG "%s:allocation failed for pl_info\n",
|
||||||
|
__func__);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
pl_dev->pl_info = &pl_info_lnx->info;
|
||||||
|
pl_dev->name = WLANDEV_BASENAME;
|
||||||
|
proc_name = pl_dev->name;
|
||||||
|
if (!pl_dev->pl_funcs)
|
||||||
|
pl_dev->pl_funcs = &ol_pl_funcs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Valid for both direct attach and offload architecture
|
||||||
|
*/
|
||||||
|
pl_dev->pl_funcs->pktlog_init(scn);
|
||||||
|
} else {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* initialize log info
|
||||||
|
* might be good to move to pktlog_init
|
||||||
|
*/
|
||||||
|
/* pl_dev->tgt_pktlog_alloced = false; */
|
||||||
|
pl_dev->vendor_cmd_send = false;
|
||||||
|
pl_info_lnx->proc_entry = NULL;
|
||||||
|
pl_info_lnx->sysctl_header = NULL;
|
||||||
|
|
||||||
|
proc_entry = proc_create_data(proc_name, PKTLOG_PROC_PERM,
|
||||||
|
g_pktlog_pde, &pktlog_fops,
|
||||||
|
&pl_info_lnx->info);
|
||||||
|
|
||||||
|
if (proc_entry == NULL) {
|
||||||
|
printk(PKTLOG_TAG "%s: create_proc_entry failed for %s\n",
|
||||||
|
__func__, proc_name);
|
||||||
|
goto attach_fail1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_info_lnx->proc_entry = proc_entry;
|
||||||
|
|
||||||
|
if (pktlog_sysctl_register(scn)) {
|
||||||
|
printk(PKTLOG_TAG "%s: sysctl register failed for %s\n",
|
||||||
|
__func__, proc_name);
|
||||||
|
goto attach_fail2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
attach_fail2:
|
||||||
|
remove_proc_entry(proc_name, g_pktlog_pde);
|
||||||
|
|
||||||
|
attach_fail1:
|
||||||
|
if (pl_dev)
|
||||||
|
kfree(pl_dev->pl_info);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pktlog_sysctl_unregister(struct ol_pktlog_dev_t *pl_dev)
|
||||||
|
{
|
||||||
|
struct ath_pktlog_info_lnx *pl_info_lnx;
|
||||||
|
|
||||||
|
if (!pl_dev) {
|
||||||
|
printk("%s: Invalid pktlog context\n", __func__);
|
||||||
|
ASSERT(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_info_lnx = (pl_dev) ? PL_INFO_LNX(pl_dev->pl_info) :
|
||||||
|
PL_INFO_LNX(g_pktlog_info);
|
||||||
|
|
||||||
|
if (pl_info_lnx->sysctl_header) {
|
||||||
|
unregister_sysctl_table(pl_info_lnx->sysctl_header);
|
||||||
|
pl_info_lnx->sysctl_header = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pktlog_detach(struct ol_txrx_pdev_t *handle)
|
||||||
|
{
|
||||||
|
struct ol_txrx_pdev_t *txrx_pdev;
|
||||||
|
struct ol_pktlog_dev_t *pl_dev;
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
|
||||||
|
txrx_pdev = handle;
|
||||||
|
if (!txrx_pdev) {
|
||||||
|
printk("%s: Invalid txrx_pdev context\n", __func__);
|
||||||
|
ASSERT(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_dev = txrx_pdev->pl_dev;
|
||||||
|
if (!pl_dev) {
|
||||||
|
printk("%s: Invalid pktlog context\n", __func__);
|
||||||
|
ASSERT(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_info = pl_dev->pl_info;
|
||||||
|
remove_proc_entry(WLANDEV_BASENAME, g_pktlog_pde);
|
||||||
|
pktlog_sysctl_unregister(pl_dev);
|
||||||
|
pktlog_cleanup(pl_info);
|
||||||
|
|
||||||
|
if (pl_info->buf) {
|
||||||
|
pktlog_release_buf(txrx_pdev);
|
||||||
|
pl_dev->tgt_pktlog_alloced = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pl_dev) {
|
||||||
|
kfree(pl_info);
|
||||||
|
pl_dev->pl_info = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pktlog_open(struct inode *i, struct file *f)
|
||||||
|
{
|
||||||
|
PKTLOG_MOD_INC_USE_COUNT;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pktlog_release(struct inode *i, struct file *f)
|
||||||
|
{
|
||||||
|
PKTLOG_MOD_DEC_USE_COUNT;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef MIN
|
||||||
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktlog_read_proc_entry() - This function is used to read data from the
|
||||||
|
* proc entry into the readers buffer
|
||||||
|
* @buf: Readers buffer
|
||||||
|
* @nbytes: Number of bytes to read
|
||||||
|
* @ppos: Offset within the drivers buffer
|
||||||
|
* @pl_info: Packet log information pointer
|
||||||
|
* @read_complete: Boolean value indication whether read is complete
|
||||||
|
*
|
||||||
|
* This function is used to read data from the proc entry into the readers
|
||||||
|
* buffer. Its functionality is similar to 'pktlog_read' which does
|
||||||
|
* copy to user to the user space buffer
|
||||||
|
*
|
||||||
|
* Return: Number of bytes read from the buffer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
pktlog_read_proc_entry(char *buf, size_t nbytes, loff_t *ppos,
|
||||||
|
struct ath_pktlog_info *pl_info, bool *read_complete)
|
||||||
|
{
|
||||||
|
size_t bufhdr_size;
|
||||||
|
size_t count = 0, ret_val = 0;
|
||||||
|
int rem_len;
|
||||||
|
int start_offset, end_offset;
|
||||||
|
int fold_offset, ppos_data, cur_rd_offset, cur_wr_offset;
|
||||||
|
struct ath_pktlog_buf *log_buf = pl_info->buf;
|
||||||
|
*read_complete = false;
|
||||||
|
|
||||||
|
if (log_buf == NULL) {
|
||||||
|
*read_complete = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*ppos == 0 && pl_info->log_state) {
|
||||||
|
pl_info->saved_state = pl_info->log_state;
|
||||||
|
pl_info->log_state = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufhdr_size = sizeof(log_buf->bufhdr);
|
||||||
|
|
||||||
|
/* copy valid log entries from circular buffer into user space */
|
||||||
|
rem_len = nbytes;
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
if (*ppos < bufhdr_size) {
|
||||||
|
count = MIN((bufhdr_size - *ppos), rem_len);
|
||||||
|
qdf_mem_copy(buf, ((char *)&log_buf->bufhdr) + *ppos,
|
||||||
|
count);
|
||||||
|
rem_len -= count;
|
||||||
|
ret_val += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_offset = log_buf->rd_offset;
|
||||||
|
cur_wr_offset = log_buf->wr_offset;
|
||||||
|
|
||||||
|
if ((rem_len == 0) || (start_offset < 0))
|
||||||
|
goto rd_done;
|
||||||
|
|
||||||
|
fold_offset = -1;
|
||||||
|
cur_rd_offset = start_offset;
|
||||||
|
|
||||||
|
/* Find the last offset and fold-offset if the buffer is folded */
|
||||||
|
do {
|
||||||
|
struct ath_pktlog_hdr *log_hdr;
|
||||||
|
int log_data_offset;
|
||||||
|
|
||||||
|
log_hdr = (struct ath_pktlog_hdr *) (log_buf->log_data +
|
||||||
|
cur_rd_offset);
|
||||||
|
|
||||||
|
log_data_offset = cur_rd_offset + sizeof(struct ath_pktlog_hdr);
|
||||||
|
|
||||||
|
if ((fold_offset == -1)
|
||||||
|
&& ((pl_info->buf_size - log_data_offset)
|
||||||
|
<= log_hdr->size))
|
||||||
|
fold_offset = log_data_offset - 1;
|
||||||
|
|
||||||
|
PKTLOG_MOV_RD_IDX(cur_rd_offset, log_buf, pl_info->buf_size);
|
||||||
|
|
||||||
|
if ((fold_offset == -1) && (cur_rd_offset == 0)
|
||||||
|
&& (cur_rd_offset != cur_wr_offset))
|
||||||
|
fold_offset = log_data_offset + log_hdr->size - 1;
|
||||||
|
|
||||||
|
end_offset = log_data_offset + log_hdr->size - 1;
|
||||||
|
} while (cur_rd_offset != cur_wr_offset);
|
||||||
|
|
||||||
|
ppos_data = *ppos + ret_val - bufhdr_size + start_offset;
|
||||||
|
|
||||||
|
if (fold_offset == -1) {
|
||||||
|
if (ppos_data > end_offset)
|
||||||
|
goto rd_done;
|
||||||
|
|
||||||
|
count = MIN(rem_len, (end_offset - ppos_data + 1));
|
||||||
|
qdf_mem_copy(buf + ret_val,
|
||||||
|
log_buf->log_data + ppos_data,
|
||||||
|
count);
|
||||||
|
ret_val += count;
|
||||||
|
rem_len -= count;
|
||||||
|
} else {
|
||||||
|
if (ppos_data <= fold_offset) {
|
||||||
|
count = MIN(rem_len, (fold_offset - ppos_data + 1));
|
||||||
|
qdf_mem_copy(buf + ret_val,
|
||||||
|
log_buf->log_data + ppos_data,
|
||||||
|
count);
|
||||||
|
ret_val += count;
|
||||||
|
rem_len -= count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rem_len == 0)
|
||||||
|
goto rd_done;
|
||||||
|
|
||||||
|
ppos_data =
|
||||||
|
*ppos + ret_val - (bufhdr_size +
|
||||||
|
(fold_offset - start_offset + 1));
|
||||||
|
|
||||||
|
if (ppos_data <= end_offset) {
|
||||||
|
count = MIN(rem_len, (end_offset - ppos_data + 1));
|
||||||
|
qdf_mem_copy(buf + ret_val,
|
||||||
|
log_buf->log_data + ppos_data,
|
||||||
|
count);
|
||||||
|
ret_val += count;
|
||||||
|
rem_len -= count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rd_done:
|
||||||
|
if ((ret_val < nbytes) && pl_info->saved_state) {
|
||||||
|
pl_info->log_state = pl_info->saved_state;
|
||||||
|
pl_info->saved_state = 0;
|
||||||
|
}
|
||||||
|
*ppos += ret_val;
|
||||||
|
|
||||||
|
if (ret_val == 0) {
|
||||||
|
PKTLOG_LOCK(pl_info);
|
||||||
|
/* Write pointer might have been updated during the read.
|
||||||
|
* So, if some data is written into, lets not reset the pointers
|
||||||
|
* We can continue to read from the offset position
|
||||||
|
*/
|
||||||
|
if (cur_wr_offset != log_buf->wr_offset) {
|
||||||
|
*read_complete = false;
|
||||||
|
} else {
|
||||||
|
pl_info->buf->rd_offset = -1;
|
||||||
|
pl_info->buf->wr_offset = 0;
|
||||||
|
pl_info->buf->bytes_written = 0;
|
||||||
|
pl_info->buf->offset = PKTLOG_READ_OFFSET;
|
||||||
|
*read_complete = true;
|
||||||
|
}
|
||||||
|
PKTLOG_UNLOCK(pl_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
pktlog_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
|
||||||
|
{
|
||||||
|
size_t bufhdr_size;
|
||||||
|
size_t count = 0, ret_val = 0;
|
||||||
|
int rem_len;
|
||||||
|
int start_offset, end_offset;
|
||||||
|
int fold_offset, ppos_data, cur_rd_offset;
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
struct ath_pktlog_buf *log_buf;
|
||||||
|
|
||||||
|
pl_info = (struct ath_pktlog_info *)
|
||||||
|
PDE_DATA(file->f_path.dentry->d_inode);
|
||||||
|
if (!pl_info)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
log_buf = pl_info->buf;
|
||||||
|
|
||||||
|
if (log_buf == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (pl_info->log_state) {
|
||||||
|
/* Read is not allowed when write is going on
|
||||||
|
* When issuing cat command, ensure to send
|
||||||
|
* pktlog disable command first.
|
||||||
|
*/
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*ppos == 0 && pl_info->log_state) {
|
||||||
|
pl_info->saved_state = pl_info->log_state;
|
||||||
|
pl_info->log_state = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufhdr_size = sizeof(log_buf->bufhdr);
|
||||||
|
|
||||||
|
/* copy valid log entries from circular buffer into user space */
|
||||||
|
rem_len = nbytes;
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
if (*ppos < bufhdr_size) {
|
||||||
|
count = QDF_MIN((bufhdr_size - *ppos), rem_len);
|
||||||
|
if (copy_to_user(buf, ((char *)&log_buf->bufhdr) + *ppos,
|
||||||
|
count))
|
||||||
|
return -EFAULT;
|
||||||
|
rem_len -= count;
|
||||||
|
ret_val += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_offset = log_buf->rd_offset;
|
||||||
|
|
||||||
|
if ((rem_len == 0) || (start_offset < 0))
|
||||||
|
goto rd_done;
|
||||||
|
|
||||||
|
fold_offset = -1;
|
||||||
|
cur_rd_offset = start_offset;
|
||||||
|
|
||||||
|
/* Find the last offset and fold-offset if the buffer is folded */
|
||||||
|
do {
|
||||||
|
struct ath_pktlog_hdr *log_hdr;
|
||||||
|
int log_data_offset;
|
||||||
|
|
||||||
|
log_hdr = (struct ath_pktlog_hdr *)(log_buf->log_data +
|
||||||
|
cur_rd_offset);
|
||||||
|
|
||||||
|
log_data_offset = cur_rd_offset + sizeof(struct ath_pktlog_hdr);
|
||||||
|
|
||||||
|
if ((fold_offset == -1)
|
||||||
|
&& ((pl_info->buf_size - log_data_offset)
|
||||||
|
<= log_hdr->size))
|
||||||
|
fold_offset = log_data_offset - 1;
|
||||||
|
|
||||||
|
PKTLOG_MOV_RD_IDX(cur_rd_offset, log_buf, pl_info->buf_size);
|
||||||
|
|
||||||
|
if ((fold_offset == -1) && (cur_rd_offset == 0)
|
||||||
|
&& (cur_rd_offset != log_buf->wr_offset))
|
||||||
|
fold_offset = log_data_offset + log_hdr->size - 1;
|
||||||
|
|
||||||
|
end_offset = log_data_offset + log_hdr->size - 1;
|
||||||
|
} while (cur_rd_offset != log_buf->wr_offset);
|
||||||
|
|
||||||
|
ppos_data = *ppos + ret_val - bufhdr_size + start_offset;
|
||||||
|
|
||||||
|
if (fold_offset == -1) {
|
||||||
|
if (ppos_data > end_offset)
|
||||||
|
goto rd_done;
|
||||||
|
|
||||||
|
count = QDF_MIN(rem_len, (end_offset - ppos_data + 1));
|
||||||
|
if (copy_to_user(buf + ret_val,
|
||||||
|
log_buf->log_data + ppos_data, count))
|
||||||
|
return -EFAULT;
|
||||||
|
ret_val += count;
|
||||||
|
rem_len -= count;
|
||||||
|
} else {
|
||||||
|
if (ppos_data <= fold_offset) {
|
||||||
|
count = QDF_MIN(rem_len, (fold_offset - ppos_data + 1));
|
||||||
|
if (copy_to_user(buf + ret_val,
|
||||||
|
log_buf->log_data + ppos_data, count))
|
||||||
|
return -EFAULT;
|
||||||
|
ret_val += count;
|
||||||
|
rem_len -= count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rem_len == 0)
|
||||||
|
goto rd_done;
|
||||||
|
|
||||||
|
ppos_data =
|
||||||
|
*ppos + ret_val - (bufhdr_size +
|
||||||
|
(fold_offset - start_offset + 1));
|
||||||
|
|
||||||
|
if (ppos_data <= end_offset) {
|
||||||
|
count = QDF_MIN(rem_len, (end_offset - ppos_data + 1));
|
||||||
|
if (copy_to_user(buf + ret_val,
|
||||||
|
log_buf->log_data + ppos_data, count))
|
||||||
|
return -EFAULT;
|
||||||
|
ret_val += count;
|
||||||
|
rem_len -= count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rd_done:
|
||||||
|
if ((ret_val < nbytes) && pl_info->saved_state) {
|
||||||
|
pl_info->log_state = pl_info->saved_state;
|
||||||
|
pl_info->saved_state = 0;
|
||||||
|
}
|
||||||
|
*ppos += ret_val;
|
||||||
|
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef VMALLOC_VMADDR
|
||||||
|
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* vma operations for mapping vmalloced area to user space */
|
||||||
|
static void pktlog_vopen(struct vm_area_struct *vma)
|
||||||
|
{
|
||||||
|
PKTLOG_MOD_INC_USE_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pktlog_vclose(struct vm_area_struct *vma)
|
||||||
|
{
|
||||||
|
PKTLOG_MOD_DEC_USE_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pktlog_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||||
|
{
|
||||||
|
unsigned long address = (unsigned long)vmf->virtual_address;
|
||||||
|
|
||||||
|
if (address == 0UL)
|
||||||
|
return VM_FAULT_NOPAGE;
|
||||||
|
|
||||||
|
if (vmf->pgoff > vma->vm_end)
|
||||||
|
return VM_FAULT_SIGBUS;
|
||||||
|
|
||||||
|
get_page(virt_to_page((void *)address));
|
||||||
|
vmf->page = virt_to_page((void *)address);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct vm_operations_struct pktlog_vmops = {
|
||||||
|
open: pktlog_vopen,
|
||||||
|
close:pktlog_vclose,
|
||||||
|
fault:pktlog_fault,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int pktlog_mmap(struct file *file, struct vm_area_struct *vma)
|
||||||
|
{
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
|
||||||
|
pl_info = (struct ath_pktlog_info *)
|
||||||
|
PDE_DATA(file->f_path.dentry->d_inode);
|
||||||
|
|
||||||
|
if (vma->vm_pgoff != 0) {
|
||||||
|
/* Entire buffer should be mapped */
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pl_info->buf) {
|
||||||
|
printk(PKTLOG_TAG "%s: Log buffer unavailable\n", __func__);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
vma->vm_flags |= VM_LOCKED;
|
||||||
|
vma->vm_ops = &pktlog_vmops;
|
||||||
|
pktlog_vopen(vma);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pktlogmod_init(void *context)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* create the proc directory entry */
|
||||||
|
g_pktlog_pde = proc_mkdir(PKTLOG_PROC_DIR, NULL);
|
||||||
|
|
||||||
|
if (g_pktlog_pde == NULL) {
|
||||||
|
printk(PKTLOG_TAG "%s: proc_mkdir failed\n", __func__);
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attach packet log */
|
||||||
|
ret = pktlog_attach((struct hif_opaque_softc *)context);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
goto attach_fail;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
attach_fail:
|
||||||
|
remove_proc_entry(PKTLOG_PROC_DIR, NULL);
|
||||||
|
g_pktlog_pde = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pktlogmod_exit(struct ol_txrx_pdev_t *handle)
|
||||||
|
{
|
||||||
|
struct ol_pktlog_dev_t *pl_dev;
|
||||||
|
|
||||||
|
pl_dev = ol_get_pl_handle(handle);
|
||||||
|
|
||||||
|
if (!pl_dev || g_pktlog_pde == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pktlog_detach(handle);
|
||||||
|
/*
|
||||||
|
* pdev kill needs to be implemented
|
||||||
|
*/
|
||||||
|
remove_proc_entry(PKTLOG_PROC_DIR, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
715
utils/pktlog/pktlog_ac.c
Normal file
715
utils/pktlog/pktlog_ac.c
Normal file
@@ -0,0 +1,715 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* 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 "qdf_mem.h"
|
||||||
|
#include "athdefs.h"
|
||||||
|
#include "pktlog_ac_i.h"
|
||||||
|
#include "cds_api.h"
|
||||||
|
#include "wma_types.h"
|
||||||
|
#include "htc.h"
|
||||||
|
|
||||||
|
wdi_event_subscribe PKTLOG_TX_SUBSCRIBER;
|
||||||
|
wdi_event_subscribe PKTLOG_RX_SUBSCRIBER;
|
||||||
|
wdi_event_subscribe PKTLOG_RX_REMOTE_SUBSCRIBER;
|
||||||
|
wdi_event_subscribe PKTLOG_RCFIND_SUBSCRIBER;
|
||||||
|
wdi_event_subscribe PKTLOG_RCUPDATE_SUBSCRIBER;
|
||||||
|
wdi_event_subscribe PKTLOG_SW_EVENT_SUBSCRIBER;
|
||||||
|
|
||||||
|
struct ol_pl_arch_dep_funcs ol_pl_funcs = {
|
||||||
|
.pktlog_init = pktlog_init,
|
||||||
|
.pktlog_enable = pktlog_enable,
|
||||||
|
.pktlog_setsize = pktlog_setsize,
|
||||||
|
.pktlog_disable = pktlog_disable, /* valid for f/w disable */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ol_pktlog_dev_t ol_pl_dev = {
|
||||||
|
.pl_funcs = &ol_pl_funcs,
|
||||||
|
};
|
||||||
|
|
||||||
|
void ol_pl_sethandle(ol_pktlog_dev_handle *pl_handle,
|
||||||
|
struct hif_opaque_softc *scn)
|
||||||
|
{
|
||||||
|
ol_pl_dev.scn = (ol_ath_generic_softc_handle) scn;
|
||||||
|
*pl_handle = &ol_pl_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static A_STATUS pktlog_wma_post_msg(WMI_PKTLOG_EVENT event_types,
|
||||||
|
WMI_CMD_ID cmd_id, bool ini_triggered,
|
||||||
|
uint8_t user_triggered)
|
||||||
|
{
|
||||||
|
struct scheduler_msg msg = { 0 };
|
||||||
|
QDF_STATUS status;
|
||||||
|
struct ath_pktlog_wmi_params *param;
|
||||||
|
|
||||||
|
param = qdf_mem_malloc(sizeof(struct ath_pktlog_wmi_params));
|
||||||
|
|
||||||
|
if (!param)
|
||||||
|
return A_NO_MEMORY;
|
||||||
|
|
||||||
|
param->cmd_id = cmd_id;
|
||||||
|
param->pktlog_event = event_types;
|
||||||
|
param->ini_triggered = ini_triggered;
|
||||||
|
param->user_triggered = user_triggered;
|
||||||
|
|
||||||
|
msg.type = WMA_PKTLOG_ENABLE_REQ;
|
||||||
|
msg.bodyptr = param;
|
||||||
|
msg.bodyval = 0;
|
||||||
|
|
||||||
|
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
|
||||||
|
|
||||||
|
if (status != QDF_STATUS_SUCCESS) {
|
||||||
|
qdf_mem_free(param);
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return A_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline A_STATUS
|
||||||
|
pktlog_enable_tgt(struct hif_opaque_softc *_scn, uint32_t log_state,
|
||||||
|
bool ini_triggered, uint8_t user_triggered)
|
||||||
|
{
|
||||||
|
uint32_t types = 0;
|
||||||
|
|
||||||
|
if (log_state & ATH_PKTLOG_TX)
|
||||||
|
types |= WMI_PKTLOG_EVENT_TX;
|
||||||
|
|
||||||
|
if (log_state & ATH_PKTLOG_RX)
|
||||||
|
types |= WMI_PKTLOG_EVENT_RX;
|
||||||
|
|
||||||
|
if (log_state & ATH_PKTLOG_RCFIND)
|
||||||
|
types |= WMI_PKTLOG_EVENT_RCF;
|
||||||
|
|
||||||
|
if (log_state & ATH_PKTLOG_RCUPDATE)
|
||||||
|
types |= WMI_PKTLOG_EVENT_RCU;
|
||||||
|
|
||||||
|
if (log_state & ATH_PKTLOG_SW_EVENT)
|
||||||
|
types |= WMI_PKTLOG_EVENT_SW;
|
||||||
|
|
||||||
|
return pktlog_wma_post_msg(types, WMI_PDEV_PKTLOG_ENABLE_CMDID,
|
||||||
|
ini_triggered, user_triggered);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline A_STATUS
|
||||||
|
wdi_pktlog_subscribe(struct ol_txrx_pdev_t *txrx_pdev, int32_t log_state)
|
||||||
|
{
|
||||||
|
if (!txrx_pdev) {
|
||||||
|
printk("Invalid pdev in %s\n", __func__);
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
if (log_state & ATH_PKTLOG_TX) {
|
||||||
|
if (wdi_event_sub(txrx_pdev,
|
||||||
|
&PKTLOG_TX_SUBSCRIBER, WDI_EVENT_TX_STATUS)) {
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (log_state & ATH_PKTLOG_RX) {
|
||||||
|
if (wdi_event_sub(txrx_pdev,
|
||||||
|
&PKTLOG_RX_SUBSCRIBER, WDI_EVENT_RX_DESC)) {
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
if (wdi_event_sub(txrx_pdev,
|
||||||
|
&PKTLOG_RX_REMOTE_SUBSCRIBER,
|
||||||
|
WDI_EVENT_RX_DESC_REMOTE)) {
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (log_state & ATH_PKTLOG_RCFIND) {
|
||||||
|
if (wdi_event_sub(txrx_pdev,
|
||||||
|
&PKTLOG_RCFIND_SUBSCRIBER,
|
||||||
|
WDI_EVENT_RATE_FIND)) {
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (log_state & ATH_PKTLOG_RCUPDATE) {
|
||||||
|
if (wdi_event_sub(txrx_pdev,
|
||||||
|
&PKTLOG_RCUPDATE_SUBSCRIBER,
|
||||||
|
WDI_EVENT_RATE_UPDATE)) {
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (log_state & ATH_PKTLOG_SW_EVENT) {
|
||||||
|
if (wdi_event_sub(txrx_pdev,
|
||||||
|
&PKTLOG_SW_EVENT_SUBSCRIBER,
|
||||||
|
WDI_EVENT_SW_EVENT)) {
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return A_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pktlog_callback(void *pdev, enum WDI_EVENT event, void *log_data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case WDI_EVENT_TX_STATUS:
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* process TX message
|
||||||
|
*/
|
||||||
|
if (process_tx_info(pdev, log_data)) {
|
||||||
|
printk("Unable to process TX info\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WDI_EVENT_RX_DESC:
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* process RX message for local frames
|
||||||
|
*/
|
||||||
|
if (process_rx_info(pdev, log_data)) {
|
||||||
|
printk("Unable to process RX info\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WDI_EVENT_RX_DESC_REMOTE:
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* process RX message for remote frames
|
||||||
|
*/
|
||||||
|
if (process_rx_info_remote(pdev, log_data)) {
|
||||||
|
printk("Unable to process RX info\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WDI_EVENT_RATE_FIND:
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* process RATE_FIND message
|
||||||
|
*/
|
||||||
|
if (process_rate_find(pdev, log_data)) {
|
||||||
|
printk("Unable to process RC_FIND info\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WDI_EVENT_RATE_UPDATE:
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* process RATE_UPDATE message
|
||||||
|
*/
|
||||||
|
if (process_rate_update(pdev, log_data)) {
|
||||||
|
printk("Unable to process RC_UPDATE\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WDI_EVENT_SW_EVENT:
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* process SW EVENT message
|
||||||
|
*/
|
||||||
|
if (process_sw_event(pdev, log_data)) {
|
||||||
|
printk("Unable to process SW_EVENT\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
A_STATUS
|
||||||
|
wdi_pktlog_unsubscribe(struct ol_txrx_pdev_t *txrx_pdev, uint32_t log_state)
|
||||||
|
{
|
||||||
|
if (log_state & ATH_PKTLOG_TX) {
|
||||||
|
if (wdi_event_unsub(txrx_pdev,
|
||||||
|
&PKTLOG_TX_SUBSCRIBER,
|
||||||
|
WDI_EVENT_TX_STATUS)) {
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (log_state & ATH_PKTLOG_RX) {
|
||||||
|
if (wdi_event_unsub(txrx_pdev,
|
||||||
|
&PKTLOG_RX_SUBSCRIBER, WDI_EVENT_RX_DESC)) {
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
if (wdi_event_unsub(txrx_pdev,
|
||||||
|
&PKTLOG_RX_REMOTE_SUBSCRIBER,
|
||||||
|
WDI_EVENT_RX_DESC_REMOTE)) {
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (log_state & ATH_PKTLOG_RCFIND) {
|
||||||
|
if (wdi_event_unsub(txrx_pdev,
|
||||||
|
&PKTLOG_RCFIND_SUBSCRIBER,
|
||||||
|
WDI_EVENT_RATE_FIND)) {
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (log_state & ATH_PKTLOG_RCUPDATE) {
|
||||||
|
if (wdi_event_unsub(txrx_pdev,
|
||||||
|
&PKTLOG_RCUPDATE_SUBSCRIBER,
|
||||||
|
WDI_EVENT_RATE_UPDATE)) {
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (log_state & ATH_PKTLOG_RCUPDATE) {
|
||||||
|
if (wdi_event_unsub(txrx_pdev,
|
||||||
|
&PKTLOG_SW_EVENT_SUBSCRIBER,
|
||||||
|
WDI_EVENT_SW_EVENT)) {
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return A_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pktlog_disable(struct hif_opaque_softc *scn)
|
||||||
|
{
|
||||||
|
struct ol_txrx_pdev_t *txrx_pdev =
|
||||||
|
cds_get_context(QDF_MODULE_ID_TXRX);
|
||||||
|
struct ol_pktlog_dev_t *pl_dev;
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
|
||||||
|
if (txrx_pdev == NULL ||
|
||||||
|
txrx_pdev->pl_dev == NULL ||
|
||||||
|
txrx_pdev->pl_dev->pl_info == NULL)
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
pl_dev = txrx_pdev->pl_dev;
|
||||||
|
pl_info = pl_dev->pl_info;
|
||||||
|
|
||||||
|
if (pktlog_wma_post_msg(0, WMI_PDEV_PKTLOG_DISABLE_CMDID, 0, 0)) {
|
||||||
|
printk("Failed to disable pktlog in target\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pl_dev->is_pktlog_cb_subscribed &&
|
||||||
|
wdi_pktlog_unsubscribe(txrx_pdev, pl_info->log_state)) {
|
||||||
|
printk("Cannot unsubscribe pktlog from the WDI\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
pl_dev->is_pktlog_cb_subscribed = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pktlog_init(struct hif_opaque_softc *scn)
|
||||||
|
{
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
ol_txrx_pdev_handle pdev_txrx_handle;
|
||||||
|
pdev_txrx_handle = cds_get_context(QDF_MODULE_ID_TXRX);
|
||||||
|
|
||||||
|
if (pdev_txrx_handle == NULL ||
|
||||||
|
pdev_txrx_handle->pl_dev == NULL ||
|
||||||
|
pdev_txrx_handle->pl_dev->pl_info == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pl_info = pdev_txrx_handle->pl_dev->pl_info;
|
||||||
|
|
||||||
|
OS_MEMZERO(pl_info, sizeof(*pl_info));
|
||||||
|
PKTLOG_LOCK_INIT(pl_info);
|
||||||
|
|
||||||
|
pl_info->buf_size = PKTLOG_DEFAULT_BUFSIZE;
|
||||||
|
pl_info->buf = NULL;
|
||||||
|
pl_info->log_state = 0;
|
||||||
|
pl_info->sack_thr = PKTLOG_DEFAULT_SACK_THR;
|
||||||
|
pl_info->tail_length = PKTLOG_DEFAULT_TAIL_LENGTH;
|
||||||
|
pl_info->thruput_thresh = PKTLOG_DEFAULT_THRUPUT_THRESH;
|
||||||
|
pl_info->per_thresh = PKTLOG_DEFAULT_PER_THRESH;
|
||||||
|
pl_info->phyerr_thresh = PKTLOG_DEFAULT_PHYERR_THRESH;
|
||||||
|
pl_info->trigger_interval = PKTLOG_DEFAULT_TRIGGER_INTERVAL;
|
||||||
|
pl_info->pktlen = 0;
|
||||||
|
pl_info->start_time_thruput = 0;
|
||||||
|
pl_info->start_time_per = 0;
|
||||||
|
pdev_txrx_handle->pl_dev->vendor_cmd_send = false;
|
||||||
|
|
||||||
|
PKTLOG_TX_SUBSCRIBER.callback = pktlog_callback;
|
||||||
|
PKTLOG_RX_SUBSCRIBER.callback = pktlog_callback;
|
||||||
|
PKTLOG_RX_REMOTE_SUBSCRIBER.callback = pktlog_callback;
|
||||||
|
PKTLOG_RCFIND_SUBSCRIBER.callback = pktlog_callback;
|
||||||
|
PKTLOG_RCUPDATE_SUBSCRIBER.callback = pktlog_callback;
|
||||||
|
PKTLOG_SW_EVENT_SUBSCRIBER.callback = pktlog_callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pktlog_enable(struct hif_opaque_softc *scn, int32_t log_state,
|
||||||
|
bool ini_triggered, uint8_t user_triggered,
|
||||||
|
uint32_t is_iwpriv_command)
|
||||||
|
{
|
||||||
|
struct ol_pktlog_dev_t *pl_dev;
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
struct ol_txrx_pdev_t *txrx_pdev;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (!scn) {
|
||||||
|
printk("%s: Invalid scn context\n", __func__);
|
||||||
|
ASSERT(0);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX);
|
||||||
|
if (!txrx_pdev) {
|
||||||
|
printk("%s: Invalid txrx_pdev context\n", __func__);
|
||||||
|
ASSERT(0);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_dev = txrx_pdev->pl_dev;
|
||||||
|
if (!pl_dev) {
|
||||||
|
printk("%s: Invalid pktlog context\n", __func__);
|
||||||
|
ASSERT(0);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_info = pl_dev->pl_info;
|
||||||
|
|
||||||
|
if (!pl_info)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* is_iwpriv_command : 0 indicates its a vendor command
|
||||||
|
* log_state: 0 indicates pktlog disable command
|
||||||
|
* vendor_cmd_send flag; false means no vendor pktlog enable
|
||||||
|
* command was sent previously
|
||||||
|
*/
|
||||||
|
if (is_iwpriv_command == 0 && log_state == 0 &&
|
||||||
|
pl_dev->vendor_cmd_send == false)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!pl_dev->tgt_pktlog_alloced) {
|
||||||
|
if (pl_info->buf == NULL) {
|
||||||
|
error = pktlog_alloc_buf(scn);
|
||||||
|
|
||||||
|
if (error != 0)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if (!pl_info->buf) {
|
||||||
|
printk("%s: pktlog buf alloc failed\n",
|
||||||
|
__func__);
|
||||||
|
ASSERT(0);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_info->buf->bufhdr.version = CUR_PKTLOG_VER;
|
||||||
|
pl_info->buf->bufhdr.magic_num = PKTLOG_MAGIC_NUM;
|
||||||
|
pl_info->buf->wr_offset = 0;
|
||||||
|
pl_info->buf->rd_offset = -1;
|
||||||
|
/* These below variables are used by per packet stats*/
|
||||||
|
pl_info->buf->bytes_written = 0;
|
||||||
|
pl_info->buf->msg_index = 1;
|
||||||
|
pl_info->buf->offset = PKTLOG_READ_OFFSET;
|
||||||
|
|
||||||
|
pl_info->start_time_thruput = os_get_timestamp();
|
||||||
|
pl_info->start_time_per = pl_info->start_time_thruput;
|
||||||
|
|
||||||
|
pl_dev->tgt_pktlog_alloced = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log_state != 0) {
|
||||||
|
/* WDI subscribe */
|
||||||
|
if ((!pl_dev->is_pktlog_cb_subscribed) &&
|
||||||
|
wdi_pktlog_subscribe(txrx_pdev, log_state)) {
|
||||||
|
printk("Unable to subscribe to the WDI %s\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
pl_dev->is_pktlog_cb_subscribed = true;
|
||||||
|
/* WMI command to enable pktlog on the firmware */
|
||||||
|
if (pktlog_enable_tgt(scn, log_state, ini_triggered,
|
||||||
|
user_triggered)) {
|
||||||
|
printk("Device cannot be enabled, %s\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_iwpriv_command == 0)
|
||||||
|
pl_dev->vendor_cmd_send = true;
|
||||||
|
} else {
|
||||||
|
pl_dev->pl_funcs->pktlog_disable(scn);
|
||||||
|
if (is_iwpriv_command == 0)
|
||||||
|
pl_dev->vendor_cmd_send = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_info->log_state = log_state;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pktlog_setsize(struct hif_opaque_softc *scn, int32_t size)
|
||||||
|
{
|
||||||
|
ol_txrx_pdev_handle pdev_txrx_handle =
|
||||||
|
cds_get_context(QDF_MODULE_ID_TXRX);
|
||||||
|
struct ol_pktlog_dev_t *pl_dev;
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
|
||||||
|
if (pdev_txrx_handle == NULL ||
|
||||||
|
pdev_txrx_handle->pl_dev == NULL ||
|
||||||
|
pdev_txrx_handle->pl_dev->pl_info == NULL)
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
pl_dev = pdev_txrx_handle->pl_dev;
|
||||||
|
pl_info = pl_dev->pl_info;
|
||||||
|
|
||||||
|
if (size < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (size == pl_info->buf_size) {
|
||||||
|
qdf_print("%s: Pktlog Buff Size is already of same size.",
|
||||||
|
__func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pl_info->log_state) {
|
||||||
|
qdf_print("%s: Logging should be disabled before changing"
|
||||||
|
"buffer size.", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pl_info->buf != NULL) {
|
||||||
|
if (pl_dev->is_pktlog_cb_subscribed &&
|
||||||
|
wdi_pktlog_unsubscribe(pdev_txrx_handle,
|
||||||
|
pl_info->log_state)) {
|
||||||
|
printk("Cannot unsubscribe pktlog from the WDI\n");
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
pktlog_release_buf(pdev_txrx_handle);
|
||||||
|
pl_dev->is_pktlog_cb_subscribed = false;
|
||||||
|
pl_dev->tgt_pktlog_alloced = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size != 0) {
|
||||||
|
qdf_print("%s: New Pktlog Buff Size is %d\n", __func__, size);
|
||||||
|
pl_info->buf_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktlog_process_fw_msg() - process packetlog message
|
||||||
|
* @buff: buffer
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
void pktlog_process_fw_msg(uint32_t *buff)
|
||||||
|
{
|
||||||
|
uint32_t *pl_hdr;
|
||||||
|
uint32_t log_type;
|
||||||
|
struct ol_txrx_pdev_t *txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX);
|
||||||
|
|
||||||
|
if (!txrx_pdev) {
|
||||||
|
qdf_print("%s: txrx_pdev is NULL", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_hdr = buff;
|
||||||
|
log_type =
|
||||||
|
(*(pl_hdr + 1) & ATH_PKTLOG_HDR_LOG_TYPE_MASK) >>
|
||||||
|
ATH_PKTLOG_HDR_LOG_TYPE_SHIFT;
|
||||||
|
if ((log_type == PKTLOG_TYPE_TX_CTRL)
|
||||||
|
|| (log_type == PKTLOG_TYPE_TX_STAT)
|
||||||
|
|| (log_type == PKTLOG_TYPE_TX_MSDU_ID)
|
||||||
|
|| (log_type == PKTLOG_TYPE_TX_FRM_HDR)
|
||||||
|
|| (log_type == PKTLOG_TYPE_TX_VIRT_ADDR))
|
||||||
|
wdi_event_handler(WDI_EVENT_TX_STATUS,
|
||||||
|
txrx_pdev, pl_hdr);
|
||||||
|
else if (log_type == PKTLOG_TYPE_RC_FIND)
|
||||||
|
wdi_event_handler(WDI_EVENT_RATE_FIND,
|
||||||
|
txrx_pdev, pl_hdr);
|
||||||
|
else if (log_type == PKTLOG_TYPE_RC_UPDATE)
|
||||||
|
wdi_event_handler(WDI_EVENT_RATE_UPDATE,
|
||||||
|
txrx_pdev, pl_hdr);
|
||||||
|
else if (log_type == PKTLOG_TYPE_RX_STAT)
|
||||||
|
wdi_event_handler(WDI_EVENT_RX_DESC,
|
||||||
|
txrx_pdev, pl_hdr);
|
||||||
|
else if (log_type == PKTLOG_TYPE_SW_EVENT)
|
||||||
|
wdi_event_handler(WDI_EVENT_SW_EVENT,
|
||||||
|
txrx_pdev, pl_hdr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(QCA_WIFI_3_0_ADRASTEA)
|
||||||
|
/**
|
||||||
|
* pktlog_t2h_msg_handler() - Target to host message handler
|
||||||
|
* @context: pdev context
|
||||||
|
* @pkt: HTC packet
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static void pktlog_t2h_msg_handler(void *context, HTC_PACKET *pkt)
|
||||||
|
{
|
||||||
|
struct ol_pktlog_dev_t *pdev = (struct ol_pktlog_dev_t *)context;
|
||||||
|
qdf_nbuf_t pktlog_t2h_msg = (qdf_nbuf_t) pkt->pPktContext;
|
||||||
|
uint32_t *msg_word;
|
||||||
|
|
||||||
|
/* check for successful message reception */
|
||||||
|
if (pkt->Status != A_OK) {
|
||||||
|
if (pkt->Status != A_ECANCELED)
|
||||||
|
pdev->htc_err_cnt++;
|
||||||
|
qdf_nbuf_free(pktlog_t2h_msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* confirm alignment */
|
||||||
|
qdf_assert((((unsigned long)qdf_nbuf_data(pktlog_t2h_msg)) & 0x3) == 0);
|
||||||
|
|
||||||
|
msg_word = (uint32_t *) qdf_nbuf_data(pktlog_t2h_msg);
|
||||||
|
pktlog_process_fw_msg(msg_word);
|
||||||
|
|
||||||
|
qdf_nbuf_free(pktlog_t2h_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktlog_tx_resume_handler() - resume callback
|
||||||
|
* @context: pdev context
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static void pktlog_tx_resume_handler(void *context)
|
||||||
|
{
|
||||||
|
qdf_print("%s: Not expected", __func__);
|
||||||
|
qdf_assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktlog_h2t_send_complete() - send complete indication
|
||||||
|
* @context: pdev context
|
||||||
|
* @htc_pkt: HTC packet
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
static void pktlog_h2t_send_complete(void *context, HTC_PACKET *htc_pkt)
|
||||||
|
{
|
||||||
|
qdf_print("%s: Not expected", __func__);
|
||||||
|
qdf_assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktlog_h2t_full() - queue full indication
|
||||||
|
* @context: pdev context
|
||||||
|
* @pkt: HTC packet
|
||||||
|
*
|
||||||
|
* Return: HTC action
|
||||||
|
*/
|
||||||
|
static HTC_SEND_FULL_ACTION pktlog_h2t_full(void *context, HTC_PACKET *pkt)
|
||||||
|
{
|
||||||
|
return HTC_SEND_FULL_KEEP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktlog_htc_connect_service() - create new endpoint for packetlog
|
||||||
|
* @pdev - pktlog pdev
|
||||||
|
*
|
||||||
|
* Return: 0 for success/failure
|
||||||
|
*/
|
||||||
|
static int pktlog_htc_connect_service(struct ol_pktlog_dev_t *pdev)
|
||||||
|
{
|
||||||
|
HTC_SERVICE_CONNECT_REQ connect;
|
||||||
|
HTC_SERVICE_CONNECT_RESP response;
|
||||||
|
A_STATUS status;
|
||||||
|
|
||||||
|
qdf_mem_set(&connect, sizeof(connect), 0);
|
||||||
|
qdf_mem_set(&response, sizeof(response), 0);
|
||||||
|
|
||||||
|
connect.pMetaData = NULL;
|
||||||
|
connect.MetaDataLength = 0;
|
||||||
|
connect.EpCallbacks.pContext = pdev;
|
||||||
|
connect.EpCallbacks.EpTxComplete = pktlog_h2t_send_complete;
|
||||||
|
connect.EpCallbacks.EpTxCompleteMultiple = NULL;
|
||||||
|
connect.EpCallbacks.EpRecv = pktlog_t2h_msg_handler;
|
||||||
|
connect.EpCallbacks.ep_resume_tx_queue = pktlog_tx_resume_handler;
|
||||||
|
|
||||||
|
/* rx buffers currently are provided by HIF, not by EpRecvRefill */
|
||||||
|
connect.EpCallbacks.EpRecvRefill = NULL;
|
||||||
|
connect.EpCallbacks.RecvRefillWaterMark = 1;
|
||||||
|
/* N/A, fill is done by HIF */
|
||||||
|
|
||||||
|
connect.EpCallbacks.EpSendFull = pktlog_h2t_full;
|
||||||
|
/*
|
||||||
|
* Specify how deep to let a queue get before htc_send_pkt will
|
||||||
|
* call the EpSendFull function due to excessive send queue depth.
|
||||||
|
*/
|
||||||
|
connect.MaxSendQueueDepth = PKTLOG_MAX_SEND_QUEUE_DEPTH;
|
||||||
|
|
||||||
|
/* disable flow control for HTT data message service */
|
||||||
|
connect.ConnectionFlags |= HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL;
|
||||||
|
|
||||||
|
/* connect to control service */
|
||||||
|
connect.service_id = PACKET_LOG_SVC;
|
||||||
|
|
||||||
|
status = htc_connect_service(pdev->htc_pdev, &connect, &response);
|
||||||
|
|
||||||
|
if (status != A_OK) {
|
||||||
|
pdev->mt_pktlog_enabled = false;
|
||||||
|
return -EIO; /* failure */
|
||||||
|
}
|
||||||
|
|
||||||
|
pdev->htc_endpoint = response.Endpoint;
|
||||||
|
pdev->mt_pktlog_enabled = true;
|
||||||
|
|
||||||
|
return 0; /* success */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktlog_htc_attach() - attach pktlog HTC service
|
||||||
|
*
|
||||||
|
* Return: 0 for success/failure
|
||||||
|
*/
|
||||||
|
int pktlog_htc_attach(void)
|
||||||
|
{
|
||||||
|
struct ol_txrx_pdev_t *txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX);
|
||||||
|
struct ol_pktlog_dev_t *pdev = NULL;
|
||||||
|
void *htc_pdev = cds_get_context(QDF_MODULE_ID_HTC);
|
||||||
|
|
||||||
|
if ((!txrx_pdev) || (!txrx_pdev->pl_dev) || (!htc_pdev))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
pdev = txrx_pdev->pl_dev;
|
||||||
|
pdev->htc_pdev = htc_pdev;
|
||||||
|
return pktlog_htc_connect_service(pdev);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int pktlog_htc_attach(void)
|
||||||
|
{
|
||||||
|
struct ol_txrx_pdev_t *txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX);
|
||||||
|
struct ol_pktlog_dev_t *pdev = NULL;
|
||||||
|
|
||||||
|
if (!txrx_pdev)
|
||||||
|
return -EINVAL;
|
||||||
|
pdev = txrx_pdev->pl_dev;
|
||||||
|
pdev->mt_pktlog_enabled = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* REMOVE_PKT_LOG */
|
871
utils/pktlog/pktlog_internal.c
Normal file
871
utils/pktlog/pktlog_internal.c
Normal file
@@ -0,0 +1,871 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
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) {
|
||||||
|
printk("Invalid parg in %s\n", __func__);
|
||||||
|
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) {
|
||||||
|
printk("Invalid log_buf in %s\n", __func__);
|
||||||
|
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;
|
||||||
|
#ifdef HELIUMPLUS
|
||||||
|
log_hdr->type_specific_data = plarg->type_specific_data;
|
||||||
|
#endif
|
||||||
|
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 ol_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;
|
||||||
|
#ifdef HELIUMPLUS
|
||||||
|
plarg.type_specific_data = pl_hdr->type_specific_data;
|
||||||
|
#endif
|
||||||
|
if (flags & PHFLAGS_INTERRUPT_CONTEXT) {
|
||||||
|
/*
|
||||||
|
* We are already in interupt 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct txctl_frm_hdr frm_hdr;
|
||||||
|
|
||||||
|
#ifndef HELIUMPLUS
|
||||||
|
static void process_ieee_hdr(void *data)
|
||||||
|
{
|
||||||
|
uint8_t dir;
|
||||||
|
struct ieee80211_frame *wh = (struct ieee80211_frame *)(data);
|
||||||
|
|
||||||
|
frm_hdr.framectrl = *(uint16_t *) (wh->i_fc);
|
||||||
|
frm_hdr.seqctrl = *(uint16_t *) (wh->i_seq);
|
||||||
|
dir = (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK);
|
||||||
|
|
||||||
|
if (dir == IEEE80211_FC1_DIR_TODS) {
|
||||||
|
frm_hdr.bssid_tail =
|
||||||
|
(wh->i_addr1[IEEE80211_ADDR_LEN - 2] << 8) | (wh->
|
||||||
|
i_addr1
|
||||||
|
[IEEE80211_ADDR_LEN
|
||||||
|
- 1]);
|
||||||
|
frm_hdr.sa_tail =
|
||||||
|
(wh->i_addr2[IEEE80211_ADDR_LEN - 2] << 8) | (wh->
|
||||||
|
i_addr2
|
||||||
|
[IEEE80211_ADDR_LEN
|
||||||
|
- 1]);
|
||||||
|
frm_hdr.da_tail =
|
||||||
|
(wh->i_addr3[IEEE80211_ADDR_LEN - 2] << 8) | (wh->
|
||||||
|
i_addr3
|
||||||
|
[IEEE80211_ADDR_LEN
|
||||||
|
- 1]);
|
||||||
|
} else if (dir == IEEE80211_FC1_DIR_FROMDS) {
|
||||||
|
frm_hdr.bssid_tail =
|
||||||
|
(wh->i_addr2[IEEE80211_ADDR_LEN - 2] << 8) | (wh->
|
||||||
|
i_addr2
|
||||||
|
[IEEE80211_ADDR_LEN
|
||||||
|
- 1]);
|
||||||
|
frm_hdr.sa_tail =
|
||||||
|
(wh->i_addr3[IEEE80211_ADDR_LEN - 2] << 8) | (wh->
|
||||||
|
i_addr3
|
||||||
|
[IEEE80211_ADDR_LEN
|
||||||
|
- 1]);
|
||||||
|
frm_hdr.da_tail =
|
||||||
|
(wh->i_addr1[IEEE80211_ADDR_LEN - 2] << 8) | (wh->
|
||||||
|
i_addr1
|
||||||
|
[IEEE80211_ADDR_LEN
|
||||||
|
- 1]);
|
||||||
|
} else {
|
||||||
|
frm_hdr.bssid_tail =
|
||||||
|
(wh->i_addr3[IEEE80211_ADDR_LEN - 2] << 8) | (wh->
|
||||||
|
i_addr3
|
||||||
|
[IEEE80211_ADDR_LEN
|
||||||
|
- 1]);
|
||||||
|
frm_hdr.sa_tail =
|
||||||
|
(wh->i_addr2[IEEE80211_ADDR_LEN - 2] << 8) | (wh->
|
||||||
|
i_addr2
|
||||||
|
[IEEE80211_ADDR_LEN
|
||||||
|
- 1]);
|
||||||
|
frm_hdr.da_tail =
|
||||||
|
(wh->i_addr1[IEEE80211_ADDR_LEN - 2] << 8) | (wh->
|
||||||
|
i_addr1
|
||||||
|
[IEEE80211_ADDR_LEN
|
||||||
|
- 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fill_ieee80211_hdr_data() - fill ieee802.11 data header
|
||||||
|
* @txrx_pdev: txrx pdev
|
||||||
|
* @pl_msdu_info: msdu info
|
||||||
|
* @data: data received from event
|
||||||
|
*
|
||||||
|
* Return: none
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
fill_ieee80211_hdr_data(struct ol_txrx_pdev_t *txrx_pdev,
|
||||||
|
struct ath_pktlog_msdu_info *pl_msdu_info, void *data)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
uint32_t *htt_tx_desc;
|
||||||
|
struct ol_tx_desc_t *tx_desc;
|
||||||
|
uint8_t msdu_id_offset = MSDU_ID_INFO_ID_OFFSET;
|
||||||
|
uint16_t tx_desc_id;
|
||||||
|
uint32_t *msdu_id_info = (uint32_t *)
|
||||||
|
((void *)data + sizeof(struct ath_pktlog_hdr));
|
||||||
|
uint32_t *msdu_id = (uint32_t *) ((char *)msdu_id_info +
|
||||||
|
msdu_id_offset);
|
||||||
|
uint8_t *addr, *vap_addr;
|
||||||
|
uint8_t vdev_id;
|
||||||
|
qdf_nbuf_t netbuf;
|
||||||
|
uint32_t len;
|
||||||
|
|
||||||
|
|
||||||
|
pl_msdu_info->num_msdu = *msdu_id_info;
|
||||||
|
pl_msdu_info->priv_size = sizeof(uint32_t) *
|
||||||
|
pl_msdu_info->num_msdu + sizeof(uint32_t);
|
||||||
|
|
||||||
|
for (i = 0; i < pl_msdu_info->num_msdu; i++) {
|
||||||
|
/*
|
||||||
|
* Handle big endianness
|
||||||
|
* Increment msdu_id once after retrieving
|
||||||
|
* lower 16 bits and uppper 16 bits
|
||||||
|
*/
|
||||||
|
if (!(i % 2)) {
|
||||||
|
tx_desc_id = ((*msdu_id & TX_DESC_ID_LOW_MASK)
|
||||||
|
>> TX_DESC_ID_LOW_SHIFT);
|
||||||
|
} else {
|
||||||
|
tx_desc_id = ((*msdu_id & TX_DESC_ID_HIGH_MASK)
|
||||||
|
>> TX_DESC_ID_HIGH_SHIFT);
|
||||||
|
msdu_id += 1;
|
||||||
|
}
|
||||||
|
tx_desc = ol_tx_desc_find(txrx_pdev, tx_desc_id);
|
||||||
|
qdf_assert(tx_desc);
|
||||||
|
netbuf = tx_desc->netbuf;
|
||||||
|
htt_tx_desc = (uint32_t *) tx_desc->htt_tx_desc;
|
||||||
|
qdf_assert(htt_tx_desc);
|
||||||
|
|
||||||
|
qdf_nbuf_peek_header(netbuf, &addr, &len);
|
||||||
|
|
||||||
|
if (len < (2 * IEEE80211_ADDR_LEN)) {
|
||||||
|
qdf_print("TX frame does not have a valid address\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Adding header information for the TX data frames */
|
||||||
|
vdev_id = (uint8_t) (*(htt_tx_desc +
|
||||||
|
HTT_TX_VDEV_ID_WORD) >>
|
||||||
|
HTT_TX_VDEV_ID_SHIFT) &
|
||||||
|
HTT_TX_VDEV_ID_MASK;
|
||||||
|
|
||||||
|
vap_addr = wma_get_vdev_address_by_vdev_id(vdev_id);
|
||||||
|
|
||||||
|
frm_hdr.da_tail = (addr[IEEE80211_ADDR_LEN - 2] << 8) |
|
||||||
|
(addr[IEEE80211_ADDR_LEN - 1]);
|
||||||
|
frm_hdr.sa_tail =
|
||||||
|
(addr[2 * IEEE80211_ADDR_LEN - 2] << 8) |
|
||||||
|
(addr[2 * IEEE80211_ADDR_LEN - 1]);
|
||||||
|
if (vap_addr) {
|
||||||
|
frm_hdr.bssid_tail =
|
||||||
|
(vap_addr[IEEE80211_ADDR_LEN - 2] << 8) |
|
||||||
|
(vap_addr[IEEE80211_ADDR_LEN - 1]);
|
||||||
|
} else {
|
||||||
|
frm_hdr.bssid_tail = 0x0000;
|
||||||
|
}
|
||||||
|
pl_msdu_info->priv.msdu_len[i] = *(htt_tx_desc +
|
||||||
|
HTT_TX_MSDU_LEN_DWORD)
|
||||||
|
& HTT_TX_MSDU_LEN_MASK;
|
||||||
|
/*
|
||||||
|
* Add more information per MSDU
|
||||||
|
* e.g., protocol information
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HELIUMPLUS
|
||||||
|
A_STATUS process_tx_info(struct ol_txrx_pdev_t *txrx_pdev, void *data)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Must include to process different types
|
||||||
|
* TX_CTL, TX_STATUS, TX_MSDU_ID, TX_FRM_HDR
|
||||||
|
*/
|
||||||
|
struct ol_pktlog_dev_t *pl_dev;
|
||||||
|
struct ath_pktlog_hdr pl_hdr;
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
uint32_t *pl_tgt_hdr;
|
||||||
|
|
||||||
|
if (!txrx_pdev) {
|
||||||
|
printk("Invalid pdev in %s\n", __func__);
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
qdf_assert(txrx_pdev->pl_dev);
|
||||||
|
qdf_assert(data);
|
||||||
|
pl_dev = txrx_pdev->pl_dev;
|
||||||
|
|
||||||
|
pl_tgt_hdr = (uint32_t *) data;
|
||||||
|
/*
|
||||||
|
* Makes the short words (16 bits) portable b/w little endian
|
||||||
|
* and big endian
|
||||||
|
*/
|
||||||
|
pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) &
|
||||||
|
ATH_PKTLOG_HDR_FLAGS_MASK) >>
|
||||||
|
ATH_PKTLOG_HDR_FLAGS_SHIFT;
|
||||||
|
pl_hdr.flags |= PKTLOG_HDR_SIZE_16;
|
||||||
|
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.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) &
|
||||||
|
ATH_PKTLOG_HDR_MAC_ID_MASK) >>
|
||||||
|
ATH_PKTLOG_HDR_MAC_ID_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);
|
||||||
|
pl_hdr.type_specific_data =
|
||||||
|
*(pl_tgt_hdr + ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET);
|
||||||
|
pl_info = pl_dev->pl_info;
|
||||||
|
|
||||||
|
if (pl_hdr.log_type == PKTLOG_TYPE_TX_CTRL) {
|
||||||
|
size_t log_size = sizeof(frm_hdr) + pl_hdr.size;
|
||||||
|
void *txdesc_hdr_ctl = (void *)
|
||||||
|
pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr);
|
||||||
|
qdf_assert(txdesc_hdr_ctl);
|
||||||
|
qdf_assert(pl_hdr.size < (370 * sizeof(u_int32_t)));
|
||||||
|
|
||||||
|
qdf_mem_copy(txdesc_hdr_ctl, &frm_hdr, sizeof(frm_hdr));
|
||||||
|
qdf_mem_copy((char *)txdesc_hdr_ctl + sizeof(frm_hdr),
|
||||||
|
((void *)data +
|
||||||
|
sizeof(struct ath_pktlog_hdr)),
|
||||||
|
pl_hdr.size);
|
||||||
|
pl_hdr.size = log_size;
|
||||||
|
cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
|
||||||
|
txdesc_hdr_ctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pl_hdr.log_type == PKTLOG_TYPE_TX_STAT) {
|
||||||
|
struct ath_pktlog_tx_status txstat_log;
|
||||||
|
size_t log_size = pl_hdr.size;
|
||||||
|
|
||||||
|
txstat_log.ds_status = (void *)
|
||||||
|
pktlog_getbuf(pl_dev, pl_info,
|
||||||
|
log_size, &pl_hdr);
|
||||||
|
qdf_assert(txstat_log.ds_status);
|
||||||
|
qdf_mem_copy(txstat_log.ds_status,
|
||||||
|
((void *)data + sizeof(struct ath_pktlog_hdr)),
|
||||||
|
pl_hdr.size);
|
||||||
|
cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
|
||||||
|
txstat_log.ds_status);
|
||||||
|
}
|
||||||
|
return A_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
A_STATUS process_tx_info(struct ol_txrx_pdev_t *txrx_pdev, void *data)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Must include to process different types
|
||||||
|
* TX_CTL, TX_STATUS, TX_MSDU_ID, TX_FRM_HDR
|
||||||
|
*/
|
||||||
|
struct ol_pktlog_dev_t *pl_dev;
|
||||||
|
struct ath_pktlog_hdr pl_hdr;
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
uint32_t *pl_tgt_hdr;
|
||||||
|
|
||||||
|
if (!txrx_pdev) {
|
||||||
|
qdf_print("Invalid pdev in %s\n", __func__);
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
qdf_assert(txrx_pdev->pl_dev);
|
||||||
|
qdf_assert(data);
|
||||||
|
pl_dev = txrx_pdev->pl_dev;
|
||||||
|
|
||||||
|
pl_tgt_hdr = (uint32_t *) data;
|
||||||
|
/*
|
||||||
|
* Makes the short words (16 bits) portable b/w little endian
|
||||||
|
* and big endian
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
|
pl_info = pl_dev->pl_info;
|
||||||
|
|
||||||
|
if (pl_hdr.log_type == PKTLOG_TYPE_TX_FRM_HDR) {
|
||||||
|
/* Valid only for the TX CTL */
|
||||||
|
process_ieee_hdr(data + sizeof(pl_hdr));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pl_hdr.log_type == PKTLOG_TYPE_TX_VIRT_ADDR) {
|
||||||
|
A_UINT32 desc_id = (A_UINT32)
|
||||||
|
*((A_UINT32 *) (data + sizeof(pl_hdr)));
|
||||||
|
A_UINT32 vdev_id = desc_id;
|
||||||
|
|
||||||
|
/* if the pkt log msg is for the bcn frame the vdev id
|
||||||
|
* is piggybacked in desc_id and the MSB of the desc ID
|
||||||
|
* would be set to FF
|
||||||
|
*/
|
||||||
|
#define BCN_DESC_ID 0xFF
|
||||||
|
if ((desc_id >> 24) == BCN_DESC_ID) {
|
||||||
|
void *data;
|
||||||
|
A_UINT32 buf_size;
|
||||||
|
|
||||||
|
vdev_id &= 0x00FFFFFF;
|
||||||
|
data = wma_get_beacon_buffer_by_vdev_id(vdev_id,
|
||||||
|
&buf_size);
|
||||||
|
if (data) {
|
||||||
|
process_ieee_hdr(data);
|
||||||
|
qdf_mem_free(data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* TODO: get the hdr content for mgmt frames from
|
||||||
|
* Tx mgmt desc pool
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pl_hdr.log_type == PKTLOG_TYPE_TX_CTRL) {
|
||||||
|
struct ath_pktlog_txctl txctl_log;
|
||||||
|
size_t log_size = sizeof(txctl_log.priv);
|
||||||
|
|
||||||
|
txctl_log.txdesc_hdr_ctl = (void *)pktlog_getbuf(pl_dev,
|
||||||
|
pl_info,
|
||||||
|
log_size,
|
||||||
|
&pl_hdr);
|
||||||
|
|
||||||
|
if (!txctl_log.txdesc_hdr_ctl) {
|
||||||
|
printk
|
||||||
|
("failed to get buf for txctl_log.txdesc_hdr_ctl\n");
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* frm hdr is currently Valid only for local frames
|
||||||
|
* Add capability to include the fmr hdr for remote frames
|
||||||
|
*/
|
||||||
|
txctl_log.priv.frm_hdr = frm_hdr;
|
||||||
|
qdf_assert(txctl_log.priv.txdesc_ctl);
|
||||||
|
qdf_mem_copy((void *)&txctl_log.priv.txdesc_ctl,
|
||||||
|
((void *)data + sizeof(struct ath_pktlog_hdr)),
|
||||||
|
pl_hdr.size);
|
||||||
|
qdf_assert(txctl_log.txdesc_hdr_ctl);
|
||||||
|
qdf_mem_copy(txctl_log.txdesc_hdr_ctl, &txctl_log.priv,
|
||||||
|
sizeof(txctl_log.priv));
|
||||||
|
pl_hdr.size = log_size;
|
||||||
|
cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
|
||||||
|
txctl_log.txdesc_hdr_ctl);
|
||||||
|
/* Add Protocol information and HT specific information */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pl_hdr.log_type == PKTLOG_TYPE_TX_STAT) {
|
||||||
|
struct ath_pktlog_tx_status txstat_log;
|
||||||
|
size_t log_size = pl_hdr.size;
|
||||||
|
|
||||||
|
txstat_log.ds_status = (void *)
|
||||||
|
pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr);
|
||||||
|
qdf_assert(txstat_log.ds_status);
|
||||||
|
qdf_mem_copy(txstat_log.ds_status,
|
||||||
|
((void *)data + sizeof(struct ath_pktlog_hdr)),
|
||||||
|
pl_hdr.size);
|
||||||
|
cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
|
||||||
|
txstat_log.ds_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pl_hdr.log_type == PKTLOG_TYPE_TX_MSDU_ID) {
|
||||||
|
struct ath_pktlog_msdu_info pl_msdu_info;
|
||||||
|
size_t log_size;
|
||||||
|
|
||||||
|
qdf_mem_set(&pl_msdu_info, sizeof(pl_msdu_info), 0);
|
||||||
|
log_size = sizeof(pl_msdu_info.priv);
|
||||||
|
|
||||||
|
if (pl_dev->mt_pktlog_enabled == false)
|
||||||
|
fill_ieee80211_hdr_data(txrx_pdev, &pl_msdu_info, data);
|
||||||
|
|
||||||
|
pl_msdu_info.ath_msdu_info = pktlog_getbuf(pl_dev, pl_info,
|
||||||
|
log_size, &pl_hdr);
|
||||||
|
qdf_mem_copy((void *)&pl_msdu_info.priv.msdu_id_info,
|
||||||
|
((void *)data + sizeof(struct ath_pktlog_hdr)),
|
||||||
|
sizeof(pl_msdu_info.priv.msdu_id_info));
|
||||||
|
qdf_mem_copy(pl_msdu_info.ath_msdu_info, &pl_msdu_info.priv,
|
||||||
|
sizeof(pl_msdu_info.priv));
|
||||||
|
cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
|
||||||
|
pl_msdu_info.ath_msdu_info);
|
||||||
|
}
|
||||||
|
return A_OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
A_STATUS process_rx_info_remote(void *pdev, void *data)
|
||||||
|
{
|
||||||
|
struct ol_pktlog_dev_t *pl_dev;
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
struct htt_host_rx_desc_base *rx_desc;
|
||||||
|
struct ath_pktlog_hdr pl_hdr;
|
||||||
|
struct ath_pktlog_rx_info rxstat_log;
|
||||||
|
size_t log_size;
|
||||||
|
struct ol_rx_remote_data *r_data = (struct ol_rx_remote_data *)data;
|
||||||
|
qdf_nbuf_t msdu;
|
||||||
|
|
||||||
|
if (!pdev) {
|
||||||
|
printk("Invalid pdev in %s\n", __func__);
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
if (!r_data) {
|
||||||
|
printk("Invalid data in %s\n", __func__);
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
pl_dev = ((struct ol_txrx_pdev_t *)pdev)->pl_dev;
|
||||||
|
pl_info = pl_dev->pl_info;
|
||||||
|
msdu = r_data->msdu;
|
||||||
|
|
||||||
|
while (msdu) {
|
||||||
|
rx_desc =
|
||||||
|
(struct htt_host_rx_desc_base *)(qdf_nbuf_data(msdu)) - 1;
|
||||||
|
log_size =
|
||||||
|
sizeof(*rx_desc) - sizeof(struct htt_host_fw_desc_base);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Construct the pktlog header pl_hdr
|
||||||
|
* Because desc is DMA'd to the host memory
|
||||||
|
*/
|
||||||
|
pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S);
|
||||||
|
pl_hdr.missed_cnt = 0;
|
||||||
|
#if defined(HELIUMPLUS)
|
||||||
|
pl_hdr.macId = r_data->mac_id;
|
||||||
|
pl_hdr.log_type = PKTLOG_TYPE_RX_STAT;
|
||||||
|
pl_hdr.flags |= PKTLOG_HDR_SIZE_16;
|
||||||
|
#else
|
||||||
|
pl_hdr.log_type = PKTLOG_TYPE_RX_STAT;
|
||||||
|
#endif
|
||||||
|
pl_hdr.size = sizeof(*rx_desc) -
|
||||||
|
sizeof(struct htt_host_fw_desc_base);
|
||||||
|
#if defined(HELIUMPLUS)
|
||||||
|
pl_hdr.timestamp =
|
||||||
|
rx_desc->ppdu_end.rx_pkt_end.phy_timestamp_1_lower_32;
|
||||||
|
pl_hdr.type_specific_data = 0xDEADAA;
|
||||||
|
#else
|
||||||
|
pl_hdr.timestamp = rx_desc->ppdu_end.tsf_timestamp;
|
||||||
|
#endif /* !defined(HELIUMPLUS) */
|
||||||
|
rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info,
|
||||||
|
log_size, &pl_hdr);
|
||||||
|
qdf_mem_copy(rxstat_log.rx_desc, (void *)rx_desc +
|
||||||
|
sizeof(struct htt_host_fw_desc_base), pl_hdr.size);
|
||||||
|
cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
|
||||||
|
rxstat_log.rx_desc);
|
||||||
|
msdu = qdf_nbuf_next(msdu);
|
||||||
|
}
|
||||||
|
return A_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
A_STATUS process_rx_info(void *pdev, void *data)
|
||||||
|
{
|
||||||
|
struct ol_pktlog_dev_t *pl_dev;
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
struct ath_pktlog_rx_info rxstat_log;
|
||||||
|
struct ath_pktlog_hdr pl_hdr;
|
||||||
|
size_t log_size;
|
||||||
|
uint32_t *pl_tgt_hdr;
|
||||||
|
|
||||||
|
if (!pdev) {
|
||||||
|
printk("Invalid pdev in %s", __func__);
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
pl_dev = ((struct ol_txrx_pdev_t *)pdev)->pl_dev;
|
||||||
|
pl_info = pl_dev->pl_info;
|
||||||
|
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;
|
||||||
|
#ifdef HELIUMPLUS
|
||||||
|
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.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) &
|
||||||
|
ATH_PKTLOG_HDR_MAC_ID_MASK) >>
|
||||||
|
ATH_PKTLOG_HDR_MAC_ID_SHIFT;
|
||||||
|
pl_hdr.flags |= PKTLOG_HDR_SIZE_16;
|
||||||
|
#else
|
||||||
|
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;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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);
|
||||||
|
log_size = pl_hdr.size;
|
||||||
|
rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info,
|
||||||
|
log_size, &pl_hdr);
|
||||||
|
|
||||||
|
qdf_mem_copy(rxstat_log.rx_desc,
|
||||||
|
(void *)data + sizeof(struct ath_pktlog_hdr), pl_hdr.size);
|
||||||
|
cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc);
|
||||||
|
|
||||||
|
return A_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
A_STATUS process_rate_find(void *pdev, void *data)
|
||||||
|
{
|
||||||
|
struct ol_pktlog_dev_t *pl_dev;
|
||||||
|
struct ath_pktlog_hdr pl_hdr;
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
size_t log_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Will be uncommented when the rate control find
|
||||||
|
* for pktlog is implemented in the firmware.
|
||||||
|
* Currently derived from the TX PPDU status
|
||||||
|
*/
|
||||||
|
struct ath_pktlog_rc_find rcf_log;
|
||||||
|
uint32_t *pl_tgt_hdr;
|
||||||
|
|
||||||
|
if (!pdev) {
|
||||||
|
qdf_print("Invalid pdev in %s\n", __func__);
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
if (!data) {
|
||||||
|
qdf_print("Invalid data in %s\n", __func__);
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_tgt_hdr = (uint32_t *) data;
|
||||||
|
/*
|
||||||
|
* Makes the short words (16 bits) portable b/w little endian
|
||||||
|
* and big endian
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
#ifdef HELIUMPLUS
|
||||||
|
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.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) &
|
||||||
|
ATH_PKTLOG_HDR_MAC_ID_MASK) >>
|
||||||
|
ATH_PKTLOG_HDR_MAC_ID_SHIFT;
|
||||||
|
pl_hdr.flags |= PKTLOG_HDR_SIZE_16;
|
||||||
|
#else
|
||||||
|
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;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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);
|
||||||
|
pl_dev = ((struct ol_txrx_pdev_t *)pdev)->pl_dev;
|
||||||
|
pl_info = pl_dev->pl_info;
|
||||||
|
log_size = pl_hdr.size;
|
||||||
|
rcf_log.rcFind = (void *)pktlog_getbuf(pl_dev, pl_info,
|
||||||
|
log_size, &pl_hdr);
|
||||||
|
|
||||||
|
qdf_mem_copy(rcf_log.rcFind,
|
||||||
|
((char *)data + sizeof(struct ath_pktlog_hdr)),
|
||||||
|
pl_hdr.size);
|
||||||
|
cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcf_log.rcFind);
|
||||||
|
|
||||||
|
return A_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
A_STATUS process_sw_event(void *pdev, void *data)
|
||||||
|
{
|
||||||
|
struct ol_pktlog_dev_t *pl_dev;
|
||||||
|
struct ath_pktlog_hdr pl_hdr;
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
size_t log_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Will be uncommented when the rate control find
|
||||||
|
* for pktlog is implemented in the firmware.
|
||||||
|
* Currently derived from the TX PPDU status
|
||||||
|
*/
|
||||||
|
struct ath_pktlog_sw_event sw_event;
|
||||||
|
uint32_t *pl_tgt_hdr;
|
||||||
|
|
||||||
|
if (!pdev) {
|
||||||
|
qdf_print("Invalid pdev in %s\n", __func__);
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
if (!data) {
|
||||||
|
qdf_print("Invalid data in %s\n", __func__);
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_tgt_hdr = (uint32_t *) data;
|
||||||
|
/*
|
||||||
|
* Makes the short words (16 bits) portable b/w little endian
|
||||||
|
* and big endian
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
#ifdef HELIUMPLUS
|
||||||
|
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.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) &
|
||||||
|
ATH_PKTLOG_HDR_MAC_ID_MASK) >>
|
||||||
|
ATH_PKTLOG_HDR_MAC_ID_SHIFT;
|
||||||
|
#else
|
||||||
|
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;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
#ifdef HELIUMPLUS
|
||||||
|
pl_hdr.type_specific_data =
|
||||||
|
*(pl_tgt_hdr + ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pl_dev = ((struct ol_txrx_pdev_t *)pdev)->pl_dev;
|
||||||
|
pl_info = pl_dev->pl_info;
|
||||||
|
log_size = pl_hdr.size;
|
||||||
|
sw_event.sw_event = (void *)pktlog_getbuf(pl_dev, pl_info,
|
||||||
|
log_size, &pl_hdr);
|
||||||
|
|
||||||
|
qdf_mem_copy(sw_event.sw_event,
|
||||||
|
((char *)data + sizeof(struct ath_pktlog_hdr)),
|
||||||
|
pl_hdr.size);
|
||||||
|
|
||||||
|
return A_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
A_STATUS process_rate_update(void *pdev, void *data)
|
||||||
|
{
|
||||||
|
struct ol_pktlog_dev_t *pl_dev;
|
||||||
|
struct ath_pktlog_hdr pl_hdr;
|
||||||
|
size_t log_size;
|
||||||
|
struct ath_pktlog_info *pl_info;
|
||||||
|
struct ath_pktlog_rc_update rcu_log;
|
||||||
|
uint32_t *pl_tgt_hdr;
|
||||||
|
|
||||||
|
if (!pdev) {
|
||||||
|
printk("Invalid pdev in %s\n", __func__);
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
if (!data) {
|
||||||
|
printk("Invalid data in %s\n", __func__);
|
||||||
|
return A_ERROR;
|
||||||
|
}
|
||||||
|
pl_tgt_hdr = (uint32_t *) data;
|
||||||
|
/*
|
||||||
|
* Makes the short words (16 bits) portable b/w little endian
|
||||||
|
* and big endian
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
#ifdef HELIUMPLUS
|
||||||
|
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.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) &
|
||||||
|
ATH_PKTLOG_HDR_MAC_ID_MASK) >>
|
||||||
|
ATH_PKTLOG_HDR_MAC_ID_SHIFT;
|
||||||
|
pl_hdr.flags |= PKTLOG_HDR_SIZE_16;
|
||||||
|
#else
|
||||||
|
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;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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);
|
||||||
|
pl_dev = ((struct ol_txrx_pdev_t *)pdev)->pl_dev;
|
||||||
|
log_size = pl_hdr.size;
|
||||||
|
pl_info = pl_dev->pl_info;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Will be uncommented when the rate control update
|
||||||
|
* for pktlog is implemented in the firmware.
|
||||||
|
* Currently derived from the TX PPDU status
|
||||||
|
*/
|
||||||
|
rcu_log.txRateCtrl = (void *)pktlog_getbuf(pl_dev, pl_info,
|
||||||
|
log_size, &pl_hdr);
|
||||||
|
qdf_mem_copy(rcu_log.txRateCtrl,
|
||||||
|
((char *)data + sizeof(struct ath_pktlog_hdr)),
|
||||||
|
pl_hdr.size);
|
||||||
|
cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcu_log.txRateCtrl);
|
||||||
|
return A_OK;
|
||||||
|
}
|
||||||
|
#endif /*REMOVE_PKT_LOG */
|
127
utils/ptt/inc/wlan_ptt_sock_svc.h
Normal file
127
utils/ptt/inc/wlan_ptt_sock_svc.h
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
#ifdef PTT_SOCK_SVC_ENABLE
|
||||||
|
int ptt_sock_activate_svc(void);
|
||||||
|
void ptt_sock_deactivate_svc(void);
|
||||||
|
int ptt_sock_send_msg_to_app(tAniHdr *wmsg, int radio, int src_mod, int pid);
|
||||||
|
#else
|
||||||
|
static inline int ptt_sock_activate_svc(void) { return 0; }
|
||||||
|
static inline void ptt_sock_deactivate_svc(void) { return; }
|
||||||
|
static inline int ptt_sock_send_msg_to_app(tAniHdr *wmsg, int radio,
|
||||||
|
int src_mod, int pid)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
typedef struct sAniAppRegReq {
|
||||||
|
tAniNlModTypes type; /* module id */
|
||||||
|
int pid; /* process id */
|
||||||
|
} tAniNlAppRegReq;
|
||||||
|
typedef struct sAniNlAppRegRsp {
|
||||||
|
tAniHdr wniHdr; /* Generic WNI msg header */
|
||||||
|
tAniNlAppRegReq regReq; /* The original request msg */
|
||||||
|
int ret; /* Return code */
|
||||||
|
} tAniNlAppRegRsp;
|
||||||
|
#endif
|
231
utils/ptt/src/wlan_ptt_sock_svc.c
Normal file
231
utils/ptt/src/wlan_ptt_sock_svc.c
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
|
* above copyright notice and this permission notice appear in all
|
||||||
|
* copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was originally distributed by Qualcomm Atheros, Inc.
|
||||||
|
* under proprietary terms before Copyright ownership was assigned
|
||||||
|
* to the Linux Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* 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>
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
/** ptt Process ID */
|
||||||
|
static int32_t ptt_pid = INVALID_PID;
|
||||||
|
|
||||||
|
#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%p:", 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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 == NULL) {
|
||||||
|
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 (NULL == 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;
|
||||||
|
memcpy(&wnl->wmsg, 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(skb, pid, MSG_DONTWAIT);
|
||||||
|
else
|
||||||
|
err = nl_srv_bcast(skb);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process tregisteration request and send registration response messages
|
||||||
|
* to the PTT Socket App in user space
|
||||||
|
*/
|
||||||
|
static void ptt_sock_proc_reg_req(tAniHdr *wmsg, int radio)
|
||||||
|
{
|
||||||
|
tAniNlAppRegReq *reg_req;
|
||||||
|
tAniNlAppRegRsp rspmsg;
|
||||||
|
reg_req = (tAniNlAppRegReq *) (wmsg + 1);
|
||||||
|
memset((char *)&rspmsg, 0, sizeof(rspmsg));
|
||||||
|
/* send reg response message to the application */
|
||||||
|
rspmsg.ret = ANI_NL_MSG_OK;
|
||||||
|
rspmsg.regReq.type = reg_req->type;
|
||||||
|
/*Save the pid */
|
||||||
|
ptt_pid = reg_req->pid;
|
||||||
|
rspmsg.regReq.pid = reg_req->pid;
|
||||||
|
rspmsg.wniHdr.type = cpu_to_be16(ANI_MSG_APP_REG_RSP);
|
||||||
|
rspmsg.wniHdr.length = cpu_to_be16(sizeof(rspmsg));
|
||||||
|
if (ptt_sock_send_msg_to_app((tAniHdr *) &rspmsg.wniHdr, radio,
|
||||||
|
ANI_NL_MSG_PUMAC, ptt_pid) < 0) {
|
||||||
|
PTT_TRACE(QDF_TRACE_LEVEL_INFO,
|
||||||
|
"%s: Error sending ANI_MSG_APP_REG_RSP to pid[%d]\n",
|
||||||
|
__func__, ptt_pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process all the messages from the PTT Socket App in user space
|
||||||
|
*/
|
||||||
|
static void ptt_proc_pumac_msg(struct sk_buff *skb, tAniHdr *wmsg, int radio)
|
||||||
|
{
|
||||||
|
u16 ani_msg_type = be16_to_cpu(wmsg->type);
|
||||||
|
switch (ani_msg_type) {
|
||||||
|
case ANI_MSG_APP_REG_REQ:
|
||||||
|
PTT_TRACE(QDF_TRACE_LEVEL_INFO,
|
||||||
|
"%s: Received ANI_MSG_APP_REG_REQ [0x%X]\n", __func__,
|
||||||
|
ani_msg_type);
|
||||||
|
ptt_sock_proc_reg_req(wmsg, radio);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PTT_TRACE(QDF_TRACE_LEVEL_ERROR,
|
||||||
|
"%s: Received Unknown Msg Type[0x%X]\n", __func__,
|
||||||
|
ani_msg_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process all the Netlink messages from PTT Socket app in user space
|
||||||
|
*/
|
||||||
|
static int ptt_sock_rx_nlink_msg(struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
tAniNlHdr *wnl;
|
||||||
|
int radio;
|
||||||
|
int type;
|
||||||
|
wnl = (tAniNlHdr *) skb->data;
|
||||||
|
radio = wnl->radio;
|
||||||
|
type = wnl->nlh.nlmsg_type;
|
||||||
|
switch (type) {
|
||||||
|
case ANI_NL_MSG_PUMAC: /* Message from the PTT socket APP */
|
||||||
|
PTT_TRACE(QDF_TRACE_LEVEL_INFO,
|
||||||
|
"%s: Received ANI_NL_MSG_PUMAC Msg [0x%X]\n",
|
||||||
|
__func__, type);
|
||||||
|
ptt_proc_pumac_msg(skb, &wnl->wmsg, radio);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PTT_TRACE(QDF_TRACE_LEVEL_ERROR, "%s: Unknown NL Msg [0x%X]\n",
|
||||||
|
__func__, type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ptt_sock_activate_svc() - activate PTT service
|
||||||
|
*
|
||||||
|
* Return: 0
|
||||||
|
*/
|
||||||
|
int ptt_sock_activate_svc(void)
|
||||||
|
{
|
||||||
|
ptt_pid = INVALID_PID;
|
||||||
|
nl_srv_register(ANI_NL_MSG_PUMAC, ptt_sock_rx_nlink_msg);
|
||||||
|
nl_srv_register(ANI_NL_MSG_PTT, ptt_sock_rx_nlink_msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ptt_sock_deactivate_svc() - deactivate PTT service
|
||||||
|
*
|
||||||
|
* Return: Void
|
||||||
|
*/
|
||||||
|
void ptt_sock_deactivate_svc(void)
|
||||||
|
{
|
||||||
|
ptt_pid = INVALID_PID;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* PTT_SOCK_SVC_ENABLE */
|
Reference in New Issue
Block a user